diff --git a/Kernel/Arch/aarch64/RPi/Mailbox.cpp b/Kernel/Arch/aarch64/RPi/Mailbox.cpp index 237ed89c17..9ac0849591 100644 --- a/Kernel/Arch/aarch64/RPi/Mailbox.cpp +++ b/Kernel/Arch/aarch64/RPi/Mailbox.cpp @@ -130,4 +130,40 @@ u32 Mailbox::query_firmware_version() return message_queue.query_firmware_version.version; } +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface#get-command-line +// +// Note: This function is called very early in the boot process, before the heap or the console +// is initialized. Please ensure that it does the minimum amount of work possible. +StringView Mailbox::query_kernel_command_line(Bytes buffer) +{ + // We want to use the user-provided buffer rather than a fixed-size one on the stack, + // so we need to construct the message manually. + auto aligned_buffer = buffer.align_to(16); + if (aligned_buffer.size() < 24) + return ""sv; + + auto max_response_length = aligned_buffer.size() - 24; + + auto* message = reinterpret_cast(aligned_buffer.data()); + message[0] = aligned_buffer.size(); + message[1] = MBOX_REQUEST; + + message[2] = 0x0005'0001; // Query command line + message[3] = max_response_length; + message[4] = max_response_length; + + message[aligned_buffer.size() / sizeof(u32) - 1] = 0; + + if (!the().send_queue(message, aligned_buffer.size())) + return ""sv; + + // Bit 31 indicates that this is a response, the rest denote the length. + auto response_length = message[4] & 0x7fff'ffff; + + if (response_length > max_response_length) + return ""sv; // The buffer was too small to hold the response. + + return StringView { (char const*)&message[5], response_length }; +} + } diff --git a/Kernel/Arch/aarch64/RPi/Mailbox.h b/Kernel/Arch/aarch64/RPi/Mailbox.h index c1e67b6e17..658254d6c4 100644 --- a/Kernel/Arch/aarch64/RPi/Mailbox.h +++ b/Kernel/Arch/aarch64/RPi/Mailbox.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace Kernel::RPi { @@ -51,6 +52,9 @@ public: bool send_queue(void* queue, u32 queue_size) const; u32 query_firmware_version(); + + // Returns the kernel command line as a StringView into the given buffer. + StringView query_kernel_command_line(Bytes buffer); }; } diff --git a/Kernel/Arch/init.cpp b/Kernel/Arch/init.cpp index 883e450d7d..86f5fa082f 100644 --- a/Kernel/Arch/init.cpp +++ b/Kernel/Arch/init.cpp @@ -149,6 +149,10 @@ READONLY_AFTER_INIT u8 multiboot_framebuffer_type; Atomic g_boot_console; +#if ARCH(AARCH64) +READONLY_AFTER_INIT static u8 s_command_line_buffer[512]; +#endif + extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo const& boot_info) { g_in_early_boot = true; @@ -193,7 +197,8 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo con multiboot_module_entry_t modules[] = {}; multiboot_modules = modules; multiboot_modules_count = 0; - kernel_cmdline = ""sv; + // FIXME: Read the /chosen/bootargs property. + kernel_cmdline = RPi::Mailbox::the().query_kernel_command_line(s_command_line_buffer); #endif setup_serial_debug();