Exclusive Protocol Open on GraphicsOutput Stops Logging from Working Even After Drop
Closed this issue · 2 comments
Hello,
For your situational awareness: I'm new to UEFI and Rust so I apologize for any assumptions I'm making, this is all a learning experiment for me at the end of the day.
I don't want to attest whether this is a bug so right now its more of a question. But when getting exclusive protocol access via the demonstrated code of a the GraphicsOutput, follow on info prints no longer work even after dropping. On one hand, it makes sense if I get a exclusive protocol handle, it would disable other mechanisms from working like the logging macros. But even when it drops, it doesnt restore the logging functionality which I find to be unexpected. There could also be a very obvious mechanism to fix afterwards like with the mode? But this is all to new me that it was not obvious.
If this is expected ignore me, to get around this I am getting a none exclusive handle for now.
uefi Version 0.35.0 via Cargo
Current dependencies
log = "0.4.21"
uefi = { version = "0.35.0", features = [ "panic_handler", "logger" ] }
Expected
info!("Works");
let proto = boot::get_handle_for_protocol::<GraphicsOutput>().unwrap();
info!("Works 2");
let gop = boot::open_protocol_exclusive::<GraphicsOutput>(proto).unwrap();
info!("No Longer Seeable");
Not Expected
info!("Works");
let proto = boot::get_handle_for_protocol::<GraphicsOutput>().unwrap();
info!("Works 2");
{
let gop = boot::open_protocol_exclusive::<GraphicsOutput>(proto).unwrap();
}
info!("No Longer Seeable Still");
Non exclusive example works fine, which is expected
info!("Works");
let proto = boot::get_handle_for_protocol::<GraphicsOutput>().unwrap();
info!("Works 2");
let mut gop = unsafe {
boot::open_protocol::<GraphicsOutput>(
boot::OpenProtocolParams {
handle: proto,
agent: image_handle(),
controller: None,
},
boot::OpenProtocolAttributes::GetProtocol).unwrap()
};
info!("Works 3");
Thanks in advance for any thoughts/help!
This is expected behavior, as a somewhat annoying consequence of how exclusive mode works in the UEFI model. Quoting from the spec:
EXCLUSIVE: Used by applications to gain exclusive access to a protocol interface. If any drivers have the protocol interface opened with an attribute of BY_DRIVER, then an attempt will be made to remove them by calling the driver’s Stop() function.
In other words, opening in exclusive mode doesn't just act as a lock, it also actively disconnects any conflicting drivers.
There are two ways to deal with this:
- Accept the use of
unsafeand open in non-exclusive mode. This is often a reasonable tradeoff when dealing with UEFI protocols. (For example, I've observed that opening protocols in exclusive mode can be a performance problem in some cases, as it takes a while for some drivers to close down.) - Reconnect other controllers after you are done using the exclusive-mode protocol. See
boot::connect_controller. Example of this in the test-runner:reconnect_serial_to_console.
Thank you for the quick and helpful response that also includes the spec! I apologize for the wasted ticket, and I will explore the suggestions you provided.