[U-Boot] [RFC PATCH] x86: Support booting SeaBIOS

Bin Meng bmeng.cn at gmail.com
Tue Sep 29 12:17:57 CEST 2015


SeaBIOS is an open source implementation of a 16-bit X86 BIOS.
It can run in an emulator or natively on X86 hardware with the
use of coreboot. With SeaBIOS's help, we can boot some OSes
that require 16-bit BIOS services like Windows/DOS.

As U-Boot, we have to manually create a table where SeaBIOS gets
system information (eg: E820) from. The table unfortunately has
to follow the coreboot table format as SeaBIOS currently supports
booting as a coreboot payload. No U-Boot native support there.

Booting SeaBIOS is done via U-Boot's bootelf command.

This is the initial attempt to support booting SeaBIOS from U-Boot.
If the basic concept is good, I can spend time working on follow-on
patches to enable BIOS tables as well as graphics support. One issue
is that U-Boot x86 does not has a ROM file system like coreboot.
This brings difficulities to pass PCI option ROM to SeaBIOS, if we
don't modify SeaBIOS's source codes. Maybe we should promote CBFS
in U-Boot x86?

This is tested on an Intel Crown Bay board with VGA card, booting
SeaBIOS then chain loading a GRUB on a USB drive, then Linux kernel
finally.

Signed-off-by: Bin Meng <bmeng.cn at gmail.com>

---

 arch/x86/Kconfig              | 10 ++++++++++
 arch/x86/include/asm/tables.h | 29 +++++++++++++++++++++++++++++
 arch/x86/lib/tables.c         | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5e42d7d..b432ff8 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -401,6 +401,16 @@ config PCIE_ECAM_SIZE
 	  so a default 0x10000000 size covers all of the 256 buses which is the
 	  maximum number of PCI buses as defined by the PCI specification.
 
+config SEABIOS
+	bool "Support booting SeaBIOS"
+	help
+	  SeaBIOS is an open source implementation of a 16-bit X86 BIOS.
+	  It can run in an emulator or natively on X86 hardware with the use
+	  of coreboot/U-Boot. By turning on this option, U-Boot prepares
+	  all the configuration tables that are necessary to boot SeaBIOS.
+
+	  Check http://www.seabios.org/SeaBIOS for details.
+
 source "arch/x86/lib/efi/Kconfig"
 
 endmenu
diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h
index 0aa6d9b..a083cac 100644
--- a/arch/x86/include/asm/tables.h
+++ b/arch/x86/include/asm/tables.h
@@ -7,6 +7,32 @@
 #ifndef _X86_TABLES_H_
 #define _X86_TABLES_H_
 
+#ifdef CONFIG_SEABIOS
+
+#define CB_TAG_MEMORY	1
+
+struct cb_header {
+	u8 signature[4];
+	u32 header_bytes;
+	u32 header_checksum;
+	u32 table_bytes;
+	u32 table_checksum;
+	u32 table_entries;
+};
+
+struct cb_memory_range {
+	u64 start;
+	u64 size;
+	u32 type;
+};
+
+struct cb_memory {
+	u32 tag;
+	u32 size;
+	struct cb_memory_range map[0];
+};
+#endif
+
 /*
  * All x86 tables happen to like the address range from 0xf0000 to 0x100000.
  * We use 0xf0000 as the starting address to store those tables, including
@@ -14,6 +40,9 @@
  */
 #define ROM_TABLE_ADDR	0xf0000
 
+/* SeaBIOS expects coreboot tables at address range 0x0000-0x1000 */
+#define CB_TABLE_ADDR	0x800
+
 /**
  * table_compute_checksum() - Compute a table checksum
  *
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index f15b2e2..5849b2f 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -9,6 +9,7 @@
 #include <asm/mpspec.h>
 #include <asm/tables.h>
 #include <asm/acpi_table.h>
+#include <asm/e820.h>
 
 u8 table_compute_checksum(void *v, int len)
 {
@@ -36,6 +37,41 @@ void table_fill_string(char *dest, const char *src, size_t n, char pad)
 		dest[i] = pad;
 }
 
+#ifdef CONFIG_SEABIOS
+static u32 write_cb_tables(u32 addr)
+{
+	struct cb_header *cbh = (struct cb_header *)addr;
+	struct cb_memory *mem;
+	struct cb_memory_range *map;
+	struct e820entry entry[32];
+	int num, i;
+
+	memset(cbh, 0, sizeof(struct cb_header));
+	strncpy((char *)cbh->signature, "LBIO", 4);
+	cbh->header_bytes = sizeof(struct cb_header);
+
+	/* populate memory map table */
+	mem = (struct cb_memory *)(cbh + 1);
+	mem->tag = CB_TAG_MEMORY;
+	map = mem->map;
+	num = install_e820_map(32, entry);
+	for (i = 0; i < num; i++) {
+		map->start = entry[i].addr;
+		map->size = entry[i].size;
+		map->type = entry[i].type;
+		map++;
+	}
+	mem->size = num * sizeof(struct cb_memory_range) + 8;
+
+	cbh->table_bytes = mem->size;
+	cbh->table_checksum = compute_ip_checksum(mem, cbh->table_bytes);
+	cbh->table_entries = 1;
+	cbh->header_checksum = compute_ip_checksum(cbh, cbh->header_bytes);
+
+	return (u32)map;
+}
+#endif
+
 void write_tables(void)
 {
 	u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR;
@@ -56,4 +92,7 @@ void write_tables(void)
 	rom_table_end = write_acpi_tables(rom_table_end);
 	rom_table_end = ALIGN(rom_table_end, 1024);
 #endif
+#ifdef CONFIG_SEABIOS
+	write_cb_tables(CB_TABLE_ADDR);
+#endif
 }
-- 
1.8.2.1



More information about the U-Boot mailing list