redox_uefi_std 0.1.14

UEFI standard library
Documentation
use core::ptr;
use core::slice;

use uefi::guid::GLOBAL_VARIABLE_GUID;

use crate::ffi::wstr;
use crate::prelude::*;
use crate::system_table;

fn get(name: &str, data: &mut [u8]) -> Result<usize> {
    let wname = wstr(name);
    let mut data_size = data.len();
    let status = (system_table().RuntimeServices.GetVariable)(
        wname.as_ptr(),
        &GLOBAL_VARIABLE_GUID,
        ptr::null_mut(),
        &mut data_size,
        data.as_mut_ptr(),
    );
    match status {
        Status::SUCCESS => Ok(data_size),
        _ => Err(status),
    }
}

fn set(name: &str, data: &[u8]) -> Result<usize> {
    let wname = wstr(name);
    let access = 1 | 2 | 4;
    let data_size = data.len();
    let status = (system_table().RuntimeServices.SetVariable)(
        wname.as_ptr(),
        &GLOBAL_VARIABLE_GUID,
        access,
        data_size,
        data.as_ptr(),
    );
    match status {
        Status::SUCCESS => Ok(data_size),
        _ => Err(status),
    }
}

pub fn get_boot_current() -> Result<u16> {
    let mut data = [0; 2];
    let count = get("BootCurrent", &mut data)?;
    if count == 2 {
        Ok((data[0] as u16) | ((data[1] as u16) << 8))
    } else {
        Err(Status::LOAD_ERROR)
    }
}

pub fn get_boot_next() -> Result<u16> {
    let mut data = [0; 2];
    let count = get("BootNext", &mut data)?;
    if count == 2 {
        Ok((data[0] as u16) | ((data[1] as u16) << 8))
    } else {
        Err(Status::LOAD_ERROR)
    }
}

pub fn set_boot_next(num_opt: Option<u16>) -> Result<usize> {
    if let Some(num) = num_opt {
        set("BootNext", &[num as u8, (num >> 8) as u8])
    } else {
        set("BootNext", &[])
    }
}

pub fn get_boot_order() -> Result<Vec<u16>> {
    let mut data = [0; 4096];
    let count = get("BootOrder", &mut data)?;

    let mut order = vec![];
    for chunk in data[..count].chunks(2) {
        if chunk.len() == 2 {
            order.push((chunk[0] as u16) | (chunk[1] as u16) << 8);
        }
    }
    Ok(order)
}

pub fn set_boot_order(order: &[u16]) -> Result<usize> {
    set("BootOrder", unsafe {
        slice::from_raw_parts(order.as_ptr() as *const u8, order.len() * 2)
    })
}

pub fn get_boot_item(num: u16) -> Result<Vec<u8>> {
    let mut data = [0; 4096];
    let count = get(&format!("Boot{:>04X}", num), &mut data)?;
    if count < 6 {
        Err(Status::LOAD_ERROR)
    } else {
        Ok(data[..count].to_vec())
    }
}

pub fn set_boot_item(num: u16, data: &[u8]) -> Result<usize> {
    set(&format!("Boot{:>04X}", num), data)
}

pub fn get_os_indications() -> Result<u64> {
    let mut data = [0; 8];
    let count = get("OsIndications", &mut data)?;
    if count == 8 {
        Ok((data[0] as u64)
            | ((data[1] as u64) << 8)
            | ((data[2] as u64) << 16)
            | ((data[3] as u64) << 24)
            | ((data[4] as u64) << 32)
            | ((data[5] as u64) << 40)
            | ((data[6] as u64) << 48)
            | ((data[7] as u64) << 56))
    } else {
        Err(Status::LOAD_ERROR)
    }
}

pub fn set_os_indications(indications_opt: Option<u64>) -> Result<usize> {
    if let Some(indications) = indications_opt {
        set(
            "OsIndications",
            &[
                indications as u8,
                (indications >> 8) as u8,
                (indications >> 16) as u8,
                (indications >> 24) as u8,
                (indications >> 32) as u8,
                (indications >> 40) as u8,
                (indications >> 48) as u8,
                (indications >> 56) as u8,
            ],
        )
    } else {
        set("OsIndications", &[])
    }
}

pub fn get_os_indications_supported() -> Result<u64> {
    let mut data = [0; 8];
    let count = get("OsIndicationsSupported", &mut data)?;
    if count == 8 {
        Ok((data[0] as u64)
            | ((data[1] as u64) << 8)
            | ((data[2] as u64) << 16)
            | ((data[3] as u64) << 24)
            | ((data[4] as u64) << 32)
            | ((data[5] as u64) << 40)
            | ((data[6] as u64) << 48)
            | ((data[7] as u64) << 56))
    } else {
        Err(Status::LOAD_ERROR)
    }
}