diff --git a/docs/OVMF_VARS.fd b/docs/OVMF_VARS.fd index 96121fd..b39c0c8 100644 Binary files a/docs/OVMF_VARS.fd and b/docs/OVMF_VARS.fd differ diff --git a/scripts/run_emulator.sh b/scripts/run_emulator.sh index 35692da..849545c 100755 --- a/scripts/run_emulator.sh +++ b/scripts/run_emulator.sh @@ -40,8 +40,8 @@ overhead_percentage=20 overhead_size=$((bootloader_size * overhead_percentage / 100)) total_size=$((bootloader_size + overhead_size)) -# Ensure the size is at least 4MB -minimum_size=$((4 * 1024 * 1024)) +# Ensure the size is at least 100MB +minimum_size=$((100 * 1024 * 1024)) # 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 )) @@ -66,6 +66,10 @@ mount_directory=$(mktemp --tmpdir="$script_directory" -d) sudo mount -v "${loop_device}p1" "$mount_directory" sudo mkdir -pv "${mount_directory}/EFI/BOOT/" 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}" echo "Partition and formatting ✓" diff --git a/src/boot_services.rs b/src/boot_services.rs index 641082c..e5abc15 100644 --- a/src/boot_services.rs +++ b/src/boot_services.rs @@ -9,6 +9,103 @@ use crate::types::Handle; **/ #[repr(C)] pub struct BootServicesTable { - efi_table_header: TableHeader, - load_image: extern "efiapi" fn(boot_policy: bool, parent_image_hanle: Handle), + pub efi_table_header: TableHeader, + 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; } diff --git a/src/functions.rs b/src/functions.rs deleted file mode 100644 index 0d7e4e9..0000000 --- a/src/functions.rs +++ /dev/null @@ -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; diff --git a/src/os_loader.rs b/src/os_loader.rs index 8756075..a6ef0a3 100644 --- a/src/os_loader.rs +++ b/src/os_loader.rs @@ -1,32 +1,63 @@ #![no_std] #![no_main] -pub mod functions; +pub mod boot_services; +pub mod simple_text_output; pub mod structs; pub mod system_table; 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 types::Handle; -use simple_text_output::SimpleTextOutputProtocol; #[no_mangle] #[export_name = "efi_main"] -extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut SystemTable) -> usize { - unsafe { - let system_table_ref: &SystemTable = &*system_table; - let console_out: *mut SimpleTextOutputProtocol = system_table_ref.console_out; +extern "efiapi" fn efi_main(image_handle: Handle, system_table_ptr: *mut SystemTable) -> usize { + if system_table_ptr.is_null() { + return usize::from(Status::OutOfResources); } - 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] fn panic(_info: &PanicInfo) -> ! { loop {} -} \ No newline at end of file +} diff --git a/src/simple_text_output.rs b/src/simple_text_output.rs index 1b96419..9919973 100644 --- a/src/simple_text_output.rs +++ b/src/simple_text_output.rs @@ -1,18 +1,28 @@ -use crate::structs::Status; +use crate::structs::{Status, GUID}; use crate::types::Char16; #[repr(C)] pub struct SimpleTextOutputProtocol { - reset: text_reset, - output_string: text_string, - test_string: text_test_string, - query_mode: text_query_mode, - set_mode: text_set_mode, - set_attribute: text_set_attribute, - clear_screen: text_clear_screen, - set_cursor_position: text_set_cursor_position, - enable_cursor: text_enable_cursor, - mode: *mut SimpleTextOutputMode, + pub reset: text_reset, + pub output_string: text_string, + pub test_string: text_test_string, + pub query_mode: text_query_mode, + pub set_mode: text_set_mode, + pub set_attribute: text_set_attribute, + pub clear_screen: text_clear_screen, + pub set_cursor_position: text_set_cursor_position, + pub enable_cursor: text_enable_cursor, + 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 = @@ -31,7 +41,7 @@ pub type text_set_mode = extern "efiapi" fn(this: &SimpleTextOutputProtocol, mode_number: usize) -> Status; pub type text_set_attribute = 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 = extern "efiapi" fn(this: &SimpleTextOutputProtocol, column: usize, row: usize) -> Status; pub type text_enable_cursor = diff --git a/src/structs.rs b/src/structs.rs index 3b2c742..8f932a7 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -35,53 +35,146 @@ pub struct TableHeader { reserved: u32, } -#[repr(C)] +#[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, + Success = 0, + LoadError = 1, + InvalidParameter = 2, + Unsupported = 3, + BadBufferSize = 4, + BufferTooSmall = 5, + NotReady = 6, + DeviceError = 7, + WriteProtected = 8, + OutOfResources = 9, + VolumeCorrupted = 10, + VolumeFull = 11, + NoMedia = 12, + MediaChanged = 13, + NotFound = 14, + AccessDenied = 15, + NoResponse = 16, + NoMapping = 17, + Timeout = 18, + NotStarted = 19, + AlreadyStarted = 20, + Aborted = 21, + IcmpError = 22, + TftpError = 23, + ProtocolError = 24, + IncompatibleVersion = 25, + SecurityViolation = 26, + CrcError = 27, + EndOfMedia = 28, + EndOfFile = 31, + InvalidLanguage = 32, + CompromisedData = 33, + IpAddressConflict = 34, + HttpError = 35, } +impl From 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 for u64 { + fn from(status: Status) -> Self { + status as u64 + } +} + +impl From 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)] pub struct TPL {} #[repr(C)] -pub struct EFIGUID { - data1: u32, - data2: u16, - data3: u16, - data4: [u8; 8], +pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], } #[repr(C)] diff --git a/src/system_table.rs b/src/system_table.rs index bd07897..359d87c 100644 --- a/src/system_table.rs +++ b/src/system_table.rs @@ -42,21 +42,21 @@ pub struct ImageEntryPoint { system_table_pointer: *const i32, // A pointer to the EFI System Table. } -#[repr(C)] -pub struct SystemTableRevisions; -impl SystemTableRevisions { - pub const EFI_1_90_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (90)); - pub const EFI_1_80_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (80)); - pub const EFI_1_70_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (70)); - pub const EFI_1_60_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (60)); - pub const EFI_1_50_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (50)); - pub const EFI_1_40_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (40)); - pub const EFI_1_31_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (31)); - pub const EFI_1_30_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (30)); - pub const EFI_1_20_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (20)); - pub const EFI_1_10_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (10)); - pub const EFI_1_00_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (00)); - pub const EFI_0_10_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (10)); - pub const EFI_0_02_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (02)); -} +#[repr(u32)] +pub enum SystemTableRevisions { + EFI_2_100_SYSTEM_TABLE_REVISION = (2 << 16) | 100, + EFI_1_90_SYSTEM_TABLE_REVISION = ((2 << 16) | (90)), + EFI_1_80_SYSTEM_TABLE_REVISION = ((2 << 16) | (80)), + EFI_1_70_SYSTEM_TABLE_REVISION = ((2 << 16) | (70)), + EFI_1_60_SYSTEM_TABLE_REVISION = ((2 << 16) | (60)), + EFI_1_50_SYSTEM_TABLE_REVISION = ((2 << 16) | (50)), + EFI_1_40_SYSTEM_TABLE_REVISION = ((2 << 16) | (40)), + EFI_1_31_SYSTEM_TABLE_REVISION = ((2 << 16) | (31)), + EFI_1_30_SYSTEM_TABLE_REVISION = ((2 << 16) | (30)), + EFI_1_20_SYSTEM_TABLE_REVISION = ((2 << 16) | (20)), + EFI_1_10_SYSTEM_TABLE_REVISION = ((2 << 16) | (10)), + 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)), +} \ No newline at end of file