Fix System Table memory layout, achieve function calls using UEFI function pointers

This commit is contained in:
wmpod2xwie 2024-06-21 13:27:46 +10:00
parent 43d9a42bec
commit 8ca901ef50
8 changed files with 320 additions and 104 deletions

Binary file not shown.

View File

@ -40,8 +40,8 @@ overhead_percentage=20
overhead_size=$((bootloader_size * overhead_percentage / 100)) overhead_size=$((bootloader_size * overhead_percentage / 100))
total_size=$((bootloader_size + overhead_size)) total_size=$((bootloader_size + overhead_size))
# Ensure the size is at least 4MB # Ensure the size is at least 100MB
minimum_size=$((4 * 1024 * 1024)) minimum_size=$((100 * 1024 * 1024))
# Calculate the final size, which should be the maximum of total_size or minimum_size # Calculate the final size, which should be the maximum of total_size or minimum_size
final_size=$(( total_size > minimum_size ? total_size : minimum_size )) final_size=$(( total_size > minimum_size ? total_size : minimum_size ))
@ -66,6 +66,10 @@ mount_directory=$(mktemp --tmpdir="$script_directory" -d)
sudo mount -v "${loop_device}p1" "$mount_directory" sudo mount -v "${loop_device}p1" "$mount_directory"
sudo mkdir -pv "${mount_directory}/EFI/BOOT/" sudo mkdir -pv "${mount_directory}/EFI/BOOT/"
sudo cp -vf "$bootloader" "${mount_directory}/EFI/BOOT/BOOTX64.EFI" sudo cp -vf "$bootloader" "${mount_directory}/EFI/BOOT/BOOTX64.EFI"
# Create the startup.nsh script
echo -e "FS0:\ncd EFI\\BOOT\nBOOTX64.EFI" | sudo tee "${mount_directory}/startup.nsh"
sudo umount -v "${mount_directory}" sudo umount -v "${mount_directory}"
echo "Partition and formatting ✓" echo "Partition and formatting ✓"

View File

