diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s index d3169e075..c9e2db091 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s @@ -18,11 +18,24 @@ .section ".text.crt0" - /* magic multi-boot header to make GRUB happy */ + /* magic multi-boot 1 header */ .long 0x1badb002 .long 0x0 .long 0xe4524ffe + .long 0x0 /* align to 8 byte for mbi2 */ + __mbi2_start: + /* magic multi-boot 2 header */ + .long 0xe85250d6 + .long 0x0 + .long (__mbi2_end - __mbi2_start) + .long -(0xe85250d6 + (__mbi2_end - __mbi2_start)) + /* end tag - type, flags, size */ + .word 0x0 + .word 0x0 + .long 0x8 + __mbi2_end: + /********************************** ** Startup code for primary CPU ** **********************************/ @@ -31,6 +44,9 @@ .global _start _start: + /* preserve multiboot magic value register, used below later */ + movl %eax, %esi + /** * zero-fill BSS segment */ @@ -91,6 +107,9 @@ leaq _stack_high@GOTPCREL(%rip),%rax movq (%rax), %rsp + movq __initial_ax@GOTPCREL(%rip),%rax + movq %rsi, (%rax) + movq __initial_bx@GOTPCREL(%rip),%rax movq %rbx, (%rax) @@ -113,6 +132,9 @@ .p2align 8 .space 32 * 1024 _stack_high: + .globl __initial_ax + __initial_ax: + .space 8 .globl __initial_bx __initial_bx: .space 8 diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h index 89e05c503..0b835a50c 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h +++ b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h @@ -33,6 +33,10 @@ class Genode::Multiboot_info : Mmio public: + enum { + MAGIC = 0x2badb002, + }; + Multiboot_info(addr_t mbi) : Mmio(mbi) { } Multiboot_info(addr_t mbi, bool strip); diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h new file mode 100644 index 000000000..01f72fdb8 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h @@ -0,0 +1,81 @@ +/* + * \brief Multiboot 2 handling + * \author Alexander Boettcher + * \date 2017-08-11 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT2_H_ +#define _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT2_H_ + +/* base includes */ +#include + +namespace Genode { class Multiboot2_info; } + +class Genode::Multiboot2_info : Mmio +{ + private: + + struct Size : Register <0x0, 32> { }; + + struct Tag : Genode::Mmio { + enum { LOG2_SIZE = 3 }; + + struct Type : Register <0x00, 32> { enum { END = 0, MEMORY = 6 }; }; + struct Size : Register <0x04, 32> { }; + + Tag(addr_t addr) : Mmio(addr) { } + }; + + public: + + enum { MAGIC = 0x36d76289UL }; + + struct Memory : Genode::Mmio { + enum { SIZE = 3 * 8 }; + + struct Addr : Register <0x00, 64> { }; + struct Size : Register <0x08, 64> { }; + struct Type : Register <0x10, 32> { enum { MEMORY = 1 }; }; + + Memory(addr_t mmap = 0) : Mmio(mmap) { } + }; + + Multiboot2_info(addr_t mbi) : Mmio(mbi) { } + + template + void for_each_mem(FUNC functor) + { + addr_t const size = read(); + + for (addr_t tag_addr = base() + (1UL << Tag::LOG2_SIZE); + tag_addr < base() + size;) + { + Tag tag(tag_addr); + + if (tag.read() == Tag::Type::END) + return; + + if (tag.read() == Tag::Type::MEMORY) { + addr_t mem_start = tag_addr + (1UL << Tag::LOG2_SIZE) + 8; + addr_t const mem_end = tag_addr + tag.read(); + + for (; mem_start < mem_end; mem_start += Memory::SIZE) { + Memory mem(mem_start); + functor(mem); + } + } + + tag_addr += align_addr(tag.read(), Tag::LOG2_SIZE); + } + } +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT2_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc index 61c300499..bd69b4333 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc @@ -16,9 +16,12 @@ #include #include #include +#include using namespace Genode; +/* contains Multiboot MAGIC value (either version 1 or 2) */ +extern "C" Genode::addr_t __initial_ax; /* contains physical pointer to multiboot */ extern "C" Genode::addr_t __initial_bx; @@ -31,15 +34,9 @@ Bootstrap::Platform::Board::Board() Memory_region { __initial_bx & ~0xFFFUL, get_page_size() }) { - using Mmap = Multiboot_info::Mmap; static constexpr size_t initial_map_max = 1024 * 1024 * 1024; - for (unsigned i = 0; true; i++) { - Mmap v(Multiboot_info(__initial_bx).phys_ram_mmap_base(i)); - if (!v.base()) break; - - Mmap::Addr::access_t base = v.read(); - Mmap::Length::access_t size = v.read(); + auto lambda = [&] (addr_t base, addr_t size) { /* * Exclude first physical page, so that it will become part of the @@ -52,17 +49,52 @@ Bootstrap::Platform::Board::Board() if (base >= initial_map_max) { late_ram_regions.add(Memory_region { base, size }); - continue; + return; } if (base + size <= initial_map_max) { early_ram_regions.add(Memory_region { base, size }); - continue; + return; } size_t low_size = initial_map_max - base; early_ram_regions.add(Memory_region { base, low_size }); late_ram_regions.add(Memory_region { initial_map_max, size - low_size }); + }; + + if (__initial_ax == Multiboot2_info::MAGIC) { + Multiboot2_info mbi2(__initial_bx); + + mbi2.for_each_mem([&] (Multiboot2_info::Memory const & m) { + uint32_t const type = m.read(); + + if (type != Multiboot2_info::Memory::Type::MEMORY) + return; + + uint64_t const base = m.read(); + uint64_t const size = m.read(); + + lambda(base, size); + }); + + return; + } + + if (__initial_ax != Multiboot_info::MAGIC) { + error("invalid multiboot magic value: ", Hex(__initial_ax)); + return; + } + + for (unsigned i = 0; true; i++) { + using Mmap = Multiboot_info::Mmap; + + Mmap v(Multiboot_info(__initial_bx).phys_ram_mmap_base(i)); + if (!v.base()) break; + + Mmap::Addr::access_t base = v.read(); + Mmap::Length::access_t size = v.read(); + + lambda(base, size); } } diff --git a/tool/run/boot_dir/hw b/tool/run/boot_dir/hw index 174c2943f..18fb7c743 100644 --- a/tool/run/boot_dir/hw +++ b/tool/run/boot_dir/hw @@ -119,6 +119,25 @@ proc run_boot_dir {binaries} { close $fh } + if {[have_include image/uefi]} { + exec mkdir -p [run_dir]/efi/boot + exec cp [genode_dir]/tool/boot/grub2_32.efi [run_dir]/efi/boot/bootia32.efi + exec cp [genode_dir]/tool/boot/grub2_64.efi [run_dir]/efi/boot/bootx64.efi + exec mkdir -p [run_dir]/boot/grub + exec cp [genode_dir]/tool/boot/bender [run_dir]/boot/bender + + # + # Generate GRUB2 config file + # + set fh [open "[run_dir]/boot/grub/grub.cfg" "WRONLY CREAT TRUNC"] + puts $fh "set timeout=0" + puts $fh "menuentry 'Genode on base-hw' {" + puts $fh " multiboot2 /boot/bender serial_fallback" + puts $fh " module2 /image.elf" + puts $fh "}" + close $fh + } + run_image [run_dir]/image.elf # set symbolic link to image.elf file in TFTP directory for PXE boot