| 1 | const std = @import("std"); |
| 2 | const uefi = std.os.uefi; |
| 3 | const Handle = uefi.Handle; |
| 4 | const Event = uefi.Event; |
| 5 | const Guid = uefi.Guid; |
| 6 | const cc = uefi.cc; |
| 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; |
| 9 | |
| 10 | pub const BootServices = @import("tables/boot_services.zig").BootServices; |
| 11 | pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; |
| 12 | pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; |
| 13 | pub const SystemTable = @import("tables/system_table.zig").SystemTable; |
| 14 | pub const TableHeader = @import("tables/table_header.zig").TableHeader; |
| 15 | |
| 16 | pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void; |
| 17 | |
| 18 | pub const TimerDelay = enum(u32) { |
| 19 | cancel, |
| 20 | periodic, |
| 21 | relative, |
| 22 | }; |
| 23 | |
| 24 | pub const MemoryType = enum(u32) { |
| 25 | pub const Oem = math.IntFittingRange( |
| 26 | 0, |
| 27 | @backingInt(MemoryType.oem_end) - @backingInt(MemoryType.oem_start), |
| 28 | ); |
| 29 | pub const Vendor = math.IntFittingRange( |
| 30 | 0, |
| 31 | @backingInt(MemoryType.vendor_end) - @backingInt(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 = @backingInt(MemoryType.oem_start); |
| 69 | return @fromBackingInt(@intCast(oem_start + value)); |
| 70 | } |
| 71 | |
| 72 | pub fn toOem(memtype: MemoryType) ?Oem { |
| 73 | const as_int = @backingInt(memtype); |
| 74 | const oem_start = @backingInt(MemoryType.oem_start); |
| 75 | if (as_int < oem_start) return null; |
| 76 | if (as_int > @backingInt(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 = @backingInt(MemoryType.vendor_start); |
| 82 | return @fromBackingInt(@intCast(vendor_start + value)); |
| 83 | } |
| 84 | |
| 85 | pub fn toVendor(memtype: MemoryType) ?Vendor { |
| 86 | const as_int = @backingInt(memtype); |
| 87 | const vendor_start = @backingInt(MemoryType.vendor_start); |
| 88 | if (as_int < @backingInt(MemoryType.vendor_end)) return null; |
| 89 | if (as_int > @backingInt(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})", .{@backingInt(self)}); |
| 102 | } |
| 103 | }; |
| 104 | |
| 105 | pub 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 | |
| 124 | pub const MemoryMapKey = enum(usize) { _ }; |
| 125 | |
| 126 | pub 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 | |
| 134 | pub 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 | |
| 142 | pub 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 | |
| 161 | pub 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 | |
| 172 | pub const LocateSearchType = enum(u32) { |
| 173 | all_handles, |
| 174 | by_register_notify, |
| 175 | by_protocol, |
| 176 | }; |
| 177 | |
| 178 | pub const LocateSearch = union(LocateSearchType) { |
| 179 | all_handles, |
| 180 | by_register_notify: uefi.EventRegistration, |
| 181 | by_protocol: *const Guid, |
| 182 | }; |
| 183 | |
| 184 | pub 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 | |
| 213 | pub 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 | |
| 251 | pub const ProtocolInformationEntry = extern struct { |
| 252 | agent_handle: ?Handle, |
| 253 | controller_handle: ?Handle, |
| 254 | attributes: OpenProtocolAttributes, |
| 255 | open_count: u32, |
| 256 | }; |
| 257 | |
| 258 | pub const InterfaceType = enum(u32) { |
| 259 | native, |
| 260 | }; |
| 261 | |
| 262 | pub const AllocateLocation = union(AllocateType) { |
| 263 | any, |
| 264 | max_address: [*]align(4096) uefi.Page, |
| 265 | address: [*]align(4096) uefi.Page, |
| 266 | }; |
| 267 | |
| 268 | pub const AllocateType = enum(u32) { |
| 269 | any, |
| 270 | max_address, |
| 271 | address, |
| 272 | }; |
| 273 | |
| 274 | pub const PhysicalAddress = u64; |
| 275 | |
| 276 | pub const CapsuleHeader = extern struct { |
| 277 | capsule_guid: Guid, |
| 278 | header_size: u32, |
| 279 | flags: u32, |
| 280 | capsule_image_size: u32, |
| 281 | }; |
| 282 | |
| 283 | pub const UefiCapsuleBlockDescriptor = extern struct { |
| 284 | length: u64, |
| 285 | address: extern union { |
| 286 | data_block: PhysicalAddress, |
| 287 | continuation_pointer: PhysicalAddress, |
| 288 | }, |
| 289 | }; |
| 290 | |
| 291 | pub const ResetType = enum(u32) { |
| 292 | cold, |
| 293 | warm, |
| 294 | shutdown, |
| 295 | platform_specific, |
| 296 | }; |
| 297 | |
| 298 | pub 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 | |
| 307 | test { |
| 308 | std.testing.refAllDecls(@This()); |
| 309 | } |