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

How to convert value returned by get_variable_boxed() into a printable str? #925

Open
felipebalbi opened this issue Aug 23, 2023 · 5 comments

Comments

@felipebalbi
Copy link
Contributor

Hi,

I'm experimenting with uefi-rs, specifically I want to read the BootOrder variable (and the accompanying Boot#### variables) and try to write a very minimal boot manager application. Reading the content of the variables is straightforward, but how can I convert the resulting &[u8] into something I can print to the screen?

@nicholasbishop
Copy link
Member

UEFI variables can hold arbitrary data, so there's no single optimal way to print them.

BootOrder is described in section 3.3:

The BootOrder variable contains an array of UINT16 ’s that make up an ordered list of the Boot#### options. The first element in the array is the value for the first logical boot option, the second element is the value for the second logical boot option, etc.

So for BootOrder, you should deserialize it as little-endian u16 values.

Boot#### contain EFI_LOAD_OPTION, which is described in section 3.1.3. That struct contains multiple dynamically-sized fields making it a bit more complicated. You'd deserialize it by reading a little-endian u32. then a u16, then read u16 chars until the null char is reached for the description field, then deserialize the packed DevicePaths, then treating the rest of the data as the OptionalData field.

I think we should add some code to uefi-rs to help with parsing and creating EFI_LOAD_OPTION data, but I don't think we have any such code yet.

@felipebalbi
Copy link
Contributor Author

UEFI variables can hold arbitrary data, so there's no single optimal way to print them.

Right. They need to be parsed.

BootOrder is described in section 3.3:

The BootOrder variable contains an array of UINT16 ’s that make up an ordered list of the Boot#### options. The first element in the array is the value for the first logical boot option, the second element is the value for the second logical boot option, etc.

So for BootOrder, you should deserialize it as little-endian u16 values.

I got this far, yes.

Boot#### contain EFI_LOAD_OPTION, which is described in section 3.1.3. That struct contains multiple dynamically-sized fields making it a bit more complicated. You'd deserialize it by reading a little-endian u32. then a u16, then read u16 chars until the null char is reached for the description field, then deserialize the packed DevicePaths, then treating the rest of the data as the OptionalData field.

Heh, this I totally misunderstood. Thanks for the direct description. I'll try looking into this tomorrow.

I think we should add some code to uefi-rs to help with parsing and creating EFI_LOAD_OPTION data, but I don't think we have any such code yet.

Any suggestion where to put the code? A new module altogether? As part of a new EfiLoadOption type? Perhaps with a new EfiLoadOption::try_from() trait implementation? If possible, I'd like to contribute that code, but I'll probably need some rounds of review before the code is up to the project's standards.

Cheers

@nicholasbishop
Copy link
Member

Any suggestion where to put the code? A new module altogether? As part of a new EfiLoadOption type? Perhaps with a new EfiLoadOption::try_from() trait implementation? If possible, I'd like to contribute that code, but I'll probably need some rounds of review before the code is up to the project's standards.

That would be great! I'm thinking maybe a new struct LoadOption in uefi/src/data_types/load_option.rs. This would be a DST type, probably with a trailing [u8] field to contain the three DST fields.

A somewhat similar example that might help to review is the ACPI expanded device path node. The Expanded struct is defined here. Various accessor methods will be needed to get the private field data out of the DST field. (We also have a builder struct defined here for creating an Expanded node. A builder doesn't need to be part of the initial PR for this though, just a read-only struct would be a good place to start.) These structs are generated, so they look a little different from what you'll write, but should be useful as a reference.

@felipebalbi
Copy link
Contributor Author

That would be great! I'm thinking maybe a new struct LoadOption in uefi/src/data_types/load_option.rs. This would be a DST type, probably with a trailing [u8] field to contain the three DST fields.

Perfect. I'll start working on that. Do you think it makes sense to add a LoadOption iterator? This would read and parse BootOrder and its next method would read the correct variable, produce the LoadOption struct and return it.

@nicholasbishop
Copy link
Member

I'm not sure about the iterator. It's possible that kind of logic might be too specific to the application using it, so even if we provided it, bootloaders might end up re-implementing their own more specific version. Another option would be to add such code as an example (under uefi-test-runner/examples) and then see if there's anything we feel confident is generic enough to pull out of it.

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

No branches or pull requests

2 participants