aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os/uefi/tables.zig
blob: d211fcbdafd38b5986f0adfd0a8905a741a5c418 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
const std = @import("std");
const uefi = std.os.uefi;
const Handle = uefi.Handle;
const Event = uefi.Event;
const Guid = uefi.Guid;
const cc = uefi.cc;
const math = std.math;
const assert = std.debug.assert;

pub const BootServices = @import("tables/boot_services.zig").BootServices;
pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
pub const SystemTable = @import("tables/system_table.zig").SystemTable;
pub const TableHeader = @import("tables/table_header.zig").TableHeader;

pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void;

pub const TimerDelay = enum(u32) {
    cancel,
    periodic,
    relative,
};

pub const MemoryType = enum(u32) {
    pub const Oem = math.IntFittingRange(
        0,
        @intFromEnum(MemoryType.oem_end) - @intFromEnum(MemoryType.oem_start),
    );
    pub const Vendor = math.IntFittingRange(
        0,
        @intFromEnum(MemoryType.vendor_end) - @intFromEnum(MemoryType.vendor_start),
    );

    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
    reserved_memory_type,
    loader_code,
    loader_data,
    boot_services_code,
    boot_services_data,
    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
    runtime_services_code,
    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
    runtime_services_data,
    conventional_memory,
    unusable_memory,
    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
    acpi_reclaim_memory,
    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
    acpi_memory_nvs,
    memory_mapped_io,
    memory_mapped_io_port_space,
    pal_code,
    persistent_memory,
    unaccepted_memory,
    max_memory_type,
    invalid_start,
    invalid_end = 0x6FFFFFFF,
    /// MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.
    oem_start = 0x70000000,
    oem_end = 0x7FFFFFFF,
    /// MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI
    /// OS loaders that are provided by operating system vendors.
    vendor_start = 0x80000000,
    vendor_end = 0xFFFFFFFF,
    _,

    pub fn fromOem(value: Oem) MemoryType {
        const oem_start = @intFromEnum(MemoryType.oem_start);
        return @enumFromInt(oem_start + value);
    }

    pub fn toOem(memtype: MemoryType) ?Oem {
        const as_int = @intFromEnum(memtype);
        const oem_start = @intFromEnum(MemoryType.oem_start);
        if (as_int < oem_start) return null;
        if (as_int > @intFromEnum(MemoryType.oem_end)) return null;
        return @truncate(as_int - oem_start);
    }

    pub fn fromVendor(value: Vendor) MemoryType {
        const vendor_start = @intFromEnum(MemoryType.vendor_start);
        return @enumFromInt(vendor_start + value);
    }

    pub fn toVendor(memtype: MemoryType) ?Vendor {
        const as_int = @intFromEnum(memtype);
        const vendor_start = @intFromEnum(MemoryType.vendor_start);
        if (as_int < @intFromEnum(MemoryType.vendor_end)) return null;
        if (as_int > @intFromEnum(MemoryType.vendor_end)) return null;
        return @truncate(as_int - vendor_start);
    }

    pub fn format(self: MemoryType, w: *std.Io.Writer) std.Io.Writer.Error!void {
        if (self.toOem()) |oemval|
            try w.print("OEM({X})", .{oemval})
        else if (self.toVendor()) |vendorval|
            try w.print("Vendor({X})", .{vendorval})
        else if (std.enums.tagName(MemoryType, self)) |name|
            try w.print("{s}", .{name})
        else
            try w.print("INVALID({X})", .{@intFromEnum(self)});
    }
};

pub const MemoryDescriptorAttribute = packed struct(u64) {
    uc: bool,
    wc: bool,
    wt: bool,
    wb: bool,
    uce: bool,
    _pad1: u7 = 0,
    wp: bool,
    rp: bool,
    xp: bool,
    nv: bool,
    more_reliable: bool,
    ro: bool,
    sp: bool,
    cpu_crypto: bool,
    _pad2: u43 = 0,
    memory_runtime: bool,
};

pub const MemoryMapKey = enum(usize) { _ };

pub const MemoryDescriptor = extern struct {
    type: MemoryType,
    physical_start: u64,
    virtual_start: u64,
    number_of_pages: u64,
    attribute: MemoryDescriptorAttribute,
};

pub const MemoryMapInfo = struct {
    key: MemoryMapKey,
    descriptor_size: usize,
    descriptor_version: u32,
    /// The number of descriptors in the map.
    len: usize,
};

pub const MemoryMapSlice = struct {
    info: MemoryMapInfo,
    ptr: [*]align(@alignOf(MemoryDescriptor)) u8,

    pub fn iterator(self: MemoryMapSlice) MemoryDescriptorIterator {
        return .{ .ctx = self };
    }

    pub fn get(self: MemoryMapSlice, index: usize) ?*MemoryDescriptor {
        if (index >= self.info.len) return null;
        return self.getUnchecked(index);
    }

    pub fn getUnchecked(self: MemoryMapSlice, index: usize) *MemoryDescriptor {
        const offset: usize = index * self.info.descriptor_size;
        return @ptrCast(@alignCast(self.ptr[offset..]));
    }
};