@ -9,6 +9,103 @@ use crate::types::Handle;
**/ **/
#[repr(C)] #[repr(C)]
pub struct BootServicesTable { pub struct BootServicesTable {
efi_table_header: TableHeader, pub efi_table_header: TableHeader,
load_image: extern "efiapi" fn(boot_policy: bool, parent_image_hanle: Handle), pub raise_tpl: RaiseTpl,
pub restore_tpl: RestoreTpl,
pub allocate_pages: AllocatePages,
pub free_pages: FreePages,
pub get_memory_map: GetMemoryMap,
pub allocate_pool: AllocatePool,
pub free_pool: FreePool,
pub create_event: CreateEvent,
pub set_timer: SetTimer,
pub wait_for_event: WaitForEvent,
pub signal_event: SignalEvent,
pub close_event: CloseEvent,
pub check_event: CheckEvent,
pub install_protocol_interface: InstallProtocolInterface,
pub reinstall_protocol_interface: ReinstallProtocolInterface,
pub uninstall_protocol_interface: UninstallProtocolInterface,
pub handle_protocol: HandleProtocol,
pub reserved: Reserved,
pub register_protocol_notify: RegisterProtocolNotify,
pub locate_handle: LocateHandle,
pub locate_device_path: LocateDevicePath,
pub install_configuration_table: InstallConfigurationTable,
pub load_image: LoadImage,
pub start_image: StartImage,
pub exit: Exit,
pub unload_image: UnloadImage,
pub exit_boot_services: ExitBootServices,
pub get_next_monotonic_count: GetNextMonotonicCount,
pub stall: Stall,
pub set_watchdog_timer: SetWatchdogTimer,
pub connect_controller: ConnectController,
pub disconnect_contoller: DisconnectController,
pub open_protocol: OpenProtocol,
pub close_protocol: CloseProtocol,
pub open_protocol_information: OpenProtocolInformation,
pub protocol_per_handle: ProtocolPerHandle,
pub locate_handle_buffer: LocateHandleBuffer,
pub locate_protocol: LocateProtocol,
pub install_multiple_protocol_interfaces: InstallMultipleProtocolInterfaces,
pub uninstall_multiple_protocol_interfaces: UninstallMultipleProtocolInterfaces,
pub calculate_crc_32: CalculateCrc32,
pub copy_mem: CopyMem,
pub set_mem: SetMem,
pub create_event_ex: CreateEventEx,
}
pub type RaiseTpl = extern "efiapi" fn() -> Status;
pub type RestoreTpl = extern "efiapi" fn() -> Status;
pub type AllocatePages = extern "efiapi" fn() -> Status;
pub type FreePages = extern "efiapi" fn() -> Status;
pub type GetMemoryMap = extern "efiapi" fn() -> Status;
pub type AllocatePool = extern "efiapi" fn() -> Status;
pub type FreePool = extern "efiapi" fn() -> Status;
pub type CreateEvent = extern "efiapi" fn() -> Status;
pub type SetTimer = extern "efiapi" fn() -> Status;
pub type WaitForEvent = extern "efiapi" fn() -> Status;
pub type SignalEvent = extern "efiapi" fn() -> Status;
pub type CloseEvent = extern "efiapi" fn() -> Status;
pub type CheckEvent = extern "efiapi" fn() -> Status;
pub type InstallProtocolInterface = extern "efiapi" fn() -> Status;
pub type ReinstallProtocolInterface = extern "efiapi" fn() -> Status;
pub type UninstallProtocolInterface = extern "efiapi" fn() -> Status;
pub type HandleProtocol = extern "efiapi" fn() -> Status;
pub type Reserved = extern "efiapi" fn() -> Status;
pub type RegisterProtocolNotify = extern "efiapi" fn() -> Status;
pub type LocateHandle = extern "efiapi" fn() -> Status;
pub type LocateDevicePath = extern "efiapi" fn() -> Status;
pub type InstallConfigurationTable = extern "efiapi" fn() -> Status;
pub type LoadImage = extern "efiapi" fn() -> Status;
pub type StartImage = extern "efiapi" fn() -> Status;
pub type Exit = extern "efiapi" fn(
image_handle: Handle,
exit_status: Status,
exit_data_size: usize,
*const u16
) -> Status;
pub type UnloadImage = extern "efiapi" fn() -> Status;
pub type ExitBootServices = extern "efiapi" fn() -> Status;
pub type GetNextMonotonicCount = extern "efiapi" fn() -> Status;
pub type Stall = extern "efiapi" fn() -> Status;
pub type SetWatchdogTimer = extern "efiapi" fn() -> Status;
pub type ConnectController = extern "efiapi" fn() -> Status;
pub type DisconnectController = extern "efiapi" fn() -> Status;
pub type OpenProtocol = extern "efiapi" fn() -> Status;
pub type CloseProtocol = extern "efiapi" fn() -> Status;
pub type OpenProtocolInformation = extern "efiapi" fn() -> Status;
pub type ProtocolPerHandle = extern "efiapi" fn() -> Status;
pub type LocateHandleBuffer = extern "efiapi" fn() -> Status;
pub type LocateProtocol = extern "efiapi" fn() -> Status;
pub type InstallMultipleProtocolInterfaces = extern "efiapi" fn() -> Status;
pub type UninstallMultipleProtocolInterfaces = extern "efiapi" fn() -> Status;
pub type CalculateCrc32 = extern "efiapi" fn() -> Status;
pub type CopyMem = extern "efiapi" fn() -> Status;
pub type SetMem = extern "efiapi" fn() -> Status;
pub type CreateEventEx = extern "efiapi" fn() -> Status;
impl BootServicesTable {
pub const BOOT_SERVICES_SIGNATURE: u64 = 0x56524553544f4f42;
} }

View File

