Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uefi-raw: unified boolean type #1307

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Conversation

phip1611
Copy link
Contributor

@phip1611 phip1611 commented Aug 11, 2024

This streamlines the existing usages of u8 and bool. Note that BootPolicy from #1297 is seamlessly integrated into u8 and bool.

Steps to Undraft

Checklist

  • Sensible git history (for example, squash "typo" or "fix" commits). See the Rewriting History guide for help.
  • Update the changelog (if necessary)

@phip1611 phip1611 marked this pull request as draft August 11, 2024 11:00
@phip1611 phip1611 changed the title uefi-raw: unified boolean type [BLOCKED] uefi-raw: unified boolean type Aug 11, 2024
@nicholasbishop
Copy link
Contributor

nicholasbishop commented Aug 12, 2024

bool is an interesting case in terms of how far to go with worrying about undefined behavior. Creating a bool from any value other than 0 or 1 is UB. (Miri correctly catches it: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8777a1510372038e487aea18979f78ac.) The UEFI spec says pretty much the same thing: 0 and 1 are valid, other values are undefined. However, in C code it's not actually that hard to accidentally end up with a boolean-ish value that isn't 0 or 1. For example: bitwise operators like flags & MY_FLAG -- in Rust you have to explictly convert that to a bool with (flags & MY_FLAG) != 0, but not so in C.

So this ends up being similar to enums, where we carefully construct wrappers with newtype_enum! -- they can hold any bit pattern, unlike normal enums. If we want to guard against UB, then the Boolean type should be a repr(transparent) wrapper around u8, rather than a Rust bool. I think it's definitely questionable whether it's worth worrying about, but that's the explanation for why I used u8 rather than bool in most places in uefi-raw.

@phip1611 phip1611 mentioned this pull request Aug 13, 2024
2 tasks
@phip1611 phip1611 marked this pull request as ready for review October 1, 2024 11:23
@phip1611 phip1611 changed the title [BLOCKED] uefi-raw: unified boolean type uefi-raw: unified boolean type Oct 1, 2024
@phip1611
Copy link
Contributor Author

phip1611 commented Oct 1, 2024

I've come up with a new design. What do you think?

Open Question:

  • We could loosen the requirements. 0bxxxxxx1 can be a a valid bit pattern mapping to true. currently, this is a failure. What do you think?
  • Regarding check-raw and the failing CI: I'm not sure if cargo xtask check-raw brings us more benefits than breaks development 🤔 Can you please elaborate what's the idea here, @nicholasbishop ?

@nicholasbishop
Copy link
Contributor

I think this design looks good.

We could loosen the requirements. 0bxxxxxx1 can be a a valid bit pattern mapping to true. currently, this is a failure. What do you think?

Yes, I think loosening the requirements so that any non-zero value is treated as true sounds good. This matches C behavior and is also what r-efi does: https://docs.rs/r-efi/latest/src/r_efi/base.rs.html#488.

Regarding check-raw and the failing CI: I'm not sure if cargo xtask check-raw brings us more benefits than breaks development

I feel that it does. For example, with the field pub check that this PR is failing on, almost all structs in uefi-raw should have all of their fields pub, because otherwise the struct cannot really be constructed outside the crate. It's very easy to forget while writing code, and easy to miss in code review.

In this particular case, I think the easiest thing to do is to change the definition to pub struct Boolean(pub u8). There's no harm in making the field public in uefi-raw, and the Boolean type isn't used in the public API of uefi.

This way we can be ABI-compatible and guarantee lack of UB, while
being more precise in interfaces.
@@ -23,5 +23,9 @@ bitflags.workspace = true
ptr_meta.workspace = true
uguid.workspace = true

[features]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no error type in uefi-raw now, so I think the features section can be dropped


# uefi-raw - 0.8.0 (2024-09-09)

## Added

- Added `PAGE_SIZE` constant.

- Added a new `unstable` feature
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer needed

assert_eq!(Boolean::FALSE.0, 0);
assert_eq!(bool::from(Boolean(0b0)), false);
assert_eq!(bool::from(Boolean(0b1)), true);
// We do it a C: Every bit pattern not 0 is equal to true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We do it a C: Every bit pattern not 0 is equal to true
// We do it as in C: Every bit pattern not 0 is equal to true

- Fixed `boot::open_protocol` to properly handle a null interface pointer.


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tiny nit: per your changes in 4d1906e, two blank lines between each version entry

pub const fn cursor_visible(&self) -> bool {
self.data().cursor_visible
pub fn cursor_visible(&self) -> bool {
// Panic: Misbehaving UEFI impls are so unlikely; just fail
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can drop the panic comment now that conversion cannot fail

pub const fn is_removable_media(&self) -> bool {
self.0.removable_media
pub fn is_removable_media(&self) -> bool {
// Panic: Misbehaving UEFI impls are so unlikely; just fail
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can drop all the panic comments in this file too

@@ -31,6 +31,7 @@ enum ErrorKind {
ForbiddenType,
MalformedAttrs,
MissingPub,
MissingRepr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check_raw changes can all be dropped since there's no error type anymore.

@@ -15,9 +15,9 @@ details of the deprecated items that were removed in this release.
- **Breaking:** `FileSystem` no longer has a lifetime parameter, and the
deprecated conversion from `uefi::table::boot::ScopedProtocol` has been
removed.
- **Breaking:** Removed `BootPolicyError` as `BootPolicy`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Breaking:** Removed `BootPolicyError` as `BootPolicy`
- **Breaking:** Removed `BootPolicyError` as `BootPolicy` construction is no longer fallible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants