Skip to content

Patina: R-EFI 6.0 migration#1480

Open
vineelko wants to merge 51 commits into
OpenDevicePartnership:majorfrom
vineelko:users/vineelko/patina-r-efi-6-0_0425
Open

Patina: R-EFI 6.0 migration#1480
vineelko wants to merge 51 commits into
OpenDevicePartnership:majorfrom
vineelko:users/vineelko/patina-r-efi-6-0_0425

Conversation

@vineelko
Copy link
Copy Markdown
Contributor

@vineelko vineelko commented Apr 27, 2026

Description

R-EFI 6.0 Migration

Upstream r-efi 6.0 marks all extern "efiapi" function pointers in EFI Boot
Services, Runtime Services, and other protocols as unsafe, since their safety
cannot be enforced by the Rust type system at compile time.

This PR audits almost all usage of UEFI service function pointers across the Patina
codebase for correctness and safety.

  • There are three primary areas where unsafe usage has been audited:

    1. The FFI boundary - all extern "efiapi" functions
    2. The Patina wrappers - all functions within the BootServices trait that
      eventually call into the FFI
    3. Core Patina routines that implement the FFI functions
  • Not all functions in the above categories need to be marked unsafe. For
    example, extern "efiapi" close_event is not marked unsafe because it can
    safely be called with an arbitrary event parameter without causing undefined
    behavior in the Patina implementation. The event parameter is treated as an
    opaque pointer and is never dereferenced.

    That said, any indirect caller that dereferences this Boot Services function
    pointer must still use an unsafe block, since the function pointer itself is
    defined as unsafe in r-efi 6.0. In addition, inherently unsafe Rust
    functions (such as core_free_pool()) are now explicitly marked unsafe.

  • Each inspected function or call site is documented with appropriate safety
    comments where necessary, and with explanations where unsafe is not
    required.

  • There are no functional changes.

  • Clippy flags public functions that accept raw pointer parameters and pass them
    across an FFI boundary without being marked unsafe, with the following
    warning:
    "this public function might dereference a raw pointer but is not marked unsafe"

    unsafe extern "C" {
        fn some_ffi_call(ptr: *mut i32);
    }
    
    // Triggers clippy::not_unsafe_ptr_arg_deref:
    // - public function
    // - not marked `unsafe`
    // - raw pointer parameter `ptr` is passed into an `unsafe` block
    pub fn example(ptr: *mut i32) {
        unsafe { some_ffi_call(ptr) };
    }
    

    In Patina, this pattern is common for functions that take efi::Event or
    efi::Handle parameters and call Boot Services function pointers. We
    explicitly suppress this lint for such functions because these types are
    treated as opaque pointers and are never dereferenced:
    #[allow(clippy::not_unsafe_ptr_arg_deref)]

Geiger Unsafe Stats

|             | x86_64-unknown-uefi(before) | x86_64-unknown-uefi(after) | aarch64-unknown-uefi(before) | aarch64-unknown-uefi(after) |
|-------------|-----------------------------|----------------------------|------------------------------|-----------------------------|
| overall     | 11.90% (yellow)             | 16.30% (red)               | 12.20% (yellow)              | 16.30% (red)                |
| functions   | 2.60%  (green)              | 11.40% (yellow)            | 2.80%  (green)               | 11.40% (yellow)             |
| exprs       | 12.40% (yellow)             | 17.00% (red)               | 12.60% (yellow)              | 17.00% (red)                |
| item_impls  | 12.50% (yellow)             | 13.80% (yellow)            | 13.80% (yellow)              | 13.80% (yellow)             |
| item_traits | 12.10% (yellow)             | 13.00% (yellow)            | 13.00% (yellow)              | 13.00% (yellow)             |
| methods     | 5.60%  (green)              | 6.60%  (green)             | 5.60%  (green)               | 6.60%  (green)              |

How This Was Tested

Booted to UEFI Shell Q35/SBSA

Integration Instructions

All consumers of Patina will need to pick the newer Patina version when published and also should update their r-efi version to 6.0.0.

@patina-automation
Copy link
Copy Markdown
Contributor

patina-automation Bot commented Apr 27, 2026

QEMU Validation Failed

QEMU validation did not complete successfully or did not shutdown as expected.

Workflow run: https://github.com/OpenDevicePartnership/patina/actions/runs/26255574795

⚠️ Build Failure Detected

