GithubHelp home page GithubHelp logo

Comments (5)

JohnAZoidberg avatar JohnAZoidberg commented on June 30, 2024

Root cause is the exit_boot_services hook in init:

        boot_services
            .create_event(
                EventType::SIGNAL_EXIT_BOOT_SERVICES,
                Tpl::NOTIFY,
                Some(exit_boot_services),
                None,
            )
            .map(|_| ())

Even if I define it as

unsafe extern "efiapi" fn exit_boot_services(_e: Event, _ctx: Option<NonNull<c_void>>) {
}

I see the same crash. The only thing that helps is to remove the call to create_event.

from uefi-rs.

nicholasbishop avatar nicholasbishop commented on June 30, 2024

Thanks for filing this. I put together a small test that reproduces your crash: https://github.com/nicholasbishop/uefi-rs/tree/bishop-quick-exit

The problem is that uefi-services is geared towards bootloaders, where it's expected that the application won't exit. E.g. if a bootloader app uses uefi-services and launches the Linux kernel, early in startup Linux will call ExitBootServices and the bootloader app will still be in memory and its event handler will be able to run without issue.

In the case you've outlined, the application uses uefi-services to register an event handler, and that handler never gets unregistered when the application exits, and so exiting boot services triggers a crash.

I'm not sure yet how we want to solve this. One option would be to change the API so that the caller does something like let _app = uefi_services::init();, and that returned object has a Drop impl that removes the event handler. That might be to easy to get wrong on the caller side though, by accidentally dropping it too early.

from uefi-rs.

JohnAZoidberg avatar JohnAZoidberg commented on June 30, 2024

Ohh that makes sense.

Perhaps we could force the user to return object from main and the wrapper drops it.

But actually I noticed this while I'm trying to register my own callback that must run just before the OS boots, not when the app exits.

from uefi-rs.

JohnAZoidberg avatar JohnAZoidberg commented on June 30, 2024

I modified uefi-services to return the event:

diff --git i/uefi-services/src/lib.rs w/uefi-services/src/lib.rs
index 0b715b1..ee1fd04 100644
--- i/uefi-services/src/lib.rs
+++ w/uefi-services/src/lib.rs
@@ -78,11 +78,11 @@ pub fn system_table() -> NonNull<SystemTable<Boot>> {
 ///
 /// This must be called as early as possible,
 /// before trying to use logging or memory allocation capabilities.
-pub fn init(st: &mut SystemTable<Boot>) -> Result {
+pub fn init(st: &mut SystemTable<Boot>) -> Result<Option<Event>> {
     unsafe {
         // Avoid double initialization.
         if SYSTEM_TABLE.is_some() {
-            return Status::SUCCESS.to_result();
+            return Status::SUCCESS.to_result_with_val(|| { None });
         }
 
         // Setup the system table singleton
@@ -104,7 +104,7 @@ pub fn init(st: &mut SystemTable<Boot>) -> Result {
                 Some(exit_boot_services),
                 None,
             )
-            .map(|_| ())
+            .map(|e| Some(e))
     }
 }

Then in the app I can run:

#[entry]
fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    let event: Option<Event> = uefi_services::init(&mut system_table).unwrap();
    let boot_services = system_table.boot_services();

    println!("Hello World");

    if let Some(event) = event {
        // Will creash when Linux boots if we don't call this
        boot_services.close_event(event).unwrap();
    }
    Status::SUCCESS
}

and it will boot to the Linux just fine.

from uefi-rs.

nicholasbishop avatar nicholasbishop commented on June 30, 2024

I've merged #920 for this, and the remaining work is tracked in #943.

from uefi-rs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.