master
  1const std = @import("std");
  2const uefi = std.os.uefi;
  3const Handle = uefi.Handle;
  4const Event = uefi.Event;
  5const Guid = uefi.Guid;
  6const cc = uefi.cc;
  7const math = std.math;
  8const assert = std.debug.assert;
  9
 10pub const BootServices = @import("tables/boot_services.zig").BootServices;
 11pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
 12pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
 13pub const SystemTable = @import("tables/system_table.zig").SystemTable;
 14pub const TableHeader = @import("tables/table_header.zig").TableHeader;
 15
 16pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void;
 17
 18pub const TimerDelay = enum(u32) {
 19    cancel,
 20    periodic,
 21    relative,
 22};
 23
 24pub const MemoryType = enum(u32) {
 25    pub const Oem = math.IntFittingRange(
 26        0,
 27        @intFromEnum(MemoryType.oem_end) - @intFromEnum(MemoryType.oem_start),
 28    );
 29    pub const Vendor = math.IntFittingRange(
 30        0,
 31        @intFromEnum(MemoryType.vendor_end) - @intFromEnum(MemoryType.vendor_start),
 32    );
 33
 34    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
 35    reserved_memory_type,
 36    loader_code,
 37    loader_data,
 38    boot_services_code,
 39    boot_services_data,
 40    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
 41    runtime_services_code,
 42    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
 43    runtime_services_data,
 44    conventional_memory,
 45    unusable_memory,
 46    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
 47    acpi_reclaim_memory,
 48    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
 49    acpi_memory_nvs,
 50    memory_mapped_io,
 51    memory_mapped_io_port_space,
 52    pal_code,
 53    persistent_memory,
 54    unaccepted_memory,
 55    max_memory_type,
 56    invalid_start,
 57    invalid_end = 0x6FFFFFFF,
 58    /// MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.
 59    oem_start = 0x70000000,
 60    oem_end = 0x7FFFFFFF,
 61    /// MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI
 62    /// OS loaders that are provided by operating system vendors.
 63    vendor_start = 0x80000000,
 64    vendor_end = 0xFFFFFFFF,
 65    _,
 66
 67    pub fn fromOem(value: Oem) MemoryType {
 68        const oem_start = @intFromEnum(MemoryType.oem_start);
 69        return @enumFromInt(oem_start + value);
 70    }
 71
 72    pub fn toOem(memtype: MemoryType) ?Oem {
 73        const as_int = @intFromEnum(memtype);
 74        const oem_start = @intFromEnum(MemoryType.oem_start);
 75        if (as_int < oem_start) return null;
 76        if (as_int > @intFromEnum(MemoryType.oem_end)) return null;
 77        return @truncate(as_int - oem_start);
 78    }
 79
 80    pub fn fromVendor(value: Vendor) MemoryType {
 81        const vendor_start = @intFromEnum(MemoryType.vendor_start);
 82        return @enumFromInt(vendor_start + value);
 83    }
 84
 85    pub fn toVendor(memtype: MemoryType) ?Vendor {
 86        const as_int = @intFromEnum(memtype);
 87        const vendor_start = @intFromEnum(MemoryType.vendor_start);
 88        if (as_int < @intFromEnum(MemoryType.vendor_end)) return null;
 89        if (as_int > @intFromEnum(MemoryType.vendor_end)) return null;
 90        return @truncate(as_int - vendor_start);
 91    }
 92
 93    pub fn format(self: MemoryType, w: *std.Io.Writer) std.Io.Writer.Error!void {
 94        if (self.toOem()) |oemval|
 95            try w.print("OEM({X})", .{oemval})
 96        else if (self.toVendor()) |vendorval|
 97            try w.print("Vendor({X})", .{vendorval})
 98        else if (std.enums.tagName(MemoryType, self)) |name|
 99            try w.print("{s}", .{name})
100        else
101            try w.print("INVALID({X})", .{@intFromEnum(self)});
102    }
103};
104
105pub const MemoryDescriptorAttribute = packed struct(u64) {
106    uc: bool,
107    wc: bool,
108    wt: bool,
109    wb: bool,
110    uce: bool,
111    _pad1: u7 = 0,
112    wp: bool,
113    rp: bool,
114    xp: bool,
115    nv: bool,
116    more_reliable: bool,
117    ro: bool,
118    sp: bool,
119    cpu_crypto: bool,
120    _pad2: u43 = 0,
121    memory_runtime: bool,
122};
123
124pub const MemoryMapKey = enum(usize) { _ };
125
126pub const MemoryDescriptor = extern struct {
127    type: MemoryType,
128    physical_start: u64,
129    virtual_start: u64,
130    number_of_pages: u64,
131    attribute: MemoryDescriptorAttribute,
132};
133
134pub const MemoryMapInfo = struct {
135    key: MemoryMapKey,
136    descriptor_size: usize,
137    descriptor_version: u32,
138    /// The number of descriptors in the map.
139    len: usize,
140};
141
142pub const MemoryMapSlice = struct {
143    info: MemoryMapInfo,
144    ptr: [*]align(@alignOf(MemoryDescriptor)) u8,
145
146    pub fn iterator(self: MemoryMapSlice) MemoryDescriptorIterator {
147        return .{ .ctx = self };
148    }
149
150    pub fn get(self: MemoryMapSlice, index: usize) ?*MemoryDescriptor {
151        if (index >= self.info.len) return null;
152        return self.getUnchecked(index);
153    }
154
155    pub fn getUnchecked(self: MemoryMapSlice, index: usize) *MemoryDescriptor {
156        const offset: usize = index * self.info.descriptor_size;
157        return @ptrCast(@alignCast(self.ptr[offset..]));
158    }
159};
160
161pub const MemoryDescriptorIterator = struct {
162    ctx: MemoryMapSlice,
163    index: usize = 0,
164
165    pub fn next(self: *MemoryDescriptorIterator) ?*MemoryDescriptor {
166        const md = self.ctx.get(self.index) orelse return null;
167        self.index += 1;
168        return md;
169    }
170};
171
172pub const LocateSearchType = enum(u32) {
173    all_handles,
174    by_register_notify,
175    by_protocol,
176};
177
178pub const LocateSearch = union(LocateSearchType) {
179    all_handles,
180    by_register_notify: uefi.EventRegistration,
181    by_protocol: *const Guid,
182};
183
184pub const OpenProtocolAttributes = enum(u32) {
185    pub const Bits = packed struct(u32) {
186        by_handle_protocol: bool = false,
187        get_protocol: bool = false,
188        test_protocol: bool = false,
189        by_child_controller: bool = false,
190        by_driver: bool = false,
191        exclusive: bool = false,
192        reserved: u26 = 0,
193    };
194
195    by_handle_protocol = @bitCast(Bits{ .by_handle_protocol = true }),
196    get_protocol = @bitCast(Bits{ .get_protocol = true }),
197    test_protocol = @bitCast(Bits{ .test_protocol = true }),
198    by_child_controller = @bitCast(Bits{ .by_child_controller = true }),
199    by_driver = @bitCast(Bits{ .by_driver = true }),
200    by_driver_exclusive = @bitCast(Bits{ .by_driver = true, .exclusive = true }),
201    exclusive = @bitCast(Bits{ .exclusive = true }),
202    _,
203
204    pub fn fromBits(bits: Bits) OpenProtocolAttributes {
205        return @bitCast(bits);
206    }
207
208    pub fn toBits(self: OpenProtocolAttributes) Bits {
209        return @bitCast(self);
210    }
211};
212
213pub const OpenProtocolArgs = union(OpenProtocolAttributes) {
214    /// Used in the implementation of `handleProtocol`.
215    by_handle_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
216    /// Used by a driver to get a protocol interface from a handle. Care must be
217    /// taken when using this open mode because the driver that opens a protocol
218    /// interface in this manner will not be informed if the protocol interface
219    /// is uninstalled or reinstalled. The caller is also not required to close
220    /// the protocol interface with `closeProtocol`.
221    get_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
222    /// Used by a driver to test for the existence of a protocol interface on a
223    /// handle. The caller only use the return status code. The caller is also
224    /// not required to close the protocol interface with `closeProtocol`.
225    test_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
226    /// Used by bus drivers to show that a protocol interface is being used by one
227    /// of the child controllers of a bus. This information is used by
228    /// `BootServices.connectController` to recursively connect all child controllers
229    /// and by `BootServices.disconnectController` to get the list of child
230    /// controllers that a bus driver created.
231    by_child_controller: struct { agent: Handle, controller: Handle },
232    /// Used by a driver to gain access to a protocol interface. When this mode
233    /// is used, the driver’s Stop() function will be called by
234    /// `BootServices.disconnectController` if the protocol interface is reinstalled
235    /// or uninstalled. Once a protocol interface is opened by a driver with this
236    /// attribute, no other drivers will be allowed to open the same protocol interface
237    /// with the `.by_driver` attribute.
238    by_driver: struct { agent: Handle, controller: Handle },
239    /// Used by a driver to gain exclusive access to a protocol interface. If any
240    /// other drivers have the protocol interface opened with an attribute of
241    /// `.by_driver`, then an attempt will be made to remove them with
242    /// `BootServices.disconnectController`.
243    by_driver_exclusive: struct { agent: Handle, controller: Handle },
244    /// Used by applications to gain exclusive access to a protocol interface. If
245    /// any drivers have the protocol interface opened with an attribute of
246    /// `.by_driver`, then an attempt will be made to remove them by calling the
247    /// driver’s Stop() function.
248    exclusive: struct { agent: Handle, controller: ?Handle = null },
249};
250
251pub const ProtocolInformationEntry = extern struct {
252    agent_handle: ?Handle,
253    controller_handle: ?Handle,
254    attributes: OpenProtocolAttributes,
255    open_count: u32,
256};
257
258pub const InterfaceType = enum(u32) {
259    native,
260};
261
262pub const AllocateLocation = union(AllocateType) {
263    any,
264    max_address: [*]align(4096) uefi.Page,
265    address: [*]align(4096) uefi.Page,
266};
267
268pub const AllocateType = enum(u32) {
269    any,
270    max_address,
271    address,
272};
273
274pub const PhysicalAddress = u64;
275
276pub const CapsuleHeader = extern struct {
277    capsule_guid: Guid,
278    header_size: u32,
279    flags: u32,
280    capsule_image_size: u32,
281};
282
283pub const UefiCapsuleBlockDescriptor = extern struct {
284    length: u64,
285    address: extern union {
286        data_block: PhysicalAddress,
287        continuation_pointer: PhysicalAddress,
288    },
289};
290
291pub const ResetType = enum(u32) {
292    cold,
293    warm,
294    shutdown,
295    platform_specific,
296};
297
298pub const global_variable = Guid{
299    .time_low = 0x8be4df61,
300    .time_mid = 0x93ca,
301    .time_high_and_version = 0x11d2,
302    .clock_seq_high_and_reserved = 0xaa,
303    .clock_seq_low = 0x0d,
304    .node = [_]u8{ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c },
305};
306
307test {
308    std.testing.refAllDeclsRecursive(@This());
309}