authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-15 20:59:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-15 20:59:53-04:00
logc4416b224d29692556d828c0902f6416f3f5b534
tree3703daa3f28ddbf4b61db91a8bdf4664550260e4
parent92a427437c420195a55df4baee1bd0738dc4ed70
parent8223aca09bc93279a88d1439d6dfc437144ec578
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm9


35 files changed, 1224 insertions(+), 90 deletions(-)

src/analyze.cpp+24-8
......@@ -2406,8 +2406,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
24062406 ZigType *tag_int_type;
24072407 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
24082408 tag_int_type = get_c_int_type(g, CIntTypeInt);
2409 } else if (enum_type->data.enumeration.layout == ContainerLayoutAuto && field_count == 1) {
2410 tag_int_type = g->builtin_types.entry_num_lit_int;
24112409 } else {
24122410 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
24132411 }
......@@ -2420,7 +2418,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
24202418 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
24212419 if (type_is_invalid(wanted_tag_int_type)) {
24222420 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2423 } else if (wanted_tag_int_type->id != ZigTypeIdInt) {
2421 } else if (wanted_tag_int_type->id != ZigTypeIdInt &&
2422 wanted_tag_int_type->id != ZigTypeIdComptimeInt) {
24242423 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
24252424 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
24262425 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
......@@ -2538,6 +2537,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25382537 enum_type->data.enumeration.resolve_loop_flag = false;
25392538 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
25402539
2540 occupied_tag_values.deinit();
2541
25412542 return ErrorNone;
25422543}
25432544
......@@ -2804,14 +2805,12 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
28042805 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
28052806 return ErrorSemanticAnalyzeFail;
28062807 }
2807 if (tag_int_type->id != ZigTypeIdInt) {
2808 if (tag_int_type->id != ZigTypeIdInt && tag_int_type->id != ZigTypeIdComptimeInt) {
28082809 add_node_error(g, enum_type_node,
28092810 buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name)));
28102811 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
28112812 return ErrorSemanticAnalyzeFail;
28122813 }
2813 } else if (auto_layout && field_count == 1) {
2814 tag_int_type = g->builtin_types.entry_num_lit_int;
28152814 } else {
28162815 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
28172816 }
......@@ -5878,6 +5877,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
58785877 fn->err_code_spill = &alloca_gen->base;
58795878 }
58805879
5880 ZigType *largest_call_frame_type = nullptr;
5881 // Later we'll change this to be largest_call_frame_type instead of void.
5882 IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
5883 fn, g->builtin_types.entry_void, "@async_call_frame");
5884
58815885 for (size_t i = 0; i < fn->call_list.length; i += 1) {
58825886 IrInstructionCallGen *call = fn->call_list.at(i);
58835887 if (call->new_stack != nullptr) {
......@@ -5921,9 +5925,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
59215925
59225926 mark_suspension_point(call->base.scope);
59235927
5924 call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn,
5925 callee_frame_type, "");
5928 if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
5929 return err;
5930 }
5931 if (largest_call_frame_type == nullptr ||
5932 callee_frame_type->abi_size > largest_call_frame_type->abi_size)
5933 {
5934 largest_call_frame_type = callee_frame_type;
5935 }
5936
5937 call->frame_result_loc = all_calls_alloca;
59265938 }
5939 if (largest_call_frame_type != nullptr) {
5940 all_calls_alloca->value.type = get_pointer_to_type(g, largest_call_frame_type, false);
5941 }
5942
59275943 // Since this frame is async, an await might represent a suspend point, and
59285944 // therefore need to spill. It also needs to mark expr scopes as having to spill.
59295945 // For example: foo() + await z
src/codegen.cpp+31-8
......@@ -517,6 +517,8 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
517517 }
518518 if (g->have_stack_probing && !fn->def_scope->safety_off) {
519519 addLLVMFnAttrStr(llvm_fn, "probe-stack", "__zig_probe_stack");
520 } else if (g->zig_target->os == OsUefi) {
521 addLLVMFnAttrStr(llvm_fn, "no-stack-arg-probe", "");
520522 }
521523 } else {
522524 maybe_import_dll(g, llvm_fn, linkage);
......@@ -3863,6 +3865,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
38633865 ZigList<ZigType *> gen_param_types = {};
38643866 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
38653867 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
3868 LLVMValueRef frame_result_loc_uncasted = nullptr;
38663869 LLVMValueRef frame_result_loc;
38673870 LLVMValueRef awaiter_init_val;
38683871 LLVMValueRef ret_ptr;
......@@ -3871,7 +3874,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
38713874 if (instruction->modifier == CallModifierAsync) {
38723875 frame_result_loc = result_loc;
38733876 } else {
3874 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3877 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);
3878 src_assert(instruction->fn_entry != nullptr, instruction->base.source_node);
3879 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
3880 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
38753881 }
38763882 } else {
38773883 if (instruction->new_stack->value.type->id == ZigTypeIdPointer &&
......@@ -4138,6 +4144,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
41384144 }
41394145 }
41404146
4147 if (frame_result_loc_uncasted != nullptr && instruction->fn_entry != nullptr) {
4148 // Instead of a spill, we do the bitcast again. The uncasted LLVM IR instruction will
4149 // be an Alloca from the entry block, so it does not need to be spilled.
4150 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
4151 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
4152 }
4153
41414154 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
41424155 return LLVMBuildLoad(g->builder, result_ptr, "");
41434156 }
......@@ -7173,6 +7186,9 @@ static void do_code_gen(CodeGen *g) {
71737186
71747187 if (!is_async) {
71757188 // allocate async frames for noasync calls & awaits to async functions
7189 ZigType *largest_call_frame_type = nullptr;
7190 IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base,
7191 fn_table_entry->body_node, fn_table_entry, g->builtin_types.entry_void, "@async_call_frame");
71767192 for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) {
71777193 IrInstructionCallGen *call = fn_table_entry->call_list.at(i);
71787194 if (call->fn_entry == nullptr)
......@@ -7184,8 +7200,15 @@ static void do_code_gen(CodeGen *g) {
71847200 if (call->frame_result_loc != nullptr)
71857201 continue;
71867202 ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry);
7187 call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node,
7188 fn_table_entry, callee_frame_type, "");
7203 if (largest_call_frame_type == nullptr ||
7204 callee_frame_type->abi_size > largest_call_frame_type->abi_size)
7205 {
7206 largest_call_frame_type = callee_frame_type;
7207 }
7208 call->frame_result_loc = all_calls_alloca;
7209 }
7210 if (largest_call_frame_type != nullptr) {
7211 all_calls_alloca->value.type = get_pointer_to_type(g, largest_call_frame_type, false);
71897212 }
71907213 // allocate temporary stack data
71917214 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
......@@ -9074,10 +9097,6 @@ static bool want_startup_code(CodeGen *g) {
90749097 if (g->is_test_build)
90759098 return false;
90769099
9077 // start code does not handle UEFI target
9078 if (g->zig_target->os == OsUefi)
9079 return false;
9080
90819100 // WASM freestanding can still have an entry point but other freestanding targets do not.
90829101 if (g->zig_target->os == OsFreestanding && !target_is_wasm(g->zig_target))
90839102 return false;
......@@ -9087,8 +9106,12 @@ static bool want_startup_code(CodeGen *g) {
90879106 return false;
90889107
90899108 // If there is a pub main in the root source file, that means we need start code.
9090 if (g->have_pub_main)
9109 if (g->have_pub_main) {
90919110 return true;
9111 } else {
9112 if (g->zig_target->os == OsUefi)
9113 return false;
9114 }
90929115
90939116 if (g->out_type == OutTypeExe) {
90949117 // For build-exe, we might add start code even though there is no pub main, so that the
src/link.cpp+5
......@@ -1615,6 +1615,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
16151615
16161616 lj->args.append("-error-limit=0");
16171617
1618 if (g->out_type == OutTypeExe) {
1619 lj->args.append("-z");
1620 lj->args.append("stack-size=16777216"); // default to 16 MiB
1621 }
1622
16181623 if (g->linker_script) {
16191624 lj->args.append("-T");
16201625 lj->args.append(g->linker_script);
src/target.cpp+3-3
......@@ -1129,7 +1129,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
11291129}
11301130
11311131bool target_allows_addr_zero(const ZigTarget *target) {
1132 return target->os == OsFreestanding;
1132 return target->os == OsFreestanding || target->os == OsUefi;
11331133}
11341134
11351135const char *target_o_file_ext(const ZigTarget *target) {
......@@ -1585,12 +1585,12 @@ bool target_supports_fpic(const ZigTarget *target) {
15851585}
15861586
15871587bool target_supports_stack_probing(const ZigTarget *target) {
1588 return target->os != OsWindows && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64);
1588 return target->os != OsWindows && target->os != OsUefi && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64);
15891589}
15901590
15911591bool target_requires_pic(const ZigTarget *target, bool linking_libc) {
15921592 // This function returns whether non-pic code is completely invalid on the given target.
1593 return target->os == OsWindows || target_os_requires_libc(target->os) ||
1593 return target->os == OsWindows || target->os == OsUefi || target_os_requires_libc(target->os) ||
15941594 (linking_libc && target_is_glibc(target));
15951595}
15961596
src/tokenizer.cpp+7-2
......@@ -407,9 +407,14 @@ void tokenize(Buf *buf, Tokenization *out) {
407407 t.buf = buf;
408408
409409 out->line_offsets = allocate<ZigList<size_t>>(1);
410
411410 out->line_offsets->append(0);
412 for (t.pos = 0; t.pos < buf_len(t.buf); t.pos += 1) {
411
412 // Skip the UTF-8 BOM if present
413 if (buf_starts_with_mem(buf, "\xEF\xBB\xBF", 3)) {
414 t.pos += 3;
415 }
416
417 for (; t.pos < buf_len(t.buf); t.pos += 1) {
413418 uint8_t c = buf_ptr(t.buf)[t.pos];
414419 switch (t.state) {
415420 case TokenizeStateError:
std/build.zig+9-2
......@@ -1175,6 +1175,13 @@ pub const Target = union(enum) {
11751175 };
11761176 }
11771177
1178 pub fn isUefi(self: Target) bool {
1179 return switch (self.getOs()) {
1180 .uefi => true,
1181 else => false,
1182 };
1183 }
1184
11781185 pub fn isWasm(self: Target) bool {
11791186 return switch (self.getArch()) {
11801187 .wasm32, .wasm64 => true,
......@@ -1490,7 +1497,7 @@ pub const LibExeObjStep = struct {
14901497 }
14911498
14921499 pub fn producesPdbFile(self: *LibExeObjStep) bool {
1493 if (!self.target.isWindows()) return false;
1500 if (!self.target.isWindows() and !self.target.isUefi()) return false;
14941501 if (self.strip) return false;
14951502 return self.isDynamicLibrary() or self.kind == .Exe;
14961503 }
......@@ -1587,7 +1594,7 @@ pub const LibExeObjStep = struct {
15871594 /// Unless setOutputDir was called, this function must be called only in
15881595 /// the make step, from a step that has declared a dependency on this one.
15891596 pub fn getOutputPdbPath(self: *LibExeObjStep) []const u8 {
1590 assert(self.target.isWindows());
1597 assert(self.target.isWindows() or self.target.isUefi());
15911598 return fs.path.join(
15921599 self.builder.allocator,
15931600 [_][]const u8{ self.output_dir.?, self.out_pdb_filename },
std/c/freebsd.zig+3
......@@ -7,3 +7,6 @@ pub const _errno = __error;
77pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
88pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
99pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
10
11pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
12pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
std/debug.zig+39-39
......@@ -1478,10 +1478,11 @@ const LineNumberProgram = struct {
14781478 }
14791479};
14801480
1481// TODO the noasyncs here are workarounds
14811482fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
14821483 var buf = ArrayList(u8).init(allocator);
14831484 while (true) {
1484 const byte = try in_stream.readByte();
1485 const byte = try noasync in_stream.readByte();
14851486 if (byte == 0) break;
14861487 try buf.append(byte);
14871488 }
......@@ -1494,10 +1495,11 @@ fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
14941495 return di.readString();
14951496}
14961497
1498// TODO the noasyncs here are workarounds
14971499fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {
14981500 const buf = try allocator.alloc(u8, size);
14991501 errdefer allocator.free(buf);
1500 if ((try in_stream.read(buf)) < size) return error.EndOfFile;
1502 if ((try noasync in_stream.read(buf)) < size) return error.EndOfFile;
15011503 return buf;
15021504}
15031505
......@@ -1506,8 +1508,9 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
15061508 return FormValue{ .Block = buf };
15071509}
15081510
1511// TODO the noasyncs here are workarounds
15091512fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
1510 const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
1513 const block_len = try noasync in_stream.readVarInt(usize, builtin.Endian.Little, size);
15111514 return parseFormValueBlockLen(allocator, in_stream, block_len);
15121515}
15131516
......@@ -1537,27 +1540,37 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
15371540 };
15381541}
15391542
1543// TODO the noasyncs here are workarounds
15401544fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
1541 return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
1545 return if (is_64) try noasync in_stream.readIntLittle(u64) else u64(try noasync in_stream.readIntLittle(u32));
15421546}
15431547
1548// TODO the noasyncs here are workarounds
15441549fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
1545 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
1550 if (@sizeOf(usize) == 4) {
1551 return u64(try noasync in_stream.readIntLittle(u32));
1552 } else if (@sizeOf(usize) == 8) {
1553 return noasync in_stream.readIntLittle(u64);
1554 } else {
1555 unreachable;
1556 }
15461557}
15471558
1559// TODO the noasyncs here are workarounds
15481560fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
15491561 return FormValue{
15501562 .Ref = switch (size) {
1551 1 => try in_stream.readIntLittle(u8),
1552 2 => try in_stream.readIntLittle(u16),
1553 4 => try in_stream.readIntLittle(u32),
1554 8 => try in_stream.readIntLittle(u64),
1555 -1 => try leb.readULEB128(u64, in_stream),
1563 1 => try noasync in_stream.readIntLittle(u8),
1564 2 => try noasync in_stream.readIntLittle(u16),
1565 4 => try noasync in_stream.readIntLittle(u32),
1566 8 => try noasync in_stream.readIntLittle(u64),
1567 -1 => try noasync leb.readULEB128(u64, in_stream),
15561568 else => unreachable,
15571569 },
15581570 };
15591571}
15601572
1573// TODO the noasyncs here are workarounds
15611574fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
15621575 return switch (form_id) {
15631576 DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
......@@ -1565,7 +1578,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
15651578 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
15661579 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
15671580 DW.FORM_block => x: {
1568 const block_len = try leb.readULEB128(usize, in_stream);
1581 const block_len = try noasync leb.readULEB128(usize, in_stream);
15691582 return parseFormValueBlockLen(allocator, in_stream, block_len);
15701583 },
15711584 DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
......@@ -1577,11 +1590,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
15771590 return parseFormValueConstant(allocator, in_stream, signed, -1);
15781591 },
15791592 DW.FORM_exprloc => {
1580 const size = try leb.readULEB128(usize, in_stream);
1593 const size = try noasync leb.readULEB128(usize, in_stream);
15811594 const buf = try readAllocBytes(allocator, in_stream, size);
15821595 return FormValue{ .ExprLoc = buf };
15831596 },
1584 DW.FORM_flag => FormValue{ .Flag = (try in_stream.readByte()) != 0 },
1597 DW.FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 },
15851598 DW.FORM_flag_present => FormValue{ .Flag = true },
15861599 DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
15871600
......@@ -1592,12 +1605,12 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
15921605 DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1),
15931606
15941607 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
1595 DW.FORM_ref_sig8 => FormValue{ .Ref = try in_stream.readIntLittle(u64) },
1608 DW.FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readIntLittle(u64) },
15961609
15971610 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
15981611 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
15991612 DW.FORM_indirect => {
1600 const child_form_id = try leb.readULEB128(u64, in_stream);
1613 const child_form_id = try noasync leb.readULEB128(u64, in_stream);
16011614 const F = @typeOf(async parseFormValue(allocator, in_stream, child_form_id, is_64));
16021615 var frame = try allocator.create(F);
16031616 defer allocator.destroy(frame);
......@@ -1655,7 +1668,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
16551668 return null;
16561669}
16571670
1658fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
1671fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
16591672 const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
16601673 if (abbrev_code == 0) return null;
16611674 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
......@@ -1675,25 +1688,6 @@ fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Di
16751688 return result;
16761689}
16771690
1678fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
1679 const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
1680 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
1681
1682 var result = Die{
1683 .tag_id = table_entry.tag_id,
1684 .has_children = table_entry.has_children,
1685 .attrs = ArrayList(Die.Attr).init(di.allocator()),
1686 };
1687 try result.attrs.resize(table_entry.attrs.len);
1688 for (table_entry.attrs.toSliceConst()) |attr, i| {
1689 result.attrs.items[i] = Die.Attr{
1690 .id = attr.attr_id,
1691 .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
1692 };
1693 }
1694 return result;
1695}
1696
16971691fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: usize) !LineInfo {
16981692 const ofile = symbol.ofile orelse return error.MissingDebugInfo;
16991693 const gop = try di.ofiles.getOrPut(ofile);
......@@ -2103,7 +2097,7 @@ fn scanAllFunctions(di: *DwarfInfo) !void {
21032097 const next_unit_pos = this_unit_offset + next_offset;
21042098
21052099 while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
2106 const die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse continue;
2100 const die_obj = (try parseDie(di, abbrev_table, is_64)) orelse continue;
21072101 const after_die_offset = try di.dwarf_seekable_stream.getPos();
21082102
21092103 switch (die_obj.tag_id) {
......@@ -2121,13 +2115,13 @@ fn scanAllFunctions(di: *DwarfInfo) !void {
21212115 const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin);
21222116 if (ref_offset > next_offset) return error.InvalidDebugInfo;
21232117 try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
2124 this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
2118 this_die_obj = (try parseDie(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
21252119 } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| {
21262120 // Follow the DIE it points to and repeat
21272121 const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification);
21282122 if (ref_offset > next_offset) return error.InvalidDebugInfo;
21292123 try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
2130 this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
2124 this_die_obj = (try parseDie(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
21312125 } else {
21322126 break :x null;
21332127 }
......@@ -2203,7 +2197,7 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
22032197 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
22042198
22052199 const compile_unit_die = try di.allocator().create(Die);
2206 compile_unit_die.* = try parseDie(di, abbrev_table, is_64);
2200 compile_unit_die.* = (try parseDie(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
22072201
22082202 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
22092203
......@@ -2419,3 +2413,9 @@ stdcallcc fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) c_long {
24192413 else => return windows.EXCEPTION_CONTINUE_SEARCH,
24202414 }
24212415}
2416
2417pub fn dumpStackPointerAddr(prefix: []const u8) void {
2418 const sp = asm ("" : [argc] "={rsp}" (-> usize));
2419 std.debug.warn("{} sp = 0x{x}\n", prefix, sp);
2420}
2421
std/io/in_stream.zig+4-4
......@@ -6,7 +6,7 @@ const assert = std.debug.assert;
66const mem = std.mem;
77const Buffer = std.Buffer;
88
9pub const default_stack_size = 4 * 1024 * 1024;
9pub const default_stack_size = 1 * 1024 * 1024;
1010pub const stack_size: usize = if (@hasDecl(root, "stack_size_std_io_InStream"))
1111 root.stack_size_std_io_InStream
1212else
......@@ -32,10 +32,10 @@ pub fn InStream(comptime ReadError: type) type {
3232 /// End of stream is not an error condition.
3333 pub fn read(self: *Self, buffer: []u8) Error!usize {
3434 if (std.io.is_async) {
35 // Let's not be writing 0xaa in safe modes for upwards of 4 MiB for every stream read.
36 @setRuntimeSafety(false);
3537 var stack_frame: [stack_size]u8 align(stack_align) = undefined;
36 // TODO https://github.com/ziglang/zig/issues/3068
37 var result: Error!usize = undefined;
38 return await @asyncCall(&stack_frame, &result, self.readFn, self, buffer);
38 return await @asyncCall(&stack_frame, {}, self.readFn, self, buffer);
3939 } else {
4040 return self.readFn(self, buffer);
4141 }
std/os.zig+10-2
......@@ -172,8 +172,7 @@ pub fn abort() noreturn {
172172 system.abort();
173173 }
174174 if (builtin.os == .uefi) {
175 // TODO there must be a better thing to do here than loop forever
176 while (true) {}
175 exit(0); // TODO choose appropriate exit code
177176 }
178177
179178 raise(SIGABRT) catch {};
......@@ -245,6 +244,15 @@ pub fn exit(status: u8) noreturn {
245244 if (linux.is_the_target and !builtin.single_threaded) {
246245 linux.exit_group(status);
247246 }
247 if (uefi.is_the_target) {
248 // exit() is only avaliable if exitBootServices() has not been called yet.
249 // This call to exit should not fail, so we don't care about its return value.
250 if (uefi.system_table.boot_services) |bs| {
251 _ = bs.exit(uefi.handle, status, 0, null);
252 }
253 // If we can't exit, reboot the system instead.
254 uefi.system_table.runtime_services.resetSystem(uefi.tables.ResetType.ResetCold, status, 0, null);
255 }
248256 system.exit(status);
249257}
250258
std/os/bits/linux.zig+1-1
......@@ -25,7 +25,7 @@ pub const STDOUT_FILENO = 1;
2525pub const STDERR_FILENO = 2;
2626
2727/// Special value used to indicate openat should use the current working directory
28pub const AT_FDCWD = 100;
28pub const AT_FDCWD = -100;
2929
3030/// Do not follow symbolic links
3131pub const AT_SYMLINK_NOFOLLOW = 0x100;
std/os/linux/tls.zig+6-1
......@@ -132,7 +132,7 @@ pub fn setThreadPointer(addr: usize) void {
132132 }
133133}
134134
135pub fn initTLS() void {
135pub fn initTLS() ?*elf.Phdr {
136136 var tls_phdr: ?*elf.Phdr = null;
137137 var img_base: usize = 0;
138138
......@@ -159,10 +159,13 @@ pub fn initTLS() void {
159159 // Search the TLS section
160160 const phdrs = (@intToPtr([*]elf.Phdr, at_phdr))[0..at_phnum];
161161
162 var gnu_stack: ?*elf.Phdr = null;
163
162164 for (phdrs) |*phdr| {
163165 switch (phdr.p_type) {
164166 elf.PT_PHDR => img_base = at_phdr - phdr.p_vaddr,
165167 elf.PT_TLS => tls_phdr = phdr,
168 elf.PT_GNU_STACK => gnu_stack = phdr,
166169 else => continue,
167170 }
168171 }
......@@ -224,6 +227,8 @@ pub fn initTLS() void {
224227 .data_offset = data_offset,
225228 };
226229 }
230
231 return gnu_stack;
227232}
228233
229234pub fn copyTLS(addr: usize) usize {
std/os/uefi.zig+42-3
......@@ -1,6 +1,45 @@
1// TODO this is where the extern declarations go. For example, see
2// inc/efilib.h in gnu-efi-code
1pub const protocols = @import("uefi/protocols.zig");
2pub const status = @import("uefi/status.zig");
3pub const tables = @import("uefi/tables.zig");
34
45const builtin = @import("builtin");
5
66pub const is_the_target = builtin.os == .uefi;
7
8pub var handle: Handle = undefined;
9pub var system_table: *tables.SystemTable = undefined;
10
11pub const Event = *@OpaqueType();
12// GUIDs must be align(8)
13pub const Guid = extern struct {
14 time_low: u32,
15 time_mid: u16,
16 time_high_and_version: u16,
17 clock_seq_high_and_reserved: u8,
18 clock_seq_low: u8,
19 node: [6]u8,
20};
21pub const Handle = *@OpaqueType();
22pub const Time = extern struct {
23 year: u16,
24 month: u8,
25 day: u8,
26 hour: u8,
27 minute: u8,
28 second: u8,
29 _pad1: u8,
30 nanosecond: u32,
31 timezone: i16,
32 daylight: packed struct {
33 _pad1: u6,
34 in_daylight: bool,
35 adjust_daylight: bool,
36 },
37 _pad2: u8,
38
39 pub const unspecified_timezone: i16 = 0x7ff;
40};
41pub const TimeCapabilities = extern struct {
42 resolution: u32,
43 accuracy: u32,
44 sets_to_zero: bool,
45};
std/os/uefi/protocols.zig created+32
......@@ -0,0 +1,32 @@
1pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey;
2pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData;
3pub const KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState;
4pub const SimpleTextInputExProtocol = @import("protocols/simple_text_input_ex_protocol.zig").SimpleTextInputExProtocol;
5
6pub const SimpleTextOutputMode = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputMode;
7pub const SimpleTextOutputProtocol = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputProtocol;
8
9pub const SimplePointerMode = @import("protocols/simple_pointer_protocol.zig").SimplePointerMode;
10pub const SimplePointerProtocol = @import("protocols/simple_pointer_protocol.zig").SimplePointerProtocol;
11pub const SimplePointerState = @import("protocols/simple_pointer_protocol.zig").SimplePointerState;
12
13pub const AbsolutePointerMode = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerMode;
14pub const AbsolutePointerProtocol = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerProtocol;
15pub const AbsolutePointerState = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerState;
16
17pub const GraphicsOutputBltPixel = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltPixel;
18pub const GraphicsOutputBltOperation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltOperation;
19pub const GraphicsOutputModeInformation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputModeInformation;
20pub const GraphicsOutputProtocol = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocol;
21pub const GraphicsOutputProtocolMode = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocolMode;
22pub const GraphicsPixelFormat = @import("protocols/graphics_output_protocol.zig").GraphicsPixelFormat;
23pub const PixelBitmask = @import("protocols/graphics_output_protocol.zig").PixelBitmask;
24
25pub const EdidDiscoveredProtocol = @import("protocols/edid_discovered_protocol.zig").EdidDiscoveredProtocol;
26
27pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").EdidActiveProtocol;
28
29pub const EdidOverrideProtocol = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocol;
30pub const EdidOverrideProtocolAttributes = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocolAttributes;
31
32pub const RNGProtocol = @import("protocols/rng_protocol.zig").RNGProtocol;
std/os/uefi/protocols/absolute_pointer_protocol.zig created+53
......@@ -0,0 +1,53 @@
1const uefi = @import("std").os.uefi;
2const Event = uefi.Event;
3const Guid = uefi.Guid;
4
5/// UEFI Specification, Version 2.8, 12.7
6pub const AbsolutePointerProtocol = extern struct {
7 _reset: extern fn (*const AbsolutePointerProtocol, bool) usize,
8 _get_state: extern fn (*const AbsolutePointerProtocol, *AbsolutePointerState) usize,
9 wait_for_input: Event,
10 mode: *AbsolutePointerMode,
11
12 pub fn reset(self: *const AbsolutePointerProtocol, verify: bool) usize {
13 return self._reset(self, verify);
14 }
15
16 pub fn getState(self: *const AbsolutePointerProtocol, state: *AbsolutePointerState) usize {
17 return self._get_state(self, state);
18 }
19
20 pub const guid align(8) = Guid{
21 .time_low = 0x8d59d32b,
22 .time_mid = 0xc655,
23 .time_high_and_version = 0x4ae9,
24 .clock_seq_high_and_reserved = 0x9b,
25 .clock_seq_low = 0x15,
26 .node = [_]u8{ 0xf2, 0x59, 0x04, 0x99, 0x2a, 0x43 },
27 };
28};
29
30pub const AbsolutePointerMode = extern struct {
31 absolute_min_x: u64,
32 absolute_min_y: u64,
33 absolute_min_z: u64,
34 absolute_max_x: u64,
35 absolute_max_y: u64,
36 absolute_max_z: u64,
37 attributes: packed struct {
38 supports_alt_active: bool,
39 supports_pressure_as_z: bool,
40 _pad1: u30,
41 },
42};
43
44pub const AbsolutePointerState = extern struct {
45 current_x: u64 = undefined,
46 current_y: u64 = undefined,
47 current_z: u64 = undefined,
48 active_buttons: packed struct {
49 touch_active: bool,
50 alt_active: bool,
51 _pad1: u30,
52 } = undefined,
53};
std/os/uefi/protocols/edid_active_protocol.zig created+17
......@@ -0,0 +1,17 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 12.9
5pub const EdidActiveProtocol = extern struct {
6 size_of_edid: u32,
7 edid: ?[*]u8,
8
9 pub const guid align(8) = Guid{
10 .time_low = 0xbd8c1056,
11 .time_mid = 0x9f36,
12 .time_high_and_version = 0x44ec,
13 .clock_seq_high_and_reserved = 0x92,
14 .clock_seq_low = 0xa8,
15 .node = [_]u8{ 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 },
16 };
17};
std/os/uefi/protocols/edid_discovered_protocol.zig created+17
......@@ -0,0 +1,17 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 12.9
5pub const EdidDiscoveredProtocol = extern struct {
6 size_of_edid: u32,
7 edid: ?[*]u8,
8
9 pub const guid align(8) = Guid{
10 .time_low = 0x1c0c34f6,
11 .time_mid = 0xd380,
12 .time_high_and_version = 0x41fa,
13 .clock_seq_high_and_reserved = 0xa0,
14 .clock_seq_low = 0x49,
15 .node = [_]u8{ 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa },
16 };
17};
std/os/uefi/protocols/edid_override_protocol.zig created+28
......@@ -0,0 +1,28 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3const Handle = uefi.Handle;
4
5/// UEFI Specification, Version 2.8, 12.9
6pub const EdidOverrideProtocol = extern struct {
7 _get_edid: extern fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) usize,
8
9 /// attributes must be align(4)
10 pub fn getEdid(self: *const EdidOverrideProtocol, handle: Handle, attributes: *EdidOverrideProtocolAttributes, edid_size: *usize, edid: *?[*]u8) usize {
11 return self._get_edid(self, handle, attributes, edid_size, edid);
12 }
13
14 pub const guid align(8) = Guid{
15 .time_low = 0x48ecb431,
16 .time_mid = 0xfb72,
17 .time_high_and_version = 0x45c0,
18 .clock_seq_high_and_reserved = 0xa9,
19 .clock_seq_low = 0x22,
20 .node = [_]u8{ 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5 },
21 };
22};
23
24pub const EdidOverrideProtocolAttributes = packed struct {
25 dont_override: bool,
26 enable_hot_plug: bool,
27 _pad1: u30,
28};
std/os/uefi/protocols/graphics_output_protocol.zig created+79
......@@ -0,0 +1,79 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 12.9
5pub const GraphicsOutputProtocol = extern struct {
6 _query_mode: extern fn (*const GraphicsOutputProtocol, u32, *usize, **GraphicsOutputModeInformation) usize,
7 _set_mode: extern fn (*const GraphicsOutputProtocol, u32) usize,
8 _blt: extern fn (*const GraphicsOutputProtocol, ?[*]GraphicsOutputBltPixel, GraphicsOutputBltOperation, usize, usize, usize, usize, usize, usize, usize) usize,
9 mode: *GraphicsOutputProtocolMode,
10
11 pub fn queryMode(self: *const GraphicsOutputProtocol, mode: u32, size_of_info: *usize, info: **GraphicsOutputModeInformation) usize {
12 return self._query_mode(self, mode, size_of_info, info);
13 }
14
15 pub fn setMode(self: *const GraphicsOutputProtocol, mode: u32) usize {
16 return self._set_mode(self, mode);
17 }
18
19 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 {
20 return self._blt(self, blt_buffer, blt_operation, source_x, source_y, destination_x, destination_y, width, height, delta);
21 }
22
23 pub const guid align(8) = Guid{
24 .time_low = 0x9042a9de,
25 .time_mid = 0x23dc,
26 .time_high_and_version = 0x4a38,
27 .clock_seq_high_and_reserved = 0x96,
28 .clock_seq_low = 0xfb,
29 .node = [_]u8{ 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a },
30 };
31};
32
33pub const GraphicsOutputProtocolMode = extern struct {
34 max_mode: u32,
35 mode: u32,
36 info: *GraphicsOutputModeInformation,
37 size_of_info: usize,
38 frame_buffer_base: u64,
39 frame_buffer_size: usize,
40};
41
42pub const GraphicsOutputModeInformation = extern struct {
43 version: u32 = undefined,
44 horizontal_resolution: u32 = undefined,
45 vertical_resolution: u32 = undefined,
46 pixel_format: GraphicsPixelFormat = undefined,
47 pixel_information: PixelBitmask = undefined,
48 pixels_per_scan_line: u32 = undefined,
49};
50
51pub const GraphicsPixelFormat = extern enum(u32) {
52 PixelRedGreenBlueReserved8BitPerColor,
53 PixelBlueGreenRedReserved8BitPerColor,
54 PixelBitMask,
55 PixelBltOnly,
56 PixelFormatMax,
57};
58
59pub const PixelBitmask = extern struct {
60 red_mask: u32,
61 green_mask: u32,
62 blue_mask: u32,
63 reserved_mask: u32,
64};
65
66pub const GraphicsOutputBltPixel = extern struct {
67 blue: u8,
68 green: u8,
69 red: u8,
70 reserved: u8 = undefined,
71};
72
73pub const GraphicsOutputBltOperation = extern enum(u32) {
74 BltVideoFill,
75 BltVideoToBltBuffer,
76 BltBufferToVideo,
77 BltVideoToVideo,
78 GraphicsOutputBltOperationMax,
79};
std/os/uefi/protocols/rng_protocol.zig created+73
......@@ -0,0 +1,73 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 37.5
5pub const RNGProtocol = extern struct {
6 _get_info: extern fn (*const RNGProtocol, *usize, [*]align(8) Guid) usize,
7 _get_rng: extern fn (*const RNGProtocol, ?*align(8) const Guid, usize, [*]u8) usize,
8
9 pub fn getInfo(self: *const RNGProtocol, list_size: *usize, list: [*]align(8) Guid) usize {
10 return self._get_info(self, list_size, list);
11 }
12
13 pub fn getRNG(self: *const RNGProtocol, algo: ?*const Guid, value_length: usize, value: [*]u8) usize {
14 return self._get_rng(self, algo, value_length, value);
15 }
16
17 pub const guid align(8) = Guid{
18 .time_low = 0x3152bca5,
19 .time_mid = 0xeade,
20 .time_high_and_version = 0x433d,
21 .clock_seq_high_and_reserved = 0x86,
22 .clock_seq_low = 0x2e,
23 .node = [_]u8{ 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 },
24 };
25 pub const algorithm_sp800_90_hash_256 align(8) = Guid{
26 .time_low = 0xa7af67cb,
27 .time_mid = 0x603b,
28 .time_high_and_version = 0x4d42,
29 .clock_seq_high_and_reserved = 0xba,
30 .clock_seq_low = 0x21,
31 .node = [_]u8{ 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96 },
32 };
33 pub const algorithm_sp800_90_hmac_256 align(8) = Guid{
34 .time_low = 0xc5149b43,
35 .time_mid = 0xae85,
36 .time_high_and_version = 0x4f53,
37 .clock_seq_high_and_reserved = 0x99,
38 .clock_seq_low = 0x82,
39 .node = [_]u8{ 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7 },
40 };
41 pub const algorithm_sp800_90_ctr_256 align(8) = Guid{
42 .time_low = 0x44f0de6e,
43 .time_mid = 0x4d8c,
44 .time_high_and_version = 0x4045,
45 .clock_seq_high_and_reserved = 0xa8,
46 .clock_seq_low = 0xc7,
47 .node = [_]u8{ 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e },
48 };
49 pub const algorithm_x9_31_3des align(8) = Guid{
50 .time_low = 0x63c4785a,
51 .time_mid = 0xca34,
52 .time_high_and_version = 0x4012,
53 .clock_seq_high_and_reserved = 0xa3,
54 .clock_seq_low = 0xc8,
55 .node = [_]u8{ 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 },
56 };
57 pub const algorithm_x9_31_aes align(8) = Guid{
58 .time_low = 0xacd03321,
59 .time_mid = 0x777e,
60 .time_high_and_version = 0x4d3d,
61 .clock_seq_high_and_reserved = 0xb1,
62 .clock_seq_low = 0xc8,
63 .node = [_]u8{ 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 },
64 };
65 pub const algorithm_raw align(8) = Guid{
66 .time_low = 0xe43176d7,
67 .time_mid = 0xb6e8,
68 .time_high_and_version = 0x4827,
69 .clock_seq_high_and_reserved = 0xb7,
70 .clock_seq_low = 0x84,
71 .node = [_]u8{ 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 },
72 };
73};
std/os/uefi/protocols/simple_pointer_protocol.zig created+44
......@@ -0,0 +1,44 @@
1const uefi = @import("std").os.uefi;
2const Event = uefi.Event;
3const Guid = uefi.Guid;
4
5/// UEFI Specification, Version 2.8, 12.5
6pub const SimplePointerProtocol = struct {
7 _reset: extern fn (*const SimplePointerProtocol, bool) usize,
8 _get_state: extern fn (*const SimplePointerProtocol, *SimplePointerState) usize,
9 wait_for_input: Event,
10 mode: *SimplePointerMode,
11
12 pub fn reset(self: *const SimplePointerProtocol, verify: bool) usize {
13 return self._reset(self, verify);
14 }
15
16 pub fn getState(self: *const SimplePointerProtocol, state: *SimplePointerState) usize {
17 return self._get_state(self, state);
18 }
19
20 pub const guid align(8) = Guid{
21 .time_low = 0x31878c87,
22 .time_mid = 0x0b75,
23 .time_high_and_version = 0x11d5,
24 .clock_seq_high_and_reserved = 0x9a,
25 .clock_seq_low = 0x4f,
26 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
27 };
28};
29
30pub const SimplePointerMode = struct {
31 resolution_x: u64,
32 resolution_y: u64,
33 resolution_z: u64,
34 left_button: bool,
35 right_button: bool,
36};
37
38pub const SimplePointerState = struct {
39 relative_movement_x: i32 = undefined,
40 relative_movement_y: i32 = undefined,
41 relative_movement_z: i32 = undefined,
42 left_button: bool = undefined,
43 right_button: bool = undefined,
44};
std/os/uefi/protocols/simple_text_input_ex_protocol.zig created+77
......@@ -0,0 +1,77 @@
1const uefi = @import("std").os.uefi;
2const Event = uefi.Event;
3const Guid = uefi.Guid;
4
5/// UEFI Specification, Version 2.8, 12.3
6pub const SimpleTextInputExProtocol = extern struct {
7 _reset: extern fn (*const SimpleTextInputExProtocol, bool) usize,
8 _read_key_stroke_ex: extern fn (*const SimpleTextInputExProtocol, *KeyData) usize,
9 wait_for_key_ex: Event,
10 _set_state: extern fn (*const SimpleTextInputExProtocol, *const u8) usize,
11 _register_key_notify: extern fn (*const SimpleTextInputExProtocol, *const KeyData, extern fn (*const KeyData) usize, **c_void) usize,
12 _unregister_key_notify: extern fn (*const SimpleTextInputExProtocol, *const c_void) usize,
13
14 pub fn reset(self: *const SimpleTextInputExProtocol, verify: bool) usize {
15 return self._reset(self, verify);
16 }
17
18 pub fn readKeyStrokeEx(self: *const SimpleTextInputExProtocol, key_data: *KeyData) usize {
19 return self._read_key_stroke_ex(self, key_data);
20 }
21
22 pub fn setState(self: *const SimpleTextInputExProtocol, state: *const u8) usize {
23 return self._set_state(self, state);
24 }
25
26 pub fn registerKeyNotify(self: *const SimpleTextInputExProtocol, key_data: *const KeyData, notify: extern fn (*const KeyData) usize, handle: **c_void) usize {
27 return self._register_key_notify(self, key_data, notify, handle);
28 }
29
30 pub fn unregisterKeyNotify(self: *const SimpleTextInputExProtocol, handle: *const c_void) usize {
31 return self._unregister_key_notify(self, handle);
32 }
33
34 pub const guid align(8) = Guid{
35 .time_low = 0xdd9e7534,
36 .time_mid = 0x7762,
37 .time_high_and_version = 0x4698,
38 .clock_seq_high_and_reserved = 0x8c,
39 .clock_seq_low = 0x14,
40 .node = [_]u8{ 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa },
41 };
42};
43
44pub const KeyData = extern struct {
45 key: InputKey = undefined,
46 key_state: KeyState = undefined,
47};
48
49pub const KeyState = extern struct {
50 key_shift_state: packed struct {
51 right_shift_pressed: bool,
52 left_shift_pressed: bool,
53 right_control_pressed: bool,
54 left_control_pressed: bool,
55 right_alt_pressed: bool,
56 left_alt_pressed: bool,
57 right_logo_pressed: bool,
58 left_logo_pressed: bool,
59 menu_key_pressed: bool,
60 sys_req_pressed: bool,
61 _pad1: u21,
62 shift_state_valid: bool,
63 },
64 key_toggle_state: packed struct {
65 scroll_lock_active: bool,
66 num_lock_active: bool,
67 caps_lock_active: bool,
68 _pad1: u3,
69 key_state_exposed: bool,
70 toggle_state_valid: bool,
71 },
72};
73
74pub const InputKey = extern struct {
75 scan_code: u16,
76 unicode_char: u16,
77};
std/os/uefi/protocols/simple_text_output_protocol.zig created+143
......@@ -0,0 +1,143 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 12.4
5pub const SimpleTextOutputProtocol = extern struct {
6 _reset: extern fn (*const SimpleTextOutputProtocol, bool) usize,
7 _output_string: extern fn (*const SimpleTextOutputProtocol, [*]const u16) usize,
8 _test_string: extern fn (*const SimpleTextOutputProtocol, [*]const u16) usize,
9 _query_mode: extern fn (*const SimpleTextOutputProtocol, usize, *usize, *usize) usize,
10 _set_mode: extern fn (*const SimpleTextOutputProtocol, usize) usize,
11 _set_attribute: extern fn (*const SimpleTextOutputProtocol, usize) usize,
12 _clear_screen: extern fn (*const SimpleTextOutputProtocol) usize,
13 _set_cursor_position: extern fn (*const SimpleTextOutputProtocol, usize, usize) usize,
14 _enable_cursor: extern fn (*const SimpleTextOutputProtocol, bool) usize,
15 mode: *SimpleTextOutputMode,
16
17 pub fn reset(self: *const SimpleTextOutputProtocol, verify: bool) usize {
18 return self._reset(self, verify);
19 }
20
21 pub fn outputString(self: *const SimpleTextOutputProtocol, msg: [*]const u16) usize {
22 return self._output_string(self, msg);
23 }
24
25 pub fn testString(self: *const SimpleTextOutputProtocol, msg: [*]const u16) usize {
26 return self._test_string(self, msg);
27 }
28
29 pub fn queryMode(self: *const SimpleTextOutputProtocol, mode_number: usize, columns: *usize, rows: *usize) usize {
30 return self._query_mode(self, mode_number, columns, rows);
31 }
32
33 pub fn setMode(self: *const SimpleTextOutputProtocol, mode_number: usize) usize {
34 return self._set_mode(self, mode_number);
35 }
36
37 pub fn setAttribute(self: *const SimpleTextOutputProtocol, attribute: usize) usize {
38 return self._set_attribute(self, attribute);
39 }
40
41 pub fn clearScreen(self: *const SimpleTextOutputProtocol) usize {
42 return self._clear_screen(self);
43 }
44
45 pub fn setCursorPosition(self: *const SimpleTextOutputProtocol, column: usize, row: usize) usize {
46 return self._set_cursor_position(self, column, row);
47 }
48
49 pub fn enableCursor(self: *const SimpleTextOutputProtocol, visible: bool) usize {
50 return self._enable_cursor(self, visible);
51 }
52
53 pub const guid align(8) = Guid{
54 .time_low = 0x387477c2,
55 .time_mid = 0x69c7,
56 .time_high_and_version = 0x11d2,
57 .clock_seq_high_and_reserved = 0x8e,
58 .clock_seq_low = 0x39,
59 .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
60 };
61 pub const boxdraw_horizontal: u16 = 0x2500;
62 pub const boxdraw_vertical: u16 = 0x2502;
63 pub const boxdraw_down_right: u16 = 0x250c;
64 pub const boxdraw_down_left: u16 = 0x2510;
65 pub const boxdraw_up_right: u16 = 0x2514;
66 pub const boxdraw_up_left: u16 = 0x2518;
67 pub const boxdraw_vertical_right: u16 = 0x251c;
68 pub const boxdraw_vertical_left: u16 = 0x2524;
69 pub const boxdraw_down_horizontal: u16 = 0x252c;
70 pub const boxdraw_up_horizontal: u16 = 0x2534;
71 pub const boxdraw_vertical_horizontal: u16 = 0x253c;
72 pub const boxdraw_double_horizontal: u16 = 0x2550;
73 pub const boxdraw_double_vertical: u16 = 0x2551;
74 pub const boxdraw_down_right_double: u16 = 0x2552;
75 pub const boxdraw_down_double_right: u16 = 0x2553;
76 pub const boxdraw_double_down_right: u16 = 0x2554;
77 pub const boxdraw_down_left_double: u16 = 0x2555;
78 pub const boxdraw_down_double_left: u16 = 0x2556;
79 pub const boxdraw_double_down_left: u16 = 0x2557;
80 pub const boxdraw_up_right_double: u16 = 0x2558;
81 pub const boxdraw_up_double_right: u16 = 0x2559;
82 pub const boxdraw_double_up_right: u16 = 0x255a;
83 pub const boxdraw_up_left_double: u16 = 0x255b;
84 pub const boxdraw_up_double_left: u16 = 0x255c;
85 pub const boxdraw_double_up_left: u16 = 0x255d;
86 pub const boxdraw_vertical_right_double: u16 = 0x255e;
87 pub const boxdraw_vertical_double_right: u16 = 0x255f;
88 pub const boxdraw_double_vertical_right: u16 = 0x2560;
89 pub const boxdraw_vertical_left_double: u16 = 0x2561;
90 pub const boxdraw_vertical_double_left: u16 = 0x2562;
91 pub const boxdraw_double_vertical_left: u16 = 0x2563;
92 pub const boxdraw_down_horizontal_double: u16 = 0x2564;
93 pub const boxdraw_down_double_horizontal: u16 = 0x2565;
94 pub const boxdraw_double_down_horizontal: u16 = 0x2566;
95 pub const boxdraw_up_horizontal_double: u16 = 0x2567;
96 pub const boxdraw_up_double_horizontal: u16 = 0x2568;
97 pub const boxdraw_double_up_horizontal: u16 = 0x2569;
98 pub const boxdraw_vertical_horizontal_double: u16 = 0x256a;
99 pub const boxdraw_vertical_double_horizontal: u16 = 0x256b;
100 pub const boxdraw_double_vertical_horizontal: u16 = 0x256c;
101 pub const blockelement_full_block: u16 = 0x2588;
102 pub const blockelement_light_shade: u16 = 0x2591;
103 pub const geometricshape_up_triangle: u16 = 0x25b2;
104 pub const geometricshape_right_triangle: u16 = 0x25ba;
105 pub const geometricshape_down_triangle: u16 = 0x25bc;
106 pub const geometricshape_left_triangle: u16 = 0x25c4;
107 pub const arrow_up: u16 = 0x2591;
108 pub const arrow_down: u16 = 0x2593;
109 pub const black: u8 = 0x00;
110 pub const blue: u8 = 0x01;
111 pub const green: u8 = 0x02;
112 pub const cyan: u8 = 0x03;
113 pub const red: u8 = 0x04;
114 pub const magenta: u8 = 0x05;
115 pub const brown: u8 = 0x06;
116 pub const lightgray: u8 = 0x07;
117 pub const bright: u8 = 0x08;
118 pub const darkgray: u8 = 0x08;
119 pub const lightblue: u8 = 0x09;
120 pub const lightgreen: u8 = 0x0a;
121 pub const lightcyan: u8 = 0x0b;
122 pub const lightred: u8 = 0x0c;
123 pub const lightmagenta: u8 = 0x0d;
124 pub const yellow: u8 = 0x0e;
125 pub const white: u8 = 0x0f;
126 pub const background_black: u8 = 0x00;
127 pub const background_blue: u8 = 0x10;
128 pub const background_green: u8 = 0x20;
129 pub const background_cyan: u8 = 0x30;
130 pub const background_red: u8 = 0x40;
131 pub const background_magenta: u8 = 0x50;
132 pub const background_brown: u8 = 0x60;
133 pub const background_lightgray: u8 = 0x70;
134};
135
136pub const SimpleTextOutputMode = extern struct {
137 max_mode: u32, // specified as signed
138 mode: u32, // specified as signed
139 attribute: i32,
140 cursor_column: i32,
141 cursor_row: i32,
142 cursor_visible: bool,
143};
std/os/uefi/status.zig created+46
......@@ -0,0 +1,46 @@
1const high_bit = 1 << @typeInfo(usize).Int.bits - 1;
2
3/// UEFI Specification, Version 2.8, Appendix D
4pub const success: usize = 0;
5
6pub const load_error: usize = high_bit | 1;
7pub const invalid_parameter: usize = high_bit | 2;
8pub const unsupported: usize = high_bit | 3;
9pub const bad_buffer_size: usize = high_bit | 4;
10pub const buffer_too_small: usize = high_bit | 5;
11pub const not_ready: usize = high_bit | 6;
12pub const device_error: usize = high_bit | 7;
13pub const write_protected: usize = high_bit | 8;
14pub const out_of_resources: usize = high_bit | 9;
15pub const volume_corrupted: usize = high_bit | 10;
16pub const volume_full: usize = high_bit | 11;
17pub const no_media: usize = high_bit | 12;
18pub const media_changed: usize = high_bit | 13;
19pub const not_found: usize = high_bit | 14;
20pub const access_denied: usize = high_bit | 15;
21pub const no_response: usize = high_bit | 16;
22pub const no_mapping: usize = high_bit | 17;
23pub const timeout: usize = high_bit | 18;
24pub const not_started: usize = high_bit | 19;
25pub const already_started: usize = high_bit | 20;
26pub const aborted: usize = high_bit | 21;
27pub const icmp_error: usize = high_bit | 22;
28pub const tftp_error: usize = high_bit | 23;
29pub const protocol_error: usize = high_bit | 24;
30pub const incompatible_version: usize = high_bit | 25;
31pub const security_violation: usize = high_bit | 26;
32pub const crc_error: usize = high_bit | 27;
33pub const end_of_media: usize = high_bit | 28;
34pub const end_of_file: usize = high_bit | 31;
35pub const invalid_language: usize = high_bit | 32;
36pub const compromised_data: usize = high_bit | 33;
37pub const ip_address_conflict: usize = high_bit | 34;
38pub const http_error: usize = high_bit | 35;
39
40pub const warn_unknown_glyph: usize = 1;
41pub const warn_delete_failure: usize = 2;
42pub const warn_write_failure: usize = 3;
43pub const warn_buffer_too_small: usize = 4;
44pub const warn_stale_data: usize = 5;
45pub const warn_file_system: usize = 6;
46pub const warn_reset_required: usize = 7;
std/os/uefi/tables.zig created+9
......@@ -0,0 +1,9 @@
1pub const BootServices = @import("tables/boot_services.zig").BootServices;
2pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
3pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable;
4pub const MemoryDescriptor = @import("tables/boot_services.zig").MemoryDescriptor;
5pub const ResetType = @import("tables/runtime_services.zig").ResetType;
6pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
7pub const SystemTable = @import("tables/system_table.zig").SystemTable;
8pub const TableHeader = @import("tables/table_header.zig").TableHeader;
9pub const TimerDelay = @import("tables/boot_services.zig").TimerDelay;
std/os/uefi/tables/boot_services.zig created+125
......@@ -0,0 +1,125 @@
1const uefi = @import("std").os.uefi;
2const Event = uefi.Event;
3const Guid = uefi.Guid;
4const Handle = uefi.Handle;
5const TableHeader = uefi.tables.TableHeader;
6
7/// UEFI Specification, Version 2.8, 4.4
8///
9/// As the boot_services table may grow with new UEFI versions, it is important to check hdr.header_size.
10///
11/// Boot Services must not be used after exitBootServices has been called. The only exception is
12/// getMemoryMap, which may be used after the first unsuccessful call to exitBootServices.
13/// After successfully calling exitBootServices, system_table.console_in_handle, system_table.con_in,
14/// system_table.console_out_handle, system_table.con_out, system_table.standard_error_handle,
15/// system_table.std_err, and system_table.boot_services should be set to null. After setting these
16/// attributes to null, system_table.hdr.crc32 must be recomputed. See UEFI Specification, Version 2.8, 7.4.
17pub const BootServices = extern struct {
18 hdr: TableHeader,
19 raiseTpl: usize, // TODO
20 restoreTpl: usize, // TODO
21 allocatePages: usize, // TODO
22 freePages: usize, // TODO
23 getMemoryMap: extern fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) usize,
24 allocatePool: usize, // TODO
25 freePool: usize, // TODO
26 createEvent: extern fn (u32, usize, ?extern fn (Event, ?*const c_void) void, ?*const c_void, *Event) usize,
27 setTimer: extern fn (Event, TimerDelay, u64) usize,
28 waitForEvent: extern fn (usize, [*]const Event, *usize) usize,
29 signalEvent: extern fn (Event) usize,
30 closeEvent: extern fn (Event) usize,
31 checkEvent: usize, // TODO
32 installProtocolInterface: usize, // TODO
33 reinstallProtocolInterface: usize, // TODO
34 uninstallProtocolInterface: usize, // TODO
35 handleProtocol: usize, // TODO
36 reserved: *c_void,
37 registerProtocolNotify: usize, // TODO
38 locateHandle: usize, // TODO
39 locateDevicePath: usize, // TODO
40 installConfigurationTable: usize, // TODO
41 imageLoad: usize, // TODO
42 imageStart: usize, // TODO
43 exit: extern fn (Handle, usize, usize, ?*const c_void) usize,
44 imageUnload: usize, // TODO
45 exitBootServices: usize, // TODO
46 getNextMonotonicCount: usize, // TODO
47 stall: extern fn (usize) usize,
48 setWatchdogTimer: extern fn (usize, u64, usize, ?[*]const u16) usize,
49 connectController: usize, // TODO
50 disconnectController: usize, // TODO
51 openProtocol: usize, // TODO
52 closeProtocol: usize, // TODO
53 openProtocolInformation: usize, // TODO
54 protocolsPerHandle: usize, // TODO
55 locateHandleBuffer: usize, // TODO
56 locateProtocol: extern fn (*align(8) const Guid, ?*const c_void, *?*c_void) usize,
57 installMultipleProtocolInterfaces: usize, // TODO
58 uninstallMultipleProtocolInterfaces: usize, // TODO
59 calculateCrc32: usize, // TODO
60 copyMem: usize, // TODO
61 setMem: usize, // TODO
62 createEventEx: usize, // TODO
63
64 pub const signature: u64 = 0x56524553544f4f42;
65
66 pub const event_timer: u32 = 0x80000000;
67 pub const event_runtime: u32 = 0x40000000;
68 pub const event_notify_wait: u32 = 0x00000100;
69 pub const event_notify_signal: u32 = 0x00000200;
70 pub const event_signal_exit_boot_services: u32 = 0x00000201;
71 pub const event_signal_virtual_address_change: u32 = 0x00000202;
72
73 pub const tpl_application: usize = 4;
74 pub const tpl_callback: usize = 8;
75 pub const tpl_notify: usize = 16;
76 pub const tpl_high_level: usize = 31;
77};
78
79pub const TimerDelay = extern enum(u32) {
80 TimerCancel,
81 TimerPeriodic,
82 TimerRelative,
83};
84
85pub const MemoryDescriptor = extern struct {
86 type: extern enum(u32) {
87 ReservedMemoryType,
88 LoaderCode,
89 LoaderData,
90 BootServicesCode,
91 BootServicesData,
92 RuntimeServicesCode,
93 RuntimeServicesData,
94 ConventionalMemory,
95 UnusableMemory,
96 ACPIReclaimMemory,
97 ACPIMemoryNVS,
98 MemoryMappedIO,
99 MemoryMappedIOPortSpace,
100 PalCode,
101 PersistentMemory,
102 MaxMemoryType,
103 },
104 physical_start: u64,
105 virtual_start: u64,
106 number_of_pages: usize,
107 attribute: packed struct {
108 uc: bool,
109 wc: bool,
110 wt: bool,
111 wb: bool,
112 uce: bool,
113 _pad1: u7,
114 wp: bool,
115 rp: bool,
116 xp: bool,
117 nv: bool,
118 more_reliable: bool,
119 ro: bool,
120 sp: bool,
121 cpu_crypto: bool,
122 _pad2: u43,
123 memory_runtime: bool,
124 },
125};
std/os/uefi/tables/configuration_table.zig created+82
......@@ -0,0 +1,82 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3
4/// UEFI Specification, Version 2.8, 4.6
5/// Because GUIDs must be align(8), structs of this type also must be align(8)
6pub const ConfigurationTable = extern struct {
7 vendor_guid: Guid,
8 vendor_table: *c_void,
9
10 pub const acpi_20_table_guid align(8) = Guid{
11 .time_low = 0x8868e871,
12 .time_mid = 0xe4f1,
13 .time_high_and_version = 0x11d3,
14 .clock_seq_high_and_reserved = 0xbc,
15 .clock_seq_low = 0x22,
16 .node = [_]u8{ 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 },
17 };
18 pub const acpi_10_table_guid align(8) = Guid{
19 .time_low = 0xeb9d2d30,
20 .time_mid = 0x2d88,
21 .time_high_and_version = 0x11d3,
22 .clock_seq_high_and_reserved = 0x9a,
23 .clock_seq_low = 0x16,
24 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
25 };
26 pub const sal_system_table_guid align(8) = Guid{
27 .time_low = 0xeb9d2d32,
28 .time_mid = 0x2d88,
29 .time_high_and_version = 0x113d,
30 .clock_seq_high_and_reserved = 0x9a,
31 .clock_seq_low = 0x16,
32 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
33 };
34 pub const smbios_table_guid align(8) = Guid{
35 .time_low = 0xeb9d2d31,
36 .time_mid = 0x2d88,
37 .time_high_and_version = 0x11d3,
38 .clock_seq_high_and_reserved = 0x9a,
39 .clock_seq_low = 0x16,
40 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
41 };
42 pub const smbios3_table_guid align(8) = Guid{
43 .time_low = 0xf2fd1544,
44 .time_mid = 0x9794,
45 .time_high_and_version = 0x4a2c,
46 .clock_seq_high_and_reserved = 0x99,
47 .clock_seq_low = 0x2e,
48 .node = [_]u8{ 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 },
49 };
50 pub const mps_table_guid align(8) = Guid{
51 .time_low = 0xeb9d2d2f,
52 .time_mid = 0x2d88,
53 .time_high_and_version = 0x11d3,
54 .clock_seq_high_and_reserved = 0x9a,
55 .clock_seq_low = 0x16,
56 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
57 };
58 pub const json_config_data_table_guid align(8) = Guid{
59 .time_low = 0x87367f87,
60 .time_mid = 0x1119,
61 .time_high_and_version = 0x41ce,
62 .clock_seq_high_and_reserved = 0xaa,
63 .clock_seq_low = 0xec,
64 .node = [_]u8{ 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a },
65 };
66 pub const json_capsule_data_table_guid align(8) = Guid{
67 .time_low = 0x35e7a725,
68 .time_mid = 0x8dd2,
69 .time_high_and_version = 0x4cac,
70 .clock_seq_high_and_reserved = 0x80,
71 .clock_seq_low = 0x11,
72 .node = [_]u8{ 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 },
73 };
74 pub const json_capsule_result_table_guid align(8) = Guid{
75 .time_low = 0xdbc461c3,
76 .time_mid = 0xb3de,
77 .time_high_and_version = 0x422a,
78 .clock_seq_high_and_reserved = 0xb9,
79 .clock_seq_low = 0xb4,
80 .node = [_]u8{ 0x98, 0x86, 0xfd, 0x49, 0xa1, 0xe5 },
81 };
82};
std/os/uefi/tables/runtime_services.zig created+51
......@@ -0,0 +1,51 @@
1const uefi = @import("std").os.uefi;
2const Guid = uefi.Guid;
3const TableHeader = uefi.tables.TableHeader;
4const Time = uefi.Time;
5const TimeCapabilities = uefi.TimeCapabilities;
6
7/// UEFI Specification, Version 2.8, 4.5
8///
9/// As the runtime_services table may grow with new UEFI versions, it is important to check hdr.header_size.
10///
11/// Some functions may not be supported. Check the RuntimeServicesSupported variable using getVariable.
12/// getVariable is one of the functions that may not be supported. See UEFI Specification, Version 2.8, 8.1.
13///
14/// Some functions may not be called while other functions are running. See UEFI Specification, Version 2.8, 8.1.
15pub const RuntimeServices = extern struct {
16 hdr: TableHeader,
17 getTime: extern fn (*uefi.Time, ?*TimeCapabilities) usize,
18 setTime: usize, // TODO
19 getWakeupTime: usize, // TODO
20 setWakeupTime: usize, // TODO
21 setVirtualAddressMap: usize, // TODO
22 convertPointer: usize, // TODO
23 getVariable: extern fn ([*]const u16, *align(8) const Guid, ?*u32, *usize, ?*c_void) usize,
24 getNextVariableName: extern fn (*usize, [*]u16, *align(8) Guid) usize,
25 setVariable: extern fn ([*]const u16, *align(8) const Guid, u32, usize, *c_void) usize,
26 getNextHighMonotonicCount: usize, // TODO
27 resetSystem: extern fn (ResetType, usize, usize, ?*const c_void) noreturn,
28 updateCapsule: usize, // TODO
29 queryCapsuleCapabilities: usize, // TODO
30 queryVariableInfo: usize, // TODO
31
32 pub const signature: u64 = 0x56524553544e5552;
33};
34
35/// UEFI Specification, Version 2.8, 8.5.1
36pub const ResetType = extern enum(u32) {
37 ResetCold,
38 ResetWarm,
39 ResetShutdown,
40 ResetPlatformSpecific,
41};
42
43/// UEFI Specification, Version 2.8, 3.3
44pub const global_variable align(8) = Guid{
45 .time_low = 0x8be4df61,
46 .time_mid = 0x93ca,
47 .time_high_and_version = 0x11d2,
48 .clock_seq_high_and_reserved = 0xaa,
49 .clock_seq_low = 0x0d,
50 .node = [_]u8{ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c },
51};
std/os/uefi/tables/system_table.zig created+46
......@@ -0,0 +1,46 @@
1const uefi = @import("std").os.uefi;
2const BootServices = uefi.tables.BootServices;
3const ConfigurationTable = uefi.tables.ConfigurationTable;
4const Handle = uefi.Handle;
5const RuntimeServices = uefi.tables.RuntimeServices;
6const SimpleTextInputExProtocol = uefi.protocols.SimpleTextInputExProtocol;
7const SimpleTextOutputProtocol = uefi.protocols.SimpleTextOutputProtocol;
8const TableHeader = uefi.tables.TableHeader;
9
10/// UEFI Specification, Version 2.8, 4.3
11///
12/// As the system_table may grow with new UEFI versions, it is important to check hdr.header_size.
13///
14/// After successfully calling boot_services.exitBootServices, console_in_handle,
15/// con_in, console_out_handle, con_out, standard_error_handle, std_err, and
16/// boot_services should be set to null. After setting these attributes to null,
17/// hdr.crc32 must be recomputed. See UEFI Specification, Version 2.8, 7.4.
18pub const SystemTable = extern struct {
19 hdr: TableHeader,
20 firmware_vendor: *u16,
21 firmware_revision: u32,
22 console_in_handle: ?Handle,
23 con_in: ?*SimpleTextInputExProtocol,
24 console_out_handle: ?Handle,
25 con_out: ?*SimpleTextOutputProtocol,
26 standard_error_handle: ?Handle,
27 std_err: ?*SimpleTextOutputProtocol,
28 runtime_services: *RuntimeServices,
29 boot_services: ?*BootServices,
30 number_of_table_entries: usize,
31 configuration_table: *ConfigurationTable,
32
33 pub const signature: u64 = 0x5453595320494249;
34 pub const revision_1_02: u32 = (1 << 16) | 2;
35 pub const revision_1_10: u32 = (1 << 16) | 10;
36 pub const revision_2_00: u32 = (2 << 16);
37 pub const revision_2_10: u32 = (2 << 16) | 10;
38 pub const revision_2_20: u32 = (2 << 16) | 20;
39 pub const revision_2_30: u32 = (2 << 16) | 30;
40 pub const revision_2_31: u32 = (2 << 16) | 31;
41 pub const revision_2_40: u32 = (2 << 16) | 40;
42 pub const revision_2_50: u32 = (2 << 16) | 50;
43 pub const revision_2_60: u32 = (2 << 16) | 60;
44 pub const revision_2_70: u32 = (2 << 16) | 70;
45 pub const revision_2_80: u32 = (2 << 16) | 80;
46};
std/os/uefi/tables/table_header.zig created+8
......@@ -0,0 +1,8 @@
1/// UEFI Specification, Version 2.8, 4.2
2pub const TableHeader = extern struct {
3 signature: u64,
4 revision: u32,
5 header_size: u32,
6 crc32: u32,
7 reserved: u32,
8};
std/special/start.zig+57-12
......@@ -4,8 +4,9 @@ const root = @import("root");
44const std = @import("std");
55const builtin = @import("builtin");
66const assert = std.debug.assert;
7const uefi = std.os.uefi;
78
8var argc_ptr: [*]usize = undefined;
9var starting_stack_ptr: [*]usize = undefined;
910
1011const is_wasm = switch (builtin.arch) {
1112 .wasm32, .wasm64 => true,
......@@ -19,6 +20,8 @@ comptime {
1920 @export("WinMainCRTStartup", WinMainCRTStartup, .Strong);
2021 } else if (is_wasm and builtin.os == .freestanding) {
2122 @export("_start", wasm_freestanding_start, .Strong);
23 } else if (builtin.os == .uefi) {
24 @export("EfiMain", EfiMain, .Strong);
2225 } else {
2326 @export("_start", _start, .Strong);
2427 }
......@@ -28,6 +31,29 @@ extern fn wasm_freestanding_start() void {
2831 _ = callMain();
2932}
3033
34extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
35 const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'";
36 uefi.handle = handle;
37 uefi.system_table = system_table;
38
39 switch (@typeInfo(@typeOf(root.main).ReturnType)) {
40 .NoReturn => {
41 root.main();
42 },
43 .Void => {
44 root.main();
45 return 0;
46 },
47 .Int => |info| {
48 if (info.bits != @typeInfo(usize).Int.bits) {
49 @compileError(bad_efi_main_ret);
50 }
51 return root.main();
52 },
53 else => @compileError(bad_efi_main_ret),
54 }
55}
56
3157nakedcc fn _start() noreturn {
3258 if (builtin.os == builtin.Os.wasi) {
3359 std.os.wasi.proc_exit(callMain());
......@@ -35,17 +61,17 @@ nakedcc fn _start() noreturn {
3561
3662 switch (builtin.arch) {
3763 .x86_64 => {
38 argc_ptr = asm (""
64 starting_stack_ptr = asm (""
3965 : [argc] "={rsp}" (-> [*]usize)
4066 );
4167 },
4268 .i386 => {
43 argc_ptr = asm (""
69 starting_stack_ptr = asm (""
4470 : [argc] "={esp}" (-> [*]usize)
4571 );
4672 },
4773 .aarch64, .aarch64_be, .arm => {
48 argc_ptr = asm ("mov %[argc], sp"
74 starting_stack_ptr = asm ("mov %[argc], sp"
4975 : [argc] "=r" (-> [*]usize)
5076 );
5177 },
......@@ -77,8 +103,8 @@ fn posixCallMainAndExit() noreturn {
77103 if (builtin.os == builtin.Os.freebsd) {
78104 @setAlignStack(16);
79105 }
80 const argc = argc_ptr[0];
81 const argv = @ptrCast([*][*]u8, argc_ptr + 1);
106 const argc = starting_stack_ptr[0];
107 const argv = @ptrCast([*][*]u8, starting_stack_ptr + 1);
82108
83109 const envp_optional = @ptrCast([*]?[*]u8, argv + argc + 1);
84110 var envp_count: usize = 0;
......@@ -90,21 +116,40 @@ fn posixCallMainAndExit() noreturn {
90116 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
91117 std.os.linux.elf_aux_maybe = auxv;
92118 // Initialize the TLS area
93 std.os.linux.tls.initTLS();
119 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
94120
95121 if (std.os.linux.tls.tls_image) |tls_img| {
96122 const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
97123 const tp = std.os.linux.tls.copyTLS(tls_addr);
98124 std.os.linux.tls.setThreadPointer(tp);
99125 }
126
127 // TODO This is disabled because what should we do when linking libc and this code
128 // does not execute? And also it's causing a test failure in stack traces in release modes.
129
130 //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further
131 //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down
132 //// the stack and requires "probing". So here we allocate our own stack.
133 //const wanted_stack_size = gnu_stack_phdr.p_memsz;
134 //assert(wanted_stack_size % std.mem.page_size == 0);
135 //// Allocate an extra page as the guard page.
136 //const total_size = wanted_stack_size + std.mem.page_size;
137 //const new_stack = std.os.mmap(
138 // null,
139 // total_size,
140 // std.os.PROT_READ | std.os.PROT_WRITE,
141 // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS,
142 // -1,
143 // 0,
144 //) catch @panic("out of memory");
145 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
146 //std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));
100147 }
101148
102 std.os.exit(callMainWithArgs(argc, argv, envp));
149 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));
103150}
104151
105// This is marked inline because for some reason LLVM in release mode fails to inline it,
106// and we want fewer call frames in stack traces.
107inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
152fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
108153 std.os.argv = argv[0..argc];
109154 std.os.environ = envp;
110155
......@@ -117,7 +162,7 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
117162 var env_count: usize = 0;
118163 while (c_envp[env_count] != null) : (env_count += 1) {}
119164 const envp = @ptrCast([*][*]u8, c_envp)[0..env_count];
120 return callMainWithArgs(@intCast(usize, c_argc), c_argv, envp);
165 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);
121166}
122167
123168// General error message for a malformed return type
std/thread.zig+1-1
......@@ -145,7 +145,7 @@ pub const Thread = struct {
145145 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
146146 // TODO compile-time call graph analysis to determine stack upper bound
147147 // https://github.com/ziglang/zig/issues/157
148 const default_stack_size = 8 * 1024 * 1024;
148 const default_stack_size = 16 * 1024 * 1024;
149149
150150 const Context = @typeOf(context);
151151 comptime assert(@ArgType(@typeOf(startFn), 0) == Context);
std/zig/tokenizer.zig+10-1
......@@ -222,9 +222,11 @@ pub const Tokenizer = struct {
222222 },
223223 };
224224 } else {
225 // Skip the UTF-8 BOM if present
226 const src_start = if (mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else usize(0);
225227 return Tokenizer{
226228 .buffer = buffer,
227 .index = 0,
229 .index = src_start,
228230 .pending_invalid_token = null,
229231 };
230232 }
......@@ -1455,6 +1457,13 @@ test "tokenizer - line comment followed by identifier" {
14551457 });
14561458}
14571459
1460test "tokenizer - UTF-8 BOM is recognized and skipped" {
1461 testTokenize("\xEF\xBB\xBFa;\n", [_]Token.Id{
1462 Token.Id.Identifier,
1463 Token.Id.Semicolon,
1464 });
1465}
1466
14581467fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
14591468 var tokenizer = Tokenizer.init(source);
14601469 for (expected_tokens) |expected_token_id| {
test/stage1/behavior/enum.zig+23
......@@ -1007,3 +1007,26 @@ test "enum literal casting to error union with payload enum" {
10071007
10081008 expect((try bar) == Bar.B);
10091009}
1010
1011test "enum with one member and u1 tag type @enumToInt" {
1012 const Enum = enum(u1) {
1013 Test,
1014 };
1015 expect(@enumToInt(Enum.Test) == 0);
1016}
1017
1018test "enum with comptime_int tag type" {
1019 const Enum = enum(comptime_int) {
1020 One = 3,
1021 Two = 2,
1022 Three = 1,
1023 };
1024 comptime expect(@TagType(Enum) == comptime_int);
1025}
1026
1027test "enum with one member default to u0 tag type" {
1028 const E0 = enum {
1029 X,
1030 };
1031 comptime expect(@TagType(E0) == u0);
1032}
test/stage1/behavior/union.zig+19-3
......@@ -324,7 +324,7 @@ test "union with only 1 field casted to its enum type" {
324324
325325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326326 const Tag = @TagType(Expr);
327 comptime expect(@TagType(Tag) == comptime_int);
327 comptime expect(@TagType(Tag) == u0);
328328 var t = Tag(e);
329329 expect(t == Expr.Literal);
330330}
......@@ -335,7 +335,7 @@ test "union with only 1 field casted to its enum type which has enum value speci
335335 Bool: bool,
336336 };
337337
338 const Tag = enum {
338 const Tag = enum(comptime_int) {
339339 Literal = 33,
340340 };
341341
......@@ -469,7 +469,7 @@ test "union no tag with struct member" {
469469}
470470
471471fn testComparison() void {
472 var x = Payload{.A = 42};
472 var x = Payload{ .A = 42 };
473473 expect(x == .A);
474474 expect(x != .B);
475475 expect(x != .C);
......@@ -494,3 +494,19 @@ test "packed union generates correctly aligned LLVM type" {
494494 };
495495 foo[0].f1();
496496}
497
498test "union with one member defaults to u0 tag type" {
499 const U0 = union(enum) {
500 X: u32,
501 };
502 comptime expect(@TagType(@TagType(U0)) == u0);
503}
504
505test "union with comptime_int tag" {
506 const Union = union(enum(comptime_int)) {
507 X: u32,
508 Y: u16,
509 Z: u8,
510 };
511 comptime expect(@TagType(@TagType(Union)) == comptime_int);
512}