From aa113b17449e67dbd808587b411aeb21ea869974 Mon Sep 17 00:00:00 2001 From: andromeda Date: Mon, 19 Oct 2026 18:54:26 -0400 Subject: minimal running stub --- .gitignore | 1 + README.md | 1 + lib/uefi.c3l/LICENSE | 21 -- lib/uefi.c3l/README.md | 77 ------- lib/uefi.c3l/extension/console.c3 | 18 ++ lib/uefi.c3l/extension/file.c3 | 22 ++ lib/uefi.c3l/manifest.json | 33 +-- lib/uefi.c3l/src/def.c3i | 221 ------------------- lib/uefi.c3l/src/err.c3 | 129 ------------ lib/uefi.c3l/src/exports.c3 | 216 ------------------- lib/uefi.c3l/src/guid.c3 | 82 -------- lib/uefi.c3l/src/lib/console.c3 | 132 ------------ lib/uefi.c3l/src/lib/init.c3 | 92 -------- lib/uefi.c3l/src/lib/input.c3 | 36 ---- lib/uefi.c3l/src/lib/private/print.c3 | 159 -------------- lib/uefi.c3l/src/lib/string.c3 | 145 ------------- lib/uefi.c3l/src/lib/system.c3 | 268 ------------------------ lib/uefi.c3l/src/lib/util.c3 | 19 -- lib/uefi.c3l/src/protocol/console.c3 | 225 -------------------- lib/uefi.c3l/src/protocol/evt_timer_task.c3 | 103 --------- lib/uefi.c3l/src/protocol/handler.c3 | 86 -------- lib/uefi.c3l/src/protocol/image.c3 | 27 --- lib/uefi.c3l/src/protocol/mem.c3 | 105 ---------- lib/uefi.c3l/src/protocol/misc_boot_svcs.c3 | 25 --- lib/uefi.c3l/src/protocol/misc_runtime_svcs.c3 | 124 ----------- lib/uefi.c3l/src/protocol/time.c3 | 23 -- lib/uefi.c3l/src/protocol/variable.c3 | 68 ------ lib/uefi.c3l/uefi/guid.c3i | 29 +++ lib/uefi.c3l/uefi/protocol/console.c3i | 173 +++++++++++++++ lib/uefi.c3l/uefi/protocol/file.c3i | 59 ++++++ lib/uefi.c3l/uefi/protocol/image.c3i | 23 ++ lib/uefi.c3l/uefi/protocol/services/boot.c3i | 86 ++++++++ lib/uefi.c3l/uefi/protocol/services/mem.c3i | 36 ++++ lib/uefi.c3l/uefi/protocol/services/runtime.c3i | 36 ++++ lib/uefi.c3l/uefi/protocol/services/time.c3i | 31 +++ lib/uefi.c3l/uefi/status.c3i | 174 +++++++++++++++ lib/uefi.c3l/uefi/uefi.c3i | 59 ++++++ main.c3 | 9 +- project.json | 19 +- scripts/copy-uefi-c3l.sh | 4 +- scripts/run.sh | 25 +++ 41 files changed, 798 insertions(+), 2423 deletions(-) create mode 100644 README.md delete mode 100644 lib/uefi.c3l/LICENSE delete mode 100644 lib/uefi.c3l/README.md create mode 100644 lib/uefi.c3l/extension/console.c3 create mode 100644 lib/uefi.c3l/extension/file.c3 delete mode 100644 lib/uefi.c3l/src/def.c3i delete mode 100644 lib/uefi.c3l/src/err.c3 delete mode 100644 lib/uefi.c3l/src/exports.c3 delete mode 100644 lib/uefi.c3l/src/guid.c3 delete mode 100644 lib/uefi.c3l/src/lib/console.c3 delete mode 100644 lib/uefi.c3l/src/lib/init.c3 delete mode 100644 lib/uefi.c3l/src/lib/input.c3 delete mode 100644 lib/uefi.c3l/src/lib/private/print.c3 delete mode 100644 lib/uefi.c3l/src/lib/string.c3 delete mode 100644 lib/uefi.c3l/src/lib/system.c3 delete mode 100644 lib/uefi.c3l/src/lib/util.c3 delete mode 100644 lib/uefi.c3l/src/protocol/console.c3 delete mode 100644 lib/uefi.c3l/src/protocol/evt_timer_task.c3 delete mode 100644 lib/uefi.c3l/src/protocol/handler.c3 delete mode 100644 lib/uefi.c3l/src/protocol/image.c3 delete mode 100644 lib/uefi.c3l/src/protocol/mem.c3 delete mode 100644 lib/uefi.c3l/src/protocol/misc_boot_svcs.c3 delete mode 100644 lib/uefi.c3l/src/protocol/misc_runtime_svcs.c3 delete mode 100644 lib/uefi.c3l/src/protocol/time.c3 delete mode 100644 lib/uefi.c3l/src/protocol/variable.c3 create mode 100644 lib/uefi.c3l/uefi/guid.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/console.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/file.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/image.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/services/boot.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/services/mem.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/services/runtime.c3i create mode 100644 lib/uefi.c3l/uefi/protocol/services/time.c3i create mode 100644 lib/uefi.c3l/uefi/status.c3i create mode 100644 lib/uefi.c3l/uefi/uefi.c3i create mode 100755 scripts/run.sh diff --git a/.gitignore b/.gitignore index 5b04841..a508176 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/ out/ build/ out/ +disk.qcow2 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f6c11a8 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +./lib/uefi.c3l from boson-bootloader diff --git a/lib/uefi.c3l/LICENSE b/lib/uefi.c3l/LICENSE deleted file mode 100644 index e3cd020..0000000 --- a/lib/uefi.c3l/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Zack Puhl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/uefi.c3l/README.md b/lib/uefi.c3l/README.md deleted file mode 100644 index f9cb4e3..0000000 --- a/lib/uefi.c3l/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# uefi.c3l - UEFI Definitions & Library for C3 -A gnu-efi-like library enabling UEFI bootloader development in C3. - - -## Installation -The library is incredibly easy to pull and use right away. - -1. Change to your project's `lib` directory. -2. Clone this repository: `git clone https://github.com/NotsoanoNimus/uefi.c3l.git`. -3. Start developing with `import uefi;` where needed. - -Most c3c projects will automatically source modules from their `lib` folders. If this is not the case, you can use the following `c3c` parameters to source the library: `--lib uefi --libdir lib/` - -This will certainly be improved as the project becomes more mature. - - -## Compiling EFI Binaries -I need to revisit this, but I have been successfully compiling my EFI test binaries with the following: -``` -~$ c3c compile-only src/*.c3 --link-libc=no --no-entry \ - --target windows-x64 --lib uefi --libdir ./lib - -~$ clang -target x86_64-unknown-windows -nostdlib -fno-stack-protector -mno-red-zone \ - -ffreestanding -fPIC -Wl,-entry:efi_main -Wl,-subsystem:efi_application \ - -fuse-ld=lld-link -mno-stack-arg-probe -v -o test.efi ./obj/windows-x64/*.obj -``` - -I'm pretty sure I'm switching up my compilation and linker arguments for this right now. :shrug: Again, to be improved as the project matures. - -This snippet explicitly uses `clang` and `lld-link` in order to generate the EFI application. For me, it's a must; however, others may be more comfortable linking with another tool like `gcc`. It's all the same after `c3c` generates its objects. - - -## Example Usage -The following example shows what a "Hello World" style EFI application might look like in C3. When it starts, it sets a baseline console color, clears the window, and attempts to enable the Graphics Output Protocol and draw a simple rectangle. - -Some of these methods currently don't exist; this is more of a "finished product" presentation. - - -```cpp -module hello_uefi; - -import uefi; - - -fn EfiStatus efi_main(EfiHandle image_handle, SystemTable* system_table) @export("efi_main") -{ - pre_load::init(image_handle, system_table)!!; - - console::clear_to({YELLOW, RED}); - - io::cprintn(@wstring("Enabling GOP mode..."), {GREEN, BLACK})!!; - - if (catch excuse = sys::enable_gop()) { - io::cprintn(@wstring("ERROR: Failed to initialize Graphics Output Protocol."), {RED, BLACK})!!; - } else { - gop::draw_rect( - {0, 0, 100, 200}, - {{0xff, 0x12, 0x34, 0x56}, {.a = 0xff, .r = 0xdd}} /* {r,g,b,a} */ - ); - } - - sys::@stall(s2us(3)); /* s2us == sec-to-microsec */ - sys::@reset(SHUTDOWN); -} - -``` - - -## TODOs -In no particular order... -- [ ] Finish C3 standard library integration, to provide helpful constructs like String formatting and such. -- [ ] Implement all macro exports for System, Console, etc. -- [ ] Organize library imports such that `uefi` isn't just bulk-imported everywhere. -- [ ] Unit/Integration testing. - - Not sure if this will require a mock UEFI environment, or if it will need to be on a function-by-function basis. We'll see. -- [ ] Graphics library support and support functions . - - [ ] e.g. an optional BLT-based framebuffer lib. diff --git a/lib/uefi.c3l/extension/console.c3 b/lib/uefi.c3l/extension/console.c3 new file mode 100644 index 0000000..07f2c14 --- /dev/null +++ b/lib/uefi.c3l/extension/console.c3 @@ -0,0 +1,18 @@ +module uefi::protocol::console; + +macro SimpleTextOutputProtocol.clear_screen(&self) => self._clear_screen(self); +macro SimpleTextOutputProtocol.@output_string(&self, #string) { + $switch ($Typeof(#string)): + $case EfiString: + return self._output_string(self, #string); + $case WString: + return self._output_string(self, (EfiString)#string); + $case String: + return self._output_string(self, (EfiString)&&$$wstr16(#string)); + $default: + $echo($Typeof(#string)); + $error("Unknown string type for @output_string"); + $endswitch +} + +macro SimpleTextInputProtocol.read_key(&self, EfiInputKey* key) => self._read_key(self, key); diff --git a/lib/uefi.c3l/extension/file.c3 b/lib/uefi.c3l/extension/file.c3 new file mode 100644 index 0000000..1e40e83 --- /dev/null +++ b/lib/uefi.c3l/extension/file.c3 @@ -0,0 +1,22 @@ +module uefi::protocol::file; + +macro FileProtocol.open(&self, FileProtocol** newHandle, WChar* fileName, FileOpenMode openMode, ulong attributes) + => self._open(self, newHandle, fileName, openMode, attributes); + +macro FileProtocol.close(&self) => self._close(self); +macro FileProtocol.delete(&self) => self._delete(self); +macro FileProtocol.read(&self, usz* bufSize, void* buf) => self._read(self, bufSize, buf); +macro FileProtocol.write(&self, usz* bufSize, void* buf) => self._write(self, bufSize, buf); +macro FileProtocol.get_position(&self, ulong* pos) => self._get_position(self, pos); +macro FileProtocol.set_position(&self, ulong pos) => self._set_position(self, pos); +macro FileProtocol.get_info(&self, EfiGuid* infoType, usz* bufSize, void* buf) => self._get_info(self, infoType, bufSize, buf); +macro FileProtocol.set_info(&self, EfiGuid* infoType, usz bufSize, void* buf) => self._set_info(self, infoType, bufSize, buf); +macro FileProtocol.flush(&self) => self._flush(self); + +macro FileSystemProtocol.open_volume(&self, FileProtocol** fileProt) => self._open_volume(self, fileProt); + +constdef FileOpenMode : inline ulong { + CREATE = 0, + READ = 1, + WRITE = 2, +} diff --git a/lib/uefi.c3l/manifest.json b/lib/uefi.c3l/manifest.json index 1f5f60b..c807cfa 100644 --- a/lib/uefi.c3l/manifest.json +++ b/lib/uefi.c3l/manifest.json @@ -1,27 +1,10 @@ { - "provides" : "uefi", - "sources" : [ "src/**" ], - "targets" : { - "openbsd-x64" : { - "link-args" : [], - "dependencies" : [], - "linked-libraries" : [], - }, - "windows-aarch64" : { - // Extra flags to the linker for this target: - "link-args" : [], - // C3 libraries this target depends on: - "dependencies" : [], - // The external libraries to link for this target: - "linked-libraries" : [] - }, - "windows-x64" : { - // Extra flags to the linker for this target: - "link-args" : [ "-nostdlib", "-ffreestanding" ], - // C3 libraries this target depends on: - "dependencies" : [], - // The external libraries to link for this target: - "linked-libraries" : [] - }, - } + "provides": "uefi", + "sources": [ + "uefi/**", + "extension/**" + ], + "targets": { + "windows-x64": {} + } } diff --git a/lib/uefi.c3l/src/def.c3i b/lib/uefi.c3l/src/def.c3i deleted file mode 100644 index 769f15e..0000000 --- a/lib/uefi.c3l/src/def.c3i +++ /dev/null @@ -1,221 +0,0 @@ -module uefi; - - -/** EFI_HANDLE alias (sec x.x.x of the UEFI 2.11 specification). */ -typedef EfiHandle = void*; - -/** All UEFI strings are wchar_t strings (Wide-Char types). */ -alias EfiString = ushort[]; -alias EfiStringRaw = ushort*; - -/** ... But ASCII strings can also be used and dynamically converted to wide ones. */ -alias AsciiString = char[]; -alias AsciiStringRaw = char*; - -/** EFI_EVENT alias (sec 7.1.1 of the UEFI 2.11 specification). */ -typedef EfiEvent = void*; - - -/** EFI_TABLE_HEADER structure (sec 4.2.1 of the UEFI 2.11 specification). - * The same section contains the following constant expressions - * as well as the EFI_SYSTEM_TABLE structure. */ -struct EfiTableHeader @packed -{ - ulong signature; - uint revision; - uint header_size; - uint crc32; - uint _reserved; -} - -const ulong EFI_SYSTEM_TABLE_SIGNATURE = 0x5453595320494249; -const uint EFI_2_100_SYSTEM_TABLE_REVISION = ((2 << 16) | (100)); -const uint EFI_2_90_SYSTEM_TABLE_REVISION = ((2 << 16) | (90)); -const uint EFI_2_80_SYSTEM_TABLE_REVISION = ((2 << 16) | (80)); -const uint EFI_2_70_SYSTEM_TABLE_REVISION = ((2 << 16) | (70)); -const uint EFI_2_60_SYSTEM_TABLE_REVISION = ((2 << 16) | (60)); -const uint EFI_2_50_SYSTEM_TABLE_REVISION = ((2 << 16) | (50)); -const uint EFI_2_40_SYSTEM_TABLE_REVISION = ((2 << 16) | (40)); -const uint EFI_2_31_SYSTEM_TABLE_REVISION = ((2 << 16) | (31)); -const uint EFI_2_30_SYSTEM_TABLE_REVISION = ((2 << 16) | (30)); -const uint EFI_2_20_SYSTEM_TABLE_REVISION = ((2 << 16) | (20)); -const uint EFI_2_10_SYSTEM_TABLE_REVISION = ((2 << 16) | (10)); -const uint EFI_2_00_SYSTEM_TABLE_REVISION = ((2 << 16) | (00)); -const uint EFI_1_10_SYSTEM_TABLE_REVISION = ((1 << 16) | (10)); -const uint EFI_1_02_SYSTEM_TABLE_REVISION = ((1 << 16) | (02)); -const uint EFI_SYSTEM_TABLE_REVISION = EFI_2_100_SYSTEM_TABLE_REVISION; -const uint EFI_SPECIFICATION_VERSION = EFI_SYSTEM_TABLE_REVISION; - -/* NOTE: Do NOT pack this struct: firmware_revision being 32-bit causes misalignment */ -struct SystemTable -{ - EfiTableHeader header; - EfiStringRaw firmware_vendor; - uint firmware_revision; - EfiHandle conin_handle; - SimpleTextInputProtocol* conin; - EfiHandle conout_handle; - SimpleTextOutputProtocol* conout; - EfiHandle conerr_handle; - SimpleTextOutputProtocol* conerr; - RuntimeServices* runtime_services; - BootServices* boot_services; - usz num_entries; - ConfigurationTable* configuration_table; -} - - -/** EFI_CONFIGURATION_TABLE structure (sec 4.6.1 of the UEFI 2.11 specification). */ -struct ConfigurationTable @packed -{ - EfiGuid vendor_guid; - void* vendor_table; -} - - -/* EFI_BOOT_SERVICES structure (4.4.1) */ -const ulong EFI_BOOT_SERVICES_SIGNATURE = 0x56524553544f4f42; // 'BOOTSERV' <- EightCC -const uint EFI_BOOT_SERVICES_REVISION = EFI_SPECIFICATION_VERSION; - -struct BootServices @packed -{ - EfiTableHeader header; - - /* Task priority services (uefi::proto::evt) */ - FnRaiseTpl raise_tpl; - FnRestoreTpl restore_tpl; - - /* Memory services (uefi::proto::mem) */ - FnAllocatePages allocate_pages; - FnFreePages free_pages; - FnGetMemoryMap get_memory_map; - FnAllocatePool allocate_pool; - FnFreePool free_pool; - - /* Event and Timer services (uefi::proto::evt) */ - FnCreateEvent create_event; - FnSetTimer set_timer; - FnWaitForEvent wait_for_event; - FnSignalEvent signal_event; - FnCloseEvent close_event; - FnCheckEvent check_event; - - /* Protocol Handler services (uefi::proto::handler) */ - FnInstallProtocolInterface install_protocol_interface; - FnReinstallProtocolInterface reinstall_protocol_interface; - FnUninstallProtocolInterface uninstall_protocol_interface; - FnHandleProtocol handle_protocol; - void* _reserved; /* alright then */ - FnRegisterProtocolNotify register_protocol_notify; - FnLocateHandle locate_handle; - FnLocateDevicePath locate_device_path; - FnInstallConfigurationTable install_configuration_table; - - /* Image services (uefi::proto::image) */ - FnLoadImage load_image; - FnStartImage start_image; - FnExitImage exit_image; - FnUnloadImage unload_image; - FnExitBootServices exit_boot_services; - - /* Misc services (uefi::proto::misc_bs) */ - FnGetNextMonotonicCount get_next_monotonic_count; - FnStall stall; - FnSetWatchdogTimer set_watchdog_timer; - - /* Driver Support services (uefi::proto::handler) */ - FnConnectController connect_controller; - FnDisconnectController disconnect_controller; - - /* Open/Close Protocol services (uefi::proto::handler) */ - FnOpenProtocol open_protocol; - FnCloseProtocol close_protocol; - FnOpenProtocolInformation open_protocol_information; - - /* Library services (uefi::proto::handler) */ - FnProtocolsPerHandle protocols_per_handle; - FnLocateHandleBuffer locate_handle_buffer; - FnLocateProtocol locate_protocol; - FnInstallMultipleProtocolInterfaces install_multiple_protocol_interfaces; - FnUninstallMultipleProtocolInterfaces uninstall_multiple_protocol_interfaces; - - /* 32-bit CRC services (uefi::proto::misc_bs) */ - FnCalculateCrc32 calculate_crc32; - - /* More misc/trailing services */ - FnCopyMem copy_mem; - FnSetMem set_mem; - FnCreateEventEx create_event_ex; -} - - -struct RuntimeServices @packed -{ - EfiTableHeader header; - - /* Time services (uefi::proto::time) */ - FnGetTime get_time; - FnSetTime set_time; - FnGetWakeupTime get_wakeup_time; - FnSetWakeupTime set_wakeup_time; - - /* Virtual Memory services (uefi::proto::mem) */ - FnSetVirtualAddressMap set_virtual_address_map; - FnConvertPointer convert_pointer; - - /* Variable services (uefi::proto::variable) */ - FnGetVariable get_variable; - FnGetNextVariableName get_next_variable_name; - FnSetVariable set_variable; - - /* Miscellaneous and Capsule services (uefi::proto::misc_rt) */ - FnGetNextHighMonotonicCount get_next_high_monotonic_count; - FnResetSystem reset_system; - FnUpdateCapsule update_capsule; - FnQueryCapsuleCapabilities query_capsule_capabilities; - FnQueryVariableInfo query_variable_info; -} - - -/** EFI_GUID structure (sec x.x.x of the UEFI 2.11 specification). */ -struct EfiGuid @packed -{ - uint data1; - ushort data2; - ushort data3; - char[8] data4; -} - - -/** EFI_TIME structure (sec 8.3.1 of the UEFI 2.11 specification). */ -struct EfiTime @packed -{ - ushort year; - char month; - char day; - char hour; - char minute; - char second; - char _pad1; - uint nanosecond; - short timezone; - EfiDaylightFlags daylight; - char _pad2; -} - -bitstruct EfiDaylightFlags : char -{ - bool adjust : 0; - bool in_daylight : 1; - char reserved : 2..7; -} - -const short EFI_UNSPECIFIED_TIMEZONE = 0x07FF; - -/** EFI_TIME_CAPABILITIES (sec 8.3.1 of the UEFI 2.11 specification). */ -struct EfiTimeCapabilities @packed -{ - uint resolution; - uint accuracy; - bool sets_to_zero; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/err.c3 b/lib/uefi.c3l/src/err.c3 deleted file mode 100644 index d21729b..0000000 --- a/lib/uefi.c3l/src/err.c3 +++ /dev/null @@ -1,129 +0,0 @@ -/* EFI errors can actually be faults: they should raise exceptions - in the handling of a program, if the user so chooses to. */ -module uefi::efi_error; -faultdef - NO_FAULT, - LOAD_ERROR, - INVALID_PARAMETER, - UNSUPPORTED, - BAD_BUFFER_SIZE, - BUFFER_TOO_SMALL, - NOT_READY, - DEVICE_ERROR, - WRITE_PROTECTED, - OUT_OF_RESOURCES, - VOLUME_CORRUPTED, - VOLUME_FULL, - NO_MEDIA, - MEDIA_CHANGED, - NOT_FOUND, - ACCESS_DENIED, - NO_RESPONSE, - NO_MAPPING, - TIMEOUT, - NOT_STARTED, - ALREADY_STARTED, - ABORTED, - ICMP_ERROR, - TFTP_ERROR, - PROTOCOL_ERROR, - INCOMPATIBLE_VERSION, - SECURITY_VIOLATION, - CRC_ERROR, - END_OF_MEDIA, - UNKNOWN_29, // NOTE: UEFI spec is missing this definition. - UNKNOWN_30, // NOTE: UEFI spec is missing this definition. - END_OF_FILE, - INVALID_LANGUAGE, - COMPROMISED_DATA, - IP_ADDRESS_CONFLICT, - HTTP_ERROR, - EFILIB_UNINITIALIZED, // Used for efilib calls when init() hasn't been called. - UNKNOWN_STATUS; /* Fallback for an unknown status code. */ - -module uefi::efi_warning; -faultdef - UNKNOWN_GLYPH, DELETE_FAILURE, WRITE_FAILURE, BUFFER_TOO_SMALL, STALE_DATA, FILE_SYSTEM, RESET_REQUIRED; - - -module uefi; - -import uefi::efi_error; -import uefi::efi_warning; - -/** EFI_STATUS enum (apx D of the UEFI 2.11 specification). */ -macro @efi_err($x) @private => (usz)((1l << ((usz::size * 8) - 1)) | $x); -macro @efi_warn($x) @private => (usz)$x; - -enum EfiStatus : usz (usz raw, fault fault_type) -{ - SUCCESS { 0, efi_error::NO_FAULT }, - - LOAD_ERROR { @efi_err(1), efi_error::LOAD_ERROR }, - INVALID_PARAMETER { @efi_err(2), efi_error::INVALID_PARAMETER }, - UNSUPPORTED { @efi_err(3), efi_error::UNSUPPORTED }, - BAD_BUFFER_SIZE { @efi_err(4), efi_error::BAD_BUFFER_SIZE }, - BUFFER_TOO_SMALL { @efi_err(5), efi_error::BUFFER_TOO_SMALL }, - NOT_READY { @efi_err(6), efi_error::NOT_READY }, - DEVICE_ERROR { @efi_err(7), efi_error::DEVICE_ERROR }, - WRITE_PROTECTED { @efi_err(8), efi_error::WRITE_PROTECTED }, - OUT_OF_RESOURCES { @efi_err(9), efi_error::OUT_OF_RESOURCES }, - VOLUME_CORRUPTED { @efi_err(10), efi_error::VOLUME_CORRUPTED }, - VOLUME_FULL { @efi_err(11), efi_error::VOLUME_FULL }, - NO_MEDIA { @efi_err(12), efi_error::NO_MEDIA }, - MEDIA_CHANGED { @efi_err(13), efi_error::MEDIA_CHANGED }, - NOT_FOUND { @efi_err(14), efi_error::NOT_FOUND }, - ACCESS_DENIED { @efi_err(15), efi_error::ACCESS_DENIED }, - NO_RESPONSE { @efi_err(16), efi_error::NO_RESPONSE }, - NO_MAPPING { @efi_err(17), efi_error::NO_MAPPING }, - TIMEOUT { @efi_err(18), efi_error::TIMEOUT }, - NOT_STARTED { @efi_err(19), efi_error::NOT_STARTED }, - ALREADY_STARTED { @efi_err(20), efi_error::ALREADY_STARTED }, - ABORTED { @efi_err(21), efi_error::ABORTED }, - ICMP_ERROR { @efi_err(22), efi_error::ICMP_ERROR }, - TFTP_ERROR { @efi_err(23), efi_error::TFTP_ERROR }, - PROTOCOL_ERROR { @efi_err(24), efi_error::PROTOCOL_ERROR }, - INCOMPATIBLE_VERSION { @efi_err(25), efi_error::INCOMPATIBLE_VERSION }, - SECURITY_VIOLATION { @efi_err(26), efi_error::SECURITY_VIOLATION }, - CRC_ERROR { @efi_err(27), efi_error::CRC_ERROR }, - END_OF_MEDIA { @efi_err(28), efi_error::END_OF_MEDIA }, - UNKNOWN_29 { @efi_err(29), efi_error::UNKNOWN_29 }, /* NOTE: UEFI spec is missing this definition. */ - UNKNOWN_30 { @efi_err(30), efi_error::UNKNOWN_30 }, /* NOTE: UEFI spec is missing this definition. */ - END_OF_FILE { @efi_err(31), efi_error::END_OF_FILE }, - INVALID_LANGUAGE { @efi_err(32), efi_error::INVALID_LANGUAGE }, - COMPROMISED_DATA { @efi_err(33), efi_error::COMPROMISED_DATA }, - IP_ADDRESS_CONFLICT { @efi_err(34), efi_error::IP_ADDRESS_CONFLICT }, - HTTP_ERROR { @efi_err(35), efi_error::HTTP_ERROR }, - - WARN_UNKNOWN_GLYPH { @efi_warn(1), efi_warning::UNKNOWN_GLYPH }, - WARN_DELETE_FAILURE { @efi_warn(2), efi_warning::DELETE_FAILURE }, - WARN_WRITE_FAILURE { @efi_warn(3), efi_warning::WRITE_FAILURE }, - WARN_BUFFER_TOO_SMALL { @efi_warn(4), efi_warning::BUFFER_TOO_SMALL }, - WARN_STALE_DATA { @efi_warn(5), efi_warning::STALE_DATA }, - WARN_FILE_SYSTEM { @efi_warn(6), efi_warning::FILE_SYSTEM }, - WARN_RESET_REQUIRED { @efi_warn(7), efi_warning::RESET_REQUIRED }, -} - - -// ////////////////////////////////////////////////////////////////////// -<* - Handle EFI errors when they occur. - @param status : `The EfiStatus code to check` - @param throw_on_warnings : `Return a ``true`` value on EFI_WARN_... codes` - @return ```false`` on success. ``true`` when ``throw_on_warnings`` is false and ``status`` is a warning. Returns a fault otherwise.` -*> -fn bool? efi_error(EfiStatus status, bool throw_on_warnings = true) @export("efi_error") @builtin -{ - switch - { - case status == SUCCESS: return false; - - case status >= EfiStatus.WARN_UNKNOWN_GLYPH && status <= EfiStatus.WARN_RESET_REQUIRED: - return throw_on_warnings ? status.fault_type~ : true; - - case status >= EfiStatus.LOAD_ERROR && status <= EfiStatus.HTTP_ERROR: - return status.fault_type~; - } - - return efi_error::UNKNOWN_STATUS~; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/exports.c3 b/lib/uefi.c3l/src/exports.c3 deleted file mode 100644 index 332311c..0000000 --- a/lib/uefi.c3l/src/exports.c3 +++ /dev/null @@ -1,216 +0,0 @@ -// ------------------------------------------------------------------ -module uefi; -import uefi::efi_system @public; - - -extern fn void initialize_lib(EfiHandle, SystemTable*); - -PanicFn panic_func = (PanicFn)&uefi::efilib::pre_load::default_panic; - - -// ------------------------------------------------------------------ -module uefi::io; -import uefi; -import uefi::efi_system @public; - - -// interface LibcFile -// { -// // -// } -// typedef OutStream (LibcFile) = uptr; -// const OutStream STDERR @export("stderr") = (OutStream)efi_system::efi_sys.console.stderr; - -macro EfiStatus? memdump( - void* ptr, - usz len, - usz $align = 16 -) @maydiscard => efi_system::efi_sys.console.printn(a2w(efi_system::efi_sys.create_memdump(ptr, len, $align))); -macro EfiStatus? cmemdump( - ConsoleColor color, - void* ptr, - usz len, - usz $align = 16 -) @maydiscard => efi_system::efi_sys.console.cprintn(color, a2w(efi_system::efi_sys.create_memdump(ptr, len, $align))); - -macro EfiStatus? wprint(EfiString str) @maydiscard => efi_system::efi_sys.console.print(str); -macro EfiStatus? wprintn(EfiString str) @maydiscard => efi_system::efi_sys.console.printn(str); -macro EfiStatus? wfprint( - SimpleTextOutputProtocol* stream, - EfiString str -) @maydiscard => efi_system::efi_sys.console.print(str, stream); -macro EfiStatus? wfprintn( - SimpleTextOutputProtocol* stream, - EfiString str -) @maydiscard => efi_system::efi_sys.console.printn(str, stream); -macro EfiStatus? wprinte(EfiString str, args...) @maydiscard => efi_system::efi_sys.console.printe(str, ...args); -macro EfiStatus? wfprinte( - SimpleTextOutputProtocol* stream, - EfiString str, - args... -) @maydiscard => efi_system::efi_sys.console.fprinte(stream, str, ...args); - -macro EfiStatus? print(AsciiString str) @maydiscard => efi_system::efi_sys.console.print(a2w(str)); -macro EfiStatus? printn(AsciiString str) @maydiscard => efi_system::efi_sys.console.printn(a2w(str)); -macro EfiStatus? fprint( - SimpleTextOutputProtocol* stream, - AsciiString str -) @maydiscard => efi_system::efi_sys.console.print(a2w(str), stream); -macro EfiStatus? fprintn( - SimpleTextOutputProtocol* stream, - AsciiString str -) @maydiscard => efi_system::efi_sys.console.printn(a2w(str), stream); -macro EfiStatus? printe(AsciiString str, args...) @maydiscard => efi_system::efi_sys.console.printn(a2w(str), ...args); -macro EfiStatus? fprinte( - SimpleTextOutputProtocol* stream, - AsciiString str, - args... -) @maydiscard => efi_system::efi_sys.console.printn(stream, a2w(str), ...args); - -macro EfiStatus? wcprint( - ConsoleColor color, - EfiString str -) @maydiscard => efi_system::efi_sys.console.cprint(color, str); -macro EfiStatus? wcprintn( - ConsoleColor color, - EfiString str -) @maydiscard => efi_system::efi_sys.console.cprintn(color, str); -macro EfiStatus? wcprinte( - ConsoleColor color, - EfiString str, - args... -) @maydiscard => efi_system::efi_sys.console.cprinte(color, str, ...args); -macro EfiStatus? cprint( - ConsoleColor color, - AsciiString str -) @maydiscard => efi_system::efi_sys.console.cprint(color, a2w(str)); -macro EfiStatus? cprintn( - ConsoleColor color, - AsciiString str -) @maydiscard => efi_system::efi_sys.console.cprintn(color, a2w(str)); -macro EfiStatus? cprinte( - ConsoleColor color, - AsciiString str, - args... -) @maydiscard => efi_system::efi_sys.console.cprinte(color, a2w(str), ...args); - - -// ------------------------------------------------------------------ -module uefi::str; -import uefi; -import uefi::efi_system @public; - - -// - - -// ------------------------------------------------------------------ -module uefi::console; -import uefi; -import uefi::efi_system @public; - - -macro void? clear_to( - ConsoleColor color, - bool preserve = false, - bool reset_cursor = true -) @maydiscard => efi_system::efi_sys.console.clear(color, preserve, reset_cursor); -macro void? clear() @maydiscard => (void)(efi_error( - efi_system::efi_sys.console.stdout.clear_screen(efi_system::efi_sys.console.stdout) -)!); - - -// ------------------------------------------------------------------ -module uefi::sys; -import uefi; -import uefi::efi_system @public; - - -macro BootServices* bs() => efi_system::efi_sys.boot_services; -macro RuntimeServices* rs() => efi_system::efi_sys.runtime_services; -macro SystemTable* st() => efi_system::efi_sys.system_table; -macro EfiHandle image() => efi_system::efi_sys.image_handle; - -macro SimpleTextOutputProtocol* stdout() => efi_system::efi_sys.console.stdout; -macro SimpleTextOutputProtocol* stderr() => efi_system::efi_sys.console.stderr; -macro any stdin() => !sys::stdin_extended() ? efi_system::efi_sys.console.stdin : efi_system::efi_sys.console.stdin_ex; -macro bool stdin_extended() => null != efi_system::efi_sys.console.stdin_ex; - -macro void @stall(usz $duration) @builtin => efi_system::efi_sys.stall($duration); - -macro void @reset( - ResetType $type, - EfiStatus code = SUCCESS, - char[] buffer = { } -) @noreturn @builtin => efi_system::efi_sys.reset($type, code, buffer); - -macro void hang() @noreturn -{ - sys::@disable_watchdog(); - while (true) sys::@stall(500_000); -} -macro void halt() @noreturn => sys::hang(); -fn void lock() @noreturn -{ - while (true);} - -macro void @panic( - $message -) @builtin => efi_system::efi_sys.panic( - "[" +++ $$FILE +++ ":" +++ $$FUNC +++ ":" +++ $$LINE +++ "] PANIC! " +++ $message -); - -macro bool? @set_watchdog(usz $seconds) @maydiscard => efi_system::efi_sys.set_watchdog_timer($seconds); -macro bool? @disable_watchdog() @maydiscard => efi_system::efi_sys.set_watchdog_timer(0); -macro bool? set_watchdog_full( - usz seconds, - ulong code = -1, - usz data_size = 0, - EfiStringRaw data = null -) @maydiscard => efi_system::efi_sys.set_watchdog_timer(seconds, code, data_size, data); - -macro ulong? get_next_monotonic_count() @maydiscard => efi_system::efi_sys.get_next_monotonic_count(); - -macro uint? get_crc32(void* data @noalias, usz data_size) => efi_system::efi_sys.calculate_crc32(data, data_size); - -macro SystemMemoryMap*? get_memory_map() => efi_system::efi_sys.get_memory_map(); - - -// ------------------------------------------------------------------ -module uefi::mem; -import uefi; -import uefi::efi_system @public; - - -fn void* memcpy(void* into, void* from, usz length) @export("memcpy") @nostrip -{ - efi_system::efi_sys.memcpy(into, from, length); - return into; -} - -fn void* memmove(void* into, void* from, usz length) @export("memmove") @nostrip -{ - void* tmp = malloc(length); - memcpy(tmp, from, length); - memcpy(into, tmp, length); - free(tmp); - return into; -} - -fn void memset( - void* at, - char value, - usz length -) @export("memset") @nostrip => efi_system::efi_sys.memset(at, value, length); - -fn void* malloc(usz size) @export("malloc") @nostrip => efi_system::efi_sys.malloc(size)!!; -fn void* calloc(usz num, usz size) @export("calloc") @nostrip => efi_system::efi_sys.calloc(num, size)!!; - -fn void* realloc( - void* pool, - usz prev_len, - usz new_len -) @export("realloc") @nostrip => efi_system::efi_sys.realloc(pool, prev_len, new_len)!!; - -fn void free(void* pool) @export("free") @nostrip => efi_system::efi_sys.free(pool); -fn void? free_safe(void* pool) @export("free_safe") @nostrip => efi_system::efi_sys.free_safe(pool); diff --git a/lib/uefi.c3l/src/guid.c3 b/lib/uefi.c3l/src/guid.c3 deleted file mode 100644 index 25d1c7b..0000000 --- a/lib/uefi.c3l/src/guid.c3 +++ /dev/null @@ -1,82 +0,0 @@ -module uefi::guid; -import uefi; - - -/* SYSTEM TABLE GUIDS: - Sections 4.6.1.x, 4.6.2 - .5 show industry-standard - configuration table identifiers (guids). */ -const EfiGuid ACPI_20_TABLE = { 0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 } }; - -/* It's reasonable to assume most machines nowadays default to ACPI 2.0+. - However, ACPI_10_TABLE below is still defined in case there's no match - on ACPI_TABLE here. */ -const EfiGuid ACPI_TABLE = ACPI_20_TABLE; - -const EfiGuid ACPI_10_TABLE = { 0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }; - -const EfiGuid SAL_SYSTEM_TABLE = { 0xeb9d2d32, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }; -const EfiGuid SMBIOS_TABLE = { 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }; -const EfiGuid SMBIOS3_TABLE = { 0xf2fd1544, 0x9794, 0x4a2, { 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 } }; -const EfiGuid MPS_TABLE = { 0xeb9d2d2f, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }; - -const EfiGuid JSON_CONFIG_DATA_TABLE = { - 0x87367f87, - 0x1119, - 0x41ce, - { 0xaa, 0xec, 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a } -}; -const EfiGuid JSON_CAPSULE_DATA_TABLE = { - 0x35e7a725, - 0x8dd2, - 0x4cac, - { 0x80, 0x11, 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 } -}; -const EfiGuid JSON_CAPSULE_RESULT_TABLE = { - 0xdbc461c3, - 0xb3de, - 0x422a, - { 0xb9, 0xb4, 0x98, 0x86, 0xfd, 0x49, 0xa1, 0xe5 } -}; - -const EfiGuid DTB_TABLE = { - 0xb1b621d5, - 0xf19c, - 0x41a5, - { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } -}; -const EfiGuid MEMORY_ATTRIBUTES_TABLE = { - 0xdcfa911d, - 0x26eb, - 0x469f, - { 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20 } -}; -const EfiGuid CONFORMANCE_PROFILES_TABLE = { - 0x36122546, - 0xf7e7, - 0x4c8f, - { 0xbd, 0x9b, 0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b } -}; -const EfiGuid CONFORMANCE_PROFILES_UEFI_SPEC = { - 0x523c91af, - 0xa195, - 0x4382, - { 0x81, 0x8d, 0x29, 0x5f, 0xe4, 0x00, 0x64, 0x65 } -}; -const EfiGuid MEMORY_RANGE_CAPSULE = { - 0xde9f0ec, - 0x88b6, - 0x428f, - { 0x97, 0x7a, 0x25, 0x8f, 0x1d, 0x0e, 0x5e, 0x72 } -}; -const EfiGuid DEBUG_IMAGE_INFO_TABLE = { - 0x49152e77, - 0x1ada, - 0x4764, - { 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b } -}; -const EfiGuid SYSTEM_RESOURCE_TABLE = { - 0xb122a263, - 0x3661, - 0x4f68, - { 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } -}; \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/console.c3 b/lib/uefi.c3l/src/lib/console.c3 deleted file mode 100644 index 862b95a..0000000 --- a/lib/uefi.c3l/src/lib/console.c3 +++ /dev/null @@ -1,132 +0,0 @@ -module uefi::efilib; -import uefi; - - -struct Console -{ - SimpleTextOutputProtocol* stdout; - SimpleTextOutputProtocol* stderr; - SimpleTextInputProtocol* stdin; - SimpleTextInputExProtocol* stdin_ex; -} - - -// --------------------------------------------------- -module uefi::efilib::efi_console @private; -import uefi; -import uefi::efilib::pre_load @public; - - -fn Console*? new(EfiHandle image, SystemTable* st) -{ - if (!pre_load::initialized) return efi_error::EFILIB_UNINITIALIZED~; - - Console* new_console; - efi_error(st.boot_services.allocate_pool(LOADER_DATA, Console::size, &new_console))!; - - new_console.stdout = st.conout; - new_console.stderr = st.conerr; - new_console.stdin = st.conin; - - // Attempt to initialize the extended input protocol. To do this, its handle must be pulled off of - // instances pre-loaded by the system's UEFI firmware. - if (catch efi_error( - st.boot_services.locate_protocol(&&guid::SIMPLE_TEXT_INPUT_EX_PROTOCOL, null, &new_console.stdin_ex) - )) new_console.stdin_ex = null; - - return new_console; -} - - -// --------------------------------------------------- -module uefi::efilib; -import uefi; - -fn EfiStatus? Console.print(&self, EfiString text, SimpleTextOutputProtocol* stream = null) -{ - if (null == (void*)stream) stream = self.stdout; - efi_error(stream.output_string(stream, text))!; - - return SUCCESS; -} - - -fn EfiStatus? Console.printn(&self, EfiString text, SimpleTextOutputProtocol* stream = null) -{ - self.print(text, stream)!; - - ushort[3] nl = { '\r', '\n', 0 }; - return self.print((EfiString)&nl, stream)!; -} - - -fn EfiStatus? Console.cprint(&self, EfiString text, ConsoleColor color, SimpleTextOutputProtocol* stream = null) -{ - if (null == (void*)stream) stream = self.stdout; - - usz previous_attr = (usz)stream.mode.current_attribute; - defer stream.set_attribute(stream, previous_attr); - - stream.set_attribute(stream, (usz)(char)color); - return self.print(text, stream); -} - - -fn EfiStatus? Console.cprintn(&self, ConsoleColor color, EfiString text, SimpleTextOutputProtocol* stream = null) -{ - self.cprint(text, color, stream)!; - - ushort[3] nl = { '\r', '\n', 0x00 }; - return self.print((EfiString)&nl); -} - - -fn EfiStatus? Console.printe(&self, EfiString text, args...) -{ - EfiString formatted_text = _expandf(text, ...args)!; - defer mem::free(formatted_text); - - return self.print(formatted_text); -} - - -fn EfiStatus? Console.fprinte(&self, SimpleTextOutputProtocol* stream, EfiString text, args...) -{ - EfiString formatted_text = _expandf(text, ...args)!; - defer mem::free(formatted_text); - - return self.print(formatted_text, stream); -} - - -fn EfiStatus? Console.cprinte(&self, ConsoleColor color, EfiString text, args...) -{ - EfiString formatted_text = _expandf(text, ...args)!; - defer mem::free(formatted_text); - - return self.cprint(formatted_text, color); -} - - -fn EfiStatus? Console.cfprinte(&self, ConsoleColor color, SimpleTextOutputProtocol* stream, EfiString text, args...) -{ - EfiString formatted_text = _expandf(text, ...args)!; - defer mem::free(formatted_text); - - return self.cprint(formatted_text, color, stream); -} - - -fn void? Console.clear(&self, ConsoleColor color, bool preserve_attr = false, bool reset_cursor = true) -{ - char previous_attr = (char)(self.stdout.mode.current_attribute & 0xFF); - - efi_error(self.stdout.set_attribute(self.stdout, (usz)(char)color))!; - self.stdout.clear_screen(self.stdout); - - /* Reinstate the old attribute if specified. */ - if (preserve_attr) efi_error(self.stdout.set_attribute(self.stdout, (usz)previous_attr))!; - - /* Reset the cursor position if specified. */ - if (reset_cursor) efi_error(self.stdout.set_cursor_position(self.stdout, 0, 0))!; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/init.c3 b/lib/uefi.c3l/src/lib/init.c3 deleted file mode 100644 index e81c5e3..0000000 --- a/lib/uefi.c3l/src/lib/init.c3 +++ /dev/null @@ -1,92 +0,0 @@ -module uefi::efilib::pre_load; -import uefi; -import uefi::efi_system @public; - - -/* Global variables/structures to be optionally used with all EFI programs. */ -bool initialized @private = false; - -SystemTable* gST @export("gST") @builtin @deprecated("Legacy symbol. Use `sys::st()` instead.") = null; - -BootServices* gBS @export("gBS") @builtin @deprecated("Legacy symbol. Use `sys::bs()` instead.") = null; -RuntimeServices* gRS @export("gRS") @builtin @deprecated("Legacy symbol. Use `sys::rs()` instead.") = null; - -EfiHandle gImageHandle @export("gImageHandle") @builtin @deprecated("Legacy symbol. Use `sys::image()` instead.") = (EfiHandle)null; - -bool in_panic @local = false; -bool panic_in_panic @local = false; - -fn void default_panic( - String message, - String file, - String function, - uint line -) @public @allow_deprecated @export("panic") @noreturn -{ - if (!initialized) sys::lock(); // spin forever, can't do anything... - - if (in_panic) - { - if (panic_in_panic) sys::lock(); // prevent infinite panic recursion - panic_in_panic = true; - - gST.conout.output_string(gST.conout, @wstring("PANIC raised within panicfn! Locking system...")); - sys::lock(); - } - - in_panic = true; - - // Create a wide string on the stack from the passed information. - ushort[1024] _w_msg; - usz _w_msg_start, x; - - foreach (i, c : file) _w_msg[i % _w_msg.len] = (ushort)c; - _w_msg_start = file.len; - - _w_msg[_w_msg_start++] = (ushort)':'; - foreach (i, c : function) _w_msg[((ulong)i + _w_msg_start) % _w_msg.len] = (ushort)c; - _w_msg_start += function.len; - - _w_msg[_w_msg_start++] = (ushort)':'; - ushort[7] _i_to_str; - for (x = 0; line && x < _i_to_str.len; line /= 10, ++x) _i_to_str[x] = (ushort)(0x30 + (line % 10)); - for (usz w = 1; w <= x; ++w) _w_msg[_w_msg_start++] = _i_to_str[x - w]; - - _w_msg[_w_msg_start++] = (ushort)':'; - foreach (i, c : message) _w_msg[((ulong)i + _w_msg_start) % _w_msg.len] = (ushort)c; - - _w_msg[1023] = 0; // explicit null-terminator - - gST.conout.output_string(gST.conout, @wstring("PANIC! ")); - gST.conout.output_string(gST.conout, &_w_msg); - - sys::lock(); -} - - -<* - Initialize the UEFI C3 library. This call should be made immediately upon EFI entry. - @param [&in] image : "The input EFI_IMAGE handle to the EFI application" - @param [&in] st : "A reference to the system table provided to the EFI application" - @return "Whether the library was successfully initialized." -*> -fn bool? init(EfiHandle image, SystemTable* st) @public @allow_deprecated -{ - builtin::panic = (PanicFn)&default_panic; // in case the user did not compile with '--panicfn' - - if (null == (void*)image || null == (void*)st) return efi_error::LOAD_ERROR~; - - // Though these are deprecated, they should hang around for the purpose of interfacing with old code. - gST = st; - gBS = st.boot_services; - gRS = st.runtime_services; - gImageHandle = image; - - /* The library is _technically_ initialized once the above pointers are populated. */ - initialized = true; - - efi_system::efi_sys = efi_system::new(image, st)!; - initialized = initialized && (null != (void*)efi_system::efi_sys); - - return initialized; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/input.c3 b/lib/uefi.c3l/src/lib/input.c3 deleted file mode 100644 index 8c896d4..0000000 --- a/lib/uefi.c3l/src/lib/input.c3 +++ /dev/null @@ -1,36 +0,0 @@ -module uefi::efilib; -import uefi; - - -fn EfiKeyData? read_key(usz timeout_ms) -{ - EfiEvent[2] events; - usz fired_event_index = 0; - - // if (timeout_ms) { - // // - // } - - while OUTER: (true) - { - // events[0] = sys::bs().wait_for_event(timeout_ms ? 2 : 1, &events, &fired_event_index); - - // any _stdin = sys::stdin(); - - // switch (_stdin.type) { - // case SimpleTextInputProtocol.typeid: - // SimpleTextInputProtocol* stdin = _stdin; - // stdin.reset(stdin, false); - - - // case SimpleTextInputExProtocol.typeId: - // SimpleTextInputExProtocol* stdin = _stdin; - // stdin.reset(stdin, false); - - // default: return efi_error::NO_MAPPING?; - // } - } -} - - -// fn bool? confirm(EfiString prompt) => {} \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/private/print.c3 b/lib/uefi.c3l/src/lib/private/print.c3 deleted file mode 100644 index 4dc2d84..0000000 --- a/lib/uefi.c3l/src/lib/private/print.c3 +++ /dev/null @@ -1,159 +0,0 @@ -module uefi::efilib @private; - -import uefi; - - -macro EfiString? @expand_param($Type, any value, #assign_to) -{ - $switch $Type: - $case EfiString: - $nextcase; - $weweoifj; - $case ushort*: - #assign_to = wstrdup((EfiStringRaw)value); - $endswitch -} - - -fn EfiString? _expandf(EfiString input, args...) -{ - if (null == (void*)input.ptr) return efi_error::INVALID_PARAMETER~; - if (0 == args.len) return wide_strdup(input); - - usz scroll = 0; - usz pool_idx = 1; - usz vararg_idx = 0; - EfiString[32] strpool; - strpool[0] = wstrdup(input)!; - EfiString dup = strpool[0]; - - while (scroll < dup.len && 0 != dup[scroll]) - { - if ((ushort)'<' != dup[scroll]) - { - ++scroll; - continue; - } - - // if (scroll == (dup.len - 1)) break; // Do NOT read past the end. - - if ((ushort)'<' == dup[scroll + 1]) - { - dup[scroll + 1] = 0; - - // if ((scroll + 2) == (dup.len - 1)) break; - - if (pool_idx >= 64) return efi_error::OUT_OF_RESOURCES~; - strpool[pool_idx] = dup[(scroll + 2):wstrlen(&dup[scroll + 2])!]; - dup = strpool[pool_idx]; - ++pool_idx; - - scroll = 0; - continue; - } - else if ((ushort)'>' == dup[scroll + 1]) - { - if (vararg_idx >= args.len) return efi_error::NO_MAPPING~; - - dup[scroll] = 0; - - if (pool_idx >= 64 - 1) return efi_error::OUT_OF_RESOURCES~; - strpool[pool_idx] = _expand_arg(args[vararg_idx])!; - ++vararg_idx; - ++pool_idx; - - strpool[pool_idx] = dup[(scroll + 2):wstrlen(&dup[scroll + 2])!]; - dup = strpool[pool_idx]; - ++pool_idx; - - scroll = 0; - continue; - } - else - { - return efi_error::INVALID_LANGUAGE~; - } - } - - usz required_buffer_size = 0; - EfiStringRaw buff = null; - scroll = 0; - - foreach (item : strpool[:pool_idx]) - { - if (!item[0]) continue; - io::wprintn(item)!; - required_buffer_size += item.bytes(); - } - - buff = mem::malloc(required_buffer_size + ushort::size); - - foreach (item : strpool[:pool_idx]) - { - if (!item[0]) continue; - - mem::memcpy(&buff[scroll], item.ptr, item.bytes()); - scroll += (item.len - 1); - - // mem::free(item.ptr); - } - - buff[wstrlen(buff)!] = 0; - io::memdump(buff, wstrlen(buff) + 2)!; - - return wslice_from_raw(buff, required_buffer_size / ushort::size); -} - - -fn EfiString? _expand_arg(any value) -{ - EfiString expansion = { }; - - switch (value.type) - { - case EfiString: nextcase; - case EfiStringRaw: - io::wprintn($$wstr16("efi_string"))!; - expansion = wide_strdup(wslice_from_raw(value, wstrlen((EfiStringRaw)value) + 1))!; - case AsciiString: - io::wprintn($$wstr16("ascii_string"))!; - expansion = a2w(slice_from_raw(value, strlen((AsciiStringRaw)value) + 1))!; - case bool: - expansion = _bool_to_str(((bool)(value.ptr)))!; - case EfiGuid: - expansion = _guid_to_str((EfiGuid*)value.ptr)!; - // case EfiDevicePath: expansion = _device_path_to_str((EfiDevicePath *)value); - case float: nextcase; - case double: - expansion = a2w("fract")!; // _fractional_to_str(value); - case int128: nextcase; - case uint128: nextcase; - case long: nextcase; - case ulong: nextcase; - case int: nextcase; - case uint: nextcase; - case short: nextcase; - case ushort: nextcase; - case ichar: nextcase; - case char: - expansion = a2w("number")!; // _number_to_str(value); - case void: - expansion = a2w("pointer")!; // _pointer_to_str(value); - default: - expansion = a2w("umm")!; // efi_error::INVALID_PARAMETER?; - } - // io::print(a2w("EXPAND: '"))!;io::print(expansion)!;io::printn(a2w("'"))!; - // io::printn(a2w(memdump(&&expansion.len, usz.sizeof)))!; - - if (null == (void*)expansion.ptr || 0 == expansion.len) return efi_error::INVALID_PARAMETER~; - - return expansion; -} - - -fn EfiString? _bool_to_str(bool b) => b ? a2w("TRUE") : a2w("FALSE"); - -fn EfiString? _guid_to_str(EfiGuid* guid) -{ - return a2w("SOMEGUID"); -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/string.c3 b/lib/uefi.c3l/src/lib/string.c3 deleted file mode 100644 index 26d4f21..0000000 --- a/lib/uefi.c3l/src/lib/string.c3 +++ /dev/null @@ -1,145 +0,0 @@ -module uefi::efilib; -import uefi; - - -fn usz? wide_strlen(ushort* rawptr) @export("wstrlen") -{ - if (null == rawptr) return efi_error::INVALID_PARAMETER~; - - usz len = 0; - while (rawptr[len]) ++len; - - return len; -} - - -fn usz? ascii_strlen(char* rawptr) @export("strlen") -{ - if (null == rawptr) return efi_error::INVALID_PARAMETER~; - - usz len = 0; - while (rawptr[len]) ++len; - - return len; -} - - -fn EfiString? ascii_to_wide(AsciiString str) @export("a2w") -{ - if (null == (void*)str.ptr || 0 == str[0]) return efi_error::INVALID_PARAMETER~; - - EfiString ret = wslice_from_raw(mem::calloc(str.len + 1, ushort::size), str.len + 1); - - for (int i = 0; i < str.len; ++i) ret[i] = (ushort)str[i]; - ret[^1] = 0; - - return ret; -} - - -fn AsciiString? wide_to_ascii(EfiString str) @export("w2a") -{ - if (null == (void*)str.ptr || 0 == str[0]) return efi_error::INVALID_PARAMETER~; - - AsciiString ret = slice_from_raw(mem::calloc(str.len + 1, char::size), str.len + 1); - - for (int i = 0; i < str.len; ++i) ret[i] = (char)str[i]; /* lossy */ - ret[^1] = 0; - - return ret; -} - - -fn EfiString? wide_strdup(EfiString str) @export("wstrdup") -{ - if (null == (void*)str.ptr) return efi_error::INVALID_PARAMETER~; - if (0 == str.len) return a2w({ 0 }); - - usz str_len = wide_strlen(str.ptr)!; - EfiString ret = wslice_from_raw(mem::calloc(str_len + 1, ushort::size), str_len + 1); - - mem::memcpy(ret, str, str_len * ushort::size); - ret[^1] = 0; - - return ret; -} - - -fn AsciiString? ascii_strdup(AsciiString str) @export("strdup") -{ - if (null == (void*)str.ptr) return efi_error::INVALID_PARAMETER~; - if (0 == str.len) return mem::calloc(1, 1)[:1]; - - AsciiString ret = slice_from_raw(mem::malloc(str.len + 1), str.len + 1); - mem::memcpy(ret, str, str.len); - ret[^1] = 0; - - return ret; -} - - -fn EfiString? wide_strcat(EfiString str, EfiString addl) @export("wstrcat") -{ - if (null == (void*)str.ptr || null == (void*)addl.ptr) return efi_error::INVALID_PARAMETER~; - - usz str_size = wide_strlen(str.ptr)! * ushort::size; - usz addl_size = wide_strlen(addl.ptr)! * ushort::size; - usz new_size = str_size + addl_size + ushort::size; - - void* buff = mem::malloc(new_size); - wstrcpy(buff, str)!; - mem::memcpy((void*)((uptr)buff + str_size), addl.ptr, addl_size); - - EfiString reinterp = wslice_from_raw(buff, new_size / ushort::size); - reinterp[^1] = 0; - - return reinterp; -} - - -fn AsciiString? ascii_strcat(AsciiString str, AsciiString addl) @export("strcat") -{ - if (null == (void*)str || null == (void*)addl) return efi_error::INVALID_PARAMETER~; - - mem::memcpy((void*)((uptr)str.ptr + str.len), addl, addl.len); - - return str; -} - - -fn void? wide_strcpy(void* to, EfiString from) @export("wstrcpy") -{ - if (null == (void*)from.ptr || null == to) return efi_error::INVALID_PARAMETER~; - - mem::memcpy(to, from.ptr, from.bytes()); - ((EfiStringRaw)to)[from.len - 1] = 0; -} - - -fn void? ascii_strcpy(void* to, AsciiString from) @export("strcpy") -{ - if (null == (void*)from.ptr || null == to) return efi_error::INVALID_PARAMETER~; - - mem::memcpy(to, from.ptr, from.bytes()); - ((AsciiStringRaw)to)[from.len - 1] = 0; -} - - -fn usz EfiString.bytes(&self) => (self.len - 1) * ushort::size; -fn usz AsciiString.bytes(&self) => (self.len - 1) * char::size; - - -macro usz? wstrlen(EfiStringRaw rawptr) @builtin => wide_strlen(rawptr); -macro EfiString? wstrdup(EfiString str) @builtin => wide_strdup(str); -macro EfiString? wstrcat(EfiString str, EfiString addl) @builtin => wide_strcat(str, addl); -macro void? wstrcpy(void* into, EfiString from) @builtin => wide_strcpy(into, from); -macro AsciiString? w2a(EfiString c) @builtin => wide_to_ascii(c); - -macro usz? strlen(AsciiStringRaw rawptr) @builtin => ascii_strlen(rawptr); -macro AsciiString? strdup(AsciiString str) @builtin => ascii_strdup(str); -macro AsciiString? strcat(AsciiString str, AsciiString addl) @builtin => ascii_strcat(str, addl); -macro void? strcpy(void* into, AsciiString from) @builtin => ascii_strcpy(into, from); -macro EfiString? a2w(AsciiString c) @builtin => ascii_to_wide(c); - -macro EfiString wslice_from_raw(void* rawptr, usz length) @builtin => ((EfiStringRaw)rawptr)[:length]; -macro AsciiString slice_from_raw(void* rawptr, usz length) @builtin => ((AsciiStringRaw)rawptr)[:length]; \ No newline at end of file diff --git a/lib/uefi.c3l/src/lib/system.c3 b/lib/uefi.c3l/src/lib/system.c3 deleted file mode 100644 index 0f68294..0000000 --- a/lib/uefi.c3l/src/lib/system.c3 +++ /dev/null @@ -1,268 +0,0 @@ -module uefi::efilib; -import uefi; - - -struct System -{ - EfiHandle image_handle; - - SystemTable* system_table; - - BootServices* boot_services; - RuntimeServices* runtime_services; - - Console* console; - - bool gop_initialized; - - // TODO: What's going on here? - // LoadedImageProtocol image_info; - MemoryType image_data_type; -} - - -// --------------------------------------------------- -module uefi::efi_system @private; -import uefi; -import uefi::efilib::efi_console @public; -import uefi::efilib::pre_load @public; - - -System* efi_sys @private = null; - - -fn System*? new(EfiHandle image, SystemTable* st) -{ - if (!pre_load::initialized) return efi_error::EFILIB_UNINITIALIZED~; - - System* new_system = null; - efi_error(st.boot_services.allocate_pool(LOADER_CODE, System::size, &new_system))!; - - if (null == new_system) return efi_error::OUT_OF_RESOURCES~; - - new_system.system_table = st; - - new_system.boot_services = st.boot_services; - new_system.runtime_services = st.runtime_services; - - new_system.image_handle = image; - - new_system.gop_initialized = false; - - new_system.console = efi_console::new(image, st)!; - - return new_system; -} - - -// --------------------------------------------------- -module uefi::efilib; -import uefi; - - -fn void System.reset( - &self, - ResetType type, - EfiStatus code = SUCCESS, - char[] buffer = { } -) @noreturn => self.runtime_services.reset_system(type, code, buffer.len, buffer.ptr); - - -fn void System.stall(&self, usz duration) => self.boot_services.stall(duration); - - -fn void System.panic(&self, AsciiString message) @noreturn @allow_deprecated -{ - if (!self.gop_initialized) - { - ushort[1024] _w_msg; - foreach (i, c : message) _w_msg[i % _w_msg.len] = (ushort)c; - gST.conout.set_attribute(gST.conout, (usz)(char)(ConsoleColor) { RED, BLACK }); - gST.conout.output_string(gST.conout, &_w_msg); - } - - sys::halt(); -} - - -fn bool? System.set_watchdog_timer( - &self, - usz timer_seconds, - ulong code = -1, - usz data_size = 0, - EfiStringRaw data = null -) => efi_error(self.boot_services.set_watchdog_timer(timer_seconds, code, data_size, data)); - - -fn ulong? System.get_next_monotonic_count(&self) -{ - ulong count_value = 0; - - efi_error(self.boot_services.get_next_monotonic_count(&count_value))!; - - return count_value; -} - -fn uint? System.calculate_crc32(&self, void* data @noalias, usz data_size) -{ - uint result = 0; - - efi_error(self.boot_services.calculate_crc32(data, data_size, &result))!; - - return result; -} - - -fn void System.free(&self, void* pool) -{ - if (null != pool) self.boot_services.free_pool(pool); -} - - -fn void? System.free_safe(&self, void* pool) -{ - if (null != pool) efi_error(self.boot_services.free_pool(pool))!; -} - - -fn void*? System.malloc(&self, usz size, MemoryType type = LIMIT) -{ - if (MemoryType.LIMIT == type) type = self.image_data_type; - - void* res; - efi_error(self.boot_services.allocate_pool(type, size, &res))!; - - return res; -} - - -fn void*? System.calloc(&self, usz size, usz length, MemoryType type = LIMIT) -{ - if (MemoryType.LIMIT == type) type = self.image_data_type; - - void* p = self.malloc(size * length, type)!; - self.memset(p, 0x00, size * length); - - return p; -} - - -fn void*? System.realloc(&self, void* pool, usz prev_len, usz new_len) -{ - if (0 == new_len) - { - self.free(pool); - return null; - } - - void* new_pool = self.calloc(1, new_len)!; - - if (null != pool) - { - self.memcpy(new_pool, pool, @min(prev_len, new_len)); - self.free(pool); - } - - return new_pool; -} - - -fn void System.memset(&self, void* at, char value, usz length) -{ - if (null == at || 0 == length) return; - - self.boot_services.set_mem(at, length, value); -} - - -fn void System.memcpy(&self, void* to, void* from, usz length) -{ - if (null == to || null == from || 0 == length) return; - - self.boot_services.copy_mem(to, from, length); -} - - -fn AsciiString? System.create_memdump(&self, void* at, usz len, usz align = 16) -{ - if (null == at || 0 == len) return efi_error::INVALID_PARAMETER~; - - AsciiString ret = slice_from_raw(self.calloc(char::size, (len * 3) + 1)!, (len * 3) + 1); - - for (usz i = 0; i < len; ++i) - { - char c = *((char*)((usz)at + i)); - char high_nibble = (c & 0xF0) >> 4; - char low_nibble = c & 0x0F; - - ret[(i * 3) + 0] = high_nibble + (high_nibble >= 10 ? ('A' - 10) : '0'); - ret[(i * 3) + 1] = low_nibble + (low_nibble >= 10 ? ('A' - 10) : '0'); - ret[(i * 3) + 2] = ((i + 1) % align) ? ' ' : '\n'; - } - - ret[len * 3] = '\0'; // paranoia - return ret; -} - - -fn SystemMemoryMap*? System.get_memory_map(&self) -{ - SystemMemoryMap* result = self.calloc(1, SystemMemoryMap::size)!; - - // The first query should return a "BUFFER_TOO_SMALL" efi error, which sets 'buffer_size' to the right value. - EfiStatus? status = self.boot_services.get_memory_map( - &result.buffer_size, - result.descriptors, - &result.map_key, - &result.descriptor_size, - &result.descriptor_version - ); - - if (catch status_as_fault = status) - { - if (efi_error::BUFFER_TOO_SMALL != status_as_fault) - { - self.free(result); - return status_as_fault~; - } - } - - if (0 == result.buffer_size || 0 == result.descriptor_size) - { - self.free(result); - return efi_error::NOT_FOUND~; - } - - // Account for the possible fragmentation/expansion of the memory map based on the below allocation. - /* NOTE: The size is 2x because a new AllocatePool range inserted into the middle of an existing entry will result - in 2 new entries: the allocation as well as the trailing region/fragment of free space. */ - result.buffer_size += (2 * result.descriptor_size); - - // Allocate the resultant buffer. - result.descriptors = self.calloc(1, result.buffer_size)!; - - status = self.boot_services.get_memory_map( - &result.buffer_size, - result.descriptors, - &result.map_key, - &result.descriptor_size, - &result.descriptor_version - ); - if (catch status_as_fault = status) - { - self.free(result.descriptors); - self.free(result); - return status_as_fault~; - } - - if (0 == result.buffer_size || 0 == result.descriptor_size) - { - self.free(result.descriptors); - self.free(result); - return efi_error::NOT_FOUND~; - } - - result.descriptors_count = result.buffer_size / result.descriptor_size; - - return result; -} diff --git a/lib/uefi.c3l/src/lib/util.c3 b/lib/uefi.c3l/src/lib/util.c3 deleted file mode 100644 index d276393..0000000 --- a/lib/uefi.c3l/src/lib/util.c3 +++ /dev/null @@ -1,19 +0,0 @@ -module uefi::core_util; - - -/* Conversion macros: s2ms, s2us, ms2us (sec to millisec, sec to microsec, millisec to microsec) */ -macro usz @s2ms(usz $x) @public @builtin => $x * 1_000; -macro usz @s2us(usz $x) @public @builtin => $x * 1_000_000; -macro usz @ms2us(usz $x) @public @builtin => $x * 1_000; - -/* min/max macros for le global use */ -macro @min(#x, #y) @public @builtin => ((#x) < (#y) ? (#x) : (#y)); -macro @max(#x, #y) @public @builtin => ((#x) > (#y) ? (#x) : (#y)); - -macro @foreach(rawptr, len; @body(index, value)) @builtin -{ - for (usz i = 0; i < len; ++i) - { - @body(i, rawptr[i]); - } -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/console.c3 b/lib/uefi.c3l/src/protocol/console.c3 deleted file mode 100644 index 1e30f30..0000000 --- a/lib/uefi.c3l/src/protocol/console.c3 +++ /dev/null @@ -1,225 +0,0 @@ -module uefi::proto::console; -import uefi; - - -/***/ -bitstruct ConsoleColor : char @bigendian -{ - TextColor background : 0..3; - TextColor foreground : 4..7; /* NOTE: bit '7' is technically not used per spec */ -} - - -/* 12.1.) Console I/O Protocol (Scan Codes - see Appendix B, Table B.1) */ -enum ScanCode : ushort (ushort raw) -{ - NULL { 0x0000 }, - UP_ARROW { 0x0001 }, - DOWN_ARROW { 0x0002 }, - RIGHT_ARROW { 0x0003 }, - LEFT_ARROW { 0x0004 }, - HOME { 0x0005 }, - END { 0x0006 }, - INSERT { 0x0007 }, - DELETE { 0x0008 }, - PAGE_UP { 0x0009 }, - PAGE_DOWN { 0x000A }, - F1 { 0x000B }, - F2 { 0x000C }, - F3 { 0x000D }, - F4 { 0x000E }, - F5 { 0x000F }, - F6 { 0x0010 }, - F7 { 0x0011 }, - F8 { 0x0012 }, - F9 { 0x0013 }, - F10 { 0x0014 }, - F11 { 0x0015 }, - F12 { 0x0016 }, - ESCAPE { 0x0017 }, - PAUSE { 0x0048 }, - F13 { 0x0068 }, - F14 { 0x0069 }, - F15 { 0x006A }, - F16 { 0x006B }, - F17 { 0x006C }, - F18 { 0x006D }, - F19 { 0x006E }, - F20 { 0x006F }, - F21 { 0x0070 }, - F22 { 0x0071 }, - F23 { 0x0072 }, - F24 { 0x0073 }, - MUTE { 0x007F }, - VOLUME_UP { 0x0080 }, - VOLUME_DOWN { 0x0081 }, - BRIGHTNESS_UP { 0x0100 }, - BRIGHTNESS_DOWN { 0x0101 }, - SUSPEND { 0x0102 }, - HIBERNATE { 0x0103 }, - TOGGLE_DISPLAY { 0x0104 }, - RECOVERY { 0x0105 }, - EJECT { 0x0106 }, -} - - -/* 12.3.) Simple Text Input Protocol */ -module uefi::guid; -const EfiGuid SIMPLE_TEXT_INPUT_PROTOCOL = { - 0x387477c1, - 0x69c7, - 0x11d2, - { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } -}; -const EfiGuid SIMPLE_TEXT_INPUT_EX_PROTOCOL = { - 0xdd9e7534, - 0x7762, - 0x4698, - { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } -}; - -module uefi::proto::console; -struct SimpleTextInputProtocol -{ - FnInputReset reset; - FnInputReadKey read_key; - EfiEvent event_wait_for_key; -} - -struct EfiInputKey -{ - ushort scan_code; - ushort unicode_char; -} - -alias FnInputReset = fn EfiStatus(SimpleTextInputProtocol*, bool); -alias FnInputReadKey = fn EfiStatus(SimpleTextInputProtocol*, EfiInputKey*); - - -/* 12.2.) Simple Text Input Ex Protocol */ -struct SimpleTextInputExProtocol -{ - FnInputResetEx reset; - FnInputReadKeyEx read_key; - EfiEvent event_wait_for_key; - FnInputSetState set_state; - FnInputRegisterKeystrokeNotify register_keystroke_notify; - FnInputUnregisterKeystrokeNotify unregister_keystroke_notify; -} - -enum KeyShiftState : uint (uint raw) -{ - SHIFT_STATE_VALID { 0x8000_0000 }, - RIGHT_SHIFT_PRESSED { 0x0000_0001 }, - LEFT_SHIFT_PRESSED { 0x0000_0002 }, - RIGHT_CONTROL_PRESSED { 0x0000_0004 }, - LEFT_CONTROL_PRESSED { 0x0000_0008 }, - RIGHT_ALT_PRESSED { 0x0000_0010 }, - LEFT_ALT_PRESSED { 0x0000_0020 }, - RIGHT_LOGO_PRESSED { 0x0000_0040 }, - LEFT_LOGO_PRESSED { 0x0000_0080 }, - MENU_KEY_PRESSED { 0x0000_0100 }, - SYS_REQ_PRESSED { 0x0000_0200 }, -} - -enum KeyToggleState : char (char raw) -{ - TOGGLE_STATE_VALID { 0x80 }, - KEY_STATE_EXPOSED { 0x40 }, - SCROLL_LOCK_ACTIVE { 0x01 }, - NUM_LOCK_ACTIVE { 0x02 }, - CAPS_LOCK_ACTIVE { 0x04 }, -} - -struct EfiKeyState -{ - KeyShiftState key_shift_state; - KeyToggleState key_toggle_state; -} - -struct EfiKeyData -{ - EfiInputKey key; - EfiKeyState key_state; -} - -alias FnInputResetEx = fn EfiStatus(SimpleTextInputExProtocol*, bool); -alias FnInputReadKeyEx = fn EfiStatus(SimpleTextInputExProtocol*, EfiKeyData*); -alias FnInputSetState = fn EfiStatus(SimpleTextInputExProtocol*, KeyToggleState*); -alias FnInputRegisterKeystrokeNotify = fn EfiStatus( - SimpleTextInputExProtocol*, - EfiKeyData*, - FnKeyNotificationFunction, - void** -); -alias FnInputUnregisterKeystrokeNotify = fn EfiStatus(EfiKeyData*); - -alias FnKeyNotificationFunction = fn EfiStatus(EfiKeyData*); - - -/* 12.4.) Simple Text Output Protocol */ -module uefi::guid; -const EfiGuid SIMPLE_TEXT_OUTPUT_PROTOCOL = { - 0x387477c2, - 0x69c7, - 0x11d2, - { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } -}; - -module uefi::proto::console; -struct SimpleTextOutputProtocol -{ - FnOutputReset reset; - FnOutputString output_string; - FnOutputTestString test_string; - FnOutputQueryMode query_mode; - FnOutputSetMode set_mode; - FnOutputSetAttribute set_attribute; - FnOutputClearScreen clear_screen; - FnOutputSetCursorPosition set_cursor_position; - FnOutputEnableCursor enable_cursor; - TextMode* mode; -} - -struct TextMode -{ - int max_mode; - int current_mode; - int current_attribute; - int current_cursor_column; - int current_cursor_row; - bool is_cursor_visible; -} - -alias FnOutputReset = fn EfiStatus(SimpleTextOutputProtocol*, bool); -alias FnOutputString = fn EfiStatus(SimpleTextOutputProtocol*, EfiStringRaw); -alias FnOutputTestString = fn EfiStatus(SimpleTextOutputProtocol*, EfiStringRaw); -alias FnOutputQueryMode = fn EfiStatus(SimpleTextOutputProtocol*, usz, usz*, usz*); -alias FnOutputSetMode = fn EfiStatus(SimpleTextOutputProtocol*, usz); -alias FnOutputSetAttribute = fn EfiStatus(SimpleTextOutputProtocol*, usz); -alias FnOutputClearScreen = fn EfiStatus(SimpleTextOutputProtocol*); -alias FnOutputSetCursorPosition = fn EfiStatus(SimpleTextOutputProtocol*, usz, usz); -alias FnOutputEnableCursor = fn EfiStatus(SimpleTextOutputProtocol*, bool); - -/* Standard terminal color constants. */ -enum TextColor : char (char raw) -{ - BLACK { 0x00 }, - BLUE { 0x01 }, - GREEN { 0x02 }, - CYAN { 0x03 }, - RED { 0x04 }, - MAGENTA { 0x05 }, - BROWN { 0x06 }, - LIGHT_GRAY { 0x07 }, - DARK_GRAY { 0x08 }, /* BRIGHT, or (BLACK|BRIGHT) */ - LIGHT_BLUE { 0x09 }, - LIGHT_GREEN { 0x0A }, - LIGHT_CYAN { 0x0B }, - LIGHT_RED { 0x0C }, - LIGHT_MAGENTA { 0x0D }, - YELLOW { 0x0E }, - WHITE { 0x0F }, -} - -macro char @efi_color($fg, $bg) @builtin @public => ($fg | ((0x07 & $bg) << 4)); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/evt_timer_task.c3 b/lib/uefi.c3l/src/protocol/evt_timer_task.c3 deleted file mode 100644 index 95c6cf3..0000000 --- a/lib/uefi.c3l/src/protocol/evt_timer_task.c3 +++ /dev/null @@ -1,103 +0,0 @@ -module uefi::proto::evt; -import uefi; - - -/* 7.1.) Event, Timer, and Task Priority Services */ -/* NOTE: EfiEvent is defined in ../def.c3, as it's more globally used. */ -enum EventType : uint (uint raw) -{ - TIMER { 0x8000_0000 }, - RUNTIME { 0x4000_0000 }, - NOTIFY_WAIT { 0x0000_0100 }, - NOTIFY_SIGNAL { 0x0000_0200 }, - SIGNAL_EXIT_BOOT_SERVICES { 0x0000_0201 }, - SIGNAL_VIRTUAL_ADDRESS_CHANGE { 0x6000_0202 }, -} - - -/* EFI_EVENT_NOTIFY (7.1.1) */ -alias FnEventNotify = fn void(EfiEvent, void*); - -/* EFI_CREATE_EVENT (7.1.1) */ -alias FnCreateEvent = fn EfiStatus(EventType, EventTpl, FnEventNotify, void*, EfiEvent*); - -/* EFI_CREATE_EVENT_EX (7.1.2) */ -alias FnCreateEventEx = fn EfiStatus(EventType, EventTpl, FnEventNotify, void*, EfiGuid*, EfiEvent*); - -/* EFI event group GUIDs (7.1.2) */ -const EfiGuid EVENT_GROUP_EXIT_BOOT_SERVICES = { - 0x27abf055, - 0xb1b8, - 0x4c26, - { 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf } -}; -const EfiGuid EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES = { - 0x8be0e274, - 0x3970, - 0x4b44, - { 0x80, 0xc5, 0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc } -}; -const EfiGuid EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE = { - 0x13fa7698, - 0xc831, - 0x49c7, - { 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 } -}; -const EfiGuid EVENT_GROUP_MEMORY_MAP_CHANGE = { - 0x78bee926, - 0x692f, - 0x48fd, - { 0x9e, 0xdb, 0x01, 0x42, 0x2e, 0xf0, 0xd7, 0xab } -}; -const EfiGuid EVENT_GROUP_READY_TO_BOOT = { - 0x7ce88fb3, - 0x4bd7, - 0x4679, - { 0x87, 0xa8, 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b } -}; -const EfiGuid EVENT_GROUP_AFTER_READY_TO_BOOT = { - 0x3a2a00ad, - 0x98b9, - 0x4cdf, - { 0xa4, 0x78, 0x70, 0x27, 0x77, 0xf1, 0xc1, 0x0b } -}; -const EfiGuid EVENT_GROUP_RESET_SYSTEM = { - 0x62da6a56, - 0x13fb, - 0x485a, - { 0xa8, 0xda, 0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b } -}; - -/* EFI_CLOSE_EVENT (7.1.3) */ -alias FnCloseEvent = fn EfiStatus(EfiEvent); - -/* EFI_SIGNAL_EVENT (7.1.4) */ -alias FnSignalEvent = fn EfiStatus(EfiEvent); - -/* EFI_WAIT_FOR_EVENT (7.1.5) */ -alias FnWaitForEvent = fn EfiStatus(usz, EfiEvent*, usz*); - -/* EFI_CHECK_EVENT (7.1.6) */ -alias FnCheckEvent = fn EfiStatus(EfiEvent); - -/* EFI_SET_TIMER (7.1.7) and EFI_TIMER_DELAY */ -alias FnSetTimer = fn EfiStatus(EfiEvent, TimerDelay, ulong); - -enum TimerDelay -{ - TIMER_CANCEL, - TIMER_PERIODIC, - TIMER_RELATIVE, -} - -/* EFI_RAISE_TPL (7.1.8) and TPL */ -alias FnRaiseTpl = fn EventTpl(EventTpl); - -typedef EventTpl = usz; -const EventTpl TPL_APPLICATION = (EventTpl)4; -const EventTpl TPL_CALLBACK = (EventTpl)8; -const EventTpl TPL_NOTIFY = (EventTpl)16; -const EventTpl TPL_HIGH_LEVEL = (EventTpl)31; - -/* EFI_RESTORE_TPL (7.1.9) */ -alias FnRestoreTpl = fn void(EventTpl); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/handler.c3 b/lib/uefi.c3l/src/protocol/handler.c3 deleted file mode 100644 index 5bc9e86..0000000 --- a/lib/uefi.c3l/src/protocol/handler.c3 +++ /dev/null @@ -1,86 +0,0 @@ -module uefi::proto::handle; -import uefi; - - -/* 7.3) Protocol Handler Services */ -/* EFI_INSTALL_PROTOCOL_INTERFACE (7.3.2) and related definitions */ -alias FnInstallProtocolInterface = fn EfiStatus(EfiHandle*, EfiGuid*, InterfaceType, void*); - -/* NOTE: EFI_HANDLE and EFI_GUID are defined in the def.c3 globals file. */ -enum InterfaceType -{ - NATIVE_INTERFACE, -} - -/* EFI_UNINSTALL_PROTOCOL_INTERFACE (7.3.3) */ -alias FnUninstallProtocolInterface = fn EfiStatus(EfiHandle*, EfiGuid*, void*); - -/* EFI_REINSTALL_PROTOCOL_INTERFACE (7.3.4) */ -alias FnReinstallProtocolInterface = fn EfiStatus(EfiHandle*, EfiGuid*, void*, void*); - -/* EFI_REGISTER_PROTOCOL_NOTIFY (7.3.5) */ -alias FnRegisterProtocolNotify = fn EfiStatus(EfiGuid*, EfiEvent, void**); - -/* EFI_LOCATE_HANDLE (7.3.6) and related */ -alias FnLocateHandle = fn EfiStatus(HandleSearchType, EfiGuid*, void*, usz*, EfiHandle*); - -enum HandleSearchType -{ - ALL_HANDLES, - BY_REGISTER_NOTIFY, - BY_PROTOCOL, -} - -/* EFI_HANDLE_PROTOCOL (7.3.7) */ -alias FnHandleProtocol = fn EfiStatus(EfiHandle, EfiGuid*, void**); - -/* EFI_LOCATE_DEVICE_PATH (7.3.8) */ -// alias FnLocateDevicePath = fn EfiStatus(EfiGuid*, device::DevicePathProtocol**, EfiHandle*); -alias FnLocateDevicePath = fn EfiStatus(EfiGuid*, void**, EfiHandle*); - -/* EFI_OPEN_PROTOCOL (7.3.9) and related */ -alias FnOpenProtocol = fn EfiStatus(EfiHandle, EfiGuid*, void**, EfiHandle, EfiHandle, OpenProtocolAttribute); - -alias OpenProtocolAttribute = uint; -const OpenProtocolAttribute BY_HANDLE_PROTOCOL = 0x0000_0001; -const OpenProtocolAttribute GET_PROTOCOL = 0x0000_0002; -const OpenProtocolAttribute TEST_PROTOCOL = 0x0000_0004; -const OpenProtocolAttribute BY_CHILD_CONTROLLER = 0x0000_0008; -const OpenProtocolAttribute BY_DRIVER = 0x0000_0010; -const OpenProtocolAttribute EXCLUSIVE = 0x0000_0020; - -/* EFI_CLOSE_PROTOCOL (7.3.10) */ -alias FnCloseProtocol = fn EfiStatus(EfiHandle, EfiGuid*, EfiHandle, EfiHandle); - -/* EFI_OPEN_PROTOCOL_INFORMATION (7.3.11) and related */ -alias FnOpenProtocolInformation = fn EfiStatus(EfiHandle, EfiGuid*, OpenProtocolInformationEntry**, usz*); - -struct OpenProtocolInformationEntry -{ - EfiHandle agent_handle; - EfiHandle controller_handle; - OpenProtocolAttribute attributes; - uint open_count; -} - -/* EFI_CONNECT_CONTROLLER (7.3.12) */ -// alias FnConnectController = fn EfiStatus(EfiHandle, EfiHandle*, device::DevicePathProtocol*, bool); -alias FnConnectController = fn EfiStatus(EfiHandle, EfiHandle*, void*, bool); - -/* EFI_DISCONNECT_CONTROLLER (7.3.13) */ -alias FnDisconnectController = fn EfiStatus(EfiHandle, EfiHandle, EfiHandle); - -/* EFI_PROTOCOLS_PER_HANDLE (7.3.14) */ -alias FnProtocolsPerHandle = fn EfiStatus(EfiHandle, EfiGuid***, usz*); - -/* EFI_LOCATE_HANDLE_BUFFER (7.3.15) */ -alias FnLocateHandleBuffer = fn EfiStatus(HandleSearchType, EfiGuid*, void*, usz*, EfiHandle**); - -/* EFI_LOCATE_PROTOCOL (7.3.16) */ -alias FnLocateProtocol = fn EfiStatus(EfiGuid*, void*, void**); - -/* EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES (7.3.17) */ -alias FnInstallMultipleProtocolInterfaces = fn EfiStatus(EfiHandle*, ...); - -/* EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES (7.3.18) */ -alias FnUninstallMultipleProtocolInterfaces = fn EfiStatus(EfiHandle, ...); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/image.c3 b/lib/uefi.c3l/src/protocol/image.c3 deleted file mode 100644 index eb1a4b1..0000000 --- a/lib/uefi.c3l/src/protocol/image.c3 +++ /dev/null @@ -1,27 +0,0 @@ -module uefi::proto::image; -import uefi; - - -/* 7.4) Image Services */ -/* EFI_IMAGE_LOAD (7.4.1) */ -// alias FnLoadImage = fn EfiStatus(bool, EfiHandle, device::DevicePathProtocol*, void*, usz, EfiHandle*); -alias FnLoadImage = fn EfiStatus(bool, EfiHandle, void*, void*, usz, EfiHandle*); - -/* const EfiGuid HII_PACKAGE_LIST_PROTOCOL = - { 0x6a1ee763, 0xd47a, 0x43b4, {0xaa,0xbe,0xef,0x1d,0xe2,0xab,0x56,0xfc} }; -alias HiiPackageListHeader = hii::PackageListProtocol; */ - -/* EFI_IMAGE_START (7.4.2) */ -alias FnStartImage = fn EfiStatus(EfiHandle, usz*, EfiStringRaw*); - -/* EFI_IMAGE_UNLOAD (7.4.3) */ -alias FnUnloadImage = fn EfiStatus(EfiHandle); - -/* EFI_IMAGE_ENTRY_POINT (7.4.4) */ -alias FnImageEntryPoint = fn EfiStatus(EfiHandle, SystemTable*); - -/* EFI_EXIT (7.4.5) */ -alias FnExitImage = fn EfiStatus(EfiHandle, EfiStatus, usz, EfiStringRaw); - -/* EFI_EXIT_BOOT_SERVICES (7.4.6) */ -alias FnExitBootServices = fn EfiStatus(EfiHandle, usz); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/mem.c3 b/lib/uefi.c3l/src/protocol/mem.c3 deleted file mode 100644 index d829005..0000000 --- a/lib/uefi.c3l/src/protocol/mem.c3 +++ /dev/null @@ -1,105 +0,0 @@ -module uefi::proto::memory; -import uefi; - - -/* 7.2.) Memory Allocation Services */ - -/* EFI_ALLOCATE_PAGES (7.2.1) and Allocation definitions */ -alias FnAllocatePages = fn EfiStatus(AllocateType, MemoryType, usz, PhysicalAddress*); - -alias PhysicalAddress = ulong; -alias VirtualAddress = ulong; -enum AllocateType -{ - ANY_PAGES, - MAX_ADDRESS, - ADDRESS, - LIMIT -} -enum MemoryType : uint -{ - RESERVED, - LOADER_CODE, - LOADER_DATA, - BOOT_SERVICES_CODE, - BOOT_SERVICES_DATA, - RUNTIME_SERVICES_CODE, - RUNTIME_SERVICES_DATA, - CONVENTIONAL, - UNUSABLE, - ACPI_RECLAIM, - ACPI_NVS, - MMIO, - MMIO_PORT_SPACE, - PAL_CODE, - PERSISTENT, - UNACCEPTED, - LIMIT -} - -/* EFI_FREE_PAGES (7.2.2) */ -alias FnFreePages = fn EfiStatus(PhysicalAddress, usz); - -/* EFI_GET_MEMORY_MAP (7.2.3) and related definitions */ -alias FnGetMemoryMap = fn EfiStatus(usz*, void*, usz*, usz*, uint*); - -const uint MEMORY_DESCRIPTOR_VERSION = 1; -struct MemoryDescriptor -{ - MemoryType type; - PhysicalAddress physical_start; - VirtualAddress virtual_start; - ulong num_pages; - MemoryAttribute attribute; -} - -struct SystemMemoryMap -{ - usz map_key; - usz buffer_size; - usz descriptor_size; - uint descriptor_version; - void* descriptors; - usz descriptors_count; -} - -typedef MemoryAttribute = ulong; -const MemoryAttribute MEMORY_UC = (MemoryAttribute)0x0000_0000_0000_0001; -const MemoryAttribute MEMORY_WC = (MemoryAttribute)0x0000_0000_0000_0002; -const MemoryAttribute MEMORY_WT = (MemoryAttribute)0x0000_0000_0000_0004; -const MemoryAttribute MEMORY_WB = (MemoryAttribute)0x0000_0000_0000_0008; -const MemoryAttribute MEMORY_UCE = (MemoryAttribute)0x0000_0000_0000_0010; -const MemoryAttribute MEMORY_WP = (MemoryAttribute)0x0000_0000_0000_1000; -const MemoryAttribute MEMORY_RP = (MemoryAttribute)0x0000_0000_0000_2000; -const MemoryAttribute MEMORY_XP = (MemoryAttribute)0x0000_0000_0000_4000; -const MemoryAttribute MEMORY_NV = (MemoryAttribute)0x0000_0000_0000_8000; -const MemoryAttribute MEMORY_MORE_RELIABLE = (MemoryAttribute)0x0000_0000_0001_0000; -const MemoryAttribute MEMORY_RO = (MemoryAttribute)0x0000_0000_0002_0000; -const MemoryAttribute MEMORY_SP = (MemoryAttribute)0x0000_0000_0004_0000; -const MemoryAttribute MEMORY_CPU_CRYPTO = (MemoryAttribute)0x0000_0000_0008_0000; -const MemoryAttribute MEMORY_HOT_PLUGGABLE = (MemoryAttribute)0x0000_0000_0010_0000; -const MemoryAttribute MEMORY_RUNTIME = (MemoryAttribute)0x8000_0000_0000_0000; -const MemoryAttribute MEMORY_ISA_VALID = (MemoryAttribute)0x4000_0000_0000_0000; -const MemoryAttribute MEMORY_ISA_MASK = (MemoryAttribute)0x0FFF_F000_0000_0000; - -/* EFI_ALLOCATE_POOL (7.2.4) */ -alias FnAllocatePool = fn EfiStatus(MemoryType, usz, void**); - -/* EFI_FREE_POOL (7.2.5) */ -alias FnFreePool = fn EfiStatus(void*); - - -/* 8.4.) Virtual Memory services */ -/* 8.4.1.) SetVirtualAddressMap() */ -alias FnSetVirtualAddressMap = fn EfiStatus(usz, usz, uint, MemoryDescriptor*); - -/* 8.4.2.) ConvertPointer() */ -alias FnConvertPointer = fn EfiStatus(usz, void**); -const usz EFI_OPTIONAL_PTR = 0x1; - -/* 8.5.3.3.) Items related to capsules */ -struct MemoryRange -{ - PhysicalAddress address; - ulong length; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/misc_boot_svcs.c3 b/lib/uefi.c3l/src/protocol/misc_boot_svcs.c3 deleted file mode 100644 index 8fc17af..0000000 --- a/lib/uefi.c3l/src/protocol/misc_boot_svcs.c3 +++ /dev/null @@ -1,25 +0,0 @@ -module uefi::proto::misc_bs; -import uefi; - - -/* 7.5) Miscellaneous Boot Services */ -/* EFI_SET_WATCHDOG_TIMER (7.5.1) */ -alias FnSetWatchdogTimer = fn EfiStatus(usz, ulong, usz, EfiStringRaw); - -/* EFI_STALL (7.5.2) */ -alias FnStall = fn EfiStatus(usz); - -/* EFI_COPY_MEM (7.5.3) */ -alias FnCopyMem = fn void(void*, void*, usz); - -/* EFI_SET_MEM (7.5.4) */ -alias FnSetMem = fn void(void*, usz, char); - -/* EFI_GET_NEXT_MONOTONIC_COUNT (7.5.5) */ -alias FnGetNextMonotonicCount = fn EfiStatus(ulong*); - -/* EFI_INSTALL_CONFIGURATION_TABLE (7.5.6) */ -alias FnInstallConfigurationTable = fn EfiStatus(EfiGuid*, void*); - -/* EFI_CALCULATE_CRC32 (7.5.7) */ -alias FnCalculateCrc32 = fn EfiStatus(void*, usz, uint*); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/misc_runtime_svcs.c3 b/lib/uefi.c3l/src/protocol/misc_runtime_svcs.c3 deleted file mode 100644 index 0ec0aba..0000000 --- a/lib/uefi.c3l/src/protocol/misc_runtime_svcs.c3 +++ /dev/null @@ -1,124 +0,0 @@ -module uefi::proto::misc_rt; -import uefi; - - -/* 8.5.) Miscellaneous Runtime services */ -/* 8.5.1.1.) ResetSystem() */ -alias FnResetSystem = fn void(ResetType, EfiStatus, usz, void*); - -enum ResetType : uint -{ - COLD, - WARM, - SHUTDOWN, - PLATFORM_SPECIFIC, -} - -/* 8.5.2.1.) GetNextHighMonotonicCount() */ -alias FnGetNextHighMonotonicCount = fn EfiStatus(uint*); - -/* 8.5.3.1.) UpdateCapsule() and related */ -alias FnUpdateCapsule = fn EfiStatus(CapsuleHeader**, usz, PhysicalAddress); - -struct CapsuleHeader -{ - EfiGuid capsule_guid; - uint header_size; - uint flags; - uint capsule_image_size; -} - -enum CapsuleFlags : uint (uint raw) -{ - PERSIST_ACROSS_RESET { 0x0001_0000 }, - POPULATE_SYSTEM_TABLE { 0x0002_0000 }, - INITIATE_RESET { 0x0004_0000 }, -} - -struct CapsuleBlockDescriptor -{ - ulong length; - union - { - PhysicalAddress data_block; - PhysicalAddress continuation_pointer; - } -} - -struct CapsuleTable -{ - uint capsule_array_number; - void* capsule_ptr; -} - -const EfiGuid EFI_MEMORY_RANGE_CAPSULE_GUID = { - 0xde9f0ec, - 0x88b6, - 0x428f, - { 0x97, 0x7a, 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72 } -}; - -struct MemoryRangeCapsule -{ - CapsuleHeader header; - uint requested_memory_type; - ulong num_memory_ranges; - MemoryRange* memory_ranges; -} - -struct MemoryRangeCapsuleResult -{ - ulong firmware_memory_requirement; - ulong num_memory_ranges; -} - -/* 8.5.3.4.) QueryCapsuleCapabilities() */ -alias FnQueryCapsuleCapabilities = fn EfiStatus(CapsuleHeader**, usz, ulong*, ResetType*); - -/* OS Indications from a nearby section */ -enum OsIndications : ulong (ulong raw) // TODO: Change to inline ulong once supported -{ - BOOT_TO_FW_UI { 0x1 }, - TIMESTAMP_REVOCATION { 0x2 }, - FILE_CAPSULE_DELIVERY_SUPPORTED { 0x4 }, - FMP_CAPSULE_SUPPORTED { 0x8 }, - CAPSULE_RESULT_VAR_SUPPORTED { 0x10 }, - START_OS_RECOVERY { 0x20 }, - START_PLATFORM_RECOVERY { 0x40 }, - JSON_CONFIG_DATA_REFRESH { 0x80 }, -} - -/* 8.5.6.1.) -- */ -const EfiGuid EFI_CAPSULE_REPORT_GUID = { - 0x39b68c46, - 0xf7fb, - 0x441b, - { 0xb6, 0xec, 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3 } -}; - -struct CapsuleResultVariableHeader -{ - uint variable_total_size; - uint reserved; /* spec says 'alignment' */ - EfiGuid capsule_guid; - EfiTime capsule_processed_at; - EfiStatus capsule_status; -} - -struct CapsuleResultVariableFMP -{ - ushort version; - char payload_index; - char update_image_index; - EfiGuid update_image_type_id; - /* implied: EfiStringRaw capsule_file_name */ - /* implied: EfiStringRaw capsule_target */ -} - -struct CapsuleResultVariableJson -{ - uint version; - uint capsule_id; - uint response_length; - char* response_data; -} \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/time.c3 b/lib/uefi.c3l/src/protocol/time.c3 deleted file mode 100644 index 261e4b1..0000000 --- a/lib/uefi.c3l/src/protocol/time.c3 +++ /dev/null @@ -1,23 +0,0 @@ -module uefi::proto::time; -import uefi; - - -/* 8.3.) Time services */ -/* 8.3.1.) GetTime() */ -alias FnGetTime = fn EfiStatus(EfiTime*, EfiTimeCapabilities*); - -struct TimeCapabilities -{ - uint resolution; - uint accuracy; - bool sets_to_zero; -} - -/* 8.3.2.) SetTime() */ -alias FnSetTime = fn EfiStatus(EfiTime*); - -/* 8.3.3.) GetWakeupTime() */ -alias FnGetWakeupTime = fn EfiStatus(bool*, bool*, EfiTime*); - -/* 8.3.4.) SetWakeupTime() */ -alias FnSetWakeupTime = fn EfiStatus(bool, EfiTime*); \ No newline at end of file diff --git a/lib/uefi.c3l/src/protocol/variable.c3 b/lib/uefi.c3l/src/protocol/variable.c3 deleted file mode 100644 index bf5175b..0000000 --- a/lib/uefi.c3l/src/protocol/variable.c3 +++ /dev/null @@ -1,68 +0,0 @@ -module uefi::proto::variable; -import uefi; - - -/* 8.2.) Variable services */ -/* 8.2.1.) GetVariable() */ -alias FnGetVariable = fn EfiStatus(EfiStringRaw, EfiGuid*, uint*, usz*, void*); - -/* Variable Attributes */ -enum EfiVarAttr : uint (uint raw) // TODO: Add `inline` inside parens when supported -{ - NON_VOLATILE { 0x0000_0001 }, - BOOTSERVICE_ACCESS { 0x0000_0002 }, - RUNTIME_ACCESS { 0x0000_0004 }, - HARDWARE_ERROR_RECORD { 0x0000_0008 }, - HR { 0x0000_0008 }, /* spec notes aliasing of this to above */ - RESERVED { 0x0000_0010 }, - TIME_BASED_AUTHENTICATED_WRITE_ACCESS { 0x0000_0020 }, - APPEND_WRITE { 0x0000_0040 }, - ENHANCED_AUTHENTICATED_ACCESS { 0x0000_0080 }, -} - -struct VariableAuthentication3CertId -{ - char type; - uint id_size; - /* implied to follow: char id[id_size]; */ -} - -/* 8.2.2.) GetNextVariableName() */ -alias FnGetNextVariableName = fn EfiStatus(usz*, EfiStringRaw, EfiGuid*); - -/* 8.2.3.) SetVariable() */ -alias FnSetVariable = fn EfiStatus(EfiStringRaw, EfiGuid*, uint, usz, void*); - -/* TODO: Too much extra complexity to use right now. Add later. */ -/* struct VariableAuthentication2 -{ - EfiTime timestamp; - WinCertificateUefiGuid auth_info; -} */ - -const char EFI_VARIABLE_AUTHENTICATION_3_TIMESTAMP_TYPE = 1; -const char EFI_VARIABLE_AUTHENTICATION_3_NONCE_TYPE = 2; -struct VariableAuthentication3 -{ - char version; - char type; - uint metadata_size; - uint flags; -} - -struct VariableAuthentication3Nonce -{ - uint nonce_size; - /* implied to follow: char nonce[nonce_size]; */ -} - -/* 8.2.4.) QueryVariableInfo() */ -alias FnQueryVariableInfo = fn EfiStatus(uint, ulong*, ulong*, ulong*); - -/* 8.2.7.2.) Hardware Error Record Variables */ -const EfiGuid EFI_HARDWARE_ERROR_VARIABLE = { - 0x414e6bdd, - 0xe47b, - 0x47cc, - { 0xb2, 0x44, 0xbb, 0x61, 0x02, 0x0c, 0xf5, 0x16 } -}; \ No newline at end of file diff --git a/lib/uefi.c3l/uefi/guid.c3i b/lib/uefi.c3l/uefi/guid.c3i new file mode 100644 index 0000000..928d6e1 --- /dev/null +++ b/lib/uefi.c3l/uefi/guid.c3i @@ -0,0 +1,29 @@ +module uefi; + +struct EfiGuid @packed { + uint data1; + ushort data2; + ushort data3; + char[8] data4; +} + +module uefi::guid; + +const EfiGuid SIMPLE_TEXT_INPUT_PROTOCOL = { 0x387477c1, 0x69c7, 0x11d2, {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} }; +const EfiGuid SIMPLE_TEXT_INPUT_EX_PROTOCOL = { 0xdd9e7534, 0x7762, 0x4698, {0x8c,0x14,0xf5,0x85,0x17,0xa6,0x25,0xaa} }; +const EfiGuid SIMPLE_TEXT_OUTPUT_PROTOCOL = { 0x387477c2, 0x69c7, 0x11d2, {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} }; + +const EfiGuid LOADED_IMAGE_PROTOCOL = {0x5b1b31A1, 0x9562, 0x11d2, {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B} }; +const EfiGuid SIMPLE_FILE_SYSTEM_PROTOCOL = {0x0964e5b22, 0x6459, 0x11d2, {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} }; +const EfiGuid FILE_INFO = {0x09576e92, 0x6d3f, 0x11d2, {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} }; +const EfiGuid FILE_SYSTEM_INFO = {0x09576e93, 0x6d3f, 0x11d2, {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} }; + +// Configuration tables +const EfiGuid ACPI_20_TABLE = { 0x8868e871, 0xe4f1, 0x11d3, {0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81} }; + +macro bool @compare(EfiGuid #a, EfiGuid #b) { + return #a.data1 == #b.data1 + && #a.data2 == #b.data2 + && #a.data3 == #b.data3 + && #a.data4 == #b.data4; +} diff --git a/lib/uefi.c3l/uefi/protocol/console.c3i b/lib/uefi.c3l/uefi/protocol/console.c3i new file mode 100644 index 0000000..19faf2d --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/console.c3i @@ -0,0 +1,173 @@ +module uefi::protocol::console; + +import uefi; + +alias InputResetFn = fn EfiStatus (SimpleTextInputProtocol*, bool); +alias InputReadKeyFn = fn EfiStatus (SimpleTextInputProtocol*, EfiInputKey*); +alias InputResetExFn = fn EfiStatus(SimpleTextInputExProtocol*, bool); +alias InputReadKeyExFn = fn EfiStatus (SimpleTextInputExProtocol*, EfiKeyData*); +alias InputSetStateFn = fn EfiStatus (SimpleTextInputExProtocol*, KeyToggleState*); +alias InputRegisterKeystrokeNotifyFn = fn EfiStatus (SimpleTextInputExProtocol*, EfiKeyData*, KeyNotificationFunctionFn, void**); +alias InputUnregisterKeystrokeNotifyFn = fn EfiStatus (EfiKeyData*); +alias KeyNotificationFunctionFn = fn EfiStatus (EfiKeyData*); +alias OutputResetFn = fn EfiStatus (SimpleTextOutputProtocol*, bool); +alias OutputStringFn = fn EfiStatus (SimpleTextOutputProtocol*, EfiString); +alias OutputTestStringFn = fn EfiStatus (SimpleTextOutputProtocol*, EfiString); +alias OutputQueryModeFn = fn EfiStatus (SimpleTextOutputProtocol*, usz, usz*, usz*); +alias OutputSetModeFn = fn EfiStatus (SimpleTextOutputProtocol*, usz); +alias OutputSetAttributeFn = fn EfiStatus (SimpleTextOutputProtocol*, usz); +alias OutputClearScreenFn = fn EfiStatus (SimpleTextOutputProtocol*); +alias OutputSetCursorPositionFn = fn EfiStatus (SimpleTextOutputProtocol*, usz, usz); +alias OutputEnableCursorFn = fn EfiStatus (SimpleTextOutputProtocol*, bool); + +bitstruct ConsoleColor : char @bigendian { + TextColor background: 0..3; + TextColor foreground: 4..6; + // bit 7 is technically not used per spec +} + +enum ScanCode : ushort (ushort raw) { + NULL { 0x0000 }, + UP_ARROW { 0x0001 }, + DOWN_ARROW { 0x0002 }, + RIGHT_ARROW { 0x0003 }, + LEFT_ARROW { 0x0004 }, + HOME { 0x0005 }, + END { 0x0006 }, + INSERT { 0x0007 }, + DELETE { 0x0008 }, + PAGE_UP { 0x0009 }, + PAGE_DOWN { 0x000A }, + F1 { 0x000B }, + F2 { 0x000C }, + F3 { 0x000D }, + F4 { 0x000E }, + F5 { 0x000F }, + F6 { 0x0010 }, + F7 { 0x0011 }, + F8 { 0x0012 }, + F9 { 0x0013 }, + F10 { 0x0014 }, + F11 { 0x0015 }, + F12 { 0x0016 }, + ESCAPE { 0x0017 }, + PAUSE { 0x0048 }, + F13 { 0x0068 }, + F14 { 0x0069 }, + F15 { 0x006A }, + F16 { 0x006B }, + F17 { 0x006C }, + F18 { 0x006D }, + F19 { 0x006E }, + F20 { 0x006F }, + F21 { 0x0070 }, + F22 { 0x0071 }, + F23 { 0x0072 }, + F24 { 0x0073 }, + MUTE { 0x007F }, + VOLUME_UP { 0x0080 }, + VOLUME_DOWN { 0x0081 }, + BRIGHTNESS_UP { 0x0100 }, + BRIGHTNESS_DOWN { 0x0101 }, + SUSPEND { 0x0102 }, + HIBERNATE { 0x0103 }, + TOGGLE_DISPLAY { 0x0104 }, + RECOVERY { 0x0105 }, + EJECT { 0x0106 }, +} + +struct SimpleTextInputProtocol { + InputResetFn _reset; + InputReadKeyFn _read_key; + EfiEvent _event_wait_for_key; +} + +struct EfiInputKey { + ushort scanCode; + ushort unicodeChar; +} + +struct SimpleTextInputExProtocol { + InputResetExFn reset; + InputReadKeyExFn read_key; + EfiEvent event_wait_for_key; + InputSetStateFn set_state; + InputRegisterKeystrokeNotifyFn register_keystroke_notify; + InputUnregisterKeystrokeNotifyFn unregister_keystroke_notify; +} + +enum KeyShiftState : uint (uint raw) { + SHIFT_STATE_VALID { 0x8000_0000 }, + RIGHT_SHIFT_PRESSED { 0x0000_0001 }, + LEFT_SHIFT_PRESSED { 0x0000_0002 }, + RIGHT_CONTROL_PRESSED { 0x0000_0004 }, + LEFT_CONTROL_PRESSED { 0x0000_0008 }, + RIGHT_ALT_PRESSED { 0x0000_0010 }, + LEFT_ALT_PRESSED { 0x0000_0020 }, + RIGHT_LOGO_PRESSED { 0x0000_0040 }, + LEFT_LOGO_PRESSED { 0x0000_0080 }, + MENU_KEY_PRESSED { 0x0000_0100 }, + SYS_REQ_PRESSED { 0x0000_0200 }, +} + +enum KeyToggleState : char (char raw) { + TOGGLE_STATE_VALID { 0x80 }, + KEY_STATE_EXPOSED { 0x40 }, + SCROLL_LOCK_ACTIVE { 0x01 }, + NUM_LOCK_ACTIVE { 0x02 }, + CAPS_LOCK_ACTIVE { 0x04 }, +} + +struct EfiKeyState { + KeyShiftState keyShiftState; + KeyToggleState keyToggleState; +} + +struct EfiKeyData { + EfiInputKey key; + EfiKeyState keyState; +} + +struct SimpleTextOutputProtocol { + OutputResetFn _reset; + OutputStringFn _output_string; + OutputTestStringFn _test_string; + OutputQueryModeFn _query_mode; + OutputSetModeFn _set_mode; + OutputSetAttributeFn _set_attribute; + OutputClearScreenFn _clear_screen; + OutputSetCursorPositionFn _set_cursor_position; + OutputEnableCursorFn _enable_cursor; + TextMode* mode; +} + +struct TextMode { + int maxMode; + int currentMode; + int currentAttribute; + int currentCursorColumn; + int currentCursorRow; + bool isCursorVisible; +} + +enum TextColor : char (char raw) { + BLACK { 0x00 }, + BLUE { 0x01 }, + GREEN { 0x02 }, + CYAN { 0x03 }, + RED { 0x04 }, + MAGENTA { 0x05 }, + BROWN { 0x06 }, + LIGHT_GRAY { 0x07 }, + DARK_GRAY { 0x08 }, + LIGHT_BLUE { 0x09 }, + LIGHT_GREEN { 0x0A }, + LIGHT_CYAN { 0x0B }, + LIGHT_RED { 0x0C }, + LIGHT_MAGENTA { 0x0D }, + YELLOW { 0x0E }, + WHITE { 0x0F }, + +} + +macro char @efi_color($fg, $bg) @builtin @public => ($fg | ((0x07 & $bg) << 4)); diff --git a/lib/uefi.c3l/uefi/protocol/file.c3i b/lib/uefi.c3l/uefi/protocol/file.c3i new file mode 100644 index 0000000..72c56d7 --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/file.c3i @@ -0,0 +1,59 @@ +module uefi::protocol::file; + +import uefi; + +alias FileOpenFn = fn EfiStatus (FileProtocol*, FileProtocol** newHandle, WChar* fileName, ulong openMode, ulong attributes); +alias FileCloseFn = fn EfiStatus (FileProtocol*); +alias FileDeleteFn = fn EfiStatus (FileProtocol*); +alias FileReadFn = fn EfiStatus (FileProtocol*, usz*, void*); +alias FileWriteFn = fn EfiStatus (FileProtocol*, usz*, void*); +alias FileGetPositionFn = fn EfiStatus (FileProtocol*, ulong*); +alias FileSetPositionFn = fn EfiStatus (FileProtocol*, ulong); +alias FileGetInfoFn = fn EfiStatus (FileProtocol*, EfiGuid*, usz*, void*); +alias FileSetInfoFn = fn EfiStatus (FileProtocol*, EfiGuid*, usz, void*); +alias FileFlushFn = fn EfiStatus (FileProtocol*); + +alias FileSystemOpenVolumeFn = fn EfiStatus (FileSystemProtocol*, FileProtocol**); + +struct FileProtocol { + ulong revision; + FileOpenFn _open; + FileCloseFn _close; + FileDeleteFn _delete; + FileReadFn _read; + FileWriteFn _write; + FileGetPositionFn _get_position; + FileSetPositionFn _set_position; + FileGetInfoFn _get_info; + FileSetInfoFn _set_info; + FileFlushFn _flush; + void* _open_ex; + void* _read_ex; + void* _write_ex; + void* _flush_ex; +} + +struct FileSystemProtocol { + ulong revision; + FileSystemOpenVolumeFn _open_volume; +} + +struct FileInfo { + ulong size; + ulong fileSize; + ulong physicalSize; + EfiTime createTime; + EfiTime lastAccessTime; + EfiTime editTime; + ulong attribute; + WChar[*] filename; +} + +struct FileSystemInfo { + ulong size; + bool readOnly; + ulong volumeSize; + ulong freeSpace; + uint blockSize; + WChar[*] volumeLabel; +} diff --git a/lib/uefi.c3l/uefi/protocol/image.c3i b/lib/uefi.c3l/uefi/protocol/image.c3i new file mode 100644 index 0000000..5d28f32 --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/image.c3i @@ -0,0 +1,23 @@ +module uefi::protocol::image; + +import uefi; +import uefi::protocol::mem; + +struct LoadedImageProtocol { + uint revision; + EfiHandle parentHandle; + SystemTable* systemTable; + + EfiHandle deviceHandle; + void* filePath; + void* reserved; + + uint loadOptionsSize; + void* loadOptions; + + void* imageBase; + ulong imageSize; + MemoryType imageCodeType; + MemoryType imageDataType; + void* unload; +} diff --git a/lib/uefi.c3l/uefi/protocol/services/boot.c3i b/lib/uefi.c3l/uefi/protocol/services/boot.c3i new file mode 100644 index 0000000..c5b8e06 --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/services/boot.c3i @@ -0,0 +1,86 @@ +module uefi::protocol::boot_services; + +import uefi::protocol::mem; + +alias AllocatePagesFn = fn EfiStatus (AllocateType, MemoryType, usz, void**); +alias AllocatePoolFn = fn EfiStatus (MemoryType, usz, void**); +alias FreePagesFn = fn EfiStatus (uptr, usz); +alias FreePoolFn = fn EfiStatus (void*); +alias GetMemoryMapFn = fn EfiStatus (usz*, MemoryDescriptor*, usz*, usz*, uint*); +alias HandleProtocolFn = fn EfiStatus (EfiHandle, EfiGuid*, void**); +alias ExitBootServicesFn = fn EfiStatus (EfiHandle, usz); +alias CopyMemFn = fn void (void* dst, void* src, usz); +alias SetMemFn = fn void (void* buf, usz, char); + +module uefi; +import uefi::protocol::boot_services; + +struct BootServices @packed { + inline TableHeader header; + + // Task priority services + void* raise_tpl; + void* restore_tpl; + + // Memory services (uefi::protocol::mem) + AllocatePagesFn allocate_pages; + FreePagesFn free_pages; + GetMemoryMapFn get_memory_map; + AllocatePoolFn allocate_pool; + FreePoolFn free_pool; + + // Event and Timer services + void* create_event; + void* set_timer; + void* wait_for_event; + void* signal_event; + void* close_event; + void* check_event; + + // Protocol Handler services + void* install_protocol_interface; + void* reinstall_protocol_interface; + void* uninstall_protocol_interface; + HandleProtocolFn handle_protocol; + void* _reserved; + void* register_protocol_notify; + void* locate_handle; + void* locate_device_path; + void* install_configuration_table; + + // Image services + void* load_image; + void* start_image; + void* exit_image; + void* unload_image; + ExitBootServicesFn exit_boot_services; + + // Misc services + void* get_next_monotonic_count; + void* stall; + void* set_watchdog_timer; + + // Driver Support services + void* connect_controller; + void* disconnect_controller; + + // Open/Close Protocol services + void* open_protocol; + void* close_protocol; + void* open_protocol_information; + + // Library services + void* protocols_per_handle; + void* locate_handle_buffer; + void* locate_protocol; + void* install_multiple_protocol_interfaces; + void* uninstall_multiple_protocol_interfaces; + + // 32-bit CRC services + void* calculate_crc32; + + // More misc services + CopyMemFn copy_mem; + SetMemFn set_mem; + void* create_event_ex; +} diff --git a/lib/uefi.c3l/uefi/protocol/services/mem.c3i b/lib/uefi.c3l/uefi/protocol/services/mem.c3i new file mode 100644 index 0000000..8b47264 --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/services/mem.c3i @@ -0,0 +1,36 @@ +module uefi::protocol::mem; + +enum MemoryType : uint { + RESERVED, + LOADER_CODE, + LOADER_DATA, + BOOT_SERVICES_CODE, + BOOT_SERVICES_DATA, + RUNTIME_SERVICES_CODE, + RUNTIME_SERVICES_DATA, + CONVENTIONAL, + UNUSABLE, + ACPI_RECLAIM, + ACPI_NVS, + MEMORY_MAPPED_IO, + MEMORY_MAPPED_IO_PORT_SPACE, + PAL_CODE, + PERSISTENT, + UNACCEPTED, +} + +enum AllocateType { + ANY_PAGES, + MAX_ADDRESS, + ADDRESS, +} + +struct MemoryDescriptor { + MemoryType type; + uptr physicalStart; + uptr virtualStart; + ulong numberOfPages; + ulong attribute; + // reserved padding + ulong _rsvd; +} diff --git a/lib/uefi.c3l/uefi/protocol/services/runtime.c3i b/lib/uefi.c3l/uefi/protocol/services/runtime.c3i new file mode 100644 index 0000000..cb690ed --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/services/runtime.c3i @@ -0,0 +1,36 @@ +module uefi::protocol::runtime_services; + +alias ResetSystemFn = fn void (ResetType, EfiStatus, usz, void*); + +enum ResetType : uint { + COLD, + WARM, + SHUTDOWN, + PLATFORM_SPECIFIC, +} + +module uefi; +import uefi::protocol::runtime_services; +import uefi::protocol::time; + +struct RuntimeServices @packed { + inline TableHeader header; + + GetTimeFn get_time; + void* set_time; + void* get_wakeup_time; + void* set_wakeup_time; + + void* set_virtual_address_map; + void* convert_pointer; + + void* get_variable; + void* get_next_variable_name; + void* set_variable; + + void* get_next_high_monotonic_count; + ResetSystemFn reset_system; + void* update_capsule; + void* query_capsule_capabilities; + void* query_variable_info; +} diff --git a/lib/uefi.c3l/uefi/protocol/services/time.c3i b/lib/uefi.c3l/uefi/protocol/services/time.c3i new file mode 100644 index 0000000..e7e20bc --- /dev/null +++ b/lib/uefi.c3l/uefi/protocol/services/time.c3i @@ -0,0 +1,31 @@ +module uefi::protocol::time; + +const short UNSPECIFIED_TIMEZONE = 0x07FF; + +struct Time @packed { + ushort year; + char month; + char day; + char hour; + char minute; + char second; + char _pad1; + uint nanosecond; + short timezone; + DaylightFlags daylight; + char _pad2; +} + +bitstruct DaylightFlags : char { + bool adjust : 0; + bool inDaylight : 1; + char reserved : 2..7; +} + +struct TimeCapabilities @packed { + uint resolution; + uint accuracy; + bool setsToZero; +} + +alias GetTimeFn = fn EfiStatus (Time*, TimeCapabilities*); diff --git a/lib/uefi.c3l/uefi/status.c3i b/lib/uefi.c3l/uefi/status.c3i new file mode 100644 index 0000000..e846cdb --- /dev/null +++ b/lib/uefi.c3l/uefi/status.c3i @@ -0,0 +1,174 @@ +module uefi::status::error; + +// Errors +faultdef + NO_FAULT, + LOAD_ERROR, + INVALID_PARAMETER, + UNSUPPORTED, + BAD_BUFFER_SIZE, + BUFFER_TOO_SMALL, + NOT_READY, + DEVICE_ERROR, + WRITE_PROTECTED, + OUT_OF_RESOURCES, + VOLUME_CORRUPTED, + VOLUME_FULL, + NO_MEDIA, + MEDIA_CHANGED, + NOT_FOUND, + ACCESS_DENIED, + NO_RESPONSE, + NO_MAPPING, + TIMEOUT, + NOT_STARTED, + ALREADY_STARTED, + ABORTED, + ICMP_ERROR, + TFTP_ERROR, + PROTOCOL_ERROR, + INCOMPATIBLE_VERSION, + SECURITY_VIOLATION, + CRC_ERROR, + END_OF_MEDIA, + UNKNOWN_29, /* UEFI spec is missing this definition. */ + UNKNOWN_30, /* UEFI spec is missing this definition. */ + END_OF_FILE, + INVALID_LANGUAGE, + COMPROMISED_DATA, + IP_ADDRESS_CONFLICT, + HTTP_ERROR, + EFILIB_UNINITIALIZED, /* Used for efilib calls when init() hasn't been called. */ + UNKNOWN_STATUS; /* Fallback for an unknown status code. */ + +module uefi::status::warning; + +// Warnings +faultdef + UNKNOWN_GLYPH, + DELETE_FAILURE, + WRITE_FAILURE, + BUFFER_TOO_SMALL, + STALE_DATA, + FILE_SYSTEM, + RESET_REQUIRED; + +module uefi; + +import uefi::status; + +macro @efi_err($x) @private => (usz)((1ul << ((usz::size * 8) - 1)) | $x); +macro @from_efi_err(#x) @private => (usz)((#x ^ (1ul << ((usz::size * 8) - 1)))+7); // add 7 warning to get the right ordinal +macro @efi_warn($x) @private => (usz)$x; + +constdef EfiStatus : ulong { + SUCCESS, + WARN_UNKNOWN_GLYPH = @efi_warn(1), + WARN_DELETE_FAILURE, + WARN_WRITE_FAILURE, + WARN_BUFFER_TOO_SMALL, + WARN_STALE_DATA, + WARN_FILE_SYSTEM, + WARN_RESET_REQUIRED, + LOAD_ERROR = @efi_err(1), + INVALID_PARAMETER, + UNSUPPORTED, + BAD_BUFFER_SIZE, + BUFFER_TOO_SMALL, + NOT_READY, + DEVICE_ERROR, + WRITE_PROTECTED, + OUT_OF_RESOURCES, + VOLUME_CORRUPTED, + VOLUME_FULL, + NO_MEDIA, + MEDIA_CHANGED, + NOT_FOUND, + ACCESS_DENIED, + NO_RESPONSE, + NO_MAPPING, + TIMEOUT, + NOT_STARTED, + ALREADY_STARTED, + ABORTED, + ICMP_ERROR, + TFTP_ERROR, + PROTOCOL_ERROR, + INCOMPATIBLE_VERSION, + SECURITY_VIOLATION, + CRC_ERROR, + END_OF_MEDIA, + UNKNOWN_29, + UNKNOWN_30, + END_OF_FILE, + INVALID_LANGUAGE, + COMPROMISED_DATA, + IP_ADDRESS_CONFLICT, + HTTP_ERROR, +} + +enum EfiStatusInternal : ulong (usz raw, fault faultType) { + SUCCESS { 0, error::NO_FAULT }, + + WARN_UNKNOWN_GLYPH { @efi_warn(1), warning::UNKNOWN_GLYPH }, + WARN_DELETE_FAILURE { @efi_warn(2), warning::DELETE_FAILURE }, + WARN_WRITE_FAILURE { @efi_warn(3), warning::WRITE_FAILURE }, + WARN_BUFFER_TOO_SMALL { @efi_warn(4), warning::BUFFER_TOO_SMALL }, + WARN_STALE_DATA { @efi_warn(5), warning::STALE_DATA }, + WARN_FILE_SYSTEM { @efi_warn(6), warning::FILE_SYSTEM }, + WARN_RESET_REQUIRED { @efi_warn(7), warning::RESET_REQUIRED }, + + LOAD_ERROR { @efi_err(1), error::LOAD_ERROR }, + INVALID_PARAMETER { @efi_err(2), error::INVALID_PARAMETER }, + UNSUPPORTED { @efi_err(3), error::UNSUPPORTED }, + BAD_BUFFER_SIZE { @efi_err(4), error::BAD_BUFFER_SIZE }, + BUFFER_TOO_SMALL { @efi_err(5), error::BUFFER_TOO_SMALL }, + NOT_READY { @efi_err(6), error::NOT_READY }, + DEVICE_ERROR { @efi_err(7), error::DEVICE_ERROR }, + WRITE_PROTECTED { @efi_err(8), error::WRITE_PROTECTED }, + OUT_OF_RESOURCES { @efi_err(9), error::OUT_OF_RESOURCES }, + VOLUME_CORRUPTED { @efi_err(10), error::VOLUME_CORRUPTED }, + VOLUME_FULL { @efi_err(11), error::VOLUME_FULL }, + NO_MEDIA { @efi_err(12), error::NO_MEDIA }, + MEDIA_CHANGED { @efi_err(13), error::MEDIA_CHANGED }, + NOT_FOUND { @efi_err(14), error::NOT_FOUND }, + ACCESS_DENIED { @efi_err(15), error::ACCESS_DENIED }, + NO_RESPONSE { @efi_err(16), error::NO_RESPONSE }, + NO_MAPPING { @efi_err(17), error::NO_MAPPING }, + TIMEOUT { @efi_err(18), error::TIMEOUT }, + NOT_STARTED { @efi_err(19), error::NOT_STARTED }, + ALREADY_STARTED { @efi_err(20), error::ALREADY_STARTED }, + ABORTED { @efi_err(21), error::ABORTED }, + ICMP_ERROR { @efi_err(22), error::ICMP_ERROR }, + TFTP_ERROR { @efi_err(23), error::TFTP_ERROR }, + PROTOCOL_ERROR { @efi_err(24), error::PROTOCOL_ERROR }, + INCOMPATIBLE_VERSION { @efi_err(25), error::INCOMPATIBLE_VERSION }, + SECURITY_VIOLATION { @efi_err(26), error::SECURITY_VIOLATION }, + CRC_ERROR { @efi_err(27), error::CRC_ERROR }, + END_OF_MEDIA { @efi_err(28), error::END_OF_MEDIA }, + UNKNOWN_29 { @efi_err(29), error::UNKNOWN_29 }, /* UEFI spec is missing this definition. */ + UNKNOWN_30 { @efi_err(30), error::UNKNOWN_30 }, /* UEFI spec is missing this definition. */ + END_OF_FILE { @efi_err(31), error::END_OF_FILE }, + INVALID_LANGUAGE { @efi_err(32), error::INVALID_LANGUAGE }, + COMPROMISED_DATA { @efi_err(33), error::COMPROMISED_DATA }, + IP_ADDRESS_CONFLICT { @efi_err(34), error::IP_ADDRESS_CONFLICT }, + HTTP_ERROR { @efi_err(35), error::HTTP_ERROR }, +} + +<* + Handle EFI errors when they occur. +*> +macro bool? efi_error(EfiStatus status, bool catchWarnings = true) @builtin { + switch { + case status == SUCCESS: return false; + + case status >= EfiStatus.WARN_UNKNOWN_GLYPH && status <= EfiStatus.WARN_RESET_REQUIRED: + EfiStatusInternal statusInternal = EfiStatusInternal::from_ordinal((ulong)status); + return catchWarnings ? statusInternal.faultType~ : true; + + case status >= EfiStatus.LOAD_ERROR && status <= EfiStatus.HTTP_ERROR: + return EfiStatusInternal::from_ordinal(@from_efi_err((ulong)status)).faultType~; + } + + return error::UNKNOWN_STATUS~; +} \ No newline at end of file diff --git a/lib/uefi.c3l/uefi/uefi.c3i b/lib/uefi.c3l/uefi/uefi.c3i new file mode 100644 index 0000000..ab215c2 --- /dev/null +++ b/lib/uefi.c3l/uefi/uefi.c3i @@ -0,0 +1,59 @@ +module uefi; + +alias EfiHandle = void*; +typedef EfiEvent = void*; + +struct TableHeader { + ulong signature; + uint revision; + uint headerSize; + uint crc32; + uint reserved; +} + +struct ConfigurationTable { + EfiGuid vendorGuid; + void* vendorTable; +} + +struct SystemTable { + TableHeader header; + EfiString firmwareVendor; + uint firmwareRevision; + EfiHandle consoleInHandle; + SimpleTextInputProtocol* conIn; + EfiHandle consoleOutHandle; + SimpleTextOutputProtocol* conOut; + EfiHandle standardErrorHandle; + SimpleTextOutputProtocol* stdErr; + RuntimeServices* runtimeServices; + BootServices* bootServices; + ulong numberOfTableEntries; + ConfigurationTable* configurationTable; +} + +alias WChar = ushort; +typedef EfiString = inline WChar*; +typedef WString = inline WChar[]; +macro WString @w(String $string) @builtin @public => $$wstr16($string); + +// Time related definitions +struct EfiTime @packed { + ushort year; + char month; + char day; + char hour; + char minute; + char second; + char _pad1; + uint nanosecond; + short timezone; + EfiDaylightFlags daylight; + char _pad2; +} + +bitstruct EfiDaylightFlags : char { + bool adjust : 0; + bool in_daylight : 1; + char reserved : 2..7; +} diff --git a/main.c3 b/main.c3 index e3a8c15..86231bf 100644 --- a/main.c3 +++ b/main.c3 @@ -20,6 +20,13 @@ import uefi; fn EfiStatus efi_main(EfiHandle image_handle, SystemTable* system_table) @export("efi_main") { - pre_load::init(image_handle, system_table)!!; return SUCCESS; } + +alias PanicFn = fn void(String message, String file, String function, int line); +PanicFn panicfn = &_panicfn; +fn void _panicfn(String reason, String file = "", String func = "", int line = 0) +{ + asm("cli"); + asm("hlt"); +} diff --git a/project.json b/project.json index a053d9a..fb9305c 100644 --- a/project.json +++ b/project.json @@ -1,5 +1,4 @@ { - "langrev": "1", "warnings": [ "no-unused" ], "dependency-search-paths": [ "lib" ], "dependencies": [ "uefi" ], @@ -8,19 +7,17 @@ "sources": [ "main.c3" ], "build-dir": "build", "output": "build", - "stack-probe": "none", - "stack-protector": "none", - "reloc": "PIC", - "win-subsystem": "efi-app", - "link-args": [ - "-nostdlib", - "-eefi_main", - ], - "link-libc": false, - "no-entry": true, + "panicfn": "c3os::panicfn", "targets": { "c3os": { "type": "executable", + "extension": ".efi", + "target": "windows-x64", + "no-entry": true, + "use-stdlib": false, + "link-libc": false, + "win-subsystem": "efi-app", + "link-args": [ "/ENTRY:efi_main" ], }, }, "cpu": "generic", diff --git a/scripts/copy-uefi-c3l.sh b/scripts/copy-uefi-c3l.sh index ddb8f11..1a2d177 100755 --- a/scripts/copy-uefi-c3l.sh +++ b/scripts/copy-uefi-c3l.sh @@ -2,7 +2,5 @@ set -x rm -r ./lib/uefi.c3l -cp -r ~/pp/c3libs/uefi.c3l ./lib/ -rm -rf ./lib/uefi.c3l/.git/ -rm ./lib/uefi.c3l/.gitignore +cp -r ~/fork/boson-bootloader/lib/uefi.c3l ./lib/ set +x diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 0000000..f2d359c --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -x + +c3c build + +mkdir -p ./build/root/EFI/BOOT/ +cp ./build/c3os.efi ./build/root/EFI/BOOT/BOOTX64.EFI +makefs -t msdos -o fat_type=12 -s 4m ./build/c3os.img ./build/root +rm -r ./build/root + +mkdir -p ./build/iso +cp ./build/c3os.img ./build/iso/c3os.img +xorriso -as mkisofs -R -f -e c3os.img -no-emul-boot -o ./build/c3os.iso ./build/iso +rm ./build/c3os.img +rm -r ./build/iso + +rm disk.qcow2 +vmctl create -s 10G disk.qcow2 +qemu-system-x86_64 \ + -drive if=pflash,readonly=yes,file=/usr/local/share/qemu/edk2-x86_64-code.fd \ + -cdrom ./build/c3os.iso + + +set +x -- cgit v1.3.1