diff --git a/Cargo.toml b/Cargo.toml index 2e0d263..045db1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" [dependencies] [[bin]] -name = "uefi_os_loader" -path = "src/uefi_os_loader.rs" +name = "os_loader" +path = "src/os_loader.rs" [features] default = [] diff --git a/scripts/run_emulator.sh b/scripts/run_emulator.sh index 3fab255..35692da 100755 --- a/scripts/run_emulator.sh +++ b/scripts/run_emulator.sh @@ -29,7 +29,7 @@ disk_image="$HOME/tmpfs/disk.img" block_size="1M" count="100" disk_size="100MiB" -bootloader="${script_directory}/../target/x86_64-unknown-uefi/release/uefi_os_loader.efi" +bootloader="${script_directory}/../target/x86_64-unknown-uefi/release/os_loader.efi" # Get the size of the bootloader in bytes bootloader_size=$(stat -c%s "$bootloader") diff --git a/src/boot_services.rs b/src/boot_services.rs new file mode 100644 index 0000000..641082c --- /dev/null +++ b/src/boot_services.rs @@ -0,0 +1,14 @@ +use crate::structs::*; +use crate::types::Handle; +/** + UEFI uses the EFI Boot Services Table, which contains a table header and pointers to all of the boot + services. The definition for this table is shown in the following code fragments. Except for the table + header, all elements in the EFI Boot Services Tables are prototypes of function pointers to functions as + defined in Section 7. The function pointers in this table are not valid after the operating system has taken + control of the platform with a call to EFI_BOOT_SERVICES.ExitBootServices(). +**/ +#[repr(C)] +pub struct BootServicesTable { + efi_table_header: TableHeader, + load_image: extern "efiapi" fn(boot_policy: bool, parent_image_hanle: Handle), +} diff --git a/src/uefi_functions.rs b/src/functions.rs similarity index 87% rename from src/uefi_functions.rs rename to src/functions.rs index dd9699d..0d7e4e9 100644 --- a/src/uefi_functions.rs +++ b/src/functions.rs @@ -1,4 +1,4 @@ -use crate::uefi_structs::{MemoryDescriptor, Status, TPL}; +use crate::structs::{MemoryDescriptor, Status, TPL}; // Task Priority Services pub type raise_tpl = fn(efi_tpl: TPL) -> Status; @@ -16,4 +16,4 @@ pub type get_memory_map = extern "efiapi" fn( map_key: *mut usize, descriptor_size: *mut usize, descriptor_version: *mut u32, -) -> Status; \ No newline at end of file +) -> Status; diff --git a/src/notes.md b/src/notes.md deleted file mode 100644 index 61004a4..0000000 --- a/src/notes.md +++ /dev/null @@ -1,42 +0,0 @@ -// -// type efi_main = fn(i32) -> i32; - -/* -Step 2: Obtain the Function Pointer - -Assuming you're given a pointer to a table that contains function pointers, you'll first need to safely access this table and the specific function pointer. This is often done by casting the provided pointer to a Rust struct that mirrors the layout of the UEFI table. Here's a simplified example: - -rust - -#[repr(C)] -struct UefiTable { - example_function: *const ExampleFunction, -} - -*/ - -/* -// Assume this is the function signature provided by UEFI. -type GetTime = unsafe extern "efiapi" fn(/* parameters */) -> /* return type */; - -#[repr(C)] -struct RuntimeServices { - // Other fields omitted - get_time: *const GetTime, - // Other fields omitted -} - -fn main() { - let runtime_services: *const RuntimeServices = /* provided by UEFI */; - - unsafe { - if let Some(services) = runtime_services.as_ref() { - if let Some(get_time) = services.get_time.as_ref() { - get_time(/* arguments */); - } - } - } -} -*/ - - diff --git a/src/uefi_os_loader.rs b/src/os_loader.rs similarity index 57% rename from src/uefi_os_loader.rs rename to src/os_loader.rs index 4ddfc72..601ffd1 100644 --- a/src/uefi_os_loader.rs +++ b/src/os_loader.rs @@ -1,18 +1,23 @@ #![no_std] #![no_main] -mod uefi_functions; -mod uefi_structs; -use core::panic::PanicInfo; +pub mod functions; +pub mod structs; +pub mod system_table; +pub mod types; +pub mod boot_services; +pub mod simple_text_output; -use uefi_structs::{Handle, SystemTable}; +use core::panic::PanicInfo; +use system_table::SystemTable; +use types::Handle; #[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 uefi_structs::SimpleTextOutputProtocol = system_table_ref.console_out; + let console_out: *mut structs::SimpleTextOutputProtocol = system_table_ref.console_out; } loop {}; 0 // EFI_SUCCESS @@ -23,5 +28,4 @@ extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut SystemTable #[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 new file mode 100644 index 0000000..d5fdf13 --- /dev/null +++ b/src/simple_text_output.rs @@ -0,0 +1,52 @@ +use crate::structs::Status; +use crate::types::Char16; + +#[repr(C)] +pub struct SimpleTextOutputProtocol {} + +pub type text_reset = + extern "efiapi" fn(this: &SimpleTextOutputProtocol, extended_verification: bool) -> Status; +pub type text_string = + extern "efiapi" fn(this: &SimpleTextOutputProtocol, string: *const Char16) -> Status; +pub type text_test_string = + extern "efiapi" fn(this: &SimpleTextOutputProtocol, string: *const Char16) -> Status; +pub type text_query_mode = extern "efiapi" fn( + this: &SimpleTextOutputProtocol, + mode_number: usize, + column: &mut usize, + rows: &mut usize, +) -> Status; +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; + + +#[repr(C)] +pub enum Attribute { + Black = 0x00 , + Blue = 0x01 , + Green = 0x02 , + Cyan = 0x03 , + Red = 0x04 , + Magenta = 0x05 , + Brown = 0x06 , + LightGray = 0x07 , + Bright = 0x08 , + // DarkGray = 0x08 , + LightBlue = 0x09 , + LightGreen = 0x0a , + LightCyan = 0x0b , + LightRed = 0x0c , + LightMagenta = 0x0d , + Yellow = 0x0e , + White = 0x0f , + // BackgroundBlack = 0x00 , + BackgroundBlue = 0x10 , + BackgroundGreen = 0x20 , + BackgroundCyan = 0x30 , + BackgroundRed = 0x40 , + BackgroundMagenta = 0x50 , + BackgroundBrown = 0x60 , + BackgroundLightGray = 0x70 , +} diff --git a/src/structs.rs b/src/structs.rs new file mode 100644 index 0000000..3b2c742 --- /dev/null +++ b/src/structs.rs @@ -0,0 +1,94 @@ +#[repr(C)] +pub struct TableSignatures; + +impl TableSignatures { + pub const SYSTEM_TABLE_SIGNATURE: u64 = 0x5453595320494249; + pub const BOOT_TABLE_SIGNATURE: u64 = 0x56524553544f4f42; +} + +#[repr(C)] +pub struct RuntimeServicesTable { + efi_table_header: TableHeader, +} + +#[repr(C)] +pub struct ACPIConfigurationTable {} + +#[repr(C)] +pub struct SMBIOSConfigurationTable {} + +#[repr(C)] +pub struct SALSystemTable {} + +#[repr(C)] +pub struct ConfigurationTable {} + +#[repr(C)] +pub struct SimpleTextInputProtocol {} + +#[repr(C)] +pub struct TableHeader { + signature: u64, + revision: u32, + header_size: u32, + crc32: u32, + reserved: u32, +} + +#[repr(C)] +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], +} + +#[repr(C)] +pub struct MemoryDescriptor { + pub type_: u32, + pub physical_start: u64, + pub virtual_start: u64, + pub number_of_pages: u64, + pub attribute: u64, +} diff --git a/src/system_table.rs b/src/system_table.rs new file mode 100644 index 0000000..5218b7f --- /dev/null +++ b/src/system_table.rs @@ -0,0 +1,61 @@ +use crate::boot_services::BootServicesTable; +use crate::structs::*; +use crate::types::Handle; + +#[repr(C)] +pub struct SystemTable { + /// The table header for the EFI System Table. This header contains the EFI_SYSTEM_TABLE_SIGNATURE and EFI_SYSTEM_TABLE_REVISION values along with the size of the EFI_SYSTEM_TABLE structure and a 32-bit CRC to verify that the contents of the EFI System Table are valid. + pub efi_table_header: TableHeader, + /// A pointer to a null terminated string that identifies the vendor that produces the system firmware for the platform. + pub firmware_vendor: *mut u16, + /// A firmware vendor specific value that identifies the revision of the system firmware for the platform. + pub firmware_revision: SystemTableRevisions, + /// The handle for the active console input device. This handle must support EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. If there is no active console, these protocols must still be present. + pub console_in_handle: Handle, + /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is associated with ConsoleInHandle. + pub console_in: *mut SimpleTextInputProtocol, + /// The handle for the active console output device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there is no active console, this protocol must still be present. + pub console_out_handle: Handle, + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle. + pub console_out: *mut SimpleTextOutputProtocol, + /// The handle for the active standard error console device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there is no active console, this protocol must still be present. + pub standard_error_handle: Handle, + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with StandardErrorHandle. + pub standard_error: *mut SimpleTextOutputProtocol, + /// A pointer to the EFI Runtime Services Table. + pub runtime_services_table_pointer: *mut RuntimeServicesTable, + /// A pointer to the EFI Boot Services Table. + pub boot_services_table_pointer: *mut BootServicesTable, + /// The number of system configuration tables in the buffer ConfigurationTable. + pub number_of_table_entries: usize, + /// A pointer to the system configuration tables. The number of entries in the table is NumberOfTableEntries. + pub configuration_table: ConfigurationTable, + // ACPIConfigurationTablePointer: *mut ACPIConfigurationTable, + // SMBIOSConfigurationTable: *mut SMBIOSConfigurationTable, + // SALSystemTable: *mut SALSystemTable +} + +#[repr(C)] +pub struct ImageEntryPoint { + image_handle: *const i32, // The firmware allocated handle for the UEFI image. + 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)); +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..7cf4cbb --- /dev/null +++ b/src/types.rs @@ -0,0 +1,4 @@ +use core; +pub type Handle = *mut core::ffi::c_void; +pub type PhysicalAddress = u64; +pub type Char16 = u16; \ No newline at end of file diff --git a/src/uefi_structs.rs b/src/uefi_structs.rs deleted file mode 100644 index e431aa1..0000000 --- a/src/uefi_structs.rs +++ /dev/null @@ -1,207 +0,0 @@ -use crate::uefi_functions::raise_tpl; - -#[repr(C)] -pub struct ImageEntryPoint { - image_handle: *const i32, // The firmware allocated handle for the UEFI image. - system_table_pointer: *const i32, // A pointer to the EFI System Table. -} - -#[repr(C)] -pub struct TableSignatures; - -impl TableSignatures { - pub const SYSTEM_TABLE_SIGNATURE: u64 = 0x5453595320494249; - pub const BOOT_TABLE_SIGNATURE: u64 = 0x56524553544f4f42; -} - -#[repr(C)] -pub struct SystemTableRevisions; - -impl SystemTableRevisions { - pub const EFI_2_90_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (90)); - pub const EFI_2_80_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (80)); - pub const EFI_2_70_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (70)); - pub const EFI_2_60_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (60)); - pub const EFI_2_50_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (50)); - pub const EFI_2_40_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (40)); - pub const EFI_2_31_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (31)); - pub const EFI_2_30_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (30)); - pub const EFI_2_20_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (20)); - pub const EFI_2_10_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (10)); - pub const EFI_2_00_SYSTEM_TABLE_REVISION: u32 = ((2 << 16) | (00)); - pub const EFI_1_10_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (10)); - pub const EFI_1_02_SYSTEM_TABLE_REVISION: u32 = ((1 << 16) | (02)); -} - -/** -UEFI uses the EFI System Table, which contains pointers to the runtime and boot services tables. The -definition for this table is shown in the following code fragments. Except for the table header, all -elements in the service tables are pointers to functions as defined in Section 7 and Section 8. Prior to a -call to EFI_BOOT_SERVICES.ExitBootServices(), all of the fields of the EFI System Table are valid. -After an operating system has taken control of the platform with a call to ExitBootServices(), only -the Hdr, FirmwareVendor, FirmwareRevision, RuntimeServices, NumberOfTableEntries, -and ConfigurationTable fields are valid - **/ -#[repr(C)] -pub struct SystemTable { - /// The table header for the EFI System Table. This header contains the EFI_SYSTEM_TABLE_SIGNATURE and EFI_SYSTEM_TABLE_REVISION values along with the size of the EFI_SYSTEM_TABLE structure and a 32-bit CRC to verify that the contents of the EFI System Table are valid. - pub efi_table_header: TableHeader, - /// A pointer to a null terminated string that identifies the vendor that produces the system firmware for the platform. - pub firmware_vendor: *mut u16, - /// A firmware vendor specific value that identifies the revision of the system firmware for the platform. - pub firmware_revision: SystemTableRevisions, - /// The handle for the active console input device. This handle must support EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. If there is no active console, these protocols must still be present. - pub console_in_handle: Handle, - /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is associated with ConsoleInHandle. - pub console_in: *mut SimpleTextInputProtocol, - /// The handle for the active console output device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there is no active console, this protocol must still be present. - pub console_out_handle: Handle, - /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle. - pub console_out: *mut SimpleTextOutputProtocol, - /// The handle for the active standard error console device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there is no active console, this protocol must still be present. - pub standard_error_handle: Handle, - /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with StandardErrorHandle. - pub standard_error: *mut SimpleTextOutputProtocol, - /// A pointer to the EFI Runtime Services Table. - pub runtime_services_table_pointer: *mut RuntimeServicesTable, - /// A pointer to the EFI Boot Services Table. - pub boot_services_table_pointer: *mut BootServicesTable, - /// The number of system configuration tables in the buffer ConfigurationTable. - pub number_of_table_entries: usize, - /// A pointer to the system configuration tables. The number of entries in the table is NumberOfTableEntries. - pub configuration_table: ConfigurationTable, - // ACPIConfigurationTablePointer: *mut ACPIConfigurationTable, - // SMBIOSConfigurationTable: *mut SMBIOSConfigurationTable, - // SALSystemTable: *mut SALSystemTable -} - -/** - UEFI uses the EFI Boot Services Table, which contains a table header and pointers to all of the boot - services. The definition for this table is shown in the following code fragments. Except for the table - header, all elements in the EFI Boot Services Tables are prototypes of function pointers to functions as - defined in Section 7. The function pointers in this table are not valid after the operating system has taken - control of the platform with a call to EFI_BOOT_SERVICES.ExitBootServices(). -**/ -#[repr(C)] -pub struct BootServicesTable { - efi_table_header: TableHeader, - load_image: extern "efiapi" fn(boot_policy: bool, parent_image_hanle: Handle), -} - -#[repr(C)] -pub struct RuntimeServicesTable { - efi_table_header: TableHeader, -} - -#[repr(C)] -pub struct ACPIConfigurationTable {} - -#[repr(C)] -pub struct SMBIOSConfigurationTable {} - -#[repr(C)] -pub struct SALSystemTable {} - -#[repr(C)] -pub struct ConfigurationTable {} - -#[repr(C)] -pub struct Handle {} - -#[repr(C)] -pub struct SimpleTextInputProtocol {} - -#[repr(C)] -pub struct SimpleTextOutputProtocol {} - -// TODO: -/* -Signature A 64-bit signature that identifies the type of table that follows. -Unique signatures have been generated for the EFI System Table, the -EFI Boot Services Table, and the EFI Runtime Services Table. -Revision The revision of the EFI Specification to which this table conforms. -The upper 16 bits of this field contain the major revision value, and -the lower 16 bits contain the minor revision value. The minor -revision values are binary coded decimals and are limited to the -range of 00..99. -When printed or displayed UEFI spec revision is referred as (Major -revision).(Minor revision upper decimal).(Minor revision lower -decimal) or (Major revision).(Minor revision upper decimal) in case -Minor revision lower decimal is set to 0. For example: -A specification with the revision value ((2<<16) | (30)) would be -referred as 2.3; -A specification with the revision value ((2<<16) | (31)) would be -referred as 2.3.1 -HeaderSize The size, in bytes, of the entire table including the -EFI_TABLE_HEADER. -CRC32 The 32-bit CRC for the entire table. This value is computed by setting -this field to 0, and computing the 32-bit CRC for HeaderSize bytes. -Reserved Reserved field that must be set to 0. -*/ - -#[repr(C)] -pub struct TableHeader { - signature: u64, - revision: u32, - header_size: u32, - crc32: u32, - reserved: u32, -} - -#[repr(C)] -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], -} - -#[repr(C)] -pub struct MemoryDescriptor { - pub type_: u32, - pub physical_start: u64, - pub virtual_start: u64, - pub number_of_pages: u64, - pub attribute: u64, -} diff --git a/src/uefi_types.rs b/src/uefi_types.rs deleted file mode 100644 index 5968bed..0000000 --- a/src/uefi_types.rs +++ /dev/null @@ -1,3 +0,0 @@ -use core; -pub type Handle = *mut core::ffi::c_void; -pub type PhysicalAddress = u64; \ No newline at end of file