Microkernel thing OS experiment (Zig ⚡)
at dev 28 kB view raw
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}