From 63d56c532d4485ff03f59ae0e79043e23bcc63d9 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Thu, 25 Jul 2019 12:16:03 +0200 Subject: [PATCH 01/12] src/target.cpp: UEFI improvements --- src/target.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target.cpp b/src/target.cpp index 6a949270a..d80c917f6 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -989,7 +989,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { } bool target_allows_addr_zero(const ZigTarget *target) { - return target->os == OsFreestanding; + return target->os == OsFreestanding || target->os == OsUefi; } const char *target_o_file_ext(const ZigTarget *target) { @@ -1414,12 +1414,12 @@ bool target_supports_fpic(const ZigTarget *target) { } bool target_supports_stack_probing(const ZigTarget *target) { - return target->os != OsWindows && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64); + return target->os != OsWindows && target->os != OsUefi && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64); } bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. - return target->os == OsWindows || target_os_requires_libc(target->os) || + return target->os == OsWindows || target->os == OsUefi || target_os_requires_libc(target->os) || (linking_libc && target_is_glibc(target)); } From 6e8ef5b6f2205ada3f2c1b4769aefdfc61aca39e Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Fri, 26 Jul 2019 15:42:50 +0200 Subject: [PATCH 02/12] std/build.zig: add checks for UEFI --- std/build.zig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/std/build.zig b/std/build.zig index 3a0c34c8d..f12631ffb 100644 --- a/std/build.zig +++ b/std/build.zig @@ -1174,6 +1174,13 @@ pub const Target = union(enum) { }; } + pub fn isUefi(self: Target) bool { + return switch (self.getOs()) { + .uefi => true, + else => false, + }; + } + pub fn isWasm(self: Target) bool { return switch (self.getArch()) { .wasm32, .wasm64 => true, @@ -1484,7 +1491,7 @@ pub const LibExeObjStep = struct { } pub fn producesPdbFile(self: *LibExeObjStep) bool { - if (!self.target.isWindows()) return false; + if (!self.target.isWindows() and !self.target.isUefi()) return false; if (self.strip) return false; return self.isDynamicLibrary() or self.kind == .Exe; } @@ -1581,7 +1588,7 @@ pub const LibExeObjStep = struct { /// Unless setOutputDir was called, this function must be called only in /// the make step, from a step that has declared a dependency on this one. pub fn getOutputPdbPath(self: *LibExeObjStep) []const u8 { - assert(self.target.isWindows()); + assert(self.target.isWindows() or self.target.isUefi()); return fs.path.join( self.builder.allocator, [_][]const u8{ self.output_dir.?, self.out_pdb_filename }, From b979fc1bcd6d1bdc19b7f518498fb8c9740d6dea Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Sun, 28 Jul 2019 23:51:51 +0200 Subject: [PATCH 03/12] initial work torwards std lib support for uefi --- src/codegen.cpp | 10 +- std/os.zig | 12 +- std/os/uefi.zig | 43 +++++- std/os/uefi/protocols.zig | 31 ++++ .../protocols/absolute_pointer_protocol.zig | 60 ++++++++ .../uefi/protocols/edid_active_protocol.zig | 17 +++ .../protocols/edid_discovered_protocol.zig | 17 +++ .../uefi/protocols/edid_override_protocol.zig | 23 +++ .../protocols/graphics_output_protocol.zig | 90 +++++++++++ std/os/uefi/protocols/rng_protocol.zig | 73 +++++++++ .../protocols/simple_pointer_protocol.zig | 54 +++++++ .../simple_text_input_ex_protocol.zig | 81 ++++++++++ .../protocols/simple_text_output_protocol.zig | 143 ++++++++++++++++++ std/os/uefi/status.zig | 46 ++++++ std/os/uefi/tables.zig | 6 + std/os/uefi/tables/boot_services.zig | 64 ++++++++ std/os/uefi/tables/configuration_table.zig | 82 ++++++++++ std/os/uefi/tables/runtime_services.zig | 41 +++++ std/os/uefi/tables/system_table.zig | 46 ++++++ std/os/uefi/tables/table_header.zig | 8 + std/special/start.zig | 26 ++++ 21 files changed, 963 insertions(+), 10 deletions(-) create mode 100644 std/os/uefi/protocols.zig create mode 100644 std/os/uefi/protocols/absolute_pointer_protocol.zig create mode 100644 std/os/uefi/protocols/edid_active_protocol.zig create mode 100644 std/os/uefi/protocols/edid_discovered_protocol.zig create mode 100644 std/os/uefi/protocols/edid_override_protocol.zig create mode 100644 std/os/uefi/protocols/graphics_output_protocol.zig create mode 100644 std/os/uefi/protocols/rng_protocol.zig create mode 100644 std/os/uefi/protocols/simple_pointer_protocol.zig create mode 100644 std/os/uefi/protocols/simple_text_input_ex_protocol.zig create mode 100644 std/os/uefi/protocols/simple_text_output_protocol.zig create mode 100644 std/os/uefi/status.zig create mode 100644 std/os/uefi/tables.zig create mode 100644 std/os/uefi/tables/boot_services.zig create mode 100644 std/os/uefi/tables/configuration_table.zig create mode 100644 std/os/uefi/tables/runtime_services.zig create mode 100644 std/os/uefi/tables/system_table.zig create mode 100644 std/os/uefi/tables/table_header.zig diff --git a/src/codegen.cpp b/src/codegen.cpp index 0ac945e8c..6ab76dea3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8540,10 +8540,6 @@ static bool want_startup_code(CodeGen *g) { if (g->is_test_build) return false; - // start code does not handle UEFI target - if (g->zig_target->os == OsUefi) - return false; - // WASM freestanding can still have an entry point but other freestanding targets do not. if (g->zig_target->os == OsFreestanding && !target_is_wasm(g->zig_target)) return false; @@ -8553,8 +8549,12 @@ static bool want_startup_code(CodeGen *g) { return false; // If there is a pub main in the root source file, that means we need start code. - if (g->have_pub_main) + if (g->have_pub_main) { return true; + } else { + if (g->zig_target->os == OsUefi) + return false; + } if (g->out_type == OutTypeExe) { // For build-exe, we might add start code even though there is no pub main, so that the diff --git a/std/os.zig b/std/os.zig index 190f02101..9e3a6d3cb 100644 --- a/std/os.zig +++ b/std/os.zig @@ -155,8 +155,7 @@ pub fn abort() noreturn { system.abort(); } if (builtin.os == .uefi) { - // TODO there must be a better thing to do here than loop forever - while (true) {} + exit(0); // TODO choose appropriate exit code } raise(SIGABRT) catch {}; @@ -228,6 +227,15 @@ pub fn exit(status: u8) noreturn { if (linux.is_the_target and !builtin.single_threaded) { linux.exit_group(status); } + if (uefi.is_the_target) { + // exit() is only avaliable if exitBootServices() has not been called yet. + // This call to exit should not fail, so we don't care about its return value. + if (uefi.system_table.boot_services) |bs| { + _ = bs.exit(uefi.handle, status, 0, null); + } + // If we can't exit, reboot the system instead. + uefi.system_table.runtime_services.resetSystem(uefi.tables.ResetType.ResetCold, status, 0, null); + } system.exit(status); } diff --git a/std/os/uefi.zig b/std/os/uefi.zig index 7102938d7..7d757098f 100644 --- a/std/os/uefi.zig +++ b/std/os/uefi.zig @@ -1,6 +1,43 @@ -// TODO this is where the extern declarations go. For example, see -// inc/efilib.h in gnu-efi-code +pub const protocols = @import("uefi/protocols.zig"); +pub const status = @import("uefi/status.zig"); +pub const tables = @import("uefi/tables.zig"); const builtin = @import("builtin"); - pub const is_the_target = builtin.os == .uefi; + +pub var handle: *Handle = undefined; +pub var system_table: *tables.SystemTable = undefined; + +pub const Event = @OpaqueType(); +// GUIDs must be align(8) +pub const Guid = extern struct { + time_low: u32, + time_mid: u16, + time_high_and_version: u16, + clock_seq_high_and_reserved: u8, + clock_seq_low: u8, + node: [6]u8, +}; +pub const Handle = @OpaqueType(); +pub const Time = extern struct { + year: u16, + month: u8, + day: u8, + hour: u8, + minute: u8, + second: u8, + pad1: u8, + nanosecond: u32, + timezone: i16, + daylight: u8, + pad2: u8, + + pub const adjust_daylight: u8 = 1; + pub const in_daylight: u8 = 2; + pub const unspecified_timezone: i16 = 0x7ff; +}; +pub const TimeCapabilities = extern struct { + resolution: u32, + accuracy: u32, + sets_to_zero: bool, +}; diff --git a/std/os/uefi/protocols.zig b/std/os/uefi/protocols.zig new file mode 100644 index 000000000..2d61ba088 --- /dev/null +++ b/std/os/uefi/protocols.zig @@ -0,0 +1,31 @@ +pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey; +pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData; +pub const KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState; +pub const SimpleTextInputExProtocol = @import("protocols/simple_text_input_ex_protocol.zig").SimpleTextInputExProtocol; + +pub const SimpleTextOutputMode = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputMode; +pub const SimpleTextOutputProtocol = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputProtocol; + +pub const SimplePointerMode = @import("protocols/simple_pointer_protocol.zig").SimplePointerMode; +pub const SimplePointerProtocol = @import("protocols/simple_pointer_protocol.zig").SimplePointerProtocol; +pub const SimplePointerState = @import("protocols/simple_pointer_protocol.zig").SimplePointerState; + +pub const AbsolutePointerMode = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerMode; +pub const AbsolutePointerProtocol = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerProtocol; +pub const AbsolutePointerState = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerState; + +pub const GraphicsOutputBltPixel = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltPixel; +pub const GraphicsOutputBltOperation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltOperation; +pub const GraphicsOutputModeInformation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputModeInformation; +pub const GraphicsOutputProtocol = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocol; +pub const GraphicsOutputProtocolMode = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocolMode; +pub const GraphicsPixelFormat = @import("protocols/graphics_output_protocol.zig").GraphicsPixelFormat; +pub const PixelBitmask = @import("protocols/graphics_output_protocol.zig").PixelBitmask; + +pub const EdidDiscoveredProtocol = @import("protocols/edid_discovered_protocol.zig").EdidDiscoveredProtocol; + +pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").EdidActiveProtocol; + +pub const EdidOverrideProtocol = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocol; + +pub const RNGProtocol = @import("protocols/rng_protocol.zig").RNGProtocol; diff --git a/std/os/uefi/protocols/absolute_pointer_protocol.zig b/std/os/uefi/protocols/absolute_pointer_protocol.zig new file mode 100644 index 000000000..ce6309b59 --- /dev/null +++ b/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -0,0 +1,60 @@ +const uefi = @import("std").os.uefi; +const Event = uefi.Event; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.7 +pub const AbsolutePointerProtocol = extern struct { + _reset: extern fn (*const AbsolutePointerProtocol, bool) usize, + _get_state: extern fn (*const AbsolutePointerProtocol, *AbsolutePointerState) usize, + wait_for_input: *Event, + mode: *AbsolutePointerMode, + + pub fn reset(self: *const AbsolutePointerProtocol, verify: bool) usize { + return self._reset(self, verify); + } + + pub fn getState(self: *const AbsolutePointerProtocol, state: *AbsolutePointerState) usize { + return self._get_state(self, state); + } + + pub const guid align(8) = Guid{ + .time_low = 0x8d59d32b, + .time_mid = 0xc655, + .time_high_and_version = 0x4ae9, + .clock_seq_high_and_reserved = 0x9b, + .clock_seq_low = 0x15, + .node = [_]u8{ 0xf2, 0x59, 0x04, 0x99, 0x2a, 0x43 }, + }; +}; + +pub const AbsolutePointerMode = extern struct { + absolute_min_x: u64, + absolute_min_y: u64, + absolute_min_z: u64, + absolute_max_x: u64, + absolute_max_y: u64, + absolute_max_z: u64, + attributes: u32, + + pub const supports_alt_active: u32 = 1; + pub const supports_pressure_as_z: u32 = 2; +}; + +pub const AbsolutePointerState = extern struct { + current_x: u64, + current_y: u64, + current_z: u64, + active_buttons: u32, + + pub fn init() AbsolutePointerState { + return AbsolutePointerState{ + .current_x = undefined, + .current_y = undefined, + .current_z = undefined, + .active_buttons = undefined, + }; + } + + pub const touch_active: u32 = 1; + pub const alt_active: u32 = 2; +}; diff --git a/std/os/uefi/protocols/edid_active_protocol.zig b/std/os/uefi/protocols/edid_active_protocol.zig new file mode 100644 index 000000000..1a96cb6cd --- /dev/null +++ b/std/os/uefi/protocols/edid_active_protocol.zig @@ -0,0 +1,17 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.9 +pub const EdidActiveProtocol = extern struct { + size_of_edid: u32, + edid: ?[*]u8, + + pub const guid align(8) = Guid{ + .time_low = 0xbd8c1056, + .time_mid = 0x9f36, + .time_high_and_version = 0x44ec, + .clock_seq_high_and_reserved = 0x92, + .clock_seq_low = 0xa8, + .node = [_]u8{ 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 }, + }; +}; diff --git a/std/os/uefi/protocols/edid_discovered_protocol.zig b/std/os/uefi/protocols/edid_discovered_protocol.zig new file mode 100644 index 000000000..f68b0fa3d --- /dev/null +++ b/std/os/uefi/protocols/edid_discovered_protocol.zig @@ -0,0 +1,17 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.9 +pub const EdidDiscoveredProtocol = extern struct { + size_of_edid: u32, + edid: ?[*]u8, + + pub const guid align(8) = Guid{ + .time_low = 0x1c0c34f6, + .time_mid = 0xd380, + .time_high_and_version = 0x41fa, + .clock_seq_high_and_reserved = 0xa0, + .clock_seq_low = 0x49, + .node = [_]u8{ 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa }, + }; +}; diff --git a/std/os/uefi/protocols/edid_override_protocol.zig b/std/os/uefi/protocols/edid_override_protocol.zig new file mode 100644 index 000000000..7ed1358ed --- /dev/null +++ b/std/os/uefi/protocols/edid_override_protocol.zig @@ -0,0 +1,23 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Handle = uefi.Handle; + +/// UEFI Specification, Version 2.8, 12.9 +pub const EdidOverrideProtocol = extern struct { + _get_edid: extern fn (*const EdidOverrideProtocol, *const Handle, *u32, *usize, *?[*]u8) usize, + + pub fn getEdid(self: *const EdidOverrideProtocol, handle: *const Handle, attributes: *u32, edid_size: *usize, edid: *?[*]u8) usize { + return self._get_edid(self, handle, attributes, edid_size, edid); + } + + pub const guid align(8) = Guid{ + .time_low = 0x48ecb431, + .time_mid = 0xfb72, + .time_high_and_version = 0x45c0, + .clock_seq_high_and_reserved = 0xa9, + .clock_seq_low = 0x22, + .node = [_]u8{ 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5 }, + }; + pub const dont_override: u32 = 1; + pub const enable_hot_plug: u32 = 2; +}; diff --git a/std/os/uefi/protocols/graphics_output_protocol.zig b/std/os/uefi/protocols/graphics_output_protocol.zig new file mode 100644 index 000000000..b4ce6a6f5 --- /dev/null +++ b/std/os/uefi/protocols/graphics_output_protocol.zig @@ -0,0 +1,90 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.9 +pub const GraphicsOutputProtocol = extern struct { + _query_mode: extern fn (*const GraphicsOutputProtocol, u32, *usize, **GraphicsOutputModeInformation) usize, + _set_mode: extern fn (*const GraphicsOutputProtocol, u32) usize, + _blt: extern fn (*const GraphicsOutputProtocol, ?[*]GraphicsOutputBltPixel, GraphicsOutputBltOperation, usize, usize, usize, usize, usize, usize, usize) usize, + mode: *GraphicsOutputProtocolMode, + + pub fn queryMode(self: *const GraphicsOutputProtocol, mode: u32, size_of_info: *usize, info: **GraphicsOutputModeInformation) usize { + return self._query_mode(self, mode, size_of_info, info); + } + + pub fn setMode(self: *const GraphicsOutputProtocol, mode: u32) usize { + return self._set_mode(self, mode); + } + + pub fn blt(self: *const GraphicsOutputProtocol, blt_buffer: ?[*]GraphicsOutputBltPixel, blt_operation: GraphicsOutputBltOperation, source_x: usize, source_y: usize, destination_x: usize, destination_y: usize, width: usize, height: usize, delta: usize) usize { + return self._blt(self, blt_buffer, blt_operation, source_x, source_y, destination_x, destination_y, width, height, delta); + } + + pub const guid align(8) = Guid{ + .time_low = 0x9042a9de, + .time_mid = 0x23dc, + .time_high_and_version = 0x4a38, + .clock_seq_high_and_reserved = 0x96, + .clock_seq_low = 0xfb, + .node = [_]u8{ 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a }, + }; +}; + +pub const GraphicsOutputProtocolMode = extern struct { + max_mode: u32, + mode: u32, + info: *GraphicsOutputModeInformation, + size_of_info: usize, + frame_buffer_base: u64, + frame_buffer_size: usize, +}; + +pub const GraphicsOutputModeInformation = extern struct { + version: u32, + horizontal_resolution: u32, + vertical_resolution: u32, + pixel_format: GraphicsPixelFormat, + pixel_information: PixelBitmask, + pixels_per_scan_line: u32, + + pub fn init() GraphicsOutputModeInformation { + return GraphicsOutputModeInformation{ + .version = undefined, + .horizontal_resolution = undefined, + .vertical_resolution = undefined, + .pixel_format = undefined, + .pixel_information = undefined, + .pixels_per_scan_line = undefined, + }; + } +}; + +pub const GraphicsPixelFormat = extern enum(u32) { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax, +}; + +pub const PixelBitmask = extern struct { + red_mask: u32, + green_mask: u32, + blue_mask: u32, + reserved_mask: u32, +}; + +pub const GraphicsOutputBltPixel = extern struct { + blue: u8, + green: u8, + red: u8, + reserved: u8 = undefined, +}; + +pub const GraphicsOutputBltOperation = extern enum(u32) { + BltVideoFill, + BltVideoToBltBuffer, + BltBufferToVideo, + BltVideoToVideo, + GraphicsOutputBltOperationMax, +}; diff --git a/std/os/uefi/protocols/rng_protocol.zig b/std/os/uefi/protocols/rng_protocol.zig new file mode 100644 index 000000000..565832caf --- /dev/null +++ b/std/os/uefi/protocols/rng_protocol.zig @@ -0,0 +1,73 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 37.5 +pub const RNGProtocol = extern struct { + _get_info: extern fn (*const RNGProtocol, *usize, [*]align(8) Guid) usize, + _get_rng: extern fn (*const RNGProtocol, ?*align(8) const Guid, usize, [*]u8) usize, + + pub fn getInfo(self: *const RNGProtocol, list_size: *usize, list: [*]align(8) Guid) usize { + return self._get_info(self, list_size, list); + } + + pub fn getRNG(self: *const RNGProtocol, algo: ?*const Guid, value_length: usize, value: [*]u8) usize { + return self._get_rng(self, algo, value_length, value); + } + + pub const guid align(8) = Guid{ + .time_low = 0x3152bca5, + .time_mid = 0xeade, + .time_high_and_version = 0x433d, + .clock_seq_high_and_reserved = 0x86, + .clock_seq_low = 0x2e, + .node = [_]u8{ 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 }, + }; + pub const algorithm_sp800_90_hash_256 align(8) = Guid{ + .time_low = 0xa7af67cb, + .time_mid = 0x603b, + .time_high_and_version = 0x4d42, + .clock_seq_high_and_reserved = 0xba, + .clock_seq_low = 0x21, + .node = [_]u8{ 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96 }, + }; + pub const algorithm_sp800_90_hmac_256 align(8) = Guid{ + .time_low = 0xc5149b43, + .time_mid = 0xae85, + .time_high_and_version = 0x4f53, + .clock_seq_high_and_reserved = 0x99, + .clock_seq_low = 0x82, + .node = [_]u8{ 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7 }, + }; + pub const algorithm_sp800_90_ctr_256 align(8) = Guid{ + .time_low = 0x44f0de6e, + .time_mid = 0x4d8c, + .time_high_and_version = 0x4045, + .clock_seq_high_and_reserved = 0xa8, + .clock_seq_low = 0xc7, + .node = [_]u8{ 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e }, + }; + pub const algorithm_x9_31_3des align(8) = Guid{ + .time_low = 0x63c4785a, + .time_mid = 0xca34, + .time_high_and_version = 0x4012, + .clock_seq_high_and_reserved = 0xa3, + .clock_seq_low = 0xc8, + .node = [_]u8{ 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 }, + }; + pub const algorithm_x9_31_aes align(8) = Guid{ + .time_low = 0xacd03321, + .time_mid = 0x777e, + .time_high_and_version = 0x4d3d, + .clock_seq_high_and_reserved = 0xb1, + .clock_seq_low = 0xc8, + .node = [_]u8{ 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 }, + }; + pub const algorithm_raw align(8) = Guid{ + .time_low = 0xe43176d7, + .time_mid = 0xb6e8, + .time_high_and_version = 0x4827, + .clock_seq_high_and_reserved = 0xb7, + .clock_seq_low = 0x84, + .node = [_]u8{ 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 }, + }; +}; diff --git a/std/os/uefi/protocols/simple_pointer_protocol.zig b/std/os/uefi/protocols/simple_pointer_protocol.zig new file mode 100644 index 000000000..8a84bb4cc --- /dev/null +++ b/std/os/uefi/protocols/simple_pointer_protocol.zig @@ -0,0 +1,54 @@ +const uefi = @import("std").os.uefi; +const Event = uefi.Event; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.5 +pub const SimplePointerProtocol = struct { + _reset: extern fn (*const SimplePointerProtocol, bool) usize, + _get_state: extern fn (*const SimplePointerProtocol, *SimplePointerState) usize, + wait_for_input: *Event, + mode: *SimplePointerMode, + + pub fn reset(self: *const SimplePointerProtocol, verify: bool) usize { + return self._reset(self, verify); + } + + pub fn getState(self: *const SimplePointerProtocol, state: *SimplePointerState) usize { + return self._get_state(self, state); + } + + pub const guid align(8) = Guid{ + .time_low = 0x31878c87, + .time_mid = 0x0b75, + .time_high_and_version = 0x11d5, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x4f, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; +}; + +pub const SimplePointerMode = struct { + resolution_x: u64, + resolution_y: u64, + resolution_z: u64, + left_button: bool, + right_button: bool, +}; + +pub const SimplePointerState = struct { + relative_movement_x: i32, + relative_movement_y: i32, + relative_movement_z: i32, + left_button: bool, + right_button: bool, + + pub fn init() SimplePointerState { + return SimplePointerState{ + .relative_movement_x = undefined, + .relative_movement_y = undefined, + .relative_movement_z = undefined, + .left_button = undefined, + .right_button = undefined, + }; + } +}; diff --git a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig new file mode 100644 index 000000000..53b0a51f7 --- /dev/null +++ b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -0,0 +1,81 @@ +const uefi = @import("std").os.uefi; +const Event = uefi.Event; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.3 +pub const SimpleTextInputExProtocol = extern struct { + _reset: extern fn (*const SimpleTextInputExProtocol, bool) usize, + _read_key_stroke_ex: extern fn (*const SimpleTextInputExProtocol, *KeyData) usize, + wait_for_key_ex: *Event, + _set_state: extern fn (*const SimpleTextInputExProtocol, *const u8) usize, + _register_key_notify: extern fn (*const SimpleTextInputExProtocol, *const KeyData, extern fn (*const KeyData) usize, **c_void) usize, + _unregister_key_notify: extern fn (*const SimpleTextInputExProtocol, *const c_void) usize, + + pub fn reset(self: *const SimpleTextInputExProtocol, verify: bool) usize { + return self._reset(self, verify); + } + + pub fn readKeyStrokeEx(self: *const SimpleTextInputExProtocol, key_data: *KeyData) usize { + return self._read_key_stroke_ex(self, key_data); + } + + pub fn setState(self: *const SimpleTextInputExProtocol, state: *const u8) usize { + return self._set_state(self, state); + } + + pub fn registerKeyNotify(self: *const SimpleTextInputExProtocol, key_data: *const KeyData, notify: extern fn (*const KeyData) usize, handle: **c_void) usize { + return self._register_key_notify(self, key_data, notify, handle); + } + + pub fn unregisterKeyNotify(self: *const SimpleTextInputExProtocol, handle: *const c_void) usize { + return self._unregister_key_notify(self, handle); + } + + pub const guid align(8) = Guid{ + .time_low = 0xdd9e7534, + .time_mid = 0x7762, + .time_high_and_version = 0x4698, + .clock_seq_high_and_reserved = 0x8c, + .clock_seq_low = 0x14, + .node = [_]u8{ 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa }, + }; +}; + +pub const KeyData = extern struct { + key: InputKey, + key_state: KeyState, + + pub fn init() KeyData { + return KeyData{ + .key = undefined, + .key_state = undefined, + }; + } +}; + +pub const KeyState = extern struct { + key_shift_state: u32, + key_toggle_state: u8, + + pub const shift_state_valid: u32 = 0x80000000; + pub const right_shift_pressed: u32 = 0x00000001; + pub const left_shift_pressed: u32 = 0x00000002; + pub const right_control_pressed: u32 = 0x00000004; + pub const left_control_pressed: u32 = 0x00000008; + pub const right_alt_pressed: u32 = 0x00000010; + pub const left_alt_pressed: u32 = 0x00000020; + pub const right_logo_pressed: u32 = 0x00000040; + pub const left_logo_pressed: u32 = 0x00000080; + pub const menu_key_pressed: u32 = 0x00000100; + pub const sys_req_pressed: u32 = 0x00000200; + pub const toggle_state_valid: u8 = 0x80; + pub const key_state_exposed: u8 = 0x40; + pub const scroll_lock_active: u8 = 0x01; + pub const num_lock_active: u8 = 0x02; + pub const caps_lock_active: u8 = 0x04; +}; + +pub const InputKey = extern struct { + scan_code: u16, + unicode_char: u16, +}; diff --git a/std/os/uefi/protocols/simple_text_output_protocol.zig b/std/os/uefi/protocols/simple_text_output_protocol.zig new file mode 100644 index 000000000..e6b2e21c7 --- /dev/null +++ b/std/os/uefi/protocols/simple_text_output_protocol.zig @@ -0,0 +1,143 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 12.4 +pub const SimpleTextOutputProtocol = extern struct { + _reset: extern fn (*const SimpleTextOutputProtocol, bool) usize, + _output_string: extern fn (*const SimpleTextOutputProtocol, [*]const u16) usize, + _test_string: extern fn (*const SimpleTextOutputProtocol, [*]const u16) usize, + _query_mode: extern fn (*const SimpleTextOutputProtocol, usize, *usize, *usize) usize, + _set_mode: extern fn (*const SimpleTextOutputProtocol, usize) usize, + _set_attribute: extern fn (*const SimpleTextOutputProtocol, usize) usize, + _clear_screen: extern fn (*const SimpleTextOutputProtocol) usize, + _set_cursor_position: extern fn (*const SimpleTextOutputProtocol, usize, usize) usize, + _enable_cursor: extern fn (*const SimpleTextOutputProtocol, bool) usize, + mode: *SimpleTextOutputMode, + + pub fn reset(self: *const SimpleTextOutputProtocol, verify: bool) usize { + return self._reset(self, verify); + } + + pub fn outputString(self: *const SimpleTextOutputProtocol, msg: [*]const u16) usize { + return self._output_string(self, msg); + } + + pub fn testString(self: *const SimpleTextOutputProtocol, msg: [*]const u16) usize { + return self._test_string(self, msg); + } + + pub fn queryMode(self: *const SimpleTextOutputProtocol, mode_number: usize, columns: *usize, rows: *usize) usize { + return self._query_mode(self, mode_number, columns, rows); + } + + pub fn setMode(self: *const SimpleTextOutputProtocol, mode_number: usize) usize { + return self._set_mode(self, mode_number); + } + + pub fn setAttribute(self: *const SimpleTextOutputProtocol, attribute: usize) usize { + return self._set_attribute(self, attribute); + } + + pub fn clearScreen(self: *const SimpleTextOutputProtocol) usize { + return self._clear_screen(self); + } + + pub fn setCursorPosition(self: *const SimpleTextOutputProtocol, column: usize, row: usize) usize { + return self._set_cursor_position(self, column, row); + } + + pub fn enableCursor(self: *const SimpleTextOutputProtocol, visible: bool) usize { + return self._enable_cursor(self, visible); + } + + pub const guid align(8) = Guid{ + .time_low = 0x387477c2, + .time_mid = 0x69c7, + .time_high_and_version = 0x11d2, + .clock_seq_high_and_reserved = 0x8e, + .clock_seq_low = 0x39, + .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b }, + }; + pub const boxdraw_horizontal: u16 = 0x2500; + pub const boxdraw_vertical: u16 = 0x2502; + pub const boxdraw_down_right: u16 = 0x250c; + pub const boxdraw_down_left: u16 = 0x2510; + pub const boxdraw_up_right: u16 = 0x2514; + pub const boxdraw_up_left: u16 = 0x2518; + pub const boxdraw_vertical_right: u16 = 0x251c; + pub const boxdraw_vertical_left: u16 = 0x2524; + pub const boxdraw_down_horizontal: u16 = 0x252c; + pub const boxdraw_up_horizontal: u16 = 0x2534; + pub const boxdraw_vertical_horizontal: u16 = 0x253c; + pub const boxdraw_double_horizontal: u16 = 0x2550; + pub const boxdraw_double_vertical: u16 = 0x2551; + pub const boxdraw_down_right_double: u16 = 0x2552; + pub const boxdraw_down_double_right: u16 = 0x2553; + pub const boxdraw_double_down_right: u16 = 0x2554; + pub const boxdraw_down_left_double: u16 = 0x2555; + pub const boxdraw_down_double_left: u16 = 0x2556; + pub const boxdraw_double_down_left: u16 = 0x2557; + pub const boxdraw_up_right_double: u16 = 0x2558; + pub const boxdraw_up_double_right: u16 = 0x2559; + pub const boxdraw_double_up_right: u16 = 0x255a; + pub const boxdraw_up_left_double: u16 = 0x255b; + pub const boxdraw_up_double_left: u16 = 0x255c; + pub const boxdraw_double_up_left: u16 = 0x255d; + pub const boxdraw_vertical_right_double: u16 = 0x255e; + pub const boxdraw_vertical_double_right: u16 = 0x255f; + pub const boxdraw_double_vertical_right: u16 = 0x2560; + pub const boxdraw_vertical_left_double: u16 = 0x2561; + pub const boxdraw_vertical_double_left: u16 = 0x2562; + pub const boxdraw_double_vertical_left: u16 = 0x2563; + pub const boxdraw_down_horizontal_double: u16 = 0x2564; + pub const boxdraw_down_double_horizontal: u16 = 0x2565; + pub const boxdraw_double_down_horizontal: u16 = 0x2566; + pub const boxdraw_up_horizontal_double: u16 = 0x2567; + pub const boxdraw_up_double_horizontal: u16 = 0x2568; + pub const boxdraw_double_up_horizontal: u16 = 0x2569; + pub const boxdraw_vertical_horizontal_double: u16 = 0x256a; + pub const boxdraw_vertical_double_horizontal: u16 = 0x256b; + pub const boxdraw_double_vertical_horizontal: u16 = 0x256c; + pub const blockelement_full_block: u16 = 0x2588; + pub const blockelement_light_shade: u16 = 0x2591; + pub const geometricshape_up_triangle: u16 = 0x25b2; + pub const geometricshape_right_triangle: u16 = 0x25ba; + pub const geometricshape_down_triangle: u16 = 0x25bc; + pub const geometricshape_left_triangle: u16 = 0x25c4; + pub const arrow_up: u16 = 0x2591; + pub const arrow_down: u16 = 0x2593; + pub const black: u8 = 0x00; + pub const blue: u8 = 0x01; + pub const green: u8 = 0x02; + pub const cyan: u8 = 0x03; + pub const red: u8 = 0x04; + pub const magenta: u8 = 0x05; + pub const brown: u8 = 0x06; + pub const lightgray: u8 = 0x07; + pub const bright: u8 = 0x08; + pub const darkgray: u8 = 0x08; + pub const lightblue: u8 = 0x09; + pub const lightgreen: u8 = 0x0a; + pub const lightcyan: u8 = 0x0b; + pub const lightred: u8 = 0x0c; + pub const lightmagenta: u8 = 0x0d; + pub const yellow: u8 = 0x0e; + pub const white: u8 = 0x0f; + pub const background_black: u8 = 0x00; + pub const background_blue: u8 = 0x10; + pub const background_green: u8 = 0x20; + pub const background_cyan: u8 = 0x30; + pub const background_red: u8 = 0x40; + pub const background_magenta: u8 = 0x50; + pub const background_brown: u8 = 0x60; + pub const background_lightgray: u8 = 0x70; +}; + +pub const SimpleTextOutputMode = extern struct { + max_mode: u32, // specified as signed + mode: u32, // specified as signed + attribute: i32, + cursor_column: i32, + cursor_row: i32, + cursor_visible: bool, +}; diff --git a/std/os/uefi/status.zig b/std/os/uefi/status.zig new file mode 100644 index 000000000..6deb741d0 --- /dev/null +++ b/std/os/uefi/status.zig @@ -0,0 +1,46 @@ +const high_bit = 1 << @typeInfo(usize).Int.bits - 1; + +/// UEFI Specification, Version 2.8, Appendix D +pub const success: usize = 0; + +pub const load_error: usize = high_bit | 1; +pub const invalid_parameter: usize = high_bit | 2; +pub const unsupported: usize = high_bit | 3; +pub const bad_buffer_size: usize = high_bit | 4; +pub const buffer_too_small: usize = high_bit | 5; +pub const not_ready: usize = high_bit | 6; +pub const device_error: usize = high_bit | 7; +pub const write_protected: usize = high_bit | 8; +pub const out_of_resources: usize = high_bit | 9; +pub const volume_corrupted: usize = high_bit | 10; +pub const volume_full: usize = high_bit | 11; +pub const no_media: usize = high_bit | 12; +pub const media_changed: usize = high_bit | 13; +pub const not_found: usize = high_bit | 14; +pub const access_denied: usize = high_bit | 15; +pub const no_response: usize = high_bit | 16; +pub const no_mapping: usize = high_bit | 17; +pub const timeout: usize = high_bit | 18; +pub const not_started: usize = high_bit | 19; +pub const already_started: usize = high_bit | 20; +pub const aborted: usize = high_bit | 21; +pub const icmp_error: usize = high_bit | 22; +pub const tftp_error: usize = high_bit | 23; +pub const protocol_error: usize = high_bit | 24; +pub const incompatible_version: usize = high_bit | 25; +pub const security_violation: usize = high_bit | 26; +pub const crc_error: usize = high_bit | 27; +pub const end_of_media: usize = high_bit | 28; +pub const end_of_file: usize = high_bit | 31; +pub const invalid_language: usize = high_bit | 32; +pub const compromised_data: usize = high_bit | 33; +pub const ip_address_conflict: usize = high_bit | 34; +pub const http_error: usize = high_bit | 35; + +pub const warn_unknown_glyph: usize = 1; +pub const warn_delete_failure: usize = 2; +pub const warn_write_failure: usize = 3; +pub const warn_buffer_too_small: usize = 4; +pub const warn_stale_data: usize = 5; +pub const warn_file_system: usize = 6; +pub const warn_reset_required: usize = 7; diff --git a/std/os/uefi/tables.zig b/std/os/uefi/tables.zig new file mode 100644 index 000000000..e5867ae65 --- /dev/null +++ b/std/os/uefi/tables.zig @@ -0,0 +1,6 @@ +pub const BootServices = @import("tables/boot_services.zig").BootServices; +pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; +pub const ResetType = @import("tables/runtime_services.zig").ResetType; +pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; +pub const SystemTable = @import("tables/system_table.zig").SystemTable; +pub const TableHeader = @import("tables/table_header.zig").TableHeader; diff --git a/std/os/uefi/tables/boot_services.zig b/std/os/uefi/tables/boot_services.zig new file mode 100644 index 000000000..2ae234f77 --- /dev/null +++ b/std/os/uefi/tables/boot_services.zig @@ -0,0 +1,64 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Handle = uefi.Handle; +const TableHeader = uefi.tables.TableHeader; + +/// UEFI Specification, Version 2.8, 4.4 +/// +/// As the boot_services table may grow with new UEFI versions, it is important to check hdr.header_size. +/// +/// Boot Services must not be used after exitBootServices has been called. The only exception is +/// getMemoryMap, which may be used after the first unsuccessful call to exitBootServices. +/// After successfully calling exitBootServices, system_table.console_in_handle, system_table.con_in, +/// system_table.console_out_handle, system_table.con_out, system_table.standard_error_handle, +/// system_table.std_err, and system_table.boot_services should be set to null. After setting these +/// attributes to null, system_table.hdr.crc32 must be recomputed. See UEFI Specification, Version 2.8, 7.4. +pub const BootServices = extern struct { + hdr: TableHeader, + raiseTpl: usize, // TODO + restoreTpl: usize, // TODO + allocatePages: usize, // TODO + freePages: usize, // TODO + getMemoryMap: usize, // TODO + allocatePool: usize, // TODO + freePool: usize, // TODO + createEvent: usize, // TODO + setTimer: usize, // TODO + waitForEvent: usize, // TODO + signalEvent: usize, // TODO + closeEvent: usize, // TODO + checkEvent: usize, // TODO + installProtocolInterface: usize, // TODO + reinstallProtocolInterface: usize, // TODO + uninstallProtocolInterface: usize, // TODO + handleProtocol: usize, // TODO + reserved: *c_void, + registerProtocolNotify: usize, // TODO + locateHandle: usize, // TODO + locateDevicePath: usize, // TODO + installConfigurationTable: usize, // TODO + imageLoad: usize, // TODO + imageStart: usize, // TODO + exit: extern fn (*const Handle, usize, usize, ?*const c_void) usize, + imageUnload: usize, // TODO + exitBootServices: usize, // TODO + getNextMonotonicCount: usize, // TODO + stall: extern fn (usize) usize, + setWatchdogTimer: extern fn (usize, u64, usize, ?[*]const u16) usize, + connectController: usize, // TODO + disconnectController: usize, // TODO + openProtocol: usize, // TODO + closeProtocol: usize, // TODO + openProtocolInformation: usize, // TODO + protocolsPerHandle: usize, // TODO + locateHandleBuffer: usize, // TODO + locateProtocol: extern fn (*align(8) const Guid, ?*const c_void, *?*c_void) usize, + installMultipleProtocolInterfaces: usize, // TODO + uninstallMultipleProtocolInterfaces: usize, // TODO + calculateCrc32: usize, // TODO + copyMem: usize, // TODO + setMem: usize, // TODO + createEventEx: usize, // TODO + + pub const signature: u64 = 0x56524553544f4f42; +}; diff --git a/std/os/uefi/tables/configuration_table.zig b/std/os/uefi/tables/configuration_table.zig new file mode 100644 index 000000000..eb99e0847 --- /dev/null +++ b/std/os/uefi/tables/configuration_table.zig @@ -0,0 +1,82 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +/// UEFI Specification, Version 2.8, 4.6 +/// Because GUIDs must be align(8), structs of this type also must be align(8) +pub const ConfigurationTable = extern struct { + vendor_guid: Guid, + vendor_table: *c_void, + + pub const acpi_20_table_guid align(8) = Guid{ + .time_low = 0x8868e871, + .time_mid = 0xe4f1, + .time_high_and_version = 0x11d3, + .clock_seq_high_and_reserved = 0xbc, + .clock_seq_low = 0x22, + .node = [_]u8{ 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 }, + }; + pub const acpi_10_table_guid align(8) = Guid{ + .time_low = 0xeb9d2d30, + .time_mid = 0x2d88, + .time_high_and_version = 0x11d3, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x16, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; + pub const sal_system_table_guid align(8) = Guid{ + .time_low = 0xeb9d2d32, + .time_mid = 0x2d88, + .time_high_and_version = 0x113d, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x16, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; + pub const smbios_table_guid align(8) = Guid{ + .time_low = 0xeb9d2d31, + .time_mid = 0x2d88, + .time_high_and_version = 0x11d3, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x16, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; + pub const smbios3_table_guid align(8) = Guid{ + .time_low = 0xf2fd1544, + .time_mid = 0x9794, + .time_high_and_version = 0x4a2c, + .clock_seq_high_and_reserved = 0x99, + .clock_seq_low = 0x2e, + .node = [_]u8{ 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 }, + }; + pub const mps_table_guid align(8) = Guid{ + .time_low = 0xeb9d2d2f, + .time_mid = 0x2d88, + .time_high_and_version = 0x11d3, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x16, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; + pub const json_config_data_table_guid align(8) = Guid{ + .time_low = 0x87367f87, + .time_mid = 0x1119, + .time_high_and_version = 0x41ce, + .clock_seq_high_and_reserved = 0xaa, + .clock_seq_low = 0xec, + .node = [_]u8{ 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a }, + }; + pub const json_capsule_data_table_guid align(8) = Guid{ + .time_low = 0x35e7a725, + .time_mid = 0x8dd2, + .time_high_and_version = 0x4cac, + .clock_seq_high_and_reserved = 0x80, + .clock_seq_low = 0x11, + .node = [_]u8{ 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 }, + }; + pub const json_capsule_result_table_guid align(8) = Guid{ + .time_low = 0xdbc461c3, + .time_mid = 0xb3de, + .time_high_and_version = 0x422a, + .clock_seq_high_and_reserved = 0xb9, + .clock_seq_low = 0xb4, + .node = [_]u8{ 0x98, 0x86, 0xfd, 0x49, 0xa1, 0xe5 }, + }; +}; diff --git a/std/os/uefi/tables/runtime_services.zig b/std/os/uefi/tables/runtime_services.zig new file mode 100644 index 000000000..bae808ac8 --- /dev/null +++ b/std/os/uefi/tables/runtime_services.zig @@ -0,0 +1,41 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const TableHeader = uefi.tables.TableHeader; +const Time = uefi.Time; +const TimeCapabilities = uefi.TimeCapabilities; + +/// UEFI Specification, Version 2.8, 4.5 +/// +/// As the runtime_services table may grow with new UEFI versions, it is important to check hdr.header_size. +/// +/// Some functions may not be supported. Check the RuntimeServicesSupported variable using getVariable. +/// getVariable is one of the functions that may not be supported. See UEFI Specification, Version 2.8, 8.1. +/// +/// Some functions may not be called while other functions are running. See UEFI Specification, Version 2.8, 8.1. +pub const RuntimeServices = extern struct { + hdr: TableHeader, + getTime: extern fn (*uefi.Time, ?*TimeCapabilities) usize, + setTime: usize, // TODO + getWakeupTime: usize, // TODO + setWakeupTime: usize, // TODO + setVirtualAddressMap: usize, // TODO + convertPointer: usize, // TODO + getVariable: extern fn ([*]const u16, *align(8) const Guid, ?*u32, *usize, ?*c_void) usize, + getNextVariableName: extern fn (*usize, [*]u16, *align(8) Guid) usize, + setVariable: extern fn ([*]const u16, *align(8) const Guid, u32, usize, *c_void) usize, + getNextHighMonotonicCount: usize, // TODO + resetSystem: extern fn (ResetType, usize, usize, ?*const c_void) noreturn, + updateCapsule: usize, // TODO + queryCapsuleCapabilities: usize, // TODO + queryVariableInfo: usize, // TODO + + pub const signature: u64 = 0x56524553544e5552; +}; + +/// UEFI Specification, Version 2.8, 8.5.1 +pub const ResetType = extern enum(u32) { + ResetCold, + ResetWarm, + ResetShutdown, + ResetPlatformSpecific, +}; diff --git a/std/os/uefi/tables/system_table.zig b/std/os/uefi/tables/system_table.zig new file mode 100644 index 000000000..31534d03b --- /dev/null +++ b/std/os/uefi/tables/system_table.zig @@ -0,0 +1,46 @@ +const uefi = @import("std").os.uefi; +const BootServices = uefi.tables.BootServices; +const ConfigurationTable = uefi.tables.ConfigurationTable; +const Handle = uefi.Handle; +const RuntimeServices = uefi.tables.RuntimeServices; +const SimpleTextInputExProtocol = uefi.protocols.SimpleTextInputExProtocol; +const SimpleTextOutputProtocol = uefi.protocols.SimpleTextOutputProtocol; +const TableHeader = uefi.tables.TableHeader; + +/// UEFI Specification, Version 2.8, 4.3 +/// +/// As the system_table may grow with new UEFI versions, it is important to check hdr.header_size. +/// +/// After successfully calling boot_services.exitBootServices, console_in_handle, +/// con_in, console_out_handle, con_out, standard_error_handle, std_err, and +/// boot_services should be set to null. After setting these attributes to null, +/// hdr.crc32 must be recomputed. See UEFI Specification, Version 2.8, 7.4. +pub const SystemTable = extern struct { + hdr: TableHeader, + firmware_vendor: *u16, + firmware_revision: u32, + console_in_handle: ?*Handle, + con_in: ?*SimpleTextInputExProtocol, + console_out_handle: ?*Handle, + con_out: ?*SimpleTextOutputProtocol, + standard_error_handle: ?*Handle, + std_err: ?*SimpleTextOutputProtocol, + runtime_services: *RuntimeServices, + boot_services: ?*BootServices, + number_of_table_entries: usize, + configuration_table: *ConfigurationTable, + + pub const signature: u64 = 0x5453595320494249; + pub const revision_1_02: u32 = (1 << 16) | 2; + pub const revision_1_10: u32 = (1 << 16) | 10; + pub const revision_2_00: u32 = (2 << 16); + pub const revision_2_10: u32 = (2 << 16) | 10; + pub const revision_2_20: u32 = (2 << 16) | 20; + pub const revision_2_30: u32 = (2 << 16) | 30; + pub const revision_2_31: u32 = (2 << 16) | 31; + pub const revision_2_40: u32 = (2 << 16) | 40; + pub const revision_2_50: u32 = (2 << 16) | 50; + pub const revision_2_60: u32 = (2 << 16) | 60; + pub const revision_2_70: u32 = (2 << 16) | 70; + pub const revision_2_80: u32 = (2 << 16) | 80; +}; diff --git a/std/os/uefi/tables/table_header.zig b/std/os/uefi/tables/table_header.zig new file mode 100644 index 000000000..b955768e6 --- /dev/null +++ b/std/os/uefi/tables/table_header.zig @@ -0,0 +1,8 @@ +/// UEFI Specification, Version 2.8, 4.2 +pub const TableHeader = extern struct { + signature: u64, + revision: u32, + header_size: u32, + crc32: u32, + reserved: u32, +}; diff --git a/std/special/start.zig b/std/special/start.zig index f8a018e0a..dbd0912d9 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -4,6 +4,7 @@ const root = @import("root"); const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; +const uefi = std.os.uefi; var argc_ptr: [*]usize = undefined; @@ -19,6 +20,8 @@ comptime { @export("WinMainCRTStartup", WinMainCRTStartup, .Strong); } else if (is_wasm and builtin.os == .freestanding) { @export("_start", wasm_freestanding_start, .Strong); + } else if (builtin.os == .uefi) { + @export("EfiMain", EfiMain, .Strong); } else { @export("_start", _start, .Strong); } @@ -28,6 +31,29 @@ extern fn wasm_freestanding_start() void { _ = callMain(); } +extern fn EfiMain(handle: *uefi.Handle, system_table: *uefi.tables.SystemTable) usize { + const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'"; + uefi.handle = handle; + uefi.system_table = system_table; + + switch (@typeInfo(@typeOf(root.main).ReturnType)) { + .NoReturn => { + root.main(); + }, + .Void => { + root.main(); + return 0; + }, + .Int => |info| { + if (info.bits != @typeInfo(usize).Int.bits) { + @compileError(bad_efi_main_ret); + } + return root.main(); + }, + else => @compileError(bad_efi_main_ret), + } +} + nakedcc fn _start() noreturn { if (builtin.os == builtin.Os.wasi) { std.os.wasi.proc_exit(callMain()); From 20ce0b9952167d531f0a0e679c1b0409e9049d09 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Mon, 5 Aug 2019 18:26:13 +0200 Subject: [PATCH 04/12] std/os/uefi: replace integer bit fields with packed structs --- std/os/uefi.zig | 12 +++--- std/os/uefi/protocols.zig | 1 + .../protocols/absolute_pointer_protocol.zig | 20 +++++---- .../uefi/protocols/edid_override_protocol.zig | 12 ++++-- .../simple_text_input_ex_protocol.zig | 43 +++++++++++-------- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/std/os/uefi.zig b/std/os/uefi.zig index 7d757098f..58508df38 100644 --- a/std/os/uefi.zig +++ b/std/os/uefi.zig @@ -26,14 +26,16 @@ pub const Time = extern struct { hour: u8, minute: u8, second: u8, - pad1: u8, + _pad1: u8, nanosecond: u32, timezone: i16, - daylight: u8, - pad2: u8, + daylight: packed struct { + _pad1: u6, + in_daylight: bool, + adjust_daylight: bool, + }, + _pad2: u8, - pub const adjust_daylight: u8 = 1; - pub const in_daylight: u8 = 2; pub const unspecified_timezone: i16 = 0x7ff; }; pub const TimeCapabilities = extern struct { diff --git a/std/os/uefi/protocols.zig b/std/os/uefi/protocols.zig index 2d61ba088..2c8d870af 100644 --- a/std/os/uefi/protocols.zig +++ b/std/os/uefi/protocols.zig @@ -27,5 +27,6 @@ pub const EdidDiscoveredProtocol = @import("protocols/edid_discovered_protocol.z pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").EdidActiveProtocol; pub const EdidOverrideProtocol = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocol; +pub const EdidOverrideProtocolAttributes = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocolAttributes; pub const RNGProtocol = @import("protocols/rng_protocol.zig").RNGProtocol; diff --git a/std/os/uefi/protocols/absolute_pointer_protocol.zig b/std/os/uefi/protocols/absolute_pointer_protocol.zig index ce6309b59..6621b3128 100644 --- a/std/os/uefi/protocols/absolute_pointer_protocol.zig +++ b/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -34,17 +34,24 @@ pub const AbsolutePointerMode = extern struct { absolute_max_x: u64, absolute_max_y: u64, absolute_max_z: u64, - attributes: u32, - - pub const supports_alt_active: u32 = 1; - pub const supports_pressure_as_z: u32 = 2; + attributes: packed struct { + _pad1: u6, + supports_pressure_as_z: bool, + supports_alt_active: bool, + _pad2: u24, + }, }; pub const AbsolutePointerState = extern struct { current_x: u64, current_y: u64, current_z: u64, - active_buttons: u32, + active_buttons: packed struct { + _pad1: u6, + alt_active: bool, + touch_active: bool, + _pad2: u24, + }, pub fn init() AbsolutePointerState { return AbsolutePointerState{ @@ -54,7 +61,4 @@ pub const AbsolutePointerState = extern struct { .active_buttons = undefined, }; } - - pub const touch_active: u32 = 1; - pub const alt_active: u32 = 2; }; diff --git a/std/os/uefi/protocols/edid_override_protocol.zig b/std/os/uefi/protocols/edid_override_protocol.zig index 7ed1358ed..b4d3240ee 100644 --- a/std/os/uefi/protocols/edid_override_protocol.zig +++ b/std/os/uefi/protocols/edid_override_protocol.zig @@ -6,7 +6,8 @@ const Handle = uefi.Handle; pub const EdidOverrideProtocol = extern struct { _get_edid: extern fn (*const EdidOverrideProtocol, *const Handle, *u32, *usize, *?[*]u8) usize, - pub fn getEdid(self: *const EdidOverrideProtocol, handle: *const Handle, attributes: *u32, edid_size: *usize, edid: *?[*]u8) usize { + /// attributes must be align(4) + pub fn getEdid(self: *const EdidOverrideProtocol, handle: *const Handle, attributes: *EdidOverrideProtocolAttributes, edid_size: *usize, edid: *?[*]u8) usize { return self._get_edid(self, handle, attributes, edid_size, edid); } @@ -18,6 +19,11 @@ pub const EdidOverrideProtocol = extern struct { .clock_seq_low = 0x22, .node = [_]u8{ 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5 }, }; - pub const dont_override: u32 = 1; - pub const enable_hot_plug: u32 = 2; +}; + +pub const EdidOverrideProtocolAttributes = packed struct { + _pad1: u6, + enable_hot_plug: bool, + dont_override: bool, + _pad2: u24, }; diff --git a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig index 53b0a51f7..78d5cf2c8 100644 --- a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig +++ b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -54,25 +54,30 @@ pub const KeyData = extern struct { }; pub const KeyState = extern struct { - key_shift_state: u32, - key_toggle_state: u8, - - pub const shift_state_valid: u32 = 0x80000000; - pub const right_shift_pressed: u32 = 0x00000001; - pub const left_shift_pressed: u32 = 0x00000002; - pub const right_control_pressed: u32 = 0x00000004; - pub const left_control_pressed: u32 = 0x00000008; - pub const right_alt_pressed: u32 = 0x00000010; - pub const left_alt_pressed: u32 = 0x00000020; - pub const right_logo_pressed: u32 = 0x00000040; - pub const left_logo_pressed: u32 = 0x00000080; - pub const menu_key_pressed: u32 = 0x00000100; - pub const sys_req_pressed: u32 = 0x00000200; - pub const toggle_state_valid: u8 = 0x80; - pub const key_state_exposed: u8 = 0x40; - pub const scroll_lock_active: u8 = 0x01; - pub const num_lock_active: u8 = 0x02; - pub const caps_lock_active: u8 = 0x04; + key_shift_state: packed struct { + left_logo_pressed: bool, + right_logo_pressed: bool, + left_alt_pressed: bool, + right_alt_pressed: bool, + left_control_pressed: bool, + right_control_pressed: bool, + left_shift_pressed: bool, + right_shift_pressed: bool, + _pad1: u6, + sys_req_pressed: bool, + menu_key_pressed: bool, + _pad2: u15, + shift_state_valid: bool, + }, + key_toggle_state: packed struct { + toggle_state_valid: bool, + _pad1: u2, + key_state_exposed: bool, + caps_lock_active: bool, + _pad2: u1, + num_lock_active: bool, + scroll_lock_active: bool, + }, }; pub const InputKey = extern struct { From 88fdb303ff7a33d87207bbd61a648c5c1dbe56ad Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Tue, 6 Aug 2019 18:06:18 +0200 Subject: [PATCH 05/12] std/os/uefi: replace init() with default values --- .../protocols/absolute_pointer_protocol.zig | 17 ++++---------- .../protocols/graphics_output_protocol.zig | 23 +++++-------------- .../protocols/simple_pointer_protocol.zig | 20 ++++------------ .../simple_text_input_ex_protocol.zig | 11 ++------- 4 files changed, 17 insertions(+), 54 deletions(-) diff --git a/std/os/uefi/protocols/absolute_pointer_protocol.zig b/std/os/uefi/protocols/absolute_pointer_protocol.zig index 6621b3128..b1fcc4902 100644 --- a/std/os/uefi/protocols/absolute_pointer_protocol.zig +++ b/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -43,22 +43,13 @@ pub const AbsolutePointerMode = extern struct { }; pub const AbsolutePointerState = extern struct { - current_x: u64, - current_y: u64, - current_z: u64, + current_x: u64 = undefined, + current_y: u64 = undefined, + current_z: u64 = undefined, active_buttons: packed struct { _pad1: u6, alt_active: bool, touch_active: bool, _pad2: u24, - }, - - pub fn init() AbsolutePointerState { - return AbsolutePointerState{ - .current_x = undefined, - .current_y = undefined, - .current_z = undefined, - .active_buttons = undefined, - }; - } + } = undefined, }; diff --git a/std/os/uefi/protocols/graphics_output_protocol.zig b/std/os/uefi/protocols/graphics_output_protocol.zig index b4ce6a6f5..4713df050 100644 --- a/std/os/uefi/protocols/graphics_output_protocol.zig +++ b/std/os/uefi/protocols/graphics_output_protocol.zig @@ -40,23 +40,12 @@ pub const GraphicsOutputProtocolMode = extern struct { }; pub const GraphicsOutputModeInformation = extern struct { - version: u32, - horizontal_resolution: u32, - vertical_resolution: u32, - pixel_format: GraphicsPixelFormat, - pixel_information: PixelBitmask, - pixels_per_scan_line: u32, - - pub fn init() GraphicsOutputModeInformation { - return GraphicsOutputModeInformation{ - .version = undefined, - .horizontal_resolution = undefined, - .vertical_resolution = undefined, - .pixel_format = undefined, - .pixel_information = undefined, - .pixels_per_scan_line = undefined, - }; - } + version: u32 = undefined, + horizontal_resolution: u32 = undefined, + vertical_resolution: u32 = undefined, + pixel_format: GraphicsPixelFormat = undefined, + pixel_information: PixelBitmask = undefined, + pixels_per_scan_line: u32 = undefined, }; pub const GraphicsPixelFormat = extern enum(u32) { diff --git a/std/os/uefi/protocols/simple_pointer_protocol.zig b/std/os/uefi/protocols/simple_pointer_protocol.zig index 8a84bb4cc..26d11ca7f 100644 --- a/std/os/uefi/protocols/simple_pointer_protocol.zig +++ b/std/os/uefi/protocols/simple_pointer_protocol.zig @@ -36,19 +36,9 @@ pub const SimplePointerMode = struct { }; pub const SimplePointerState = struct { - relative_movement_x: i32, - relative_movement_y: i32, - relative_movement_z: i32, - left_button: bool, - right_button: bool, - - pub fn init() SimplePointerState { - return SimplePointerState{ - .relative_movement_x = undefined, - .relative_movement_y = undefined, - .relative_movement_z = undefined, - .left_button = undefined, - .right_button = undefined, - }; - } + relative_movement_x: i32 = undefined, + relative_movement_y: i32 = undefined, + relative_movement_z: i32 = undefined, + left_button: bool = undefined, + right_button: bool = undefined, }; diff --git a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig index 78d5cf2c8..16f676fd2 100644 --- a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig +++ b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -42,15 +42,8 @@ pub const SimpleTextInputExProtocol = extern struct { }; pub const KeyData = extern struct { - key: InputKey, - key_state: KeyState, - - pub fn init() KeyData { - return KeyData{ - .key = undefined, - .key_state = undefined, - }; - } + key: InputKey = undefined, + key_state: KeyState = undefined, }; pub const KeyState = extern struct { From 9445b3f057bdeb57cdb02c86b94145ae9a345531 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Fri, 9 Aug 2019 23:12:59 +0200 Subject: [PATCH 06/12] std/os/uefi: change type of Handle from @OpaqueType to *@OpaqueType --- std/os/uefi.zig | 4 ++-- std/os/uefi/protocols/edid_override_protocol.zig | 4 ++-- std/os/uefi/tables/boot_services.zig | 2 +- std/os/uefi/tables/system_table.zig | 6 +++--- std/special/start.zig | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/std/os/uefi.zig b/std/os/uefi.zig index 58508df38..9ddaad5aa 100644 --- a/std/os/uefi.zig +++ b/std/os/uefi.zig @@ -5,7 +5,7 @@ pub const tables = @import("uefi/tables.zig"); const builtin = @import("builtin"); pub const is_the_target = builtin.os == .uefi; -pub var handle: *Handle = undefined; +pub var handle: Handle = undefined; pub var system_table: *tables.SystemTable = undefined; pub const Event = @OpaqueType(); @@ -18,7 +18,7 @@ pub const Guid = extern struct { clock_seq_low: u8, node: [6]u8, }; -pub const Handle = @OpaqueType(); +pub const Handle = *@OpaqueType(); pub const Time = extern struct { year: u16, month: u8, diff --git a/std/os/uefi/protocols/edid_override_protocol.zig b/std/os/uefi/protocols/edid_override_protocol.zig index b4d3240ee..f7228f3c7 100644 --- a/std/os/uefi/protocols/edid_override_protocol.zig +++ b/std/os/uefi/protocols/edid_override_protocol.zig @@ -4,10 +4,10 @@ const Handle = uefi.Handle; /// UEFI Specification, Version 2.8, 12.9 pub const EdidOverrideProtocol = extern struct { - _get_edid: extern fn (*const EdidOverrideProtocol, *const Handle, *u32, *usize, *?[*]u8) usize, + _get_edid: extern fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) usize, /// attributes must be align(4) - pub fn getEdid(self: *const EdidOverrideProtocol, handle: *const Handle, attributes: *EdidOverrideProtocolAttributes, edid_size: *usize, edid: *?[*]u8) usize { + pub fn getEdid(self: *const EdidOverrideProtocol, handle: Handle, attributes: *EdidOverrideProtocolAttributes, edid_size: *usize, edid: *?[*]u8) usize { return self._get_edid(self, handle, attributes, edid_size, edid); } diff --git a/std/os/uefi/tables/boot_services.zig b/std/os/uefi/tables/boot_services.zig index 2ae234f77..813677910 100644 --- a/std/os/uefi/tables/boot_services.zig +++ b/std/os/uefi/tables/boot_services.zig @@ -39,7 +39,7 @@ pub const BootServices = extern struct { installConfigurationTable: usize, // TODO imageLoad: usize, // TODO imageStart: usize, // TODO - exit: extern fn (*const Handle, usize, usize, ?*const c_void) usize, + exit: extern fn (Handle, usize, usize, ?*const c_void) usize, imageUnload: usize, // TODO exitBootServices: usize, // TODO getNextMonotonicCount: usize, // TODO diff --git a/std/os/uefi/tables/system_table.zig b/std/os/uefi/tables/system_table.zig index 31534d03b..23140f984 100644 --- a/std/os/uefi/tables/system_table.zig +++ b/std/os/uefi/tables/system_table.zig @@ -19,11 +19,11 @@ pub const SystemTable = extern struct { hdr: TableHeader, firmware_vendor: *u16, firmware_revision: u32, - console_in_handle: ?*Handle, + console_in_handle: ?Handle, con_in: ?*SimpleTextInputExProtocol, - console_out_handle: ?*Handle, + console_out_handle: ?Handle, con_out: ?*SimpleTextOutputProtocol, - standard_error_handle: ?*Handle, + standard_error_handle: ?Handle, std_err: ?*SimpleTextOutputProtocol, runtime_services: *RuntimeServices, boot_services: ?*BootServices, diff --git a/std/special/start.zig b/std/special/start.zig index dbd0912d9..cffd432f7 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -31,7 +31,7 @@ extern fn wasm_freestanding_start() void { _ = callMain(); } -extern fn EfiMain(handle: *uefi.Handle, system_table: *uefi.tables.SystemTable) usize { +extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize { const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'"; uefi.handle = handle; uefi.system_table = system_table; From 47ce736abec2d97c70eed619b5a6a58edeb4816a Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Sat, 10 Aug 2019 00:32:43 +0200 Subject: [PATCH 07/12] std/os/uefi: add basic Event support --- std/os/uefi.zig | 2 +- .../protocols/absolute_pointer_protocol.zig | 2 +- .../protocols/simple_pointer_protocol.zig | 2 +- .../simple_text_input_ex_protocol.zig | 2 +- std/os/uefi/tables.zig | 1 + std/os/uefi/tables/boot_services.zig | 25 ++++++++++++++++--- 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/std/os/uefi.zig b/std/os/uefi.zig index 9ddaad5aa..db46d50c1 100644 --- a/std/os/uefi.zig +++ b/std/os/uefi.zig @@ -8,7 +8,7 @@ pub const is_the_target = builtin.os == .uefi; pub var handle: Handle = undefined; pub var system_table: *tables.SystemTable = undefined; -pub const Event = @OpaqueType(); +pub const Event = *@OpaqueType(); // GUIDs must be align(8) pub const Guid = extern struct { time_low: u32, diff --git a/std/os/uefi/protocols/absolute_pointer_protocol.zig b/std/os/uefi/protocols/absolute_pointer_protocol.zig index b1fcc4902..8be52ad7e 100644 --- a/std/os/uefi/protocols/absolute_pointer_protocol.zig +++ b/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -6,7 +6,7 @@ const Guid = uefi.Guid; pub const AbsolutePointerProtocol = extern struct { _reset: extern fn (*const AbsolutePointerProtocol, bool) usize, _get_state: extern fn (*const AbsolutePointerProtocol, *AbsolutePointerState) usize, - wait_for_input: *Event, + wait_for_input: Event, mode: *AbsolutePointerMode, pub fn reset(self: *const AbsolutePointerProtocol, verify: bool) usize { diff --git a/std/os/uefi/protocols/simple_pointer_protocol.zig b/std/os/uefi/protocols/simple_pointer_protocol.zig index 26d11ca7f..369bc76aa 100644 --- a/std/os/uefi/protocols/simple_pointer_protocol.zig +++ b/std/os/uefi/protocols/simple_pointer_protocol.zig @@ -6,7 +6,7 @@ const Guid = uefi.Guid; pub const SimplePointerProtocol = struct { _reset: extern fn (*const SimplePointerProtocol, bool) usize, _get_state: extern fn (*const SimplePointerProtocol, *SimplePointerState) usize, - wait_for_input: *Event, + wait_for_input: Event, mode: *SimplePointerMode, pub fn reset(self: *const SimplePointerProtocol, verify: bool) usize { diff --git a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig index 16f676fd2..e23a68bac 100644 --- a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig +++ b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -6,7 +6,7 @@ const Guid = uefi.Guid; pub const SimpleTextInputExProtocol = extern struct { _reset: extern fn (*const SimpleTextInputExProtocol, bool) usize, _read_key_stroke_ex: extern fn (*const SimpleTextInputExProtocol, *KeyData) usize, - wait_for_key_ex: *Event, + wait_for_key_ex: Event, _set_state: extern fn (*const SimpleTextInputExProtocol, *const u8) usize, _register_key_notify: extern fn (*const SimpleTextInputExProtocol, *const KeyData, extern fn (*const KeyData) usize, **c_void) usize, _unregister_key_notify: extern fn (*const SimpleTextInputExProtocol, *const c_void) usize, diff --git a/std/os/uefi/tables.zig b/std/os/uefi/tables.zig index e5867ae65..51caed19d 100644 --- a/std/os/uefi/tables.zig +++ b/std/os/uefi/tables.zig @@ -4,3 +4,4 @@ pub const ResetType = @import("tables/runtime_services.zig").ResetType; pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; pub const SystemTable = @import("tables/system_table.zig").SystemTable; pub const TableHeader = @import("tables/table_header.zig").TableHeader; +pub const TimerDelay = @import("tables/boot_services.zig").TimerDelay; diff --git a/std/os/uefi/tables/boot_services.zig b/std/os/uefi/tables/boot_services.zig index 813677910..6007552bd 100644 --- a/std/os/uefi/tables/boot_services.zig +++ b/std/os/uefi/tables/boot_services.zig @@ -1,4 +1,5 @@ const uefi = @import("std").os.uefi; +const Event = uefi.Event; const Guid = uefi.Guid; const Handle = uefi.Handle; const TableHeader = uefi.tables.TableHeader; @@ -22,10 +23,10 @@ pub const BootServices = extern struct { getMemoryMap: usize, // TODO allocatePool: usize, // TODO freePool: usize, // TODO - createEvent: usize, // TODO - setTimer: usize, // TODO + createEvent: extern fn (u32, usize, ?extern fn (Event, ?*const c_void) void, ?*const c_void, *Event) usize, + setTimer: extern fn (Event, TimerDelay, u64) usize, waitForEvent: usize, // TODO - signalEvent: usize, // TODO + signalEvent: extern fn (Event) usize, closeEvent: usize, // TODO checkEvent: usize, // TODO installProtocolInterface: usize, // TODO @@ -61,4 +62,22 @@ pub const BootServices = extern struct { createEventEx: usize, // TODO pub const signature: u64 = 0x56524553544f4f42; + + pub const event_timer: u32 = 0x80000000; + pub const event_runtime: u32 = 0x40000000; + pub const event_notify_wait: u32 = 0x00000100; + pub const event_notify_signal: u32 = 0x00000200; + pub const event_signal_exit_boot_services: u32 = 0x00000201; + pub const event_signal_virtual_address_change: u32 = 0x00000202; + + pub const tpl_application: usize = 4; + pub const tpl_callback: usize = 8; + pub const tpl_notify: usize = 16; + pub const tpl_high_level: usize = 31; +}; + +pub const TimerDelay = extern enum(u32) { + TimerCancel, + TimerPeriodic, + TimerRelative, }; From a9b3700c6e5dbc830b648a585970ad61a34c5d63 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Sat, 10 Aug 2019 01:00:09 +0200 Subject: [PATCH 08/12] src/codegen: configure stack probes explicitly --- src/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 6ab76dea3..91c4a47a5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -474,6 +474,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { } if (g->have_stack_probing && !fn_table_entry->def_scope->safety_off) { addLLVMFnAttrStr(fn_table_entry->llvm_value, "probe-stack", "__zig_probe_stack"); + } else { + addLLVMFnAttrStr(fn_table_entry->llvm_value, "no-stack-arg-probe", ""); } } else { maybe_import_dll(g, fn_table_entry->llvm_value, linkage); From 70e62b86121dc5d54073bb34fe950ce6b3dff2cd Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Sun, 11 Aug 2019 15:50:03 +0200 Subject: [PATCH 09/12] std/os/uefi: some more events --- std/os/uefi/tables/boot_services.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/os/uefi/tables/boot_services.zig b/std/os/uefi/tables/boot_services.zig index 6007552bd..ae548137c 100644 --- a/std/os/uefi/tables/boot_services.zig +++ b/std/os/uefi/tables/boot_services.zig @@ -25,9 +25,9 @@ pub const BootServices = extern struct { freePool: usize, // TODO createEvent: extern fn (u32, usize, ?extern fn (Event, ?*const c_void) void, ?*const c_void, *Event) usize, setTimer: extern fn (Event, TimerDelay, u64) usize, - waitForEvent: usize, // TODO + waitForEvent: extern fn (usize, [*]const Event, *usize) usize, signalEvent: extern fn (Event) usize, - closeEvent: usize, // TODO + closeEvent: extern fn (Event) usize, checkEvent: usize, // TODO installProtocolInterface: usize, // TODO reinstallProtocolInterface: usize, // TODO From 03abc6edf450cfa6a55a3d416def44595a19a453 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Mon, 2 Sep 2019 20:34:00 +0200 Subject: [PATCH 10/12] std/os/uefi: add global_variable guid --- std/os/uefi/tables.zig | 1 + std/os/uefi/tables/runtime_services.zig | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/std/os/uefi/tables.zig b/std/os/uefi/tables.zig index 51caed19d..901591dea 100644 --- a/std/os/uefi/tables.zig +++ b/std/os/uefi/tables.zig @@ -1,5 +1,6 @@ pub const BootServices = @import("tables/boot_services.zig").BootServices; pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; +pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable; pub const ResetType = @import("tables/runtime_services.zig").ResetType; pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; pub const SystemTable = @import("tables/system_table.zig").SystemTable; diff --git a/std/os/uefi/tables/runtime_services.zig b/std/os/uefi/tables/runtime_services.zig index bae808ac8..53cb17db5 100644 --- a/std/os/uefi/tables/runtime_services.zig +++ b/std/os/uefi/tables/runtime_services.zig @@ -39,3 +39,13 @@ pub const ResetType = extern enum(u32) { ResetShutdown, ResetPlatformSpecific, }; + +/// UEFI Specification, Version 2.8, 3.3 +pub const global_variable align(8) = Guid{ + .time_low = 0x8be4df61, + .time_mid = 0x93ca, + .time_high_and_version = 0x11d2, + .clock_seq_high_and_reserved = 0xaa, + .clock_seq_low = 0x0d, + .node = [_]u8{ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c }, +}; From 8db41b7adbd0d1112a914d05ed94e9b55cfaf2db Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Mon, 2 Sep 2019 19:04:26 +0200 Subject: [PATCH 11/12] std/os/uefi: add support for getting memory map --- std/os/uefi/tables.zig | 1 + std/os/uefi/tables/boot_services.zig | 44 +++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/std/os/uefi/tables.zig b/std/os/uefi/tables.zig index 901591dea..fbb9abe7f 100644 --- a/std/os/uefi/tables.zig +++ b/std/os/uefi/tables.zig @@ -1,6 +1,7 @@ pub const BootServices = @import("tables/boot_services.zig").BootServices; pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable; +pub const MemoryDescriptor = @import("tables/boot_services.zig").MemoryDescriptor; pub const ResetType = @import("tables/runtime_services.zig").ResetType; pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; pub const SystemTable = @import("tables/system_table.zig").SystemTable; diff --git a/std/os/uefi/tables/boot_services.zig b/std/os/uefi/tables/boot_services.zig index ae548137c..55b0de347 100644 --- a/std/os/uefi/tables/boot_services.zig +++ b/std/os/uefi/tables/boot_services.zig @@ -20,7 +20,7 @@ pub const BootServices = extern struct { restoreTpl: usize, // TODO allocatePages: usize, // TODO freePages: usize, // TODO - getMemoryMap: usize, // TODO + getMemoryMap: extern fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) usize, allocatePool: usize, // TODO freePool: usize, // TODO createEvent: extern fn (u32, usize, ?extern fn (Event, ?*const c_void) void, ?*const c_void, *Event) usize, @@ -81,3 +81,45 @@ pub const TimerDelay = extern enum(u32) { TimerPeriodic, TimerRelative, }; + +pub const MemoryDescriptor = extern struct { + type: extern enum(u32) { + ReservedMemoryType, + LoaderCode, + LoaderData, + BootServicesCode, + BootServicesData, + RuntimeServicesCode, + RuntimeServicesData, + ConventionalMemory, + UnusableMemory, + ACPIReclaimMemory, + ACPIMemoryNVS, + MemoryMappedIO, + MemoryMappedIOPortSpace, + PalCode, + PersistentMemory, + MaxMemoryType, + }, + physical_start: u64, + virtual_start: u64, + number_of_pages: usize, + attribute: packed struct { + uc: bool, + wc: bool, + wt: bool, + wb: bool, + uce: bool, + _pad1: u7, + wp: bool, + rp: bool, + xp: bool, + nv: bool, + more_reliable: bool, + ro: bool, + sp: bool, + cpu_crypto: bool, + _pad2: u43, + memory_runtime: bool, + }, +}; From 5e874a89b991fcabe8177c551c220894593c1632 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Mon, 2 Sep 2019 22:31:59 +0200 Subject: [PATCH 12/12] std/os/uefi: fix ordering of packed bit fields --- .../protocols/absolute_pointer_protocol.zig | 10 +++---- .../uefi/protocols/edid_override_protocol.zig | 5 ++-- .../simple_text_input_ex_protocol.zig | 30 +++++++++---------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/std/os/uefi/protocols/absolute_pointer_protocol.zig b/std/os/uefi/protocols/absolute_pointer_protocol.zig index 8be52ad7e..df5a93031 100644 --- a/std/os/uefi/protocols/absolute_pointer_protocol.zig +++ b/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -35,10 +35,9 @@ pub const AbsolutePointerMode = extern struct { absolute_max_y: u64, absolute_max_z: u64, attributes: packed struct { - _pad1: u6, - supports_pressure_as_z: bool, supports_alt_active: bool, - _pad2: u24, + supports_pressure_as_z: bool, + _pad1: u30, }, }; @@ -47,9 +46,8 @@ pub const AbsolutePointerState = extern struct { current_y: u64 = undefined, current_z: u64 = undefined, active_buttons: packed struct { - _pad1: u6, - alt_active: bool, touch_active: bool, - _pad2: u24, + alt_active: bool, + _pad1: u30, } = undefined, }; diff --git a/std/os/uefi/protocols/edid_override_protocol.zig b/std/os/uefi/protocols/edid_override_protocol.zig index f7228f3c7..ad2eec120 100644 --- a/std/os/uefi/protocols/edid_override_protocol.zig +++ b/std/os/uefi/protocols/edid_override_protocol.zig @@ -22,8 +22,7 @@ pub const EdidOverrideProtocol = extern struct { }; pub const EdidOverrideProtocolAttributes = packed struct { - _pad1: u6, - enable_hot_plug: bool, dont_override: bool, - _pad2: u24, + enable_hot_plug: bool, + _pad1: u30, }; diff --git a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig index e23a68bac..5507b8950 100644 --- a/std/os/uefi/protocols/simple_text_input_ex_protocol.zig +++ b/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -48,28 +48,26 @@ pub const KeyData = extern struct { pub const KeyState = extern struct { key_shift_state: packed struct { - left_logo_pressed: bool, - right_logo_pressed: bool, - left_alt_pressed: bool, - right_alt_pressed: bool, - left_control_pressed: bool, - right_control_pressed: bool, - left_shift_pressed: bool, right_shift_pressed: bool, - _pad1: u6, - sys_req_pressed: bool, + left_shift_pressed: bool, + right_control_pressed: bool, + left_control_pressed: bool, + right_alt_pressed: bool, + left_alt_pressed: bool, + right_logo_pressed: bool, + left_logo_pressed: bool, menu_key_pressed: bool, - _pad2: u15, + sys_req_pressed: bool, + _pad1: u21, shift_state_valid: bool, }, key_toggle_state: packed struct { - toggle_state_valid: bool, - _pad1: u2, - key_state_exposed: bool, - caps_lock_active: bool, - _pad2: u1, - num_lock_active: bool, scroll_lock_active: bool, + num_lock_active: bool, + caps_lock_active: bool, + _pad1: u3, + key_state_exposed: bool, + toggle_state_valid: bool, }, };