Home > Mobile >  How do I read user input in uefi-rs (UEFI Rust wrapper)
How do I read user input in uefi-rs (UEFI Rust wrapper)

Time:07-27

I want to know if there is any way I can read user input in UEFI using the uefi-rs Rust wrapper. (or possibly any other way I can gather user input in UEFI with Rust)

I have tried many different approaches with read_key, the key event, and one didn't even compile and the other one only printed zeros. I have also scavenged through dozens of GitHub repositories, but seemingly none of those used these methods.

The first method (read key):

    let bs = st.boot_services();
    let read_key =  st.stdin().read_key();
    let unwrap = read_key.unwrap();
    if unwrap.is_some() {
        st.stdout().write_str(&unwrap.expect("Error").fmt(&mut fmt::Formatter).to_string()).expect("Failed to write to the console.");
    }

And the second method (wait for event):

    let mut binding = st.unsafe_clone();
    key_event = binding.stdin().wait_for_key_event();
    let result = bs.wait_for_event(&mut [key_event.unsafe_clone()]);
    let usize = result.unwrap();
    st.stdout().write_str(&usize.to_string()).expect("Failed to write to the console.");

There are probably many beginner mistakes in there because I am not extremely experienced with Rust. I did a few projects and now I found this, so I wanted to try it. User input is a thing that is comparably easy in Assembly. (from what I've experienced with Rust so far)

If anyone knows a repository I could check or knows the answer, please help. Have been working on this for hours now.

Link to the crate docs: https://docs.rs/uefi/latest/uefi/ Source code: https://github.com/rust-osdev/uefi-rs

CodePudding user response:

Here is a short example to read input until the user presses 'ESC'.

#![no_main]
#![no_std]
#![feature(abi_efiapi)]

use core::fmt::{Write};
use uefi::{prelude::*, proto::console::text::ScanCode, Char16};

#[entry]
fn main(_handle: Handle, mut st: SystemTable<Boot>) -> Status {
    uefi_services::init(&mut st).unwrap();
    
    let mut exit_flag = false;

    while !exit_flag {
        let key = st.stdin().read_key().expect("Expected input");
        let _ = match key {
            Some(k) =>  {
                match k {
                    uefi::proto::console::text::Key::Printable(p) => {
                        write!(st.stdout(), "A printable key was entered: {:?}\r\n", p).expect("Write failed");
                        if p == Char16::try_from(27u16).expect("Unable to convert the ESC ascii code to Char16") {
                            exit_flag = true;
                        }
                    }
                    uefi::proto::console::text::Key::Special(s) => {
                        write!(st.stdout(), "A special key was entered: {:?}\r\n", s).expect("Write failed");
                        if s == ScanCode::ESCAPE {
                            exit_flag = true;
                        }
                    }
                };             
            },
            None => {}
        };
    }

    Status::SUCCESS
}

I have never used uefi-rs before, there may be better solutions to handle input with this crate.

Take the template as starting point and replace main.rs. Build with: cargo nightly build --target x86_64-unknown-uefi

  • Related