Microkernel thing OS experiment (Zig ⚡)
1const builtin = @import("builtin");
2const config = @import("config");
3const std = @import("std");
4
5pub const Arch = enum {
6 x86_64,
7 aarch64,
8 riscv64,
9 loongarch64,
10};
11
12pub const api_revision = config.api_revision;
13pub const arch: Arch = switch (builtin.cpu.arch) {
14 .x86_64 => .x86_64,
15 .aarch64 => .aarch64,
16 .riscv64 => .riscv64,
17 .loongarch64 => .loongarch64,
18 else => |arch_tag| @compileError("Unsupported architecture: " ++ @tagName(arch_tag)),
19};
20
21fn id(a: u64, b: u64) [4]u64 {
22 return .{ 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, a, b };
23}
24
25fn LiminePtr(comptime Type: type) type {
26 return if (config.no_pointers) u64 else Type;
27}
28
29const init_pointer = if (config.no_pointers)
30 0
31else
32 null;
33
34pub const RequestsStartMarker = extern struct {
35 marker: [4]u64 = .{
36 0xf6b8f4b39de7d1ae,
37 0xfab91a6940fcb9cf,
38 0x785c6ed015d3e316,
39 0x181e920a7852b9d9,
40 },
41};
42
43pub const RequestsEndMarker = extern struct {
44 marker: [2]u64 = .{ 0xadc0e0531bb10d03, 0x9572709f31764c62 },
45};
46
47pub const BaseRevision = extern struct {
48 magic: [2]u64 = .{ 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc },
49 revision: u64,
50
51 pub fn init(revision: u64) @This() {
52 return .{ .revision = revision };
53 }
54
55 pub fn loadedRevision(self: @This()) u64 {
56 return self.magic[1];
57 }
58
59 pub fn isValid(self: @This()) bool {
60 return self.magic[1] != 0x6a7b384944536bdc;
61 }
62
63 pub fn isSupported(self: @This()) bool {
64 return self.revision == 0;
65 }
66};
67
68pub const Uuid = extern struct {
69 a: u32,
70 b: u16,
71 c: u16,
72 d: [8]u8,
73};
74
75pub const MediaType = enum(u32) {
76 generic = 0,
77 optical = 1,
78 tftp = 2,
79 _,
80};
81
82const LimineFileV1 = extern struct {
83 revision: u64,
84 address: LiminePtr(*align(4096) anyopaque),
85 size: u64,
86 path: LiminePtr([*:0]u8),
87 cmdline: LiminePtr([*:0]u8),
88 media_type: MediaType,
89 unused: u32,
90 tftp_ip: u32,
91 tftp_port: u32,
92 partition_index: u32,
93 mbr_disk_id: u32,
94 gpt_disk_uuid: Uuid,
95 gpt_part_uuid: Uuid,
96 part_uuid: Uuid,
97};
98
99const LimineFileV2 = extern struct {
100 revision: u64,
101 address: LiminePtr(*align(4096) anyopaque),
102 size: u64,
103 path: LiminePtr([*:0]u8),
104 string: LiminePtr([*:0]u8),
105 media_type: MediaType,
106 unused: u32,
107 tftp_ip: u32,
108 tftp_port: u32,
109 partition_index: u32,
110 mbr_disk_id: u32,
111 gpt_disk_uuid: Uuid,
112 gpt_part_uuid: Uuid,
113 part_uuid: Uuid,
114};
115
116pub const File = if (config.api_revision >= 3)
117 LimineFileV2
118else
119 LimineFileV1;
120
121// Boot info
122
123pub const BootloaderInfoResponse = extern struct {
124 revision: u64,
125 name: LiminePtr([*:0]u8),
126 version: LiminePtr([*:0]u8),
127};
128
129pub const BootloaderInfoRequest = extern struct {
130 id: [4]u64 = id(0xf55038d8e2a1202f, 0x279426fcf5f59740),
131 revision: u64 = 0,
132 response: LiminePtr(?*BootloaderInfoResponse) = init_pointer,
133};
134
135// Executable command line
136
137pub const ExecutableCmdlineResponse = extern struct {
138 revision: u64,
139 cmdline: LiminePtr([*:0]u8),
140};
141
142pub const ExecutableCmdlineRequest = extern struct {
143 id: [4]u64 = id(0x4b161536e598651e, 0xb390ad4a2f1f303a),
144 revision: u64 = 0,
145 response: LiminePtr(?*ExecutableCmdlineResponse) = init_pointer,
146};
147
148// Firmware type
149
150pub const FirmwareType = enum(u64) {
151 x86_bios = 0,
152 uefi32 = 1,
153 uefi64 = 2,
154 sbi = 3,
155 _,
156};
157
158pub const FirmwareTypeResponse = extern struct {
159 revision: u64,
160 firmware_type: FirmwareType,
161};
162
163pub const FirmwareTypeRequest = extern struct {
164 id: [4]u64 = id(0x8c2f75d90bef28a8, 0x7045a4688eac00c3),
165 revision: u64 = 0,
166 response: LiminePtr(?*FirmwareTypeResponse) = init_pointer,
167};
168
169// Stack size
170
171pub const StackSizeResponse = extern struct {
172 revision: u64,
173};
174
175pub const StackSizeRequest = extern struct {
176 id: [4]u64 = id(0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d),
177 revision: u64 = 0,
178 response: LiminePtr(?*StackSizeResponse) = init_pointer,
179 stack_size: u64,
180};
181
182// HHDM
183
184pub const HhdmResponse = extern struct {
185 revision: u64,
186 offset: u64,
187};
188
189pub const HhdmRequest = extern struct {
190 id: [4]u64 = id(0x48dcf1cb8ad2b852, 0x63984e959a98244b),
191 revision: u64 = 0,
192 response: LiminePtr(?*HhdmResponse) = init_pointer,
193};
194
195// Framebuffer
196
197pub const FramebufferMemoryModel = enum(u8) {
198 rgb = 1,
199 _,
200};
201
202pub const VideoMode = extern struct {
203 pitch: u64,
204 width: u64,
205 height: u64,
206 bpp: u16,
207 memory_model: FramebufferMemoryModel,
208 red_mask_size: u8,
209 red_mask_shift: u8,
210 green_mask_size: u8,
211 green_mask_shift: u8,
212 blue_mask_size: u8,
213 blue_mask_shift: u8,
214};
215
216pub const Framebuffer = extern struct {
217 address: LiminePtr(*anyopaque),
218 width: u64,
219 height: u64,
220 pitch: u64,
221 bpp: u16,
222 memory_model: FramebufferMemoryModel,
223 red_mask_size: u8,
224 red_mask_shift: u8,
225 green_mask_size: u8,
226 green_mask_shift: u8,
227 blue_mask_size: u8,
228 blue_mask_shift: u8,
229 edid_size: u64,
230 edid: LiminePtr(?*anyopaque),
231 // Response revision 1
232 mode_count: u64,
233 modes: LiminePtr([*]*VideoMode),
234
235 /// Helper function to retrieve the EDID data as a slice.
236 /// This function will return null if the EDID size is 0 or if
237 /// the EDID pointer is null.
238 pub fn getEdid(self: @This()) ?[*]u8 {
239 if (self.edid_size == 0 or self.edid == null) {
240 return null;
241 }
242 return @as([*]u8, self.edid.?)[0..self.edid_size];
243 }
244
245 /// Helper function to retrieve a slice of the modes array.
246 /// This function is only available since revision 1 of the response and
247 /// will return an error if called with an older response. This is to
248 /// prevent the user from possibly accessing uninitialized memory.
249 pub fn getModes(self: @This(), response: *FramebufferResponse) ![]*VideoMode {
250 if (response.revision < 1) {
251 return error.NotSupported;
252 }
253 return self.modes[0..self.mode_count];
254 }
255};
256
257pub const FramebufferResponse = extern struct {
258 revision: u64,
259 framebuffer_count: u64,
260 framebuffers: LiminePtr(?[*]*Framebuffer),
261
262 /// Helper function to retrieve a slice of the framebuffers array.
263 /// This function will return null if the framebuffer count is 0 or if
264 /// the framebuffers pointer is null.
265 pub fn getFramebuffers(self: @This()) []*Framebuffer {
266 if (self.framebuffer_count == 0 or self.framebuffers == null) {
267 return &.{};
268 }
269 return self.framebuffers.?[0..self.framebuffer_count];
270 }
271};
272
273pub const FramebufferRequest = extern struct {
274 id: [4]u64 = id(0x9d5827dcd881dd75, 0xa3148604f6fab11b),
275 revision: u64 = 1,
276 response: LiminePtr(?*FramebufferResponse) = init_pointer,
277};
278
279// Terminal
280
281const TerminalDeprecated = struct {
282 const deprecation_message =
283 \\The Terminal feature was deprecated and is no longer available.
284 \\Kernels are encouraged to manually implement terminal support
285 \\using the Framebuffer feature instead. If you need an easy to
286 \\integrate solution, consider using https://github.com/mintsuki/flanterm.
287 ;
288
289 pub const TerminalCallbackType = @compileError(deprecation_message);
290 pub const TerminalCallbackEscapeParams = @compileError(deprecation_message);
291 pub const TerminalCallbackPosReportParams = @compileError(deprecation_message);
292 pub const TerminalCallbackKbdLedsState = @compileError(deprecation_message);
293 pub const TerminalCallbackKbdLedsParams = @compileError(deprecation_message);
294 pub const TerminalWrite = @compileError(deprecation_message);
295 pub const TerminalCallback = @compileError(deprecation_message);
296 pub const Terminal = @compileError(deprecation_message);
297 pub const TerminalResponse = @compileError(deprecation_message);
298 pub const TerminalRequest = @compileError(deprecation_message);
299};
300
301pub const TerminalFeature = if (config.allow_deprecated) struct {
302 pub const TerminalCallbackType = enum(u64) {
303 dec = 10,
304 bell = 20,
305 private_id = 30,
306 status_report = 40,
307 pos_report = 50,
308 kbd_leds = 60,
309 mode = 70,
310 linux = 80,
311 _,
312 };
313
314 pub const TerminalCallbackEscapeParams = struct {
315 a1: u64,
316 a2: u64,
317 a3: u64,
318
319 /// Initialize a TerminalCallbackEscapeParams struct, which is used for
320 /// decoding the parameters of the terminal callbacks that handle escape sequences.
321 pub fn init(a1: u64, a2: u64, a3: u64) @This() {
322 return .{ .a1 = a1, .a2 = a2, .a3 = a3 };
323 }
324
325 /// Retrieve the array of values passed to the escape sequence.
326 pub fn values(self: @This()) []u32 {
327 const values_ptr: [*]u32 = @intFromPtr(self.a2);
328 return values_ptr[0..self.a1];
329 }
330
331 /// Retrieve the final character in a DEC or ECMA-48 Mode Switch
332 /// escape sequence.
333 /// This is the character that is used to determine the type of
334 /// sequence that was sent, usually 'h' or 'l'.
335 pub fn finalChar(self: @This()) u8 {
336 return @intCast(self.a3);
337 }
338 };
339
340 pub const TerminalCallbackPosReportParams = struct {
341 a1: u64,
342 a2: u64,
343
344 /// Initialize a TerminalCallbackPosReportParams struct, which is used for
345 /// decoding the parameters of a position report terminal callback.
346 pub fn init(a1: u64, a2: u64) @This() {
347 return .{ .a1 = a1, .a2 = a2 };
348 }
349
350 /// Retrieve the X position of the cursor.
351 pub fn x(self: @This()) u64 {
352 return self.a1;
353 }
354
355 /// Retrieve the Y position of the cursor.
356 pub fn y(self: @This()) u64 {
357 return self.a2;
358 }
359 };
360
361 pub const TerminalCallbackKbdLedsState = enum(u64) {
362 clear_all = 0,
363 set_scroll_lock = 1,
364 set_num_lock = 2,
365 set_caps_lock = 3,
366 _,
367 };
368
369 pub const TerminalCallbackKbdLedsParams = struct {
370 a1: u64,
371
372 /// Initialize a TerminalCallbackKbdLedsParams struct, which is used for
373 /// decoding the parameters of a keyboard LEDs terminal callback.
374 pub fn init(a1: u64) @This() {
375 return .{ .a1 = a1 };
376 }
377
378 /// Retrieve the state of the Caps Lock LED.
379 pub fn state(self: @This()) TerminalCallbackKbdLedsState {
380 return @enumFromInt(self.a1);
381 }
382 };
383
384 pub const TerminalWrite = *const fn (*Terminal, [*]const u8, u64) callconv(.c) void;
385
386 pub const TerminalCallback = *const fn (*Terminal, TerminalCallbackType, u64, u64, u64) callconv(.c) void;
387
388 pub const Terminal = extern struct {
389 columns: u64,
390 rows: u64,
391 framebuffer: LiminePtr(?*Framebuffer),
392 };
393
394 pub const TerminalResponse = extern struct {
395 revision: u64,
396 terminal_count: u64,
397 terminals: LiminePtr(?[*]*Terminal),
398 write_fn: LiminePtr(TerminalWrite),
399
400 /// Helper function to retrieve a slice of the terminals array.
401 /// This function will return null if the terminal count is 0 or if
402 /// the terminals pointer is null.
403 pub fn getTerminals(self: @This()) []*Terminal {
404 if (self.terminal_count == 0 or self.terminals == null) {
405 return &.{};
406 }
407 return self.terminals.?[0..self.terminal_count];
408 }
409
410 /// Helper function to write to a terminal.
411 pub fn write(self: @This(), terminal: *Terminal, data: []const u8) void {
412 const write_fn: TerminalWrite = if (config.no_pointers)
413 @ptrFromInt(self.write_fn)
414 else
415 self.write_fn;
416
417 write_fn(terminal, data.ptr, data.len);
418 }
419 };
420
421 pub const TerminalRequest = extern struct {
422 id: [4]u64 = id(0xc8ac59310c2b0844, 0xa68d0c7265d38878),
423 revision: u64 = 0,
424 response: LiminePtr(?*TerminalResponse) = init_pointer,
425 callback: LiminePtr(?TerminalCallback),
426 };
427} else TerminalDeprecated;
428
429// Paging mode
430
431pub const PagingMode = switch (arch) {
432 .x86_64 => enum(u64) {
433 @"4lvl",
434 @"5lvl",
435 _,
436
437 const min: @This() = .@"4lvl";
438 const max: @This() = .@"5lvl";
439 const default: @This() = .@"4lvl";
440 },
441 .aarch64 => enum(u64) {
442 @"4lvl",
443 @"5lvl",
444 _,
445
446 const min: @This() = .@"4lvl";
447 const max: @This() = .@"5lvl";
448 const default: @This() = .@"4lvl";
449 },
450 .riscv64 => enum(u64) {
451 sv39,
452 sv48,
453 sv57,
454 _,
455
456 const min: @This() = .sv39;
457 const max: @This() = .sv57;
458 const default: @This() = .sv48;
459 },
460 .loongarch64 => enum(u64) {
461 @"4lvl",
462 _,
463
464 const min: @This() = .@"4lvl";
465 const max: @This() = .@"4lvl";
466 const default: @This() = .@"4lvl";
467 },
468};
469
470pub const PagingModeResponse = extern struct {
471 revision: u64,
472 mode: PagingMode,
473};
474
475pub const PagingModeRequest = extern struct {
476 id: [4]u64 = id(0x95c1a0edab0944cb, 0xa4e5cb3842f7488a),
477 revision: u64 = 0,
478 response: LiminePtr(?*PagingModeResponse) = init_pointer,
479 mode: PagingMode = .default,
480 max_mode: PagingMode = .max,
481 min_mode: PagingMode = .min,
482};
483
484// 5-level paging
485
486const FiveLevelPagingDeprecated = struct {
487 const deprecation_message =
488 \\The 5-level paging feature was deprecated and is no longer available.
489 \\Kernels are encouraged to manually request 5-level paging support
490 \\using the Paging mode feature instead.
491 ;
492
493 pub const FiveLevelPagingResponse = @compileError(deprecation_message);
494 pub const FiveLevelPagingRequest = @compileError(deprecation_message);
495};
496
497pub const FiveLevelPagingFeature = if (config.allow_deprecated) struct {
498 pub const FiveLevelPagingResponse = extern struct {
499 revision: u64,
500 };
501
502 pub const FiveLevelPagingRequest = extern struct {
503 id: [4]u64 = id(0x94469551da9b3192, 0xebe5e86db7382888),
504 revision: u64 = 0,
505 response: LiminePtr(?*FiveLevelPagingResponse) = init_pointer,
506 };
507} else FiveLevelPagingDeprecated;
508
509// MP (formerly SMP)
510
511pub const GotoAddress = *const fn (*SmpMpInfo) callconv(.c) noreturn;
512
513const SmpMpFlags = switch (arch) {
514 .x86_64 => packed struct(u32) {
515 x2apic: bool = false,
516 reserved: u31 = 0,
517 },
518 .aarch64, .riscv64, .loongarch64 => packed struct(u64) {
519 reserved: u64 = 0,
520 },
521};
522
523const SmpMpInfo = switch (arch) {
524 .x86_64 => extern struct {
525 processor_id: u32,
526 lapic_id: u32,
527 reserved: u64,
528 goto_address: LiminePtr(?GotoAddress),
529 extra_argument: u64,
530 },
531 .aarch64 => extern struct {
532 processor_id: u32,
533 mpidr: u64,
534 reserved: u64,
535 goto_address: LiminePtr(?GotoAddress),
536 extra_argument: u64,
537 },
538 .riscv64 => extern struct {
539 processor_id: u64,
540 hartid: u64,
541 reserved: u64,
542 goto_address: LiminePtr(?GotoAddress),
543 extra_argument: u64,
544 },
545 .loongarch64 => extern struct {
546 reserved: u64,
547 },
548};
549
550const SmpMpResponse = switch (arch) {
551 .x86_64 => extern struct {
552 revision: u64,
553 flags: SmpMpFlags,
554 bsp_lapic_id: u32,
555 cpu_count: u64,
556 cpus: LiminePtr(?[*]*SmpMpInfo),
557
558 /// Helper function to retrieve a slice of the CPUs array.
559 /// This function will return null if the CPU count is 0 or if
560 /// the CPUs pointer is null.
561 pub fn getCpus(self: @This()) []*SmpMpInfo {
562 if (self.cpu_count == 0 or self.cpus == null) {
563 return &.{};
564 }
565 return self.cpus.?[0..self.cpu_count];
566 }
567 },
568 .aarch64 => extern struct {
569 revision: u64,
570 flags: SmpMpFlags,
571 bsp_mpidr: u64,
572 cpu_count: u64,
573 cpus: LiminePtr(?[*]*SmpMpInfo),
574
575 /// Helper function to retrieve a slice of the CPUs array.
576 /// This function will return null if the CPU count is 0 or if
577 /// the CPUs pointer is null.
578 pub fn getCpus(self: @This()) []*SmpMpInfo {
579 if (self.cpu_count == 0 or self.cpus == null) {
580 return &.{};
581 }
582 return self.cpus.?[0..self.cpu_count];
583 }
584 },
585 .riscv64 => extern struct {
586 revision: u64,
587 flags: SmpMpFlags,
588 bsp_hartid: u64,
589 cpu_count: u64,
590 cpus: LiminePtr(?[*]*SmpMpInfo),
591
592 /// Helper function to retrieve a slice of the CPUs array.
593 /// This function will return null if the CPU count is 0 or if
594 /// the CPUs pointer is null.
595 pub fn getCpus(self: @This()) []*SmpMpInfo {
596 if (self.cpu_count == 0 or self.cpus == null) {
597 return &.{};
598 }
599 return self.cpus.?[0..self.cpu_count];
600 }
601 },
602 .loongarch64 => extern struct {
603 cpu_count: u64,
604 cpus: LiminePtr(?[*]*SmpMpInfo),
605
606 /// Helper function to retrieve a slice of the CPUs array.
607 /// This function will return null if the CPU count is 0 or if
608 /// the CPUs pointer is null.
609 pub fn getCpus(self: @This()) []*SmpMpInfo {
610 if (self.cpu_count == 0 or self.cpus == null) {
611 return &.{};
612 }
613 return self.cpus.?[0..self.cpu_count];
614 }
615 },
616};
617
618const SmpMpRequest = extern struct {
619 id: [4]u64 = id(0x95a67b819a1b857e, 0xa0b61b723b6a73e0),
620 revision: u64 = 0,
621 response: LiminePtr(?*SmpMpResponse) = init_pointer,
622 // The `flags` field in the request is 64-bit on *all* platforms, even
623 // though the flags enum is 32-bit on x86_64. This is to ensure that the
624 // struct is not too small on x86_64 there is a `reserved: u32` field after it.
625 flags: SmpMpFlags = .{},
626 reserved: u32 = 0,
627};
628
629const MpFeature = struct {
630 pub const MpFlags = SmpMpFlags;
631 pub const MpInfo = SmpMpInfo;
632 pub const MpResponse = SmpMpResponse;
633 pub const MpRequest = SmpMpRequest;
634};
635
636const SmpFeature = struct {
637 pub const SmpFlags = SmpMpFlags;
638 pub const SmpInfo = SmpMpInfo;
639 pub const SmpResponse = SmpMpResponse;
640 pub const SmpRequest = SmpMpRequest;
641};
642
643pub const SmpMpFeature = if (config.api_revision >= 1)
644 MpFeature
645else
646 SmpFeature;
647
648// Memory map
649
650const MemoryMapTypeV1 = enum(u64) {
651 usable = 0,
652 reserved = 1,
653 acpi_reclaimable = 2,
654 acpi_nvs = 3,
655 bad_memory = 4,
656 bootloader_reclaimable = 5,
657 kernel_and_modules = 6,
658 framebuffer = 7,
659 _,
660};
661
662const MemoryMapTypeV2 = enum(u64) {
663 usable = 0,
664 reserved = 1,
665 acpi_reclaimable = 2,
666 acpi_nvs = 3,
667 bad_memory = 4,
668 bootloader_reclaimable = 5,
669 executable_and_modules = 6,
670 framebuffer = 7,
671 _,
672};
673
674pub const MemoryMapType = if (config.api_revision >= 2)
675 MemoryMapTypeV2
676else
677 MemoryMapTypeV1;
678
679pub const MemoryMapEntry = extern struct {
680 base: u64,
681 length: u64,
682 type: MemoryMapType,
683};
684
685pub const MemoryMapResponse = extern struct {
686 revision: u64,
687 entry_count: u64,
688 entries: LiminePtr(?[*]*MemoryMapEntry),
689
690 /// Helper function to retrieve a slice of the entries array.
691 /// This function will return null if the entry count is 0 or if
692 /// the entries pointer is null.
693 pub fn getEntries(self: @This()) []*MemoryMapEntry {
694 if (self.entry_count == 0 or self.entries == null) {
695 return &.{};
696 }
697 return self.entries.?[0..self.entry_count];
698 }
699};
700
701pub const MemoryMapRequest = extern struct {
702 id: [4]u64 = id(0x67cf3d9d378a806f, 0xe304acdfc50c3c62),
703 revision: u64 = 0,
704 response: LiminePtr(?*MemoryMapResponse) = init_pointer,
705};
706
707// Entry point
708
709pub const EntryPoint = *const fn () callconv(.c) noreturn;
710
711pub const EntryPointResponse = extern struct {
712 revision: u64,
713};
714
715pub const EntryPointRequest = extern struct {
716 id: [4]u64 = id(0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a),
717 revision: u64 = 0,
718 response: LiminePtr(?*EntryPointResponse) = init_pointer,
719 entry: LiminePtr(EntryPoint),
720};
721
722// Executable file (formerly Kernel file)
723
724pub const ExecutableFileFeature = if (config.api_revision >= 2) struct {
725 pub const ExecutableFileResponse = extern struct {
726 revision: u64,
727 executable_file: LiminePtr(*File),
728 };
729
730 pub const ExecutableFileRequest = extern struct {
731 id: [4]u64 = id(0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69),
732 revision: u64 = 0,
733 response: LiminePtr(?*ExecutableFileResponse) = init_pointer,
734 };
735} else KernelFileFeature;
736
737const KernelFileFeature = struct {
738 pub const KernelFileResponse = extern struct {
739 revision: u64,
740 kernel_file: LiminePtr(*File),
741 };
742
743 pub const KernelFileRequest = extern struct {
744 id: [4]u64 = id(0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69),
745 revision: u64 = 0,
746 response: LiminePtr(?*KernelFileResponse) = init_pointer,
747 };
748};
749
750// Module
751
752pub const InternalModuleFlag = packed struct(u64) {
753 required: bool,
754 compressed: bool,
755 reserved: u62 = 0,
756};
757
758const InternalModuleV1 = extern struct {
759 path: LiminePtr([*:0]const u8),
760 cmdline: LiminePtr([*:0]const u8),
761 flags: InternalModuleFlag,
762};
763
764const InternalModuleV2 = extern struct {
765 path: LiminePtr([*:0]const u8),
766 string: LiminePtr([*:0]const u8),
767 flags: InternalModuleFlag,
768};
769
770pub const InternalModule = if (config.api_revision >= 3)
771 InternalModuleV2
772else
773 InternalModuleV1;
774
775pub const ModuleResponse = extern struct {
776 revision: u64,
777 module_count: u64,
778 modules: LiminePtr(?[*]*File),
779
780 /// Helper function to retrieve a slice of the modules array.
781 /// This function will return null if the module count is 0 or if
782 /// the modules pointer is null.
783 pub fn getModules(self: @This()) []*File {
784 if (self.module_count == 0 or self.modules == null) {
785 return &.{};
786 }
787 return self.modules.?[0..self.module_count];
788 }
789};
790
791pub const ModuleRequest = extern struct {
792 id: [4]u64 = id(0x3e7e279702be32af, 0xca1c4f3bd1280cee),
793 revision: u64 = 1,
794 response: LiminePtr(?*ModuleResponse) = init_pointer,
795 // Request revision 1
796 internal_module_count: u64 = 0,
797 internal_modules: LiminePtr(?[*]const *const InternalModule) =
798 if (config.no_pointers) 0 else null,
799};
800
801// RSDP
802
803const RsdpResponseV1 = extern struct {
804 revision: u64,
805 address: LiminePtr(*anyopaque),
806};
807
808const RsdpResponseV2 = extern struct {
809 revision: u64,
810 address: u64,
811};
812
813/// The response to the RSDP request. If the base revision is 1 or higher,
814/// the response will contain physical addresses to the RSDP, otherwise
815/// the response will contain virtual addresses to the RSDP.
816pub const RsdpResponse = if (config.api_revision >= 1)
817 RsdpResponseV2
818else
819 RsdpResponseV1;
820
821pub const RsdpRequest = extern struct {
822 id: [4]u64 = id(0xc5e77b6b397e7b43, 0x27637845accdcf3c),
823 revision: u64 = 0,
824 response: LiminePtr(?*RsdpResponse) = init_pointer,
825};
826
827// SMBIOS
828
829const SmBiosResponseV1 = extern struct {
830 revision: u64,
831 entry_32: LiminePtr(?*anyopaque),
832 entry_64: LiminePtr(?*anyopaque),
833};
834
835const SmBiosResponseV2 = extern struct {
836 revision: u64,
837 entry_32: u64,
838 entry_64: u64,
839};
840
841/// The response to the SMBIOS request. If the base revision is 3 or higher,
842/// the response will contain physical addresses to the SMBIOS entries, otherwise
843/// the response will contain virtual addresses to the SMBIOS entries.
844pub const SmBiosResponse = if (config.api_revision >= 1)
845 SmBiosResponseV2
846else
847 SmBiosResponseV1;
848
849pub const SmBiosRequest = extern struct {
850 id: [4]u64 = id(0x9e9046f11e095391, 0xaa4a520fefbde5ee),
851 revision: u64 = 0,
852 response: LiminePtr(?*SmBiosResponse) = init_pointer,
853};
854
855// EFI system table
856
857///
858const EfiSystemTableResponseV1 = extern struct {
859 revision: u64,
860 address: LiminePtr(?*std.os.uefi.tables.SystemTable),
861};
862
863const EfiSystemTableResponseV2 = extern struct {
864 revision: u64,
865 address: u64,
866};
867
868/// The response to the EFI system table request. If the base revision is 3
869/// or higher, the response will contain a physical address to the system table,
870/// otherwise the response will contain a virtual address to the system table.
871pub const EfiSystemTableResponse = if (config.api_revision >= 1)
872 EfiSystemTableResponseV2
873else
874 EfiSystemTableResponseV1;
875
876pub const EfiSystemTableRequest = extern struct {
877 id: [4]u64 = id(0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc),
878 revision: u64 = 0,
879 response: LiminePtr(?*EfiSystemTableResponse) = init_pointer,
880};
881
882// EFI memory map
883
884pub const EfiMemoryMapResponse = extern struct {
885 revision: u64,
886 memmap: LiminePtr(*anyopaque),
887 memmap_size: u64,
888 desc_size: u64,
889 desc_version: u64,
890};
891
892pub const EfiMemoryMapRequest = extern struct {
893 id: [4]u64 = id(0x7df62a431d6872d5, 0xa4fcdfb3e57306c8),
894 revision: u64 = 0,
895 response: LiminePtr(?*EfiMemoryMapResponse) = init_pointer,
896};
897
898// Date at boot (formerly Boot time)
899
900pub const DateAtBootFeature = if (config.api_revision >= 3) struct {
901 pub const DateAtBootResponse = extern struct {
902 revision: u64,
903 timestamp: i64,
904 };
905
906 pub const DateAtBootRequest = extern struct {
907 id: [4]u64 = id(0x502746e184c088aa, 0xfbc5ec83e6327893),
908 revision: u64 = 0,
909 response: LiminePtr(?*DateAtBootResponse) = init_pointer,
910 };
911} else BootTimeFeature;
912
913const BootTimeFeature = struct {
914 pub const BootTimeResponse = extern struct {
915 revision: u64,
916 boot_time: i64,
917 };
918
919 pub const BootTimeRequest = extern struct {
920 id: [4]u64 = id(0x502746e184c088aa, 0xfbc5ec83e6327893),
921 revision: u64 = 0,
922 response: LiminePtr(?*BootTimeResponse) = init_pointer,
923 };
924};
925
926// Executable address (formerly Kernel address)
927
928const ExecutableAddressFeature = if (config.api_revision >= 2) struct {
929 pub const ExecutableAddressResponse = extern struct {
930 revision: u64,
931 physical_base: u64,
932 virtual_base: u64,
933 };
934
935 pub const ExecutableAddressRequest = extern struct {
936 id: [4]u64 = id(0x71ba76863cc55f63, 0xb2644a48c516a487),
937 revision: u64 = 0,
938 response: LiminePtr(?*ExecutableAddressResponse) = init_pointer,
939 };
940} else KernelAddressFeature;
941
942const KernelAddressFeature = struct {
943 pub const KernelAddressResponse = extern struct {
944 revision: u64,
945 physical_base: u64,
946 virtual_base: u64,
947 };
948
949 pub const KernelAddressRequest = extern struct {
950 id: [4]u64 = id(0x71ba76863cc55f63, 0xb2644a48c516a487),
951 revision: u64 = 0,
952 response: LiminePtr(?*KernelAddressResponse) = init_pointer,
953 };
954};
955
956// Device Tree Blob
957
958pub const DtbResponse = extern struct {
959 revision: u64,
960 dtb_ptr: LiminePtr(*anyopaque),
961};
962
963pub const DtbRequest = extern struct {
964 id: [4]u64 = id(0xb40ddb48fb54bac7, 0x545081493f81ffb7),
965 revision: u64 = 0,
966 response: LiminePtr(?*DtbResponse) = init_pointer,
967};
968
969// RISC-V Boot Hart ID
970
971pub const RiscvBootHartIdResponse = extern struct {
972 revision: u64,
973 bsp_hartid: u64,
974};
975
976pub const RiscvBootHartIdRequest = extern struct {
977 id: [4]u64 = id(0x1369359f025525f9, 0x2ff2a56178391bb6),
978 revision: u64 = 0,
979 response: LiminePtr(?*RiscvBootHartIdResponse) = init_pointer,
980};
981
982comptime {
983 if (config.api_revision > 3) {
984 @compileError("Limine API revision must be 3 or lower");
985 }
986
987 std.testing.refAllDeclsRecursive(@This());
988}