Skip to content

Commit

Permalink
Update uefi-rs to 0.32
Browse files Browse the repository at this point in the history
  • Loading branch information
YtvwlD committed Sep 17, 2024
1 parent 3303297 commit 2fefb3a
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 205 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion towboot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ default-target = "i686-unknown-uefi"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
uefi = { version = "0.31", features = ["alloc", "global_allocator", "logger", "panic_handler"] }
uefi = { version = "0.32", features = ["alloc", "global_allocator", "logger", "panic_handler"] }
acpi = "5.0"
smbios-lib = { git = "https://github.com/hhuOS/smbios-lib.git", branch = "main", default-features = false, features = ["no_std"] }
x86 = "0.52"
Expand Down
20 changes: 13 additions & 7 deletions towboot/src/boot/config_tables.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Handle UEFI config tables.
use alloc::slice;
use alloc::vec::Vec;

use log::{debug, warn};
use multiboot12::information::InfoBuilder;
use acpi::rsdp::Rsdp;
use smbioslib::{SMBiosEntryPoint32, SMBiosEntryPoint64};
use uefi::system::with_config_table;
use uefi::table::cfg::{
ConfigTableEntry, ACPI_GUID, ACPI2_GUID, DEBUG_IMAGE_INFO_GUID,
DXE_SERVICES_GUID, HAND_OFF_BLOCK_LIST_GUID, LZMA_COMPRESS_GUID,
Expand All @@ -13,22 +16,25 @@ use uefi::table::cfg::{

/// Go through all of the configuration tables.
/// Some of them are interesting for Multiboot2.
pub(super) fn parse_for_multiboot(
config_tables: &[ConfigTableEntry], info_builder: &mut InfoBuilder,
) {
pub(super) fn parse_for_multiboot(info_builder: &mut InfoBuilder) {
// first, copy all config table pointers
// TODO: remove this when with_config_table takes a FnMut
let config_tables: Vec<ConfigTableEntry> = with_config_table(|s|
s.iter().cloned().collect()
);
debug!("going through configuration tables...");
for table in config_tables {
match table.guid {
ACPI_GUID => handle_acpi(table, info_builder),
ACPI2_GUID => handle_acpi(table, info_builder),
ACPI_GUID => handle_acpi(&table, info_builder),
ACPI2_GUID => handle_acpi(&table, info_builder),
DEBUG_IMAGE_INFO_GUID => debug!("ignoring image debug info"),
DXE_SERVICES_GUID => debug!("ignoring dxe services table"),
HAND_OFF_BLOCK_LIST_GUID => debug!("ignoring hand-off block list"),
LZMA_COMPRESS_GUID => debug!("ignoring lzma filesystem"),
MEMORY_STATUS_CODE_RECORD_GUID => debug!("ignoring early memory info"),
MEMORY_TYPE_INFORMATION_GUID => debug!("ignoring early memory info"),
SMBIOS_GUID => handle_smbios(table, info_builder),
SMBIOS3_GUID => handle_smbios(table, info_builder),
SMBIOS_GUID => handle_smbios(&table, info_builder),
SMBIOS3_GUID => handle_smbios(&table, info_builder),
guid => debug!("ignoring table {guid}"),
}
}
Expand Down
42 changes: 18 additions & 24 deletions towboot/src/boot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ use core::arch::asm;
use core::ffi::c_void;
use core::ptr::NonNull;
use uefi::prelude::*;
use uefi::boot::{exit_boot_services, image_handle, memory_map, MemoryType, ScopedProtocol};
use uefi::mem::memory_map::{MemoryMap, MemoryMapMut};
use uefi::proto::console::gop::GraphicsOutput;
use uefi::table::system_table_boot;
use uefi::table::boot::{ScopedProtocol, MemoryType};
use uefi::table::cfg::ConfigTableEntry;
use uefi::table::system_table_raw;

use log::{debug, info, error, warn};

Expand Down Expand Up @@ -204,8 +203,8 @@ fn get_kernel_uefi_entry(
fn prepare_multiboot_information(
entry: &Entry, header: Header, load_base_address: Option<u32>,
modules: &[Allocation], symbols: Option<Symbols>,
graphics_output: Option<ScopedProtocol<GraphicsOutput>>, image: Handle,
config_tables: &[ConfigTableEntry], boot_services_exited: bool,
graphics_output: Option<ScopedProtocol<GraphicsOutput>>,
boot_services_exited: bool,
) -> InfoBuilder {
let mut info_builder = header.info_builder();

Expand Down Expand Up @@ -249,12 +248,12 @@ fn prepare_multiboot_information(

// This only has an effect on Multiboot2.
// TODO: Does this stay valid when we exit Boot Services?
let systab_ptr = system_table_boot()
let systab_ptr = system_table_raw()
.expect("failed to get System Table")
.as_ptr();
let image_handle_ptr = (unsafe {
core::mem::transmute::<_, NonNull<c_void>>(image)
}).as_ptr();
let image_handle_ptr = unsafe {
core::mem::transmute::<_, NonNull<c_void>>(image_handle())
}.as_ptr();
if cfg!(target_arch = "x86") {
info_builder.set_system_table_ia32(Some(
(systab_ptr as usize).try_into().unwrap()
Expand All @@ -273,7 +272,7 @@ fn prepare_multiboot_information(
warn!("don't know how to pass the UEFI data on this target");
}

config_tables::parse_for_multiboot(config_tables, &mut info_builder);
config_tables::parse_for_multiboot(&mut info_builder);

if !boot_services_exited {
info_builder.set_boot_services_not_exited();
Expand Down Expand Up @@ -311,10 +310,9 @@ impl<'a> PreparedEntry<'a> {
/// The returned `PreparedEntry` can be used to actually boot.
/// This is non-destructive and will always return.
pub(crate) fn new(
entry: &'a Entry, image: Handle, image_fs_handle: Handle,
systab: &SystemTable<Boot>,
entry: &'a Entry, image_fs_handle: Handle,
) -> Result<PreparedEntry<'a>, Status> {
let kernel_vec: Vec<u8> = File::open(&entry.image, image_fs_handle, systab)?.try_into()?;
let kernel_vec: Vec<u8> = File::open(&entry.image, image_fs_handle)?.try_into()?;
let header = Header::from_slice(kernel_vec.as_slice()).ok_or_else(|| {
error!("invalid Multiboot header");
Status::LOAD_ERROR
Expand All @@ -326,20 +324,19 @@ impl<'a> PreparedEntry<'a> {
// Load all modules, fail completely if one fails to load.
// just always use whole pages, that's easier for us
let modules_vec: Vec<Allocation> = entry.modules.iter().map(|module|
File::open(&module.image, image_fs_handle, systab)
File::open(&module.image, image_fs_handle)
.and_then(|f| f.try_into_allocation(&entry.quirks))
).collect::<Result<Vec<_>, _>>()?;
info!("loaded {} modules", modules_vec.len());
for (index, module) in modules_vec.iter().enumerate() {
debug!("loaded module {} to {:?}", index, module.as_ptr());
}

let graphics_output = video::setup_video(&header, systab, &entry.quirks);
let graphics_output = video::setup_video(&header, &entry.quirks);

let multiboot_information = prepare_multiboot_information(
entry, header, loaded_kernel.load_base_address, &modules_vec,
loaded_kernel.symbols_struct(), graphics_output, image,
systab.config_table(),
loaded_kernel.symbols_struct(), graphics_output,
!entry.quirks.contains(&Quirk::DontExitBootServices),
);

Expand All @@ -358,11 +355,11 @@ impl<'a> PreparedEntry<'a> {
/// 5. jump!
///
/// This function won't return.
pub(crate) fn boot(mut self, systab: SystemTable<Boot>) -> ! {
pub(crate) fn boot(mut self) -> ! {
// Get a memory map.
// This won't be completely accurate as we're still going to allocate
// and deallocate a bit, but it gives us a rough estimate.
let map = systab.boot_services().memory_map(MemoryType::LOADER_DATA)
let map = memory_map(MemoryType::LOADER_DATA)
.expect("failed to get memory map");
// Estimate how many entries there will be and add some.
let estimated_count = map.entries().len() + 5;
Expand All @@ -385,13 +382,10 @@ impl<'a> PreparedEntry<'a> {
debug!("passing signature {signature:x} to kernel...");
let mut memory_map = if self.loaded_kernel.should_exit_boot_services {
info!("exiting boot services...");
let (_systab, memory_map) = unsafe {
systab.exit_boot_services(MemoryType::LOADER_DATA)
};
unsafe { exit_boot_services(MemoryType::LOADER_DATA) }
// now, write! won't work anymore. Also, we can't allocate any memory.
memory_map
} else {
let memory_map = systab.boot_services().memory_map(MemoryType::LOADER_DATA).unwrap();
let memory_map = memory_map(MemoryType::LOADER_DATA).unwrap();
debug!("got {} memory areas", memory_map.entries().len());
memory_map
};
Expand Down
24 changes: 13 additions & 11 deletions towboot/src/boot/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ use alloc::collections::btree_set::BTreeSet;
use alloc::vec::Vec;

use uefi::prelude::*;
use uefi::boot::{
find_handles, image_handle, open_protocol,
OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol,
};
use uefi::proto::console::gop::{GraphicsOutput, Mode, PixelBitmask, PixelFormat};
use uefi::table::boot::{ScopedProtocol, OpenProtocolParams, OpenProtocolAttributes};

use log::{debug, warn, info, error};

Expand All @@ -18,12 +21,13 @@ use towboot_config::Quirk;
///
/// If there are multiple GPUs available, simply choose the first one.
/// If there is no available mode that matches, just use the one we're already in.
pub fn setup_video<'a>(
header: &Header, systab: &'a SystemTable<Boot>, quirks: &BTreeSet<Quirk>
) -> Option<ScopedProtocol<'a, GraphicsOutput>> {
pub fn setup_video(
header: &Header, quirks: &BTreeSet<Quirk>,
) -> Option<ScopedProtocol<GraphicsOutput>> {
info!("setting up the video...");
let wanted_resolution = match (
header.get_preferred_video_mode(), quirks.contains(&Quirk::KeepResolution)
header.get_preferred_video_mode(),
quirks.contains(&Quirk::KeepResolution),
) {
(Some(mode), false) => {
if mode.is_graphics() {
Expand All @@ -49,25 +53,23 @@ pub fn setup_video<'a>(
_ => None,
};
// just get the first one
let handles = systab
.boot_services()
.find_handles::<GraphicsOutput>()
let handles = find_handles::<GraphicsOutput>()
.expect("failed to list available graphics outputs");
let handle = handles.first().or_else(|| {
warn!("Failed to find a graphics output. Do you have a graphics card (and a driver)?");
None
})?;
// Opening a protocol non-exclusively is unsafe, but otherwise we won't get
// to see any new log messages.
let mut output: ScopedProtocol<GraphicsOutput> = unsafe { systab.boot_services().open_protocol(
let mut output: ScopedProtocol<GraphicsOutput> = unsafe { open_protocol(
OpenProtocolParams {
handle: *handle,
agent: systab.boot_services().image_handle(),
agent: image_handle(),
controller: None,
},
OpenProtocolAttributes::GetProtocol,
).ok() }?;
let modes: Vec<Mode> = output.modes(systab.boot_services()).collect();
let modes: Vec<Mode> = output.modes().collect();
debug!(
"available video modes: {:?}",
modes.iter().map(Mode::info).map(|i| (i.resolution(), i.pixel_format()))
Expand Down
8 changes: 4 additions & 4 deletions towboot/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@ fn version_info() -> String {
///
/// Returns None if just a help text has been displayed.
pub fn get(
image_fs_handle: Handle, load_options: &str, systab: &SystemTable<Boot>
image_fs_handle: Handle, load_options: &str,
) -> Result<Option<Config>, Status> {
match parse_load_options(load_options, &version_info()) {
Ok(Some(ConfigSource::File(s))) => Ok(Some(read_file(image_fs_handle, &s, systab)?)),
Ok(Some(ConfigSource::File(s))) => Ok(Some(read_file(image_fs_handle, &s)?)),
Ok(Some(ConfigSource::Given(c))) => Ok(Some(c)),
Ok(None) => Ok(None),
Err(()) => Err(Status::INVALID_PARAMETER),
}
}

/// Try to read and parse the configuration from the given file.
fn read_file(image_fs_handle: Handle, file_name: &str, systab: &SystemTable<Boot>) -> Result<Config, Status> {
let text: Vec<u8> = File::open(file_name, image_fs_handle, systab)?.try_into()?;
fn read_file(image_fs_handle: Handle, file_name: &str) -> Result<Config, Status> {
let text: Vec<u8> = File::open(file_name, image_fs_handle)?.try_into()?;
let mut config: Config = toml::from_slice(text.as_slice()).expect("failed to parse config file");
config.src = file_name.to_string();
Ok(config)
Expand Down
11 changes: 4 additions & 7 deletions towboot/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use alloc::string::ToString;
use log::{info, error};

use uefi::prelude::*;
use uefi::boot::{find_handles, open_protocol_exclusive};
use uefi::fs::{Path, PathBuf};
use uefi::data_types::CString16;
use uefi::proto::media::fs::SimpleFileSystem;
Expand Down Expand Up @@ -38,7 +39,7 @@ impl<'a> File<'a> {
/// * `Status::NOT_FOUND`: the file does not exist
/// * `Status::PROTOCOL_ERROR`: the file name is not a valid string
/// * `Status::UNSUPPORTED`: the given path does exist, but it's a directory
pub(crate) fn open(name: &'a str, image_fs_handle: Handle, systab: &SystemTable<Boot>) -> Result<Self, Status> {
pub(crate) fn open(name: &'a str, image_fs_handle: Handle) -> Result<Self, Status> {
info!("loading file '{name}'...");
let file_name = CString16::try_from(name)
.map_err(|e| {
Expand All @@ -56,9 +57,7 @@ impl<'a> File<'a> {
.strip_suffix(':')
.unwrap()
.strip_prefix("fs") {
let filesystems = systab
.boot_services()
.find_handles::<SimpleFileSystem>()
let filesystems = find_handles::<SimpleFileSystem>()
.map_err(|e| e.status())?;
let fs = filesystems.into_iter().nth(
idx.parse::<usize>().map_err(|_| {
Expand All @@ -78,9 +77,7 @@ impl<'a> File<'a> {
} else {
(image_fs_handle, file_name)
};
let mut fs = systab
.boot_services()
.open_protocol_exclusive::<SimpleFileSystem>(fs_handle)
let mut fs = open_protocol_exclusive::<SimpleFileSystem>(fs_handle)
.map_err(|e| e.status())?;
let file_handle = match fs.open_volume().map_err(|e| e.status())?.open(
&file_name,
Expand Down
Loading

0 comments on commit 2fefb3a

Please sign in to comment.