The Setup and Build patina-dxe-core-qemu step failed in the following job(s):

  • Run Patina QEMU Validation / Validate QEMU - SBSA (Linux)
  • Run Patina QEMU Validation / Validate QEMU - Q35 (Linux)
  • Run Patina QEMU Validation / Validate QEMU Q35 (Windows)

Build logs are available in the workflow run artifacts:

Download the log artifacts from the workflow run to review the build output and
determine whether the error is expected.

Is this expected? If the PR introduces breaking changes to patina that
require a corresponding update to patina-dxe-core-qemu,
the build failure is expected.

Contact a repo admin or PR reviewer to override the Patina QEMU PR Validation status check.

Job Results

Job Result
Gather Incoming PR Metadata
Run Patina QEMU Validation / Post In-Progress Notification
Run Patina QEMU Validation / Preflight Checks
Run Patina QEMU Validation / Get Constants / Get Repository Constants
Run Patina QEMU Validation / Validate QEMU - SBSA (Linux)
Run Patina QEMU Validation / Validate QEMU - Q35 (Linux)
Run Patina QEMU Validation / Validate QEMU Q35 (Windows)
Run Patina QEMU Validation / Emit PR Metadata

Error Details

qemu-validation-logs-Linux-SBSA/sbsa-linux.log (15 error/warning sections)
… (truncated)


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:125:30
    |
125 |             security_status: 0x02,
    |                              ^^^^ expected `SecurityStatus`, found integer


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:155:28
    |
155 |             feature_flags: 0x01, // Board is a hosting board
    |                            ^^^^ expected `FeatureFlags`, found integer
    |
help: call `Into::into` on this expression to convert `{integer}` into `FeatureFlags`
    |
155 |             feature_flags: 0x01.into(), // Board is a hosting board
    |                                +++++++


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:158:25
    |
