Kyösti Mälkki has uploaded this change for review.

View Change

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);
}

To view, visit change 34066. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ia14a49e37e308b05cde4dbadf0e4596bbebc9933
Gerrit-Change-Number: 34066
Gerrit-PatchSet: 1
Gerrit-Owner: Kyösti Mälkki <kyosti.malkki@gmail.com>
Gerrit-Reviewer: Kyösti Mälkki <kyosti.malkki@gmail.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange