RFC: API Version: 1.0?
Opened this issue · 7 comments
@andreeaflorescu and I recently discussed the upgrade process from 0.30.0 to 0.33.0, noting that it was not as smooth as we would have liked. This was largely due to several significant but necessary API changes. However, with our recent (and fairly invasive) updates to the free-standing functions API (see #893) and improvements to the memory map code (#1234, #1240), the codebase now appears to be in a much more stable and mature state.
Given this progress, it’s worth considering the following question:
Are we ready for 1.0.0? Is there a way forward to go there?
Blockers
- #1470
- .. more?
I don't consider any Rust UEFI project anywhere close to "1.0", because so many interfaces and types from the specifications are missing. But version numbers are cheap.
Missing types and functions, or generally speaking functionality, are not a major blocker for a 1.0 release IMHO, as the major component in x.y.z is for the API itself and not the amount of functionality. That being said, as long as new functionality can be added with 1.y.z releases without API changes, everything should be fine.
The only risk I see is that, because of the lack of functionality, we don't see certain mandatory future API changes yet.
I haven't used the crate much because I'm waiting for the license change, so my feedback is limited. I expect that most of my use will be with uefi-raw anyway since I am implementing drivers and need to construct the interfaces using the C bindings.
One thing that could be a blocker is deciding what to do about {Install,Uninstall}MultipleProtocolInterfaces:
These are just convenience functions that loop on {Install,Uninstall}ProtocolInterface, so a Rust wrapper could probably just avoid them altogether.
One thing I'd like us to consider is what our comfort level is with moving beyond a major version 1. For example, say we realized that the alignment of some auxiliary type for a rarely-used UEFI protocol was wrong. If that type is public, then even though it's a really small change, it's still considered a breaking change by semver and we would need to bump to major version 2. Since the UEFI API has such a huge surface area, I could imagine needing major release number bumps much more frequently than other 1.0 crates.
I agree with crawfxrd that 'version numbers are cheap', so personally I don't at all mind going to 1.0 soon and then bumping the major version as needed in the future. But I want to check whether we're in agreement on that.
For example, say we realized that the alignment of some auxiliary type for a rarely-used UEFI protocol was wrong.
Here it gets philosophical 🤓 For some, this is a bug fix release, despite breaking stuff.
Different folks have different opinions on that. For example, in the Rust community, typically MSRV updates are tolerated for feature releases, despite being breaking. I fully agree we should all be on the same page what we consider breaking etc, if we go to 1.0 and beyond.
I'd like to clarify that I'm not in strong favor of 1.0.0 nor against it. I just wanted to start the discussion. And Andreea was totally right when she pointed out to me that upgrading from 0.30.0 to 0.33.0 was not a pleasant experience, despite all guidelines. We should not repeat that. But I also think that this is unlikely now, as the API is more mature.
It is simply not feasible to consider the >200 protocols of "the UEFI specification"--plus PI, Shell, TCG, ACPI, and "unofficial" edk2 protocols (like BootLogo2 and GopPolicy which I will need)--as part of the core interface for "major" releases. Almost all changes would be a major release then.
I see it as a fundamental failing of UEFI that all of these were added to a single specification instead of extensions. Especially with things like GPT, EBC, networking, and DMTF's Redfish.
For the point of this issue: it should be explicitly defined what is considered as part of the Rust API interface. I would see this as truly core things from edk2 like gST, gBS, and gRT (plus whatever interfaces/types they use). This would correspond to, at least (UEFI 2.11):
- 4: EFI System Table
- 7: Services - Boot Services
- 8: Services - Runtime Services
What's more, it may be nice if the project declared some release/errata of UEFI it targeted (even if it's "latest" for every release). The errata of a release max fix (change) a datatype/interface, and there are still things "in the spec" that are wrong (but fixed/correct in edk2--pointer arguments and type typos in my experience--and this should be declared in the code).
Another thing:
There seem to be some C interfaces declared in uefi rather than uefi-raw. I would like to see these separated before declaring a 1.0 for uefi.
I will also add, in regards to licensing: "MIT OR Apache-2.0" is probably okay.
I'm pretty sure Microsoft is okay with it (I think they use Rust with MIT license), but it needs to be determined if Intel is okay with it. edk2 typically requires code to use BSD-2-Clause-Patent.
As you can guess, the "patent clause" is important (covered by Apache-2.0). Even though Intel made it, they want to make sure they can use any work anyone else makes without legal repercussions.
Imho, before v1.0 the PoolDevicePath and PoolDevicePathNode structs should be moved out of proto::device_path::text into proto::device_path. They are generally very useful - especially when implementing the EFI_DEVICE_PATH_UTILITIES_PROTOCOL which has a bunch of methods returning allocated DevicePaths.