Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Enhancement/efi shell interface#1679

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
RenTrieu wants to merge7 commits intorust-osdev:main
base:main
Choose a base branch
Loading
fromRenTrieu:enhancement/efi_shell_interface

Conversation

RenTrieu
Copy link
Contributor

This PR will implement the wrappers for EFI Shell Protocol functions to address#448 . This PR does branch off of the changes made in#596 so big thanks to@timrobertsdev for laying the groundwork!

Currently, I've implemented wrappers and wrote tests forGetEnv(),SetEnv(),GetCurDir() andSetCurDir(). My plan is to first write tests for and finish implementingExecute(),CloseFile(),CreateFile(),FindFiles(),FindFilesInDir(), andGetFileSize() since they have already been started. Then I can implement the rest in either this PR or subsequent follow up PRs (whichever is preferable).

I do have some questions about myget_env() implementation. UEFI'sGetEnv() returns the value of a variable if its name is specified. However if its name is not specified, it returns all known variable names in a*const Char16 where the names are delimited by aNULL and the end of the list is terminated by a doubleNULL.

My initial approach was to parse the*const Char16 into aVec in this case. I wrapped the return value in an Enum that can be unpacked into a single&CStr16 or into a vector of&CStr16s depending on which is expected. Is this approach okay? I was concerned that if I simply returned a&CStr16 in the "name list" case that the true size of the string wouldn't be visible since the names are separated byNULL. Also, is it okay for me to usealloc::vec::Vec? I saw that a lot of other protocols don't use anyVec at all so I'm not clear on if there are some restrictions for doing so.

Checklist

  • Execute
  • GetEnv
  • SetEnv
  • GetAlias
  • SetAlias
  • GetHelpText
  • GetDevicePathFromMap
  • GetMapFromDevicePath
  • GetDevicePathFromFilePath
  • GetFilePathFromDevicePath
  • SetMap
  • GetCurDir
  • SetCurDir
  • OpenFileList
  • FreeFileList
  • RemoveDupInFileList
  • BatchIsActive
  • IsRootShell
  • EnablePageBreak
  • DisablePageBreak
  • GetPageBreak
  • GetDeviceName
  • GetFileInfo
  • SetFileInfo
  • OpenFileByName
  • CloseFile
  • CreateFile
  • ReadFile
  • WriteFile
  • DeleteFile
  • DeleteFileByName
  • GetFilePosition
  • SetFilePosition
  • FlushFile
  • FindFiles
  • FindFilesInDir
  • GetFileSize
  • OpenRoot
  • OpenRootByHandle
  • ExecutionBreak
  • Version Variables
  • RegisterGuidName
  • GetGuidName
  • GetGuidFromName
  • GetEnvEx

phip1611 reacted with thumbs up emoji
Copy link
Member

@phip1611phip1611 left a comment
edited
Loading

Choose a reason for hiding this comment

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

Thanks for working on this! As a general rule of thumb: High-level wrappers should be close to the API ofstd and not replicate "ugly" or unusual details of the low-level API. See my suggestions forget_var

@nicholasbishop
Copy link
Member

Some general guidance:

  1. Start with a PR that just updatesuefi-raw. (As Philipp notedhere, the definition of the shell protocol that matches the C spec should go in uefi-raw. See for exampleRngProtocol.api_guidelines has some notes about how to implement stuff in uefi-raw.)
  2. Once that's merged, do small PRs that add ergonomic wrappers to theuefi crate. Small PRs will help get review done faster.
  3. RegardingVec, it's generally OK to use, but does need to be gated by thealloc feature. (I haven't looked at the code yet though, I'm just commenting generally.)
phip1611 reacted with thumbs up emoji

@RenTrieu
Copy link
ContributorAuthor

Thanks for the feedback! I will start with making the PR to updateuefi-raw as Nicholas suggested, then come back to address the other comments.

phip1611 reacted with thumbs up emoji

This commit implements wrappers for the following EFI Shell Protocolfunctions: set_env(), get_env(), set_cur_dir(), and get_cur_dir().
This commit includes tests for the following EFI Shell Protocol functions:get_env(), set_env(), get_cur_dir(), and set_cur_dir().
@RenTrieu
Copy link
ContributorAuthor

Hi all. Now that#1680 is merged, I was wondering if it would be alright to use this PR to work on the 4 ergonomic wrappers I've implemented (GetEnv(),SetEnv(),GetCurDir(),SetCurDir()). Is this sufficiently small enough? Or should I split this into two PRs- one for theEnv functions and the other forCurDir?

If it is okay to continue to use this PR, then I plan to rebase this branch onto the current main, squash the commits, and then continue from there.

@nicholasbishop
Copy link
Member

That sounds good, start with doing that in this PR. Once the changes are in this PR it's possible I might ask for it to be split up into more than one PR for review, but we can start with the assumption that one PR is OK.

