Skip to content

improve uefi support #2944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 13, 2019
12 changes: 7 additions & 5 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -8540,10 +8542,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;
Expand All @@ -8553,8 +8551,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
Expand Down
6 changes: 3 additions & 3 deletions src/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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));
}

Expand Down
11 changes: 9 additions & 2 deletions std/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 },
Expand Down
12 changes: 10 additions & 2 deletions std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we at least exit with non-zero status?

}

raise(SIGABRT) catch {};
Expand Down Expand Up @@ -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);
}

Expand Down
45 changes: 42 additions & 3 deletions std/os/uefi.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
// 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: packed struct {
_pad1: u6,
in_daylight: bool,
adjust_daylight: bool,
},
_pad2: u8,

pub const unspecified_timezone: i16 = 0x7ff;
};
pub const TimeCapabilities = extern struct {
resolution: u32,
accuracy: u32,
sets_to_zero: bool,
};
32 changes: 32 additions & 0 deletions std/os/uefi/protocols.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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 EdidOverrideProtocolAttributes = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocolAttributes;

pub const RNGProtocol = @import("protocols/rng_protocol.zig").RNGProtocol;
53 changes: 53 additions & 0 deletions std/os/uefi/protocols/absolute_pointer_protocol.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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: packed struct {
supports_alt_active: bool,
supports_pressure_as_z: bool,
_pad1: u30,
},
};

pub const AbsolutePointerState = extern struct {
current_x: u64 = undefined,
current_y: u64 = undefined,
current_z: u64 = undefined,
active_buttons: packed struct {
touch_active: bool,
alt_active: bool,
_pad1: u30,
} = undefined,
};
17 changes: 17 additions & 0 deletions std/os/uefi/protocols/edid_active_protocol.zig
Original file line number Diff line number Diff line change
@@ -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 },
};
};
17 changes: 17 additions & 0 deletions std/os/uefi/protocols/edid_discovered_protocol.zig
Original file line number Diff line number Diff line change
@@ -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 },
};
};
28 changes: 28 additions & 0 deletions std/os/uefi/protocols/edid_override_protocol.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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, Handle, *u32, *usize, *?[*]u8) usize,

/// attributes must be align(4)
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);
}

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 EdidOverrideProtocolAttributes = packed struct {
dont_override: bool,
enable_hot_plug: bool,
_pad1: u30,
};
79 changes: 79 additions & 0 deletions std/os/uefi/protocols/graphics_output_protocol.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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 = 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) {
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,
};
Loading