@ -1,19 +0,0 @@
use crate::structs::{MemoryDescriptor, Status, TPL};
// Task Priority Services
pub type raise_tpl = fn(efi_tpl: TPL) -> Status;
pub type restore_tpl = fn() -> ();
// Memory Services
pub type allocate_pages = fn() -> ();
pub type free_pages = fn() -> ();
pub type allocate_pool = fn() -> ();
pub type free_pool = fn() -> ();
pub type get_memory_map = extern "efiapi" fn(
memory_map_size: *mut usize,
memory_map: *mut MemoryDescriptor,
map_key: *mut usize,
descriptor_size: *mut usize,
descriptor_version: *mut u32,
) -> Status;

View File

@ -1,32 +1,63 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
pub mod functions; pub mod boot_services;
pub mod simple_text_output;
pub mod structs; pub mod structs;
pub mod system_table; pub mod system_table;
pub mod types; pub mod types;
pub mod boot_services;
pub mod simple_text_output;
use core::panic::PanicInfo; use core::{panic::PanicInfo, ptr::null};
use boot_services::BootServicesTable;
use simple_text_output::SimpleTextOutputProtocol;
use structs::Status;
use system_table::SystemTable; use system_table::SystemTable;
use types::Handle; use types::Handle;
use simple_text_output::SimpleTextOutputProtocol;
#[no_mangle] #[no_mangle]
#[export_name = "efi_main"] #[export_name = "efi_main"]
extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut SystemTable) -> usize { extern "efiapi" fn efi_main(image_handle: Handle, system_table_ptr: *mut SystemTable) -> usize {
unsafe { if system_table_ptr.is_null() {
let system_table_ref: &SystemTable = &*system_table; return usize::from(Status::OutOfResources);
let console_out: *mut SimpleTextOutputProtocol = system_table_ref.console_out;
} }
loop {};
0 // EFI_SUCCESS let system_table: &SystemTable = initialize_system_table(system_table_ptr);
let console_out: Option<&SimpleTextOutputProtocol> = initialize_console_out(system_table);
let boot_services_table: Option<&BootServicesTable> = initialize_boot_services(system_table);
if let Some(console_out) = console_out {
(console_out.clear_screen)(console_out);
}
if let Some(boot_services_table) = boot_services_table {
(boot_services_table.exit)(image_handle, Status::Success, 0, null());
}
usize::from(Status::Success) // EFI_SUCCESS
} }
fn initialize_system_table(system_table_ptr: *mut SystemTable) -> &'static SystemTable {
unsafe { &*system_table_ptr }
}
fn initialize_console_out(system_table: &SystemTable) -> Option<&SimpleTextOutputProtocol> {
let console_out = system_table.console_out;
if !console_out.is_null() {
unsafe { Some(&*console_out) }
} else {
None
}
}
fn initialize_boot_services(system_table: &SystemTable) -> Option<&BootServicesTable> {
if !system_table.boot_services_table_pointer.is_null() {
unsafe { Some(&*system_table.boot_services_table_pointer)}
} else {
None
}
}
#[panic_handler] #[panic_handler]
fn panic(_info: &PanicInfo) -> ! { fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
} }

View File