RenTrieu and phip1611 reacted with thumbs up emoji

@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch fromb9a3be8 to0f30078CompareJune 3, 2025 18:31
@RenTrieuRenTrieu marked this pull request as ready for reviewJune 3, 2025 20:06
@RenTrieu
Copy link
ContributorAuthor

I've rebased this branch onto the current main and updated it to disclude theShellProtocol definition moved touefi-raw. I was wondering if there is any guidance for writing tests. So far, I have done my best to look at other files and imitate the format such asuefi-test-runner/src/proto/media.rs anduefi-test-runner/src/proto/rng.rs, but if there is anything more specific I can revise what I have.

@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch 2 times, most recently from910e291 to42cad4aCompareJune 11, 2025 02:24
@RenTrieu
Copy link
ContributorAuthor

Thanks for the feedback! I have updatedget_envs() to return aVars struct that implements the Iterator trait. However, I do have a question about my implementation. When checking if a givenChar16 isNULL, I use

Char16::from_u16_unchecked(0)

to represent theNULL value for the comparison. I saw that one of the suggestions requested to use

Char16::from_u16(0).unwrap()

instead, but I don't see this function implemented forChar16. Is it alright to use the unchecked variant?

I'll start working on unit tests next! However, for Miri I will need to take some time to read its docs since I'm not familiar.

@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch from5661358 to6b35e5aCompareJune 11, 2025 15:40
@RenTrieu
Copy link
ContributorAuthor

I've updated the PR to use thecstr16! macro instead of the buffers and also added a unit test for theVars struct. Thank you for the tip on mocking the inner value with theVec, it was very helpful. Please let me know if the unit test looks alright.

phip1611 reacted with thumbs up emoji

@phip1611
Copy link
Member

LGTM! Please squash your commits a little to smaller but sensible units, then I think we are good to go

RenTrieu reacted with thumbs up emoji

RenTrieuand others added2 commitsJune 13, 2025 15:38
The UEFI get_env() implementation is used for getting individual environmentvariable values and also environment variable names. This is not intuitiveso this commit splits the function into two dedicated ones: one for accessingvalues and the other for accessing names.Co-authored-by: Philipp Schuster <phip1611@gmail.com>
Co-authored-by: Philipp Schuster <phip1611@gmail.com>
@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch fromc0b817e toa21932fCompareJune 13, 2025 22:40
@RenTrieu
Copy link
ContributorAuthor

Commits have been squashed :)

/// environment variable
/// * `None` - If environment variable does not exist
#[must_use]
pub fn get_env(&self, name: &CStr16) -> Option<&CStr16> {

Choose a reason for hiding this comment

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

In#1679 (comment), it was suggested to use the same name asstd:var. I think we should do that here, for several reasons:

phip1611 and RenTrieu reacted with thumbs up emoji
///
/// # Returns
///
/// * `Vec<env_names>` - Vector of environment variable names

Choose a reason for hiding this comment

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

Out of date, it returnsVars now. You can probably drop theReturns section here though, it's redundent with the top-level description.

phip1611 and RenTrieu reacted with thumbs up emoji
}
}

/// Gets the list of environment variables

Choose a reason for hiding this comment

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

"Gets an iterator over the names of all environment variables."

phip1611 and RenTrieu reacted with thumbs up emoji
///
/// * `Vec<env_names>` - Vector of environment variable names
#[must_use]
pub fn get_envs(&self) -> Vars {

Choose a reason for hiding this comment

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

I thinkvar_names would be a better name for this function (see comment onget_env for details). However, even better might be to make it matchstd and haveVars return an iterator over both namesand values (and then the method can be named simplyvars). Is that doable?

phip1611 and RenTrieu reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

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

Yes, sounds reasonable. High level abstractions should be close to known interfaces (such as std) and not replicate low-level details

///
/// * `Status::SUCCESS` - The variable was successfully set
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(name).cast();

Choose a reason for hiding this comment

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

Instead ofcore::ptr::from_ref, you can usename.as_ptr() (and ditto for value below).

RenTrieu reacted with thumbs up emoji
/// * `None` - Could not retrieve current directory
#[must_use]
pub fn get_cur_dir(&self, file_system_mapping: Option<&CStr16>) -> Option<&CStr16> {
let mapping_ptr: *const Char16 = file_system_mapping.map_or(ptr::null(), |x| (x.as_ptr()));

Choose a reason for hiding this comment

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

nit: parens not needed aroundx.as_ptr(). Might be clearer to write asmap_or(ptr::null(), CStr16::as_ptr).

RenTrieu reacted with thumbs up emoji
/// # Errors
///
/// * `Status::EFI_NOT_FOUND` - The directory does not exist
pub fn set_cur_dir(&self, file_system: Option<&CStr16>, directory: Option<&CStr16>) -> Status {

Choose a reason for hiding this comment

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

set_current_dir to matchstd

phip1611 and RenTrieu reacted with thumbs up emoji
/// # Returns
///
/// * `Status::SUCCESS` - The variable was successfully set
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {

Choose a reason for hiding this comment

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

Here and on other methods, returnResult (https://docs.rs/uefi/latest/uefi/type.Result.html) instead of a rawStatus. This is more convenient for users since it works with?.

phip1611 and RenTrieu reacted with thumbs up emoji
/// # Returns
///
/// * `Status::SUCCESS` - The variable was successfully set
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {

Choose a reason for hiding this comment

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

set_var to matchstd

phip1611 and RenTrieu reacted with thumbs up emoji
Some(CStr16::from_ptr(cur_start))
}
}
}

Choose a reason for hiding this comment

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

I think the implementation could be simplified, something like this:

fnnext(&mutself) ->Option<Self::Item>{let s =unsafe{CStr16::from_ptr(self.inner)};if s.is_empty(){None}else{self.inner =unsafe{self.inner.add(s.num_chars() +1)};Some(s)}}

RenTrieu reacted with thumbs up emoji
@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch from8e808c2 to3e9bff8CompareJune 24, 2025 20:44
@RenTrieu
Copy link
ContributorAuthor

Thank you for the feedback. I'm starting to understand the goal of abstracting the lower level implementation in ways that are useful for the user and will do my best to keep this in mind for future pull requests! I've addressed the function call names and return values.

For returningResult as opposed toStatus, is it alright to simply call theto_result() method and return?

As for changingVars to return both the name and value of the environment variables, is it fine to use something from thealloc crate likeVec orBox for this? I don't think I see a way to handle this without dynamically allocating memory to, at the very least, hold the pointers to the values. Please let me know if you have any suggested approaches.

@phip1611
Copy link
Member

Thank you for the feedback. I'm starting to understand the goal of abstracting the lower level implementation in ways that are useful for the user

Perfect! Thanks for your patience and valuable contributions :)

For returning Result as opposed to Status, is it alright to simply call the to_result() method and return?

Yes, perfectly fine, and also done in other parts of the code base

As for changing Vars to return both the name and value of the environment variables, is it fine to use something from the alloc crate like Vec or Box for this

Yes, that's fine. So far, we didn't have a clear guidline. IMHO,uefi in the early days tried to avoidalloc whenever possible, but over time,alloc was mandatory for more and more parts of the crate.

Now, IMHO, the guideline is: preventalloc when it is easily doable. Otherwise, go with the convenience ofalloc

@RenTrieu
Copy link
ContributorAuthor

Now, IMHO, the guideline is: preventalloc when it is easily doable. Otherwise, go with the convenience ofalloc

In this case, would be it be okay to simply store the vector of values as one of the fields ofVar? I was thinking of something like:

pubstructVars<'a>{/// Char16 containing names of environment variablesnames:*constChar16,/// Vec containing values of environment variablesvalues:Vec::<Option<&'aCStr16>>,/// Current position in veccur_pos:usize,/// Placeholder to attach a lifetime to `Vars`placeholder:PhantomData<&'aCStr16>,}

@nicholasbishop
Copy link
Member

nicholasbishop commentedJul 13, 2025
edited
Loading

In this case, would be it be okay to simply store the vector of values as one of the fields of Var?

Ideally we wouldn't store aVec of all env values (this somewhat defeats the purpose of it being an iterator, since it requires extra allocations). I'm a little unclear on the behavior ofEFI_SHELL_PROTOCOL.GetEnv() whennull is passed in -- does it return just the names of variables, or names and values?

@RenTrieu
Copy link
ContributorAuthor

I see your point on storingVec in the iterator. As forEFI_SHELL_PROTOCOL.GetEnv() in the case wherenull is passed in, only the names of the variables are returned. So for returning the values alongside the variables in theVars iterator, it seems that a little extra work has to be done to call and store the results of eitherget_env() orvar() for each variable name.

@nicholasbishop
Copy link
Member

Could Vars store a reference to the protocol, and call get_env in the next function to get each variable value one at a time?

@RenTrieu
Copy link
ContributorAuthor

That's quite a clever approach! I've written an initial implementation and did not find any issues. I will push it shortly so we can review it.

@RenTrieuRenTrieuforce-pushed theenhancement/efi_shell_interface branch fromfd136bb to7542291CompareJuly 15, 2025 04:03
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@phip1611phip1611phip1611 requested changes

@nicholasbishopnicholasbishopnicholasbishop requested changes

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@RenTrieu@nicholasbishop@phip1611

[8]ページ先頭

©2009-2025 Movatter.jp