From 7ecb31e60ca5cde8f7649414a0463ff70fbe2865 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko phcoder@gmail.com Date: Mon, 18 May 2015 19:07:16 +0200 Subject: [PATCH 2/2] Add multiboot support.
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules. Example:
menuentry "SeaBIOS (mb)" --unrestricted { root=ahci0,2 multiboot /bios.bin.elf module /vgabios_x230.rom name=pci8086,0166.rom }
the parameter name= specifies under which name SeaBIOS will see it.
Signed-off-by: Vladimir Serbinenko phcoder@gmail.com --- Makefile | 3 +- scripts/layoutrom.py | 16 +++- src/Kconfig | 7 ++ src/fw/coreboot.c | 2 + src/fw/multiboot.c | 114 ++++++++++++++++++++++ src/post.c | 1 + src/romlayout.S | 3 +- src/std/multiboot.h | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 1 + 9 files changed, 403 insertions(+), 4 deletions(-) create mode 100644 src/fw/multiboot.c create mode 100644 src/std/multiboot.h
diff --git a/Makefile b/Makefile index 3ee61af..f69f1f7 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,8 @@ SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c romfile.c x86.c optionroms.c \ hw/ahci.c hw/pvscsi.c hw/usb-xhci.c hw/usb-hub.c hw/sdcard.c \ fw/coreboot.c fw/lzmadecode.c fw/csm.c fw/biostables.c \ fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/smp.c fw/mtrr.c fw/xen.c \ - fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c + fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c \ + fw/multiboot.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc
diff --git a/scripts/layoutrom.py b/scripts/layoutrom.py index dd770fe..b793f33 100755 --- a/scripts/layoutrom.py +++ b/scripts/layoutrom.py @@ -356,7 +356,7 @@ def getRelocs(sections, tosection, type=None): and (type is None or reloc.type == type))]
# Output the linker scripts for all required sections. -def writeLinkerScripts(li, out16, out32seg, out32flat): +def writeLinkerScripts(li, out16, out32seg, out32flat, mb_section): # Write 16bit linker script filesections16 = getSectionsFileid(li.sections, '16') out = outXRefs(filesections16, useseg=1) + """ @@ -399,6 +399,11 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): filesections32flat = getSectionsFileid(li.sections, '32flat') out = outXRefs([], exportsyms=li.varlowsyms , forcedelta=li.final_sec32low_start-li.sec32low_start) + if mb_section is None: + mbstr = "" + else: + mbstr = "*(%s)" % mb_section + sec32all_start -= 12 out += outXRefs(filesections32flat, exportsyms=[li.entrysym]) + """ _reloc_min_align = 0x%x ; zonefseg_start = 0x%x ; @@ -415,6 +420,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): .text code32flat_start : { %s %s +%s code32flat_end = ABSOLUTE(.) ; } :text """ % (li.sec32init_align, @@ -428,6 +434,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): li.sec32init_start, li.sec32init_end, sec32all_start, + mbstr, relocstr, outRelSections(li.sections, 'code32flat_start')) out = COMMONHEADER + out + COMMONTRAILER + """ @@ -649,6 +656,11 @@ def main(): anchorsections = [entrysym.section] + [ section for section in allsections if section.name.startswith('.fixedaddr.')] + mb_header = symbols['32flat'].get('mb_head') + if mb_header is not None: + mb_section = mb_header.section.name + else: + mb_section = None keepsections = findReachable(anchorsections, checkKeep, symbols) sections = [section for section in allsections if section in keepsections]
@@ -685,7 +697,7 @@ def main(): li.entrysym = entrysym
# Write out linker script files. - writeLinkerScripts(li, out16, out32seg, out32flat) + writeLinkerScripts(li, out16, out32seg, out32flat, mb_section)
if __name__ == '__main__': main() diff --git a/src/Kconfig b/src/Kconfig index 45ca59c..385ce49 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -102,6 +102,13 @@ endchoice default y help Support floppy images in coreboot flash. + config MULTIBOOT + depends on COREBOOT + bool "multiboot support" + default y + help + Add multiboot header in bios.bin.raw and accept files supplied + as multiboot modules. config ENTRY_EXTRASTACK bool "Use internal stack for 16bit interrupt entry points" default y diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c index 8fd8449..ec09535 100644 --- a/src/fw/coreboot.c +++ b/src/fw/coreboot.c @@ -546,6 +546,8 @@ cbfs_payload_setup(void) break; struct cbfs_romfile_s *cfile; cfile = container_of(file, struct cbfs_romfile_s, file); + if (!cfile->fhdr) + continue; const char *filename = file->name; char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]); boot_add_cbfs(cfile->fhdr, desc, bootprio_find_named_rom(filename, 0)); diff --git a/src/fw/multiboot.c b/src/fw/multiboot.c new file mode 100644 index 0000000..7537c6a --- /dev/null +++ b/src/fw/multiboot.c @@ -0,0 +1,114 @@ +#include "block.h" // MAXDESCSIZE +#include "byteorder.h" // be32_to_cpu +#include "config.h" // CONFIG_* +#include "hw/pci.h" // pci_probe_devices +#include "lzmadecode.h" // LzmaDecode +#include "malloc.h" // free +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "paravirt.h" // PlatformRunningOn +#include "romfile.h" // romfile_findprefix +#include "stacks.h" // yield +#include "string.h" // memset +#include "util.h" // coreboot_preinit +#include "std/multiboot.h" + +struct mbfs_romfile_s { + struct romfile_s file; + void *data; +}; + +static int +extract_filename(char *dest, char *src, size_t lim) +{ + char *ptr; + for (ptr = src; *ptr; ptr++) { + if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t')) + continue; + /* memcmp stops early if it encounters \0 as it doesn't match name=. */ + if (memcmp(ptr, "name=", 5) == 0) { + int i; + char *optr = dest; + for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) { + *optr++ = *ptr++; + } + *optr++ = '\0'; + return 1; + } + } + return 0; +} + +// Copy a file to memory (uncompressing if necessary) +static int +mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) +{ + if (!CONFIG_COREBOOT_FLASH) + return -1; + + struct mbfs_romfile_s *cfile; + cfile = container_of(file, struct mbfs_romfile_s, file); + u32 size = cfile->file.size; + void *src = cfile->data; + + // Not compressed. + dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst); + if (size > maxlen) { + warn_noalloc(); + return -1; + } + iomemcpy(dst, src, size); + return size; +} + +u32 __VISIBLE entry_eax, entry_ebx; + +void +multiboot_init(void) +{ + struct multiboot_info *mbi; + if (!CONFIG_MULTIBOOT) + return; + dprintf (1, "multiboot: eax=%x, ebx=%x\n", entry_eax, entry_ebx); + if (entry_eax != MULTIBOOT_BOOTLOADER_MAGIC) + return; + mbi = (void *)entry_ebx; + dprintf (1, "mbptr=%p\n", mbi); + dprintf (1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr, + mbi->mods_count); + if (!(mbi->flags & MULTIBOOT_INFO_MODS)) + return; + int i; + struct multiboot_mod_list *mod = (void *)mbi->mods_addr; + for (i = 0; i < mbi->mods_count; i++) { + struct mbfs_romfile_s *cfile; + u8 *copy; + u32 len; + if (!mod[i].cmdline) + continue; + len = mod[i].mod_end - mod[i].mod_start; + cfile = malloc_tmp(sizeof(*cfile)); + memset(cfile, 0, sizeof(*cfile)); + dprintf (1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len); + if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline, + sizeof(cfile->file.name))) { + free (cfile); + continue; + } + dprintf (1, "assigned file name <%s>\n", cfile->file.name); + cfile->file.size = len; + copy = malloc_tmp (len); + memcpy(copy, (void *)mod[i].mod_start, len); + cfile->file.copy = mbfs_copyfile; + cfile->data = copy; + romfile_add(&cfile->file); + } +} + +#if CONFIG_MULTIBOOT +u32 __attribute__((aligned(4))) __VISIBLE mb_head[] = { + MULTIBOOT_HEADER_MAGIC, + 0, + -MULTIBOOT_HEADER_MAGIC +}; +#endif diff --git a/src/post.c b/src/post.c index 9ea5620..8d8d083 100644 --- a/src/post.c +++ b/src/post.c @@ -116,6 +116,7 @@ interface_init(void) // Setup romfile items. qemu_cfg_init(); coreboot_cbfs_init(); + multiboot_init();
// Setup ivt/bda/ebda ivt_init(); diff --git a/src/romlayout.S b/src/romlayout.S index 93b6874..9855f4f 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -13,7 +13,6 @@
.code16
- /**************************************************************** * 16bit / 32bit call trampolines ****************************************************************/ @@ -374,6 +373,8 @@ entry_bios32: entry_elf: cli cld + movl %eax, entry_eax + movl %ebx, entry_ebx lidtl (BUILD_BIOS_ADDR + pmode_IDT_info) lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48) movl $SEG32_MODE32_DS, %eax diff --git a/src/std/multiboot.h b/src/std/multiboot.h new file mode 100644 index 0000000..6c95127 --- /dev/null +++ b/src/std/multiboot.h @@ -0,0 +1,260 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the 'flags' member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the 'flags' member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/src/util.h b/src/util.h index 09bb8a9..7f75aa2 100644 --- a/src/util.h +++ b/src/util.h @@ -89,6 +89,7 @@ void coreboot_platform_setup(void); void cbfs_payload_setup(void); void coreboot_preinit(void); void coreboot_cbfs_init(void); +void multiboot_init(void); struct cb_header; void *find_cb_subtable(struct cb_header *cbh, u32 tag); struct cb_header *find_cb_table(void);
On Tue, May 19, 2015 at 08:53:05PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules.
Thanks. Are you okay with the patch below instead? In particular, are you okay with the copyright notice I added to multiboot.c?
The biggest change I made is to the way layoutrom.py places the multiboot header. The other changes are mostly minor (indentation, malloc checks, minor name changes).
BTW, is there anything that prevents seabios from overwriting the additional "module files" prior to it copying them?
-Kevin
From f6fea7e9fda4cce24eabfbc1cfea93501beefa29 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko phcoder@gmail.com Date: Mon, 18 May 2015 19:07:16 +0200 Subject: [PATCH] Add multiboot support.
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules. Example:
menuentry "SeaBIOS (mb)" --unrestricted { root=ahci0,2 multiboot /bios.bin.elf module /vgabios_x230.rom name=pci8086,0166.rom }
the parameter name= specifies under which name SeaBIOS will see it.
Signed-off-by: Vladimir Serbinenko phcoder@gmail.com Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- scripts/layoutrom.py | 8 ++ src/Kconfig | 7 ++ src/fw/multiboot.c | 111 ++++++++++++++++++++++ src/post.c | 1 + src/romlayout.S | 2 + src/std/multiboot.h | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 3 + 8 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 src/fw/multiboot.c create mode 100644 src/std/multiboot.h
diff --git a/Makefile b/Makefile index 3ee61af..0573c69 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ SRC16=$(SRCBOTH) SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c romfile.c x86.c optionroms.c \ pmm.c font.c boot.c bootsplash.c jpeg.c bmp.c \ hw/ahci.c hw/pvscsi.c hw/usb-xhci.c hw/usb-hub.c hw/sdcard.c \ - fw/coreboot.c fw/lzmadecode.c fw/csm.c fw/biostables.c \ + fw/coreboot.c fw/lzmadecode.c fw/multiboot.c fw/csm.c fw/biostables.c \ fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/smp.c fw/mtrr.c fw/xen.c \ fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c diff --git a/scripts/layoutrom.py b/scripts/layoutrom.py index dd770fe..b976fb0 100755 --- a/scripts/layoutrom.py +++ b/scripts/layoutrom.py @@ -161,6 +161,7 @@ def getSectionsPrefix(sections, prefix): # The sections (and associated information) to be placed in output rom class LayoutInfo: sections = None + config = None genreloc = None sec32init_start = sec32init_end = sec32init_align = None sec32low_start = sec32low_end = None @@ -172,6 +173,7 @@ class LayoutInfo: # Determine final memory addresses for sections def doLayout(sections, config, genreloc): li = LayoutInfo() + li.config = config li.sections = sections li.genreloc = genreloc # Determine 16bit positions @@ -399,6 +401,10 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): filesections32flat = getSectionsFileid(li.sections, '32flat') out = outXRefs([], exportsyms=li.varlowsyms , forcedelta=li.final_sec32low_start-li.sec32low_start) + multiboot_header = "" + if li.config.get('CONFIG_MULTIBOOT'): + multiboot_header = "LONG(0x1BADB002) LONG(0) LONG(-0x1BADB002)" + sec32all_start -= 3 * 4 out += outXRefs(filesections32flat, exportsyms=[li.entrysym]) + """ _reloc_min_align = 0x%x ; zonefseg_start = 0x%x ; @@ -415,6 +421,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): .text code32flat_start : { %s %s +%s code32flat_end = ABSOLUTE(.) ; } :text """ % (li.sec32init_align, @@ -428,6 +435,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): li.sec32init_start, li.sec32init_end, sec32all_start, + multiboot_header, relocstr, outRelSections(li.sections, 'code32flat_start')) out = COMMONHEADER + out + COMMONTRAILER + """ diff --git a/src/Kconfig b/src/Kconfig index 45ca59c..7be59a2 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -102,6 +102,13 @@ endchoice default y help Support floppy images in coreboot flash. + config MULTIBOOT + depends on COREBOOT + bool "multiboot support" + default y + help + Add multiboot header in bios.bin.raw and accept files supplied + as multiboot modules. config ENTRY_EXTRASTACK bool "Use internal stack for 16bit interrupt entry points" default y diff --git a/src/fw/multiboot.c b/src/fw/multiboot.c new file mode 100644 index 0000000..d9df067 --- /dev/null +++ b/src/fw/multiboot.c @@ -0,0 +1,111 @@ +// Multiboot interface support. +// +// Copyright (C) 2015 Vladimir Serbinenko phcoder@gmail.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // romfile_add +#include "std/multiboot.h" // MULTIBOOT_* +#include "string.h" // memset +#include "util.h" // multiboot_init + +struct mbfs_romfile_s { + struct romfile_s file; + void *data; +}; + +static int +extract_filename(char *dest, char *src, size_t lim) +{ + char *ptr; + for (ptr = src; *ptr; ptr++) { + if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t')) + continue; + /* memcmp stops early if it encounters \0 as it doesn't match name=. */ + if (memcmp(ptr, "name=", 5) == 0) { + int i; + char *optr = dest; + for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) { + *optr++ = *ptr++; + } + *optr++ = '\0'; + return 1; + } + } + return 0; +} + +// Copy a file to memory +static int +mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) +{ + struct mbfs_romfile_s *cfile; + cfile = container_of(file, struct mbfs_romfile_s, file); + u32 size = cfile->file.size; + void *src = cfile->data; + + // Not compressed. + dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst); + if (size > maxlen) { + warn_noalloc(); + return -1; + } + iomemcpy(dst, src, size); + return size; +} + +u32 __VISIBLE entry_elf_eax, entry_elf_ebx; + +void +multiboot_init(void) +{ + struct multiboot_info *mbi; + if (!CONFIG_MULTIBOOT) + return; + dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx); + if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC) + return; + mbi = (void *)entry_elf_ebx; + dprintf(1, "mbptr=%p\n", mbi); + dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr, + mbi->mods_count); + if (!(mbi->flags & MULTIBOOT_INFO_MODS)) + return; + int i; + struct multiboot_mod_list *mod = (void *)mbi->mods_addr; + for (i = 0; i < mbi->mods_count; i++) { + struct mbfs_romfile_s *cfile; + u8 *copy; + u32 len; + if (!mod[i].cmdline) + continue; + len = mod[i].mod_end - mod[i].mod_start; + cfile = malloc_tmp(sizeof(*cfile)); + if (!cfile) { + warn_noalloc(); + return; + } + memset(cfile, 0, sizeof(*cfile)); + dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len); + if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline, + sizeof(cfile->file.name))) { + free(cfile); + continue; + } + dprintf(1, "assigned file name <%s>\n", cfile->file.name); + cfile->file.size = len; + copy = malloc_tmp(len); + if (!copy) { + warn_noalloc(); + free(cfile); + return; + } + memcpy(copy, (void *)mod[i].mod_start, len); + cfile->file.copy = mbfs_copyfile; + cfile->data = copy; + romfile_add(&cfile->file); + } +} diff --git a/src/post.c b/src/post.c index 9ea5620..8d8d083 100644 --- a/src/post.c +++ b/src/post.c @@ -116,6 +116,7 @@ interface_init(void) // Setup romfile items. qemu_cfg_init(); coreboot_cbfs_init(); + multiboot_init();
// Setup ivt/bda/ebda ivt_init(); diff --git a/src/romlayout.S b/src/romlayout.S index 93b6874..7938e22 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -374,6 +374,8 @@ entry_bios32: entry_elf: cli cld + movl %eax, entry_elf_eax + movl %ebx, entry_elf_ebx lidtl (BUILD_BIOS_ADDR + pmode_IDT_info) lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48) movl $SEG32_MODE32_DS, %eax diff --git a/src/std/multiboot.h b/src/std/multiboot.h new file mode 100644 index 0000000..6c95127 --- /dev/null +++ b/src/std/multiboot.h @@ -0,0 +1,260 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the 'flags' member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the 'flags' member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/src/util.h b/src/util.h index 09bb8a9..6d8cc60 100644 --- a/src/util.h +++ b/src/util.h @@ -104,6 +104,9 @@ void mptable_setup(void); // fw/mtrr.c void mtrr_setup(void);
+// fw/multiboot.c +void multiboot_init(void); + // fw/pciinit.c extern const u8 pci_irqs[4]; void pci_setup(void);
On 21.05.2015 18:42, Kevin O'Connor wrote:
On Tue, May 19, 2015 at 08:53:05PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules.
Thanks. Are you okay with the patch below instead? In particular, are you okay with the copyright notice I added to multiboot.c?
Can we add "or later" clause? Otherwise looks fine and is tested
The biggest change I made is to the way layoutrom.py places the multiboot header. The other changes are mostly minor (indentation, malloc checks, minor name changes).
BTW, is there anything that prevents seabios from overwriting the additional "module files" prior to it copying them?
Looking at memory map document it seems that unlike what I've thought you do use memory at 1G. We probably need some code before malloc init to go through modules and find highest used address by modules. Is it ok if I do such adjustment?
-Kevin
From f6fea7e9fda4cce24eabfbc1cfea93501beefa29 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko phcoder@gmail.com Date: Mon, 18 May 2015 19:07:16 +0200 Subject: [PATCH] Add multiboot support.
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules. Example:
menuentry "SeaBIOS (mb)" --unrestricted { root=ahci0,2 multiboot /bios.bin.elf module /vgabios_x230.rom name=pci8086,0166.rom }
the parameter name= specifies under which name SeaBIOS will see it.
Signed-off-by: Vladimir Serbinenko phcoder@gmail.com Signed-off-by: Kevin O'Connor kevin@koconnor.net
Makefile | 2 +- scripts/layoutrom.py | 8 ++ src/Kconfig | 7 ++ src/fw/multiboot.c | 111 ++++++++++++++++++++++ src/post.c | 1 + src/romlayout.S | 2 + src/std/multiboot.h | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 3 + 8 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 src/fw/multiboot.c create mode 100644 src/std/multiboot.h
diff --git a/Makefile b/Makefile index 3ee61af..0573c69 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ SRC16=$(SRCBOTH) SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c romfile.c x86.c optionroms.c \ pmm.c font.c boot.c bootsplash.c jpeg.c bmp.c \ hw/ahci.c hw/pvscsi.c hw/usb-xhci.c hw/usb-hub.c hw/sdcard.c \
- fw/coreboot.c fw/lzmadecode.c fw/csm.c fw/biostables.c \
- fw/coreboot.c fw/lzmadecode.c fw/multiboot.c fw/csm.c fw/biostables.c \ fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/smp.c fw/mtrr.c fw/xen.c \ fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c
SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c diff --git a/scripts/layoutrom.py b/scripts/layoutrom.py index dd770fe..b976fb0 100755 --- a/scripts/layoutrom.py +++ b/scripts/layoutrom.py @@ -161,6 +161,7 @@ def getSectionsPrefix(sections, prefix): # The sections (and associated information) to be placed in output rom class LayoutInfo: sections = None
- config = None genreloc = None sec32init_start = sec32init_end = sec32init_align = None sec32low_start = sec32low_end = None
@@ -172,6 +173,7 @@ class LayoutInfo: # Determine final memory addresses for sections def doLayout(sections, config, genreloc): li = LayoutInfo()
- li.config = config li.sections = sections li.genreloc = genreloc # Determine 16bit positions
@@ -399,6 +401,10 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): filesections32flat = getSectionsFileid(li.sections, '32flat') out = outXRefs([], exportsyms=li.varlowsyms , forcedelta=li.final_sec32low_start-li.sec32low_start)
- multiboot_header = ""
- if li.config.get('CONFIG_MULTIBOOT'):
multiboot_header = "LONG(0x1BADB002) LONG(0) LONG(-0x1BADB002)"
out += outXRefs(filesections32flat, exportsyms=[li.entrysym]) + """ _reloc_min_align = 0x%x ; zonefseg_start = 0x%x ;sec32all_start -= 3 * 4
@@ -415,6 +421,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): .text code32flat_start : { %s %s +%s code32flat_end = ABSOLUTE(.) ; } :text """ % (li.sec32init_align, @@ -428,6 +435,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): li.sec32init_start, li.sec32init_end, sec32all_start,
out = COMMONHEADER + out + COMMONTRAILER + """multiboot_header, relocstr, outRelSections(li.sections, 'code32flat_start'))
diff --git a/src/Kconfig b/src/Kconfig index 45ca59c..7be59a2 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -102,6 +102,13 @@ endchoice default y help Support floppy images in coreboot flash.
- config MULTIBOOT
depends on COREBOOT
bool "multiboot support"
default y
help
Add multiboot header in bios.bin.raw and accept files supplied
config ENTRY_EXTRASTACK bool "Use internal stack for 16bit interrupt entry points" default yas multiboot modules.
diff --git a/src/fw/multiboot.c b/src/fw/multiboot.c new file mode 100644 index 0000000..d9df067 --- /dev/null +++ b/src/fw/multiboot.c @@ -0,0 +1,111 @@ +// Multiboot interface support. +// +// Copyright (C) 2015 Vladimir Serbinenko phcoder@gmail.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // romfile_add +#include "std/multiboot.h" // MULTIBOOT_* +#include "string.h" // memset +#include "util.h" // multiboot_init
+struct mbfs_romfile_s {
- struct romfile_s file;
- void *data;
+};
+static int +extract_filename(char *dest, char *src, size_t lim) +{
- char *ptr;
- for (ptr = src; *ptr; ptr++) {
if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t'))
continue;
/* memcmp stops early if it encounters \0 as it doesn't match name=. */
if (memcmp(ptr, "name=", 5) == 0) {
int i;
char *optr = dest;
for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) {
*optr++ = *ptr++;
}
*optr++ = '\0';
return 1;
}
- }
- return 0;
+}
+// Copy a file to memory +static int +mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) +{
- struct mbfs_romfile_s *cfile;
- cfile = container_of(file, struct mbfs_romfile_s, file);
- u32 size = cfile->file.size;
- void *src = cfile->data;
- // Not compressed.
- dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
- if (size > maxlen) {
warn_noalloc();
return -1;
- }
- iomemcpy(dst, src, size);
- return size;
+}
+u32 __VISIBLE entry_elf_eax, entry_elf_ebx;
+void +multiboot_init(void) +{
- struct multiboot_info *mbi;
- if (!CONFIG_MULTIBOOT)
return;
- dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx);
- if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC)
return;
- mbi = (void *)entry_elf_ebx;
- dprintf(1, "mbptr=%p\n", mbi);
- dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr,
mbi->mods_count);
- if (!(mbi->flags & MULTIBOOT_INFO_MODS))
return;
- int i;
- struct multiboot_mod_list *mod = (void *)mbi->mods_addr;
- for (i = 0; i < mbi->mods_count; i++) {
struct mbfs_romfile_s *cfile;
u8 *copy;
u32 len;
if (!mod[i].cmdline)
continue;
len = mod[i].mod_end - mod[i].mod_start;
cfile = malloc_tmp(sizeof(*cfile));
if (!cfile) {
warn_noalloc();
return;
}
memset(cfile, 0, sizeof(*cfile));
dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len);
if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline,
sizeof(cfile->file.name))) {
free(cfile);
continue;
}
dprintf(1, "assigned file name <%s>\n", cfile->file.name);
cfile->file.size = len;
copy = malloc_tmp(len);
if (!copy) {
warn_noalloc();
free(cfile);
return;
}
memcpy(copy, (void *)mod[i].mod_start, len);
cfile->file.copy = mbfs_copyfile;
cfile->data = copy;
romfile_add(&cfile->file);
- }
+} diff --git a/src/post.c b/src/post.c index 9ea5620..8d8d083 100644 --- a/src/post.c +++ b/src/post.c @@ -116,6 +116,7 @@ interface_init(void) // Setup romfile items. qemu_cfg_init(); coreboot_cbfs_init();
multiboot_init();
// Setup ivt/bda/ebda ivt_init();
diff --git a/src/romlayout.S b/src/romlayout.S index 93b6874..7938e22 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -374,6 +374,8 @@ entry_bios32: entry_elf: cli cld
movl %eax, entry_elf_eax
movl %ebx, entry_elf_ebx lidtl (BUILD_BIOS_ADDR + pmode_IDT_info) lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48) movl $SEG32_MODE32_DS, %eax
diff --git a/src/std/multiboot.h b/src/std/multiboot.h new file mode 100644 index 0000000..6c95127 --- /dev/null +++ b/src/std/multiboot.h @@ -0,0 +1,260 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
- DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
+#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1
+/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4
+/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000
+/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004
+/* Flags set in the 'flags' member of the multiboot header. */
+/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001
+/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002
+/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004
+/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+/* Flags to be set in the 'flags' member of the multiboot info structure. */
+/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008
+/* These next two are mutually exclusive */
+/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
+/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
+#ifndef ASM_FILE
+typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t;
+struct multiboot_header +{
- /* Must be MULTIBOOT_MAGIC - see above. */
- multiboot_uint32_t magic;
- /* Feature flags. */
- multiboot_uint32_t flags;
- /* The above fields plus this one must equal 0 mod 2^32. */
- multiboot_uint32_t checksum;
- /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
- multiboot_uint32_t header_addr;
- multiboot_uint32_t load_addr;
- multiboot_uint32_t load_end_addr;
- multiboot_uint32_t bss_end_addr;
- multiboot_uint32_t entry_addr;
- /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
- multiboot_uint32_t mode_type;
- multiboot_uint32_t width;
- multiboot_uint32_t height;
- multiboot_uint32_t depth;
+};
+/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{
- multiboot_uint32_t tabsize;
- multiboot_uint32_t strsize;
- multiboot_uint32_t addr;
- multiboot_uint32_t reserved;
+}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{
- multiboot_uint32_t num;
- multiboot_uint32_t size;
- multiboot_uint32_t addr;
- multiboot_uint32_t shndx;
+}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+struct multiboot_info +{
- /* Multiboot info version number */
- multiboot_uint32_t flags;
- /* Available memory from BIOS */
- multiboot_uint32_t mem_lower;
- multiboot_uint32_t mem_upper;
- /* "root" partition */
- multiboot_uint32_t boot_device;
- /* Kernel command line */
- multiboot_uint32_t cmdline;
- /* Boot-Module list */
- multiboot_uint32_t mods_count;
- multiboot_uint32_t mods_addr;
- union
- {
- multiboot_aout_symbol_table_t aout_sym;
- multiboot_elf_section_header_table_t elf_sec;
- } u;
- /* Memory Mapping buffer */
- multiboot_uint32_t mmap_length;
- multiboot_uint32_t mmap_addr;
- /* Drive Info buffer */
- multiboot_uint32_t drives_length;
- multiboot_uint32_t drives_addr;
- /* ROM configuration table */
- multiboot_uint32_t config_table;
- /* Boot Loader Name */
- multiboot_uint32_t boot_loader_name;
- /* APM table */
- multiboot_uint32_t apm_table;
- /* Video */
- multiboot_uint32_t vbe_control_info;
- multiboot_uint32_t vbe_mode_info;
- multiboot_uint16_t vbe_mode;
- multiboot_uint16_t vbe_interface_seg;
- multiboot_uint16_t vbe_interface_off;
- multiboot_uint16_t vbe_interface_len;
- multiboot_uint64_t framebuffer_addr;
- multiboot_uint32_t framebuffer_pitch;
- multiboot_uint32_t framebuffer_width;
- multiboot_uint32_t framebuffer_height;
- multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
- multiboot_uint8_t framebuffer_type;
- union
- {
- struct
- {
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
- };
- struct
- {
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
- };
- };
+}; +typedef struct multiboot_info multiboot_info_t;
+struct multiboot_color +{
- multiboot_uint8_t red;
- multiboot_uint8_t green;
- multiboot_uint8_t blue;
+};
+struct multiboot_mmap_entry +{
- multiboot_uint32_t size;
- multiboot_uint64_t addr;
- multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5
- multiboot_uint32_t type;
+} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+struct multiboot_mod_list +{
- /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
- multiboot_uint32_t mod_start;
- multiboot_uint32_t mod_end;
- /* Module command line */
- multiboot_uint32_t cmdline;
- /* padding to take it to 16 bytes (must be zero) */
- multiboot_uint32_t pad;
+}; +typedef struct multiboot_mod_list multiboot_module_t;
+#endif /* ! ASM_FILE */
+#endif /* ! MULTIBOOT_HEADER */ diff --git a/src/util.h b/src/util.h index 09bb8a9..6d8cc60 100644 --- a/src/util.h +++ b/src/util.h @@ -104,6 +104,9 @@ void mptable_setup(void); // fw/mtrr.c void mtrr_setup(void);
+// fw/multiboot.c +void multiboot_init(void);
// fw/pciinit.c extern const u8 pci_irqs[4]; void pci_setup(void);
On Thu, May 21, 2015 at 12:42:21PM -0400, Kevin O'Connor wrote:
On Tue, May 19, 2015 at 08:53:05PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
I've been successfully using SeaBIOS as secondary bootloader. In more details I have GRUB2-as-payload in flash together with coreboot. SeaBIOS binary is on the HDD and loaded by GRUB when needed. This has an unfortunate consequence that I have to keep vga oprom in flash even if usually I boot without it. This patches makes bios.bin.elf multiboot executable with files passed as modules.
Thanks. Are you okay with the patch below instead? In particular, are you okay with the copyright notice I added to multiboot.c?
FYI, I applied this patch - thanks.
-Kevin