@ -1,18 +1,28 @@
use crate::structs::Status; use crate::structs::{Status, GUID};
use crate::types::Char16; use crate::types::Char16;
#[repr(C)] #[repr(C)]
pub struct SimpleTextOutputProtocol { pub struct SimpleTextOutputProtocol {
reset: text_reset, pub reset: text_reset,
output_string: text_string, pub output_string: text_string,
test_string: text_test_string, pub test_string: text_test_string,
query_mode: text_query_mode, pub query_mode: text_query_mode,
set_mode: text_set_mode, pub set_mode: text_set_mode,
set_attribute: text_set_attribute, pub set_attribute: text_set_attribute,
clear_screen: text_clear_screen, pub clear_screen: text_clear_screen,
set_cursor_position: text_set_cursor_position, pub set_cursor_position: text_set_cursor_position,
enable_cursor: text_enable_cursor, pub enable_cursor: text_enable_cursor,
mode: *mut SimpleTextOutputMode, pub mode: *mut SimpleTextOutputMode,
}
impl SimpleTextOutputProtocol {
pub const SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID: GUID = GUID {
data1: 0x387477c2,
data2: 0x69c7,
data3: 0x11d2,
data4: [0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b],
};
} }
pub type text_reset = pub type text_reset =
@ -31,7 +41,7 @@ pub type text_set_mode =
extern "efiapi" fn(this: &SimpleTextOutputProtocol, mode_number: usize) -> Status; extern "efiapi" fn(this: &SimpleTextOutputProtocol, mode_number: usize) -> Status;
pub type text_set_attribute = pub type text_set_attribute =
extern "efiapi" fn(this: &SimpleTextOutputProtocol, Attribute: usize) -> Status; extern "efiapi" fn(this: &SimpleTextOutputProtocol, Attribute: usize) -> Status;
pub type text_clear_screen = extern "efiapi" fn(this: SimpleTextOutputProtocol) -> Status; pub type text_clear_screen = extern "efiapi" fn(this: &SimpleTextOutputProtocol) -> Status;
pub type text_set_cursor_position = pub type text_set_cursor_position =
extern "efiapi" fn(this: &SimpleTextOutputProtocol, column: usize, row: usize) -> Status; extern "efiapi" fn(this: &SimpleTextOutputProtocol, column: usize, row: usize) -> Status;
pub type text_enable_cursor = pub type text_enable_cursor =

View File

@ -35,53 +35,146 @@ pub struct TableHeader {
reserved: u32, reserved: u32,
} }
#[repr(C)] #[repr(u64)]
pub enum Status { pub enum Status {
Success, Success = 0,
LoadError, LoadError = 1,
InvalidParameter, InvalidParameter = 2,
Unsupported, Unsupported = 3,
BadBufferSize, BadBufferSize = 4,
BufferTooSmall, BufferTooSmall = 5,
NotReady, NotReady = 6,
DeviceError, DeviceError = 7,
WriteProtected, WriteProtected = 8,
OutOfResources, OutOfResources = 9,
VolumeCorrupted, VolumeCorrupted = 10,
VolumeFull, VolumeFull = 11,
NoMedia, NoMedia = 12,
MediaChanged, MediaChanged = 13,
NotFound, NotFound = 14,
AccessDenied, AccessDenied = 15,
NoResponce, NoResponse = 16,
NoMapping, NoMapping = 17,
Timeout, Timeout = 18,
NotStarted, NotStarted = 19,
AlreadyStarted, AlreadyStarted = 20,
Aborted, Aborted = 21,
IcmpError, IcmpError = 22,
TftpError, TftpError = 23,
ProtocolError, ProtocolError = 24,
IncompatibleVersion, IncompatibleVersion = 25,
SecurityViolation, SecurityViolation = 26,
CrcError, CrcError = 27,
EndOfMedia, EndOfMedia = 28,
EndOfFile, EndOfFile = 31,
InvalidLanguage, InvalidLanguage = 32,
CompromisedData, CompromisedData = 33,
IpAddressConflict, IpAddressConflict = 34,
HttpError, HttpError = 35,
} }
impl From<u64> for Status {
fn from(value: u64) -> Self {
match value {
0 => Status::Success,
1 => Status::LoadError,
2 => Status::InvalidParameter,
3 => Status::Unsupported,
4 => Status::BadBufferSize,
5 => Status::BufferTooSmall,
6 => Status::NotReady,
7 => Status::DeviceError,
8 => Status::WriteProtected,
9 => Status::OutOfResources,
10 => Status::VolumeCorrupted,
11 => Status::VolumeFull,
12 => Status::NoMedia,
13 => Status::MediaChanged,
14 => Status::NotFound,
15 => Status::AccessDenied,
16 => Status::NoResponse,
17 => Status::NoMapping,
18 => Status::Timeout,
19 => Status::NotStarted,
20 => Status::AlreadyStarted,
21 => Status::Aborted,
22 => Status::IcmpError,
23 => Status::TftpError,
24 => Status::ProtocolError,
25 => Status::IncompatibleVersion,
26 => Status::SecurityViolation,
27 => Status::CrcError,
28 => Status::EndOfMedia,
31 => Status::EndOfFile,
32 => Status::InvalidLanguage,
33 => Status::CompromisedData,
34 => Status::IpAddressConflict,
35 => Status::HttpError,
_ => Status::Unsupported, // Default case
}
}
}
impl From<Status> for u64 {
fn from(status: Status) -> Self {
status as u64
}
}
impl From<Status> for usize {
fn from(status: Status) -> Self {
status as usize
}
}
// #[repr(u64)]
// pub enum Status {
// Success,
// LoadError,
// InvalidParameter,
// Unsupported,
// BadBufferSize,
// BufferTooSmall,
// NotReady,
// DeviceError,
// WriteProtected,
// OutOfResources,
// VolumeCorrupted,
// VolumeFull,
// NoMedia,
// MediaChanged,
// NotFound,
// AccessDenied,
// NoResponce,
// NoMapping,
// Timeout,
// NotStarted,
// AlreadyStarted,
// Aborted,
// IcmpError,
// TftpError,
// ProtocolError,
// IncompatibleVersion,
// SecurityViolation,
// CrcError,
// EndOfMedia,
// EndOfFile,
// InvalidLanguage,
// CompromisedData,
// IpAddressConflict,
// HttpError,
// }
#[repr(C)] #[repr(C)]
pub struct TPL {} pub struct TPL {}
#[repr(C)] #[repr(C)]
pub struct EFIGUID { pub struct GUID {
data1: u32, pub data1: u32,
data2: u16, pub data2: u16,
data3: u16, pub data3: u16,
data4: [u8; 8], pub data4: [u8; 8],
} }
#[repr(C)] #[repr(C)]

