Kyösti Mälkki has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/34066 )
Change subject: arch/x86: Add MULTIBOOT run-time info ......................................................................
arch/x86: Add MULTIBOOT run-time info
Change-Id: Ia14a49e37e308b05cde4dbadf0e4596bbebc9933 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M payloads/Kconfig M src/arch/x86/Makefile.inc M src/arch/x86/boot.c A src/arch/x86/multiboot.c M src/arch/x86/tables.c M src/commonlib/include/commonlib/cbmem_id.h M src/commonlib/include/commonlib/multiboot.h M src/lib/coreboot_table.c 8 files changed, 182 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/66/34066/1
diff --git a/payloads/Kconfig b/payloads/Kconfig index d0f8a44..a7a16ef 100644 --- a/payloads/Kconfig +++ b/payloads/Kconfig @@ -114,6 +114,15 @@ In order to reduce the size secondary payloads take up in the ROM chip they can be compressed using the LZMA algorithm.
+config MULTIBOOT_RUNTIME + bool "Fill MultiBoot runtime info for payload" + depends on ARCH_X86 + default n + +config MULTIBOOT_RUNTIME_CMDLINE + string "Commandline passed to payload in MultiBoot runtime info" + depends on MULTIBOOT_RUNTIME + menu "Secondary Payloads"
config COREINFO_SECONDARY_PAYLOAD diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index 025b933..290b7ed 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -312,6 +312,7 @@ ramstage-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c ramstage-$(CONFIG_ACPI_BERT) += acpi_bert_storage.c ramstage-y += boot.c +ramstage-y += multiboot.c ramstage-y += c_start.S ramstage-y += cbmem.c ramstage-y += cpu.c diff --git a/src/arch/x86/boot.c b/src/arch/x86/boot.c index 5f60f13..41a5eff 100644 --- a/src/arch/x86/boot.c +++ b/src/arch/x86/boot.c @@ -11,10 +11,13 @@ * GNU General Public License for more details. */
+#include <cbmem.h> #include <commonlib/helpers.h> +#include <commonlib/multiboot.h> #include <console/console.h> #include <program_loading.h> #include <ip_checksum.h> +#include <stdint.h> #include <symbols.h>
int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size) @@ -30,6 +33,18 @@
void arch_prog_run(struct prog *prog) { + uint32_t eax = 0, ebx = 0; + + if (ENV_PAYLOAD_LOADER && (prog_type(prog) == PROG_PAYLOAD)) { + if (CONFIG(MULTIBOOT_RUNTIME)) { + void *info = cbmem_find(CBMEM_ID_MULTIBOOT); + if (info) { + eax = MULTIBOOT_BOOTLOADER_MAGIC; + ebx = (uintptr_t)info; + } + } + } + __asm__ volatile ( #ifdef __x86_64__ "jmp *%%rdi\n" @@ -37,6 +52,6 @@ "jmp *%%edi\n" #endif
- :: "D"(prog_entry(prog)) + :: "D"(prog_entry(prog)), "a" (eax), "b" (ebx) ); } diff --git a/src/arch/x86/multiboot.c b/src/arch/x86/multiboot.c new file mode 100644 index 0000000..56822a4 --- /dev/null +++ b/src/arch/x86/multiboot.c @@ -0,0 +1,139 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <bootmem.h> +#include <cbmem.h> +#include <commonlib/helpers.h> +#include <commonlib/multiboot.h> +#include <memrange.h> +#include <string.h> + +#define MAX_MMAP_ENTRIES 32 +#define MAX_CMDLINE_LEN 100 + +/* Memory reserved for CBMEM may grow here, do this step early. */ +void alloc_multiboot_info(void) +{ + struct multiboot_info *info; + uintptr_t current, cmdline_offset, mmap_offset; + + current = sizeof(*info); + current = ALIGN_UP(current, 8); + + /* Static reserver for command line. */ + cmdline_offset = current; + current += MAX_CMDLINE_LEN; + current = ALIGN_UP(current, 8); + + /* Static reserve of mmap entries. */ + mmap_offset = current; + current += MAX_MMAP_ENTRIES * sizeof(struct mmap_entry); + current = ALIGN_UP(current, 8); + + info = cbmem_add(CBMEM_ID_MULTIBOOT, current); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->cmdline = (uintptr_t)(char *)info + cmdline_offset; + info->mmap_addr = (uintptr_t)(char *)info + mmap_offset; +} + +static bool add_mmap_entry(const struct range_entry *r, void *arg) +{ + struct multiboot_info *info = arg; + struct mmap_entry *m; + uintptr_t new_entry; + + if (info->mmap_length >= MAX_MMAP_ENTRIES * sizeof(*m)) + return false; + + new_entry = info->mmap_addr + info->mmap_length; + info->mmap_length += sizeof(*m); + + m = (void *)new_entry; + m->size = sizeof(*m) - sizeof(m->size); + m->addr = range_entry_base(r); + m->len = range_entry_size(r); + + /* Don't differentiate between unavailable ranges. */ + if (range_entry_tag(r) != BM_MEM_RAM) { + m->type = MULTIBOOT_MEMORY_RESERVED; + return true; + } + + m->type = MULTIBOOT_MEMORY_AVAILABLE; + + /* Range crossing or starting at 1 MiB boundary determines + * available upper memory. */ + if ((m->addr <= 1 * MiB) && (m->addr + m->len > 1 * MiB)) + info->mem_upper = (m->addr + m->len - 1 * MiB) / KiB; + + /* Specs says to report max 640 KiB of lower memory, + * report that if we have any memory at all. */ + info->mem_lower = 640; + + return true; +} + +static void fill_memory(struct multiboot_info *info) +{ + if (!info || !info->mmap_addr) + return; + + bootmem_walk_os_mem(add_mmap_entry, info); + + if (info->mem_lower || info->mem_upper) + info->flags |= MULTIBOOT_INFO_MEMORY; + + if (info->mmap_length) + info->flags |= MULTIBOOT_INFO_MEM_MAP; +} + +const char *__weak multiboot_runtime_cmdline(void) +{ + return CONFIG_MULTIBOOT_RUNTIME_CMDLINE; +} + +static void fill_cmdline(struct multiboot_info *info) +{ + const char *s; + size_t len; + + if (!info || !info->cmdline) + return; + + s = multiboot_runtime_cmdline(); + if (!s) + return; + + /* Do not allow partial lines. */ + len = strnlen(s, 2 * MAX_CMDLINE_LEN); + if (len >= MAX_CMDLINE_LEN) + return; + + memcpy((char *)(uintptr_t)info->cmdline, s, len); + info->flags |= MULTIBOOT_INFO_CMDLINE; +} + +void fill_multiboot_info(void) +{ + struct multiboot_info *info; + + info = cbmem_find(CBMEM_ID_MULTIBOOT); + if (!info) + return; + + fill_memory(info); + fill_cmdline(info); +} diff --git a/src/arch/x86/tables.c b/src/arch/x86/tables.c index 0baa58e..58f7fa3 100644 --- a/src/arch/x86/tables.c +++ b/src/arch/x86/tables.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */
+#include <commonlib/multiboot.h> #include <console/console.h> #include <bootmem.h> #include <bootstate.h> @@ -260,6 +261,10 @@ /* Align up to page boundary for historical consistency. */ forwarding_table = ALIGN_UP(forwarding_table, 4*KiB);
+ /* We need to do this before bootmem generation. */ + if (CONFIG(MULTIBOOT_RUNTIME)) + alloc_multiboot_info(); + /* Tell static analysis we know value is left unused. */ (void)rom_table_end; } diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h index 2236c95..ff21a13 100644 --- a/src/commonlib/include/commonlib/cbmem_id.h +++ b/src/commonlib/include/commonlib/cbmem_id.h @@ -45,6 +45,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_VAR_MRCDATA 0x4d524345 #define CBMEM_ID_MTC 0xcb31d31c +#define CBMEM_ID_MULTIBOOT 0x2badb002 #define CBMEM_ID_NONE 0x00000000 #define CBMEM_ID_PIRQ 0x49525154 #define CBMEM_ID_POWER_STATE 0x50535454 @@ -108,6 +109,7 @@ { CBMEM_ID_MRCDATA, "MRC DATA " }, \ { CBMEM_ID_VAR_MRCDATA, "VARMRC DATA" }, \ { CBMEM_ID_MTC, "MTC " }, \ + { CBMEM_ID_MULTIBOOT, "MULTIBOOT " }, \ { CBMEM_ID_PIRQ, "IRQ TABLE " }, \ { CBMEM_ID_POWER_STATE, "POWER STATE" }, \ { CBMEM_ID_RAM_OOPS, "RAMOOPS " }, \ diff --git a/src/commonlib/include/commonlib/multiboot.h b/src/commonlib/include/commonlib/multiboot.h index 2aae2ea..8f338e8 100644 --- a/src/commonlib/include/commonlib/multiboot.h +++ b/src/commonlib/include/commonlib/multiboot.h @@ -264,4 +264,8 @@ }; #endif
+void alloc_multiboot_info(void); +void fill_multiboot_info(void); +const char *multiboot_runtime_cmdline(void); + #endif /* ! MULTIBOOT_HEADER */ diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index df75698..fc42ef7 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -16,6 +16,7 @@ */
#include <arch/cbconfig.h> +#include <commonlib/multiboot.h> #include <console/console.h> #include <console/uart.h> #include <ip_checksum.h> @@ -599,6 +600,11 @@ /* Add all cbmem entries into the coreboot tables. */ cbmem_add_records_to_cbtable(head);
+ /* We need to do this before checksum is calculated. + * FIXME: Find better place for the call. */ + if (CONFIG(MULTIBOOT_RUNTIME)) + fill_multiboot_info(); + /* Remember where my valid memory ranges are */ return lb_table_fini(head); }