pub const MemoryDescriptorIterator = struct {
    ctx: MemoryMapSlice,
    index: usize = 0,

    pub fn next(self: *MemoryDescriptorIterator) ?*MemoryDescriptor {
        const md = self.ctx.get(self.index) orelse return null;
        self.index += 1;
        return md;
    }
};

pub const LocateSearchType = enum(u32) {
    all_handles,
    by_register_notify,
    by_protocol,
};

pub const LocateSearch = union(LocateSearchType) {
    all_handles,
    by_register_notify: uefi.EventRegistration,
    by_protocol: *const Guid,
};

pub const OpenProtocolAttributes = enum(u32) {
    pub const Bits = packed struct(u32) {
        by_handle_protocol: bool = false,
        get_protocol: bool = false,
        test_protocol: bool = false,
        by_child_controller: bool = false,
        by_driver: bool = false,
        exclusive: bool = false,
        reserved: u26 = 0,
    };

    by_handle_protocol = @bitCast(Bits{ .by_handle_protocol = true }),
    get_protocol = @bitCast(Bits{ .get_protocol = true }),
    test_protocol = @bitCast(Bits{ .test_protocol = true }),
    by_child_controller = @bitCast(Bits{ .by_child_controller = true }),
    by_driver = @bitCast(Bits{ .by_driver = true }),
    by_driver_exclusive = @bitCast(Bits{ .by_driver = true, .exclusive = true }),
    exclusive = @bitCast(Bits{ .exclusive = true }),
    _,

    pub fn fromBits(bits: Bits) OpenProtocolAttributes {
        return @bitCast(bits);
    }

    pub fn toBits(self: OpenProtocolAttributes) Bits {
        return @bitCast(self);
    }
};

pub const OpenProtocolArgs = union(OpenProtocolAttributes) {
    /// Used in the implementation of `handleProtocol`.
    by_handle_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
    /// Used by a driver to get a protocol interface from a handle. Care must be
    /// taken when using this open mode because the driver that opens a protocol
    /// interface in this manner will not be informed if the protocol interface
    /// is uninstalled or reinstalled. The caller is also not required to close
    /// the protocol interface with `closeProtocol`.
    get_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
    /// Used by a driver to test for the existence of a protocol interface on a
    /// handle. The caller only use the return status code. The caller is also
    /// not required to close the protocol interface with `closeProtocol`.
    test_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
    /// Used by bus drivers to show that a protocol interface is being used by one
    /// of the child controllers of a bus. This information is used by
    /// `BootServices.connectController` to recursively connect all child controllers
    /// and by `BootServices.disconnectController` to get the list of child
    /// controllers that a bus driver created.
    by_child_controller: struct { agent: Handle, controller: Handle },
    /// Used by a driver to gain access to a protocol interface. When this mode
    /// is used, the driver’s Stop() function will be called by
    /// `BootServices.disconnectController` if the protocol interface is reinstalled
    /// or uninstalled. Once a protocol interface is opened by a driver with this
    /// attribute, no other drivers will be allowed to open the same protocol interface
    /// with the `.by_driver` attribute.
    by_driver: struct { agent: Handle, controller: Handle },
    /// Used by a driver to gain exclusive access to a protocol interface. If any
    /// other drivers have the protocol interface opened with an attribute of
    /// `.by_driver`, then an attempt will be made to remove them with
    /// `BootServices.disconnectController`.
    by_driver_exclusive: struct { agent: Handle, controller: Handle },
    /// Used by applications to gain exclusive access to a protocol interface. If
    /// any drivers have the protocol interface opened with an attribute of
    /// `.by_driver`, then an attempt will be made to remove them by calling the
    /// driver’s Stop() function.
    exclusive: struct { agent: Handle, controller: ?Handle = null },
};

pub const ProtocolInformationEntry = extern struct {
    agent_handle: ?Handle,
    controller_handle: ?Handle,
    attributes: OpenProtocolAttributes,
    open_count: u32,
};

pub const InterfaceType = enum(u32) {
    native,
};

pub const AllocateLocation = union(AllocateType) {
    any,
    max_address: [*]align(4096) uefi.Page,
    address: [*]align(4096) uefi.Page,
};

pub const AllocateType = enum(u32) {
    any,
    max_address,
    address,
};

pub const PhysicalAddress = u64;

pub const CapsuleHeader = extern struct {
    capsule_guid: Guid,
    header_size: u32,
    flags: u32,
    capsule_image_size: u32,
};

pub const UefiCapsuleBlockDescriptor = extern struct {
    length: u64,
    address: extern union {
        data_block: PhysicalAddress,
        continuation_pointer: PhysicalAddress,
    },
};

pub const ResetType = enum(u32) {
    cold,
    warm,
    shutdown,
    platform_specific,
};

pub const global_variable = Guid{
    .time_low = 0x8be4df61,
    .time_mid = 0x93ca,
    .time_high_and_version = 0x11d2,
    .clock_seq_high_and_reserved = 0xaa,
    .clock_seq_low = 0x0d,
    .node = [_]u8{ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c },
};

test {
    std.testing.refAllDeclsRecursive(@This());
}