blob: f8a99b2d2e51dbf052025d4c3517e8d3fab24381 [file]
// Copyright 2022 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
use super::efi::try_activate_efi_services;
use efi::{
EFI_SUCCESS, EFI_VARIABLE_BOOTSERVICE_ACCESS, EFI_VARIABLE_NON_VOLATILE,
EFI_VARIABLE_RUNTIME_ACCESS, kZirconVendorGuid,
};
use kprint::kprintln;
/// Default value for the EFI bootbyte.
const EFI_BOOT_NORMAL: u8 = 0x1;
/// EFI Variable for Reboot Reason.
const ZIRCON_BOOTBYTE_EFIVAR: [u16; 9] = [
b'b' as u16,
b'o' as u16,
b'o' as u16,
b't' as u16,
b'b' as u16,
b'y' as u16,
b't' as u16,
b'e' as u16,
0,
];
const ZIRCON_BOOTBYTE_EFIATTR: u32 =
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
/// Stores the reboot `reason` in the EFI `bootbyte` variable.
#[sanitize(address = "off")]
#[inline(never)]
pub fn efi_bootbyte_set_reason(reason: u64) {
// Switch into the EFI address space.
// SAFETY: `services` is scoped to this stack frame (strictly LIFO with respect to any caller),
// the thread's previous `VmAspace` is not switched or destroyed before `services` is dropped,
// and this function is tagged `#[sanitize(address = "off")]`.
let services = unsafe { try_activate_efi_services() };
if !services.valid() {
return;
}
// Set boot reason, clamping to be in the range of u8.
let val: u8 = if reason <= 255 { reason as u8 } else { EFI_BOOT_NORMAL };
// SAFETY: `kZirconVendorGuid` is an immutable C constant.
let vendor_guid = unsafe { &kZirconVendorGuid };
let status = services.set_variable(
&ZIRCON_BOOTBYTE_EFIVAR,
vendor_guid,
ZIRCON_BOOTBYTE_EFIATTR,
core::slice::from_ref(&val),
);
if status != EFI_SUCCESS {
kprintln!("EFI error while attempting to store bootbyte: {:x}", status);
}
}