From 76103215711d268b4b02f62e900f2be3032cf295 Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 02:18:30 +0200 Subject: Initial commit: raisernics toy kernel - Bare-metal x86_64 UEFI kernel (PE32+, no libc) - GOP framebuffer + 8x16 bitmap font - PS/2 keyboard (polling, scancode set 1) - UART 16550 serial driver (COM1, 115200 8N1) - Bump allocator as #[global_allocator] (alloc::String, Vec, format!) - UEFI memory map capture (static buffer, ADR 0001) - Shell with 7 commands (help, echo, clear, hello, info, mem, halt) - Dual output: GOP framebuffer + serial console - Makefile: run, run-gui, debug, release, image targets - tools/: qemu.sh, boot-image.sh, debug-kernel.py --- src/uefi.rs | 289 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 src/uefi.rs (limited to 'src/uefi.rs') diff --git a/src/uefi.rs b/src/uefi.rs new file mode 100644 index 0000000..2e3ed6b --- /dev/null +++ b/src/uefi.rs @@ -0,0 +1,289 @@ +use core::ffi::c_void; + +/// Opaque EFI handle +pub type Handle = *mut c_void; + +/// EFI status (0 = success, bit 63 = error code) +pub type Status = u64; + +/// Helper: UEFI error codes always have bit 63 set +const fn efi_err(n: u64) -> u64 { + n | (1u64 << 63) +} + +pub const EFI_SUCCESS: Status = 0; +pub const EFI_LOAD_ERROR: Status = efi_err(1); +pub const EFI_INVALID_PARAMETER: Status = efi_err(2); +#[allow(dead_code)] +pub const EFI_UNSUPPORTED: Status = efi_err(3); +pub const EFI_BUFFER_TOO_SMALL: Status = efi_err(5); +#[allow(dead_code)] +pub const EFI_NOT_FOUND: Status = efi_err(14); +pub const EFI_OUT_OF_RESOURCES: Status = efi_err(9); + +// --------------------------------------------------------------------------- +// GUID +// --------------------------------------------------------------------------- +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct Guid { + pub a: u32, + pub b: u16, + pub c: u16, + pub d: [u8; 8], +} + +pub const EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID: Guid = Guid { + a: 0x9042a9de, + b: 0x23dc, + c: 0x4a38, + d: [0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a], +}; + +// --------------------------------------------------------------------------- +// Table header +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct TableHeader { + pub signature: u64, + pub revision: u32, + pub header_size: u32, + pub crc32: u32, + pub reserved: u32, +} + +// --------------------------------------------------------------------------- +// Simple text output protocol (console output) +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct SimpleTextOutput { + _reset: *mut c_void, + pub output_string: unsafe extern "efiapi" fn(*mut SimpleTextOutput, *const u16) -> Status, + _test_string: *mut c_void, + _query_mode: *mut c_void, + _set_mode: *mut c_void, + _set_attribute: *mut c_void, + _clear_screen: *mut c_void, + _set_cursor_position: *mut c_void, + _enable_cursor: *mut c_void, + _mode: *mut c_void, +} + +// --------------------------------------------------------------------------- +// Simple text input protocol (keyboard input) +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct InputKey { + pub scan_code: u16, + pub unicode_char: u16, +} + +#[repr(C)] +pub struct SimpleTextInput { + _reset: *mut c_void, + pub read_key_stroke: unsafe extern "efiapi" fn(*mut SimpleTextInput, *mut InputKey) -> Status, + _wait_for_key: Handle, +} + +// --------------------------------------------------------------------------- +// Runtime services (stub — we don't use them) +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct RuntimeServices { + _hdr: TableHeader, + _reserved: [*mut c_void; 30], +} + +// --------------------------------------------------------------------------- +// Configuration table entry +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct ConfigurationTable { + pub vendor_guid: Guid, + pub vendor_table: *mut c_void, +} + +// --------------------------------------------------------------------------- +/// UEFI memory descriptor (from GetMemoryMap) +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct MemoryDescriptor { + pub kind: u32, + pub pad: u32, + pub physical_start: u64, + pub virtual_start: u64, + pub number_of_pages: u64, + pub attribute: u64, +} + +pub const MEMORY_TYPE_CONVENTIONAL: u32 = 7; +#[allow(dead_code)] +pub const MEMORY_TYPE_LOADER_DATA: u32 = 6; +#[allow(dead_code)] +pub const MEMORY_TYPE_BOOT_SERVICES_CODE: u32 = 3; +#[allow(dead_code)] +pub const MEMORY_TYPE_BOOT_SERVICES_DATA: u32 = 4; + +// --------------------------------------------------------------------------- +// Boot services table +// --------------------------------------------------------------------------- +pub type EfiGetMemoryMap = unsafe extern "efiapi" fn( + *mut usize, + *mut MemoryDescriptor, + *mut usize, + *mut usize, + *mut u32, +) -> Status; + +pub type EfiExitBootServices = unsafe extern "efiapi" fn(Handle, usize) -> Status; + +pub type EfiHandleProtocol = + unsafe extern "efiapi" fn(Handle, *const Guid, *mut *mut c_void) -> Status; + +pub type EfiLocateProtocol = + unsafe extern "efiapi" fn(*const Guid, *mut c_void, *mut *mut c_void) -> Status; + +pub type EfiAllocatePool = unsafe extern "efiapi" fn(u8, usize, *mut *mut c_void) -> Status; + +pub type EfiFreePool = unsafe extern "efiapi" fn(*mut c_void) -> Status; + +pub type EfiStall = unsafe extern "efiapi" fn(usize) -> Status; + +#[repr(C)] +pub struct BootServices { + pub hdr: TableHeader, + + // 0-1: task priority + pub raise_tpl: *mut c_void, + pub restore_tpl: *mut c_void, + + // 2-3: memory allocation + pub allocate_pages: *mut c_void, + pub free_pages: *mut c_void, + + // 4: GetMemoryMap + pub get_memory_map: EfiGetMemoryMap, + + // 5-6: pool + pub allocate_pool: EfiAllocatePool, + pub free_pool: EfiFreePool, + + // 7-12: events + pub create_event: *mut c_void, + pub set_timer: *mut c_void, + pub wait_for_event: *mut c_void, + pub signal_event: *mut c_void, + pub close_event: *mut c_void, + pub check_event: *mut c_void, + + // 13-14: protocol install + pub install_protocol_interface: *mut c_void, + pub reinstall_protocol_interface: *mut c_void, + pub uninstall_protocol_interface: *mut c_void, + + // 16: HandleProtocol + pub handle_protocol: EfiHandleProtocol, + + pub _reserved: *mut c_void, + + // 18: register protocol notify + pub register_protocol_notify: *mut c_void, + + // 19-21: locate + pub locate_handle: *mut c_void, + pub locate_device_path: *mut c_void, + pub install_configuration_table: *mut c_void, + + // 22-23: image loading + pub load_image: *mut c_void, + pub start_image: *mut c_void, + + // 24-25 + pub exit: *mut c_void, + pub unload_image: *mut c_void, + + // 26: ExitBootServices + pub exit_boot_services: EfiExitBootServices, + + // 27-29 + pub get_next_monotonic_count: *mut c_void, + pub stall: EfiStall, + pub set_watchdog_timer: *mut c_void, + + // 30-36 + pub connect_controller: *mut c_void, + pub disconnect_controller: *mut c_void, + pub open_protocol: *mut c_void, + pub close_protocol: *mut c_void, + pub open_protocol_information: *mut c_void, + pub protocols_per_handle: *mut c_void, + pub locate_handle_buffer: *mut c_void, + + // 37: LocateProtocol + pub locate_protocol: EfiLocateProtocol, + + // 38-43 + pub install_multiple_protocol_interfaces: *mut c_void, + pub uninstall_multiple_protocol_interfaces: *mut c_void, + pub calculate_crc32: *mut c_void, + pub copy_mem: *mut c_void, + pub set_mem: *mut c_void, + pub create_event_ex: *mut c_void, +} + +// --------------------------------------------------------------------------- +// Graphics Output Protocol (GOP) +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct GopModeInfo { + pub version: u32, + pub horizontal_resolution: u32, + pub vertical_resolution: u32, + pub pixel_format: u32, // PixelFormat enum + pub red_mask: u32, + pub green_mask: u32, + pub blue_mask: u32, + pub reserved_mask: u32, + pub pixels_per_scan_line: u32, +} + +pub const PIXEL_RGB: u32 = 0; +pub const PIXEL_BGR: u32 = 1; + +#[repr(C)] +pub struct GopMode { + pub max_mode: u32, + pub mode: u32, + pub info: *mut GopModeInfo, + pub info_size: usize, + pub framebuffer_base: *mut c_void, + pub framebuffer_size: usize, +} + +#[repr(C)] +pub struct GraphicsOutputProtocol { + pub query_mode: *mut c_void, + pub set_mode: *mut c_void, + pub get_current_mode: *mut c_void, + pub mode: *mut GopMode, +} + +// --------------------------------------------------------------------------- +// System table +// --------------------------------------------------------------------------- +#[repr(C)] +pub struct SystemTable { + pub hdr: TableHeader, + pub firmware_vendor: *const u16, + pub firmware_revision: u32, + pub console_in_handle: Handle, + pub con_in: *mut SimpleTextInput, + pub console_out_handle: Handle, + pub con_out: *mut SimpleTextOutput, + pub stderr_handle: Handle, + pub std_err: *mut SimpleTextOutput, + pub runtime_services: *mut RuntimeServices, + pub boot_services: *mut BootServices, + pub number_of_table_entries: usize, + pub configuration_table: *const ConfigurationTable, +} -- cgit v1.2.3