View File

@ -42,21 +42,21 @@ pub struct ImageEntryPoint {
system_table_pointer: *const i32, // A pointer to the EFI System Table. system_table_pointer: *const i32, // A pointer to the EFI System Table.
} }
#[repr(C)]
pub struct SystemTableRevisions;
impl SystemTableRevisions { #[repr(u32)]
pub const EFI_1_90_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (90)); pub enum SystemTableRevisions {
pub const EFI_1_80_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (80)); EFI_2_100_SYSTEM_TABLE_REVISION = (2 << 16) | 100,
pub const EFI_1_70_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (70)); EFI_1_90_SYSTEM_TABLE_REVISION = ((2 << 16) | (90)),
pub const EFI_1_60_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (60)); EFI_1_80_SYSTEM_TABLE_REVISION = ((2 << 16) | (80)),
pub const EFI_1_50_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (50)); EFI_1_70_SYSTEM_TABLE_REVISION = ((2 << 16) | (70)),
pub const EFI_1_40_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (40)); EFI_1_60_SYSTEM_TABLE_REVISION = ((2 << 16) | (60)),
pub const EFI_1_31_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (31)); EFI_1_50_SYSTEM_TABLE_REVISION = ((2 << 16) | (50)),
pub const EFI_1_30_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (30)); EFI_1_40_SYSTEM_TABLE_REVISION = ((2 << 16) | (40)),
pub const EFI_1_20_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (20)); EFI_1_31_SYSTEM_TABLE_REVISION = ((2 << 16) | (31)),
pub const EFI_1_10_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (10)); EFI_1_30_SYSTEM_TABLE_REVISION = ((2 << 16) | (30)),
pub const EFI_1_00_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (00)); EFI_1_20_SYSTEM_TABLE_REVISION = ((2 << 16) | (20)),
pub const EFI_0_10_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (10)); EFI_1_10_SYSTEM_TABLE_REVISION = ((2 << 16) | (10)),
pub const EFI_0_02_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (02)); EFI_1_00_SYSTEM_TABLE_REVISION = ((2 << 16) | (00)),
} EFI_0_10_SYSTEM_TABLE_REVISION = ((1 << 16) | (10)),
EFI_0_02_SYSTEM_TABLE_REVISION = ((1 << 16) | (02)),
}