hw: add UEFI boot support

via grub2 using multiboot 2

Issue #2242
This commit is contained in:
Alexander Boettcher 2017-02-02 14:25:06 +01:00 committed by Christian Helmuth
parent c2950e13eb
commit 972031cbbc
5 changed files with 168 additions and 10 deletions

View File

@ -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

View File

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

View File

@ -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 <util/mmio.h>
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 <typename FUNC>
void for_each_mem(FUNC functor)
{
addr_t const size = read<Multiboot2_info::Size>();
for (addr_t tag_addr = base() + (1UL << Tag::LOG2_SIZE);
tag_addr < base() + size;)
{
Tag tag(tag_addr);
if (tag.read<Tag::Type>() == Tag::Type::END)
return;
if (tag.read<Tag::Type>() == Tag::Type::MEMORY) {
addr_t mem_start = tag_addr + (1UL << Tag::LOG2_SIZE) + 8;
addr_t const mem_end = tag_addr + tag.read<Tag::Size>();
for (; mem_start < mem_end; mem_start += Memory::SIZE) {
Memory mem(mem_start);
functor(mem);
}
}
tag_addr += align_addr(tag.read<Tag::Size>(), Tag::LOG2_SIZE);
}
}
};
#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT2_H_ */

View File

@ -16,9 +16,12 @@
#include <bios_data_area.h>
#include <platform.h>
#include <multiboot.h>
#include <multiboot2.h>
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::Addr>();
Mmap::Length::access_t size = v.read<Mmap::Length>();
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<Multiboot2_info::Memory::Type>();
if (type != Multiboot2_info::Memory::Type::MEMORY)
return;
uint64_t const base = m.read<Multiboot2_info::Memory::Addr>();
uint64_t const size = m.read<Multiboot2_info::Memory::Size>();
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::Addr>();
Mmap::Length::access_t size = v.read<Mmap::Length>();
lambda(base, size);
}
}

View File

@ -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