rust-osdev / uefi-rs

Rust wrapper for UEFI.
https://rust-osdev.com/uefi-book
Mozilla Public License 2.0
1.23k stars 155 forks source link

OpenProtocolAttributes missing EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL #524

Closed ori-sky closed 1 week ago

ori-sky commented 1 year ago

The OpenProtocolAttributes enum is currently missing a representation of the EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL value defined by UEFI. Without this, there doesn't seem to be a way to directly open a protocol from a specified handle non-exclusively. Some example code:

let boot_services = system_table.boot_services();

let search = SearchType::from_proto::<GraphicsOutput>();
let handle_buffer = boot_services.locate_handle_buffer(search)?;

for handle in handle_buffer.handles() {
    let params = OpenProtocolParams {
        handle: *handle,
        agent: image,
        controller: None
    };
    let attribs = unsafe { core::mem::transmute(1) };
    let gop = unsafe {
        boot_services.open_protocol::<GraphicsOutput>(params, attribs)?
    };

    let modeinfo = gop.current_mode_info();
    let (width, height) = modeinfo.resolution();
    uefi_services::println!("Graphics mode: {}x{}", width, height);
}

When attempting to open the GraphicsOutput protocol exclusively here, an error seems to be encountered, presumably either upon opening the protocol or somewhere in uefi_services::println!, so non-exclusivity seems to be required here. However, the code succeeds when performing the unsafe transmute from 1 (the value that EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL is defined to be).

nicholasbishop commented 1 year ago

You can use OpenProtocolAttributes::GetProtocol for that. See https://github.com/rust-osdev/uefi-rs/blob/main/uefi-test-runner/src/proto/console/gop.rs#L5 for an example of this in action.

ori-sky commented 1 year ago

It looks like GetProtocol will work in this circumstance so this ticket probably no longer affects me, although more generally GET_PROTOCOL does have the caveat that any notification events created to be signaled upon a protocol being reinstalled will not be notified in the case of the protocol having been opened via GET_PROTOCOL -- only if it has been opened via BY_HANDLE_PROTOCOL, if I'm understanding the UEFI spec correctly.

JeffLi01 commented 1 week ago

I question whether anyone has been monitoring this issue, as the last comment was posted two years ago. Regardless, I would like to share my perspective.

only if it has been opened via BY_HANDLE_PROTOCOL, if I'm understanding the UEFI spec correctly.

As per the UEFI specification, BY_HANDLE_PROTOCOL is intended for use within the HandleProtocol() function of the EFI_BOOT_SERVICES. Its name suggests that it is meant to be employed specifically for this purpose.

In my view, the existance of attribute BY_HANDLE_PROTOCOL is intended to give the new API OpenProtocol() a chance to simulate the behavior of the OLD API HandleProtocol().

And the implemention in edk2 processes BY_HANDLE_PROTOCOL and GET_PROTOCOL the SAME way, meaning that there is no notification upon uninstallation/reinstallation of the protocol having been opened using BY_HANDLE_PROTOCOL.

Therefore, I concur with the comment for enum OpenProtocolAttributes:

// ByHandleProtocol (0x01) excluded because it is only intended to be // used in an implementation of HandleProtocol.

nicholasbishop commented 1 week ago

I question whether anyone has been monitoring this issue

I wasn't actively paying attention to this issue, but I do I get email notifications for all comments in the repo :)

I'll go ahead and close, it seems like GetHandle is sufficient.