2022-11-21 05:44:04 -05:00
|
|
|
#![no_main]
|
|
|
|
#![no_std]
|
|
|
|
#![feature(abi_efiapi)]
|
2022-11-22 18:25:52 -05:00
|
|
|
#![feature(negative_impls)]
|
2022-11-21 05:44:04 -05:00
|
|
|
|
2022-11-21 11:52:06 -05:00
|
|
|
extern crate alloc;
|
2022-11-21 10:22:44 -05:00
|
|
|
|
2022-11-22 18:25:52 -05:00
|
|
|
mod linux_loader;
|
2022-11-22 10:18:12 -05:00
|
|
|
mod pe_section;
|
2022-11-22 10:24:09 -05:00
|
|
|
mod uefi_helpers;
|
2022-11-22 10:18:12 -05:00
|
|
|
|
2022-11-23 09:40:52 -05:00
|
|
|
use pe_section::pe_section_as_string;
|
2022-11-21 11:52:06 -05:00
|
|
|
use uefi::{
|
|
|
|
prelude::*,
|
|
|
|
proto::{
|
2022-11-24 06:18:23 -05:00
|
|
|
console::text::Output,
|
2022-11-22 10:18:12 -05:00
|
|
|
loaded_image::LoadedImage,
|
2022-11-23 09:40:52 -05:00
|
|
|
media::file::{File, FileAttribute, FileMode, RegularFile},
|
2022-11-21 11:52:06 -05:00
|
|
|
},
|
2022-11-25 12:08:54 -05:00
|
|
|
CString16, Result,
|
2022-11-21 11:52:06 -05:00
|
|
|
};
|
2022-11-21 10:22:44 -05:00
|
|
|
|
2022-11-23 05:29:40 -05:00
|
|
|
use crate::{
|
|
|
|
linux_loader::InitrdLoader,
|
2022-11-23 09:40:52 -05:00
|
|
|
uefi_helpers::{booted_image_cmdline, booted_image_file, read_all},
|
2022-11-23 05:29:40 -05:00
|
|
|
};
|
2022-11-22 10:18:12 -05:00
|
|
|
|
2022-11-25 12:08:54 -05:00
|
|
|
/// Print the startup logo on boot.
|
|
|
|
fn print_logo(output: &mut Output) -> Result<()> {
|
|
|
|
output.clear()?;
|
2022-11-21 10:22:44 -05:00
|
|
|
|
2022-11-25 12:08:54 -05:00
|
|
|
output.output_string(cstr16!(
|
|
|
|
"
|
2022-11-25 11:54:17 -05:00
|
|
|
_ _ _\r
|
|
|
|
| | | | | |\r
|
|
|
|
| | __ _ _ __ ______ _| |__ ___ ___ | |_ ___\r
|
|
|
|
| |/ _` | '_ \\|_ / _` | '_ \\ / _ \\ / _ \\| __/ _ \\\r
|
|
|
|
| | (_| | | | |/ / (_| | |_) | (_) | (_) | || __/\r
|
|
|
|
|_|\\__,_|_| |_/___\\__,_|_.__/ \\___/ \\___/ \\__\\___|\r
|
2022-11-22 10:18:12 -05:00
|
|
|
\r
|
2022-11-21 10:22:44 -05:00
|
|
|
"
|
2022-11-25 12:08:54 -05:00
|
|
|
))
|
2022-11-21 10:22:44 -05:00
|
|
|
}
|
2022-11-21 05:44:04 -05:00
|
|
|
|
2022-11-25 12:05:44 -05:00
|
|
|
/// The configuration that is embedded at build time.
|
|
|
|
///
|
|
|
|
/// After lanzaboote is built, lanzatool needs to embed configuration
|
|
|
|
/// into the binary. This struct represents that information.
|
2022-11-23 09:40:52 -05:00
|
|
|
struct EmbeddedConfiguration {
|
2022-11-25 12:05:44 -05:00
|
|
|
/// The filename of the kernel to be booted. This filename is
|
|
|
|
/// relative to the root of the volume that contains the
|
|
|
|
/// lanzaboote binary.
|
2022-11-23 09:40:52 -05:00
|
|
|
kernel_filename: CString16,
|
2022-11-25 12:05:44 -05:00
|
|
|
|
|
|
|
/// The filename of the initrd to be passed to the kernel. See
|
|
|
|
/// `kernel_filename` for how to interpret these filenames.
|
2022-11-23 09:40:52 -05:00
|
|
|
initrd_filename: CString16,
|
|
|
|
}
|
|
|
|
|
2022-11-23 11:57:43 -05:00
|
|
|
impl EmbeddedConfiguration {
|
2022-11-25 12:08:54 -05:00
|
|
|
fn new(file: &mut RegularFile) -> Result<Self> {
|
2022-11-23 09:40:52 -05:00
|
|
|
file.set_position(0)?;
|
|
|
|
let file_data = read_all(file)?;
|
|
|
|
|
|
|
|
let kernel_filename =
|
|
|
|
pe_section_as_string(&file_data, ".kernelp").ok_or(Status::INVALID_PARAMETER)?;
|
|
|
|
let initrd_filename =
|
|
|
|
pe_section_as_string(&file_data, ".initrdp").ok_or(Status::INVALID_PARAMETER)?;
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
kernel_filename: CString16::try_from(kernel_filename.as_str()).unwrap(),
|
|
|
|
initrd_filename: CString16::try_from(initrd_filename.as_str()).unwrap(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 05:44:04 -05:00
|
|
|
#[entry]
|
2022-11-21 11:52:06 -05:00
|
|
|
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
2022-11-21 05:44:04 -05:00
|
|
|
uefi_services::init(&mut system_table).unwrap();
|
|
|
|
|
2022-11-25 12:08:54 -05:00
|
|
|
print_logo(system_table.stdout()).unwrap();
|
2022-11-21 09:36:39 -05:00
|
|
|
|
2022-11-23 11:57:43 -05:00
|
|
|
let config: EmbeddedConfiguration =
|
|
|
|
EmbeddedConfiguration::new(&mut booted_image_file(system_table.boot_services()).unwrap())
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to extract configuration from binary. Did you run lanzatool?");
|
2022-11-23 09:40:52 -05:00
|
|
|
|
2022-11-27 14:34:39 -05:00
|
|
|
let kernel_data;
|
|
|
|
let initrd_data;
|
2022-11-27 14:04:41 -05:00
|
|
|
|
|
|
|
{
|
2022-11-25 20:31:01 -05:00
|
|
|
let mut file_system = system_table
|
|
|
|
.boot_services()
|
|
|
|
.get_image_file_system(handle)
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to get file system handle");
|
|
|
|
let mut root = file_system
|
|
|
|
.open_volume()
|
|
|
|
.expect("Failed to find ESP root directory");
|
2022-11-25 20:31:01 -05:00
|
|
|
|
2022-11-27 14:34:39 -05:00
|
|
|
let mut kernel_file = root
|
2022-11-25 20:31:01 -05:00
|
|
|
.open(
|
|
|
|
&config.kernel_filename,
|
|
|
|
FileMode::Read,
|
|
|
|
FileAttribute::empty(),
|
|
|
|
)
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to open kernel file for reading")
|
2022-11-25 20:31:01 -05:00
|
|
|
.into_regular_file()
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Kernel is not a regular file");
|
2022-11-21 11:52:06 -05:00
|
|
|
|
2022-11-27 14:34:39 -05:00
|
|
|
kernel_data = read_all(&mut kernel_file).expect("Failed to read kernel file into memory");
|
|
|
|
|
|
|
|
let mut initrd_file = root
|
2022-11-27 14:04:41 -05:00
|
|
|
.open(
|
|
|
|
&config.initrd_filename,
|
|
|
|
FileMode::Read,
|
|
|
|
FileAttribute::empty(),
|
|
|
|
)
|
|
|
|
.expect("Failed to open initrd for reading")
|
|
|
|
.into_regular_file()
|
|
|
|
.expect("Initrd is not a regular file");
|
2022-11-27 14:34:39 -05:00
|
|
|
|
|
|
|
initrd_data = read_all(&mut initrd_file).expect("Failed to read kernel file into memory");
|
2022-11-27 14:04:41 -05:00
|
|
|
}
|
2022-11-23 06:11:20 -05:00
|
|
|
|
2022-11-25 20:47:21 -05:00
|
|
|
let kernel_cmdline =
|
|
|
|
booted_image_cmdline(system_table.boot_services()).expect("Failed to fetch command line");
|
2022-11-21 19:39:05 -05:00
|
|
|
|
2022-11-25 20:47:21 -05:00
|
|
|
let kernel_handle = {
|
|
|
|
system_table
|
|
|
|
.boot_services()
|
|
|
|
.load_image(
|
|
|
|
handle,
|
|
|
|
uefi::table::boot::LoadImageSource::FromBuffer {
|
|
|
|
buffer: &kernel_data,
|
|
|
|
file_path: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("UEFI refused to load the kernel image. It may not be signed or it may not have an EFI stub.")
|
|
|
|
};
|
2022-11-21 19:39:05 -05:00
|
|
|
|
2022-11-23 06:11:20 -05:00
|
|
|
let mut kernel_image = system_table
|
|
|
|
.boot_services()
|
|
|
|
.open_protocol_exclusive::<LoadedImage>(kernel_handle)
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to open the LoadedImage protocol");
|
2022-11-23 06:11:20 -05:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
kernel_image.set_load_options(
|
|
|
|
kernel_cmdline.as_ptr() as *const u8,
|
|
|
|
u32::try_from(kernel_cmdline.len()).unwrap(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-27 14:34:39 -05:00
|
|
|
let mut initrd_loader = InitrdLoader::new(system_table.boot_services(), handle, initrd_data)
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to load the initrd. It may not be there or it is not signed");
|
2022-11-23 06:11:20 -05:00
|
|
|
let status = system_table
|
|
|
|
.boot_services()
|
|
|
|
.start_image(kernel_handle)
|
|
|
|
.status();
|
2022-11-21 11:52:06 -05:00
|
|
|
|
2022-11-23 06:11:20 -05:00
|
|
|
initrd_loader
|
2022-11-23 06:13:45 -05:00
|
|
|
.uninstall(system_table.boot_services())
|
2022-11-25 20:47:21 -05:00
|
|
|
.expect("Failed to uninstall the initrd protocols");
|
2022-11-22 18:25:52 -05:00
|
|
|
status
|
2022-11-21 05:44:04 -05:00
|
|
|
}
|