158 |             board_type: 0x0A, // Motherboard
    |                         ^^^^ expected `BoardType`, found integer


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_test.rs:45:49
    |
 45 |         boot_services.locate_protocol_unchecked(&SMBIOS_PROTOCOL_GUID, core::ptr::null_mut()).map_err(|e| {
    |                       ------------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `r_efi::base::Guid`, found a different `r_efi::base::Guid`
    |                       |
    |                       arguments to this method are incorrect
    |
note: there are multiple different versions of crate `r_efi` in the dependency graph
   --> /.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/r-efi-6.0.0/src/base.rs:392:1
    |
392 | pub struct Guid {
    | ^^^^^^^^^^^^^^^ this is the expected type
    |
   ::: /.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/r-efi-5.3.0/src/base.rs:392:1
    |
392 | pub struct Guid {
    | --------------- this is the found type
    = help: you can use `cargo tree` to explore your dependency tree
note: method defined here
   --> /__w/patina/patina/sdk/patina/src/boot_services.rs:826:15
    |
826 |     unsafe fn locate_protocol_unchecked(
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.

error: could not compile `qemu_dxe_core` (lib) due to 12 previous errors

warning: build failed, waiting for other jobs to finish...

[cargo-make] ERROR - Error while running duckscript: Source: Unknown Line: 113 - Error while executing command, exit code: 101
qemu-validation-logs-Linux-Q35/q35-linux.log (15 error/warning sections)
… (truncated)


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:125:30
    |
125 |             security_status: 0x02,
    |                              ^^^^ expected `SecurityStatus`, found integer


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:155:28
    |
155 |             feature_flags: 0x01, // Board is a hosting board
    |                            ^^^^ expected `FeatureFlags`, found integer
    |
help: call `Into::into` on this expression to convert `{integer}` into `FeatureFlags`
    |
155 |             feature_flags: 0x01.into(), // Board is a hosting board
    |                                +++++++


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_platform.rs:158:25
    |
158 |             board_type: 0x0A, // Motherboard
    |                         ^^^^ expected `BoardType`, found integer


error[E0308]: mismatched types
   --> src/q35/component/service/smbios_test.rs:45:49
    |
 45 |         boot_services.locate_protocol_unchecked(&SMBIOS_PROTOCOL_GUID, core::ptr::null_mut()).map_err(|e| {
    |                       ------------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `r_efi::base::Guid`, found a different `r_efi::base::Guid`
    |                       |
    |                       arguments to this method are incorrect
    |
note: there are multiple different versions of crate `r_efi` in the dependency graph
   --> /.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/r-efi-6.0.0/src/base.rs:392:1
    |
392 | pub struct Guid {
    | ^^^^^^^^^^^^^^^ this is the expected type
    |
   ::: /.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/r-efi-5.3.0/src/base.rs:392:1
    |
392 | pub struct Guid {
    | --------------- this is the found type
    = help: you can use `cargo tree` to explore your dependency tree
note: method defined here
   --> /__w/patina/patina/sdk/patina/src/boot_services.rs:826:15
    |
826 |     unsafe fn locate_protocol_unchecked(
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.

error: could not compile `qemu_dxe_core` (lib) due to 12 previous errors

warning: build failed, waiting for other jobs to finish...

[cargo-make] ERROR - Error while running duckscript: Source: Unknown Line: 113 - Error while executing command, exit code: 101
qemu-validation-logs-Windows-Q35/q35-windows.log (15 error/warning sections)
… (truncated)


error[E0308]: mismatched types
   --> src\q35\component\service\smbios_platform.rs:125:30
    |
125 |             security_status: 0x02,
    |                              ^^^^ expected `SecurityStatus`, found integer


error[E0308]: mismatched types
   --> src\q35\component\service\smbios_platform.rs:155:28
    |
155 |             feature_flags: 0x01, // Board is a hosting board
    |                            ^^^^ expected `FeatureFlags`, found integer
    |
help: call `Into::into` on this expression to convert `{integer}` into `FeatureFlags`
    |
155 |             feature_flags: 0x01.into(), // Board is a hosting board
    |                                +++++++


error[E0308]: mismatched types
   --> src\q35\component\service\smbios_platform.rs:158:25
    |
158 |             board_type: 0x0A, // Motherboard
    |                         ^^^^ expected `BoardType`, found integer


error[E0308]: mismatched types
   --> src\q35\component\service\smbios_test.rs:45:49
    |
 45 |         boot_services.locate_protocol_unchecked(&SMBIOS_PROTOCOL_GUID, core::ptr::null_mut()).map_err(|e| {
    |                       ------------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `r_efi::base::Guid`, found a different `r_efi::base::Guid`
    |                       |
    |                       arguments to this method are incorrect
    |
note: there are multiple different versions of crate `r_efi` in the dependency graph
   --> C:\Users\runneradmin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\r-efi-6.0.0\src\base.rs:392:1
    |
392 | pub struct Guid {
    | ^^^^^^^^^^^^^^^ this is the expected type
    |
   ::: C:\Users\runneradmin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\r-efi-5.3.0\src\base.rs:392:1
    |
392 | pub struct Guid {
    | --------------- this is the found type
    = help: you can use `cargo tree` to explore your dependency tree
note: method defined here
   --> D:\a\patina\patina\sdk\patina\src\boot_services.rs:826:15
    |
826 |     unsafe fn locate_protocol_unchecked(
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.

error: could not compile `qemu_dxe_core` (lib) due to 12 previous errors

warning: build failed, waiting for other jobs to finish...

[cargo-make] ERROR - Error while running duckscript: Source: Unknown Line: 113 - Error while executing command, exit code: 101

Dependencies

Repository Ref
patina 6114c86
patina-dxe-core-qemu af9c5f5
patina-fw-patcher d6d246b
patina-qemu firmware v3.0.0
patina-qemu build script 965bc5f

This comment was automatically generated by the Patina QEMU PR Validation Post workflow.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 87.83505% with 59 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
patina_dxe_core/src/protocols.rs 33.33% 32 Missing ⚠️
sdk/patina/src/boot_services.rs 94.93% 11 Missing ⚠️
patina_dxe_core/src/driver_services.rs 85.42% 7 Missing ⚠️
patina_dxe_core/src/pi_dispatcher/image.rs 88.00% 6 Missing ⚠️
patina_dxe_core/src/allocator.rs 91.18% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Comment thread patina_dxe_core/src/pi_dispatcher/image.rs Outdated
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs Outdated
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs Outdated
Comment thread sdk/patina/src/boot_services.rs
Comment thread sdk/patina/src/boot_services.rs
Comment thread sdk/patina/src/boot_services.rs Outdated
Comment thread sdk/patina/src/boot_services.rs
Comment thread sdk/patina/src/boot_services.rs Outdated
@makubacki
Copy link
Copy Markdown
Collaborator

I haven't looked at the PR changes yet, but it should target the major branch due to the severity of breaking changes.

@vineelko vineelko changed the base branch from main to major April 29, 2026 17:47
@vineelko vineelko force-pushed the users/vineelko/patina-r-efi-6-0_0425 branch from 102fbd3 to ede86cc Compare April 29, 2026 17:48
@vineelko
Copy link
Copy Markdown
Contributor Author

I haven't looked at the PR changes yet, but it should target the major branch due to the severity of breaking changes.

Michael, The branch is now updated to target major instead of main.

@vineelko vineelko force-pushed the users/vineelko/patina-r-efi-6-0_0425 branch from ede86cc to 3e6fd6c Compare May 1, 2026 18:07
Comment thread sdk/patina/src/component/service/memory.rs Outdated
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs Outdated
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs Outdated
Comment thread patina_dxe_core/src/pi_dispatcher/image.rs
Comment thread patina_dxe_core/src/allocator.rs Outdated
Comment thread patina_dxe_core/src/allocator.rs Outdated
Comment thread patina_dxe_core/src/allocator.rs Outdated
Comment thread patina_dxe_core/src/driver_services.rs Outdated
Comment thread patina_dxe_core/src/memory_manager.rs Outdated
vineelko added 3 commits May 18, 2026 09:11
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
@vineelko vineelko force-pushed the users/vineelko/patina-r-efi-6-0_0425 branch from 3e6fd6c to cc656fc Compare May 19, 2026 03:31
vineelko added 12 commits May 21, 2026 07:45
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
vineelko added 26 commits May 21, 2026 14:44
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
@vineelko vineelko force-pushed the users/vineelko/patina-r-efi-6-0_0425 branch from cc656fc to 6114c86 Compare May 21, 2026 21:47
/// # Safety
///
/// `ptr` must be non-null and must point to a valid, well-formed UEFI device path
/// node that remains valid for as long as the returned `DevicePathPtr` is used.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I think in "Rust-ese" this would be

Suggested change
/// node that remains valid for as long as the returned `DevicePathPtr` is used.
/// node that remains valid for the lifetime of the returned `DevicePathPtr`.

}

// SAFETY: caller must ensure that "memory" is a valid pointer. It is null-checked above.
let address = unsafe { memory.read_unaligned() };
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

memory is treated differently depending on the allocation type.

https://uefi.org/specs/UEFI/2.11/07_Services_Boot_Services.html#efi-boot-services-allocatepages

For AllocateAnyPages, the address pointed to by memory is supposed to be ignored on input.

Can you please read through the API constraints in the spec and update this implementation to be compliant?

/// ```
///
pub unsafe fn core_disconnect_controller(
pub fn core_disconnect_controller(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I notice that you changed core_disconnect_controller() from unsafe to safe, and I understand the reasoning, given the platform/environment uncertainties during disconnect versus conditions controlled by the caller for connect. While the nuance is fine, at the function level, the asymmetry is more apparent by the fact that core_connect_controller() remains unsafe.

Can you please add a brief clarifying comment about this in the core_disconnect_controller() doc comment?

Comment on lines +35 to +39
pub unsafe fn new(ptr: *mut Protocol) -> Self {
// SAFETY: Caller guarantees ptr is non-null and valid.
debug_assert!(!ptr.is_null());
Self(ptr)
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What's the difference betwen this and just directly using NonNull<Protocol>?


From the function safety comment:

ptr must be non-null and must point to a valid, well-formed UEFI device path
node that remains valid for as long as the returned DevicePathPtr is used.

DevicePathPtr::new() let's this be violated in cases where debug asserts are not enabled:

    pub unsafe fn new(ptr: *mut Protocol) -> Self {
        // SAFETY: Caller guarantees ptr is non-null and valid.
        debug_assert!(!ptr.is_null());
        Self(ptr)
    }

Versus an implementation like that in NonNull::new():

Suggested change
pub unsafe fn new(ptr: *mut Protocol) -> Self {
// SAFETY: Caller guarantees ptr is non-null and valid.
debug_assert!(!ptr.is_null());
Self(ptr)
}
pub unsafe fn new(ptr: *mut Protocol) -> Option<Self> {
if !ptr.is_null() {
// SAFETY: The pointer is already checked and is not null
Some(unsafe { Self::new_unchecked(ptr) })
} else {
None
}
}

(the example above references a non-existing DevicePathPtr::new_unchecked(ptr) function)


My other concerns is the constructor just stores the pointer. A pointer storage operation can trivially verify that the pointer is non-null but the "validity" part of this really applies to dereference time.

All of this gives the impression that DevicePathPtr promises more safety than is actually delivered which might end up complicating safe handling of device paths overall. For example, I saw other code in image.rs leaning on safety assumptions of the type.


If this stays mostly as it is, could it just be a transparent wrapper around NonNull. Something like:

#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub struct DevicePathPtr(NonNull<Protocol>);
//...
impl DevicePathPtr {
    pub unsafe fn new_unchecked(ptr: *mut Protocol) -> Self {
        // SAFETY: caller guarantees non-null.
        Self(unsafe { NonNull::new_unchecked(ptr) })
    }

    /// Safe constructor. Returns `None` on null. No unsafe needed.
    pub fn new(ptr: *mut Protocol) -> Option<Self> {
        NonNull::new(ptr).map(Self)
    }

    pub fn as_ptr(self) -> *mut Protocol { self.0.as_ptr() }

    /// Reads the device path node header.
    ///
    /// # Safety
    /// The pointee must be a valid, well-formed UEFI device path node and remain
    /// live for the duration of the read.
    pub unsafe fn read_header(self) -> Protocol { /* ... */ }

// ...
}

This simplifies implementation reusing NonNull logic, focuses new() on storage and the nullness check, and moves header reads to be in their own unsafe blocks in callers where they have to uphold the safety invariant at the time it is relevant.

But, really, it seems to me like just using NonNull<Protocol> (this type removed) wouldn't lose much, be a little more clear, and reduce maintenance.

desc.memory_type,
uefi_size_to_pages!(desc.memory_length as usize),
&mut address as *mut efi::PhysicalAddress,
address as efi::PhysicalAddress,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You shouldn't need to cast address here.

Suggested change
address as efi::PhysicalAddress,
address,

/// Uninstalls a protocol interface on a handle.
///
/// This function is safe because `interface` is an opaque pointer used for
/// comparision but never dereferenced. All other parameters are value types.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// comparision but never dereferenced. All other parameters are value types.
/// comparison but never dereferenced. All other parameters are value types.

Comment on lines +62 to +67
/// # Safety
///
/// `handle` must be a valid pointer to an `efi::Handle` (may point to a null handle for new handle
/// creation). `protocol` must be a valid pointer to an `efi::Guid`. Both are null checked, but
/// validity of the referenced memory is the caller's responsibility. Throughout the lifetime of the
/// interface reference, the caller must ensure it remains valid.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you clarify this to specifically call out the lifetime of the protocol database (e.g. until uninstalled)? That will take the explanation from generic to more precise.

Comment on lines 1881 to 1891
@@ -1561,22 +1885,41 @@ impl BootServices for StandardBootServices {
self,
)
});
Err((s, data))
Err((status, data))
}
_ => Ok(()),
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure that this is doing what is intended.

  • I believe exit_data.as_ptr() is returning the address of exit_data on the stack (not the contained value).

  • So, exit_data.as_ptr().is_null() is always false because the stack address is not null.

    • Then, in here:
                        BootServicesBox::from_raw_parts_mut(
                          exit_data.as_mut_ptr() as *mut u8,
                          exit_data_size.assume_init(),
                          self,
                      )

The same thing happens. BootServicesBox is built from the address of the local stack variable with the correct exit_data_size value.

Also, are you sure exit_data.assume_init() is valid? The write to it in start_image_efiapi() is conditionalized.

My understanding is you can clearly get the exit data pointer and size and then do the null check and box construction. Like (not tested):

let exit_data_ptr = unsafe { exit_data.assume_init() };
let exit_data_len = unsafe { exit_data_size.assume_init() };
let data = (!exit_data_ptr.is_null() && exit_data_len > 0).then(|| unsafe {
    BootServicesBox::from_raw_parts_mut(exit_data_ptr as *mut u8, exit_data_len, self)
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Wow that's clearly a bug! Let me fix it properly. Original code incorrectly assumed as_ptr() instead of assume_init().

// This is triggered by the fact that efi::Handle aliases to *mut c_void, but
// it is an opaque handle used as a database key.
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn load_image(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

load_image() is marked safe but still has a function safety comment. This is confusing/not enforceable.

// This is triggered by the fact that efi::Event aliases to *mut c_void, but
// it is an opaque handle used as a database key.
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn exit_boot_services(&self, image_handle: efi::Handle, map_key: usize) -> Result<(), efi::Status> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since there already is a "Safety Considerations" section, can you please include that the entire Boot Services table is no longer callable after this function successfully completes?

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.

4 participants