base: use mmio framework for multiboot handling

Issue #1741
This commit is contained in:
Alexander Boettcher 2015-10-27 14:25:46 +01:00 committed by Christian Helmuth
parent 6c1906e43e
commit 7ea5884ffc
7 changed files with 121 additions and 375 deletions

View File

@ -321,7 +321,7 @@ void Platform::_setup_irq_alloc() {
_irq_alloc.add_range(0, 0x10); }
void Platform::_setup_basics()
static Fiasco::l4_kernel_info_t *get_kip()
{
using namespace Fiasco;
@ -370,14 +370,22 @@ void Platform::_setup_basics()
printf(" root "); printf(" esp: %08lx eip: %08lx\n", kip->root_esp, kip->root_eip);
}
return kip;
}
void Platform::_setup_basics()
{
using namespace Fiasco;
l4_kernel_info_t * kip = get_kip();
/* add KIP as ROM module */
_kip_rom = Rom_module((addr_t)kip, L4_PAGESIZE, "l4v2_kip");
_rom_fs.insert(&_kip_rom);
/* update multi-boot info pointer from KIP */
void *mb_info_ptr = (void *)kip->user_ptr;
_mb_info = Multiboot_info(mb_info_ptr);
if (verbose) printf("MBI @ %p\n", mb_info_ptr);
addr_t mb_info_addr = kip->user_ptr;
if (verbose) printf("MBI @ 0x%lx\n", mb_info_addr);
/* parse memory descriptors - look for virtual memory configuration */
/* XXX we support only one VM region (here and also inside RM) */
@ -412,8 +420,8 @@ void Platform::_setup_basics()
/* remove KIP and MBI area from region and IO_MEM allocator */
remove_region(Region((addr_t)kip, (addr_t)kip + L4_PAGESIZE), _region_alloc);
remove_region(Region((addr_t)kip, (addr_t)kip + L4_PAGESIZE), _io_mem_alloc);
remove_region(Region((addr_t)mb_info_ptr, (addr_t)mb_info_ptr + _mb_info.size()), _region_alloc);
remove_region(Region((addr_t)mb_info_ptr, (addr_t)mb_info_ptr + _mb_info.size()), _io_mem_alloc);
remove_region(Region(mb_info_addr, mb_info_addr + _mb_info.size()), _region_alloc);
remove_region(Region(mb_info_addr, mb_info_addr + _mb_info.size()), _io_mem_alloc);
/* remove core program image memory from region and IO_MEM allocator */
addr_t img_start = (addr_t) &_prog_img_beg;
@ -459,7 +467,8 @@ void Platform::_setup_rom()
Platform::Platform() :
_ram_alloc(nullptr), _io_mem_alloc(core_mem_alloc()),
_io_port_alloc(core_mem_alloc()), _irq_alloc(core_mem_alloc()),
_region_alloc(core_mem_alloc())
_region_alloc(core_mem_alloc()),
_mb_info(get_kip()->user_ptr, true)
{
/*
* We must be single-threaded at this stage and so this is safe.

View File

@ -282,6 +282,10 @@ static Fiasco::l4_kernel_info_t *sigma0_map_kip()
return 0;
l4_addr_t ret = l4_trunc_page(l4_utcb_mr()->mr[0]);
if (!ret)
panic("kip mapping failed");
return (l4_kernel_info_t*) ret;
}
@ -352,8 +356,6 @@ void Platform::_setup_basics()
using namespace Fiasco;
kip = sigma0_map_kip();
if (!kip)
panic("kip mapping failed");
if (kip->magic != L4_KERNEL_INFO_MAGIC)
panic("Sigma0 mapped something but not the KIP");
@ -373,9 +375,8 @@ void Platform::_setup_basics()
_rom_fs.insert(&_kip_rom);
/* update multi-boot info pointer from KIP */
void *mb_info_ptr = (void *)kip->user_ptr;
_mb_info = Multiboot_info(mb_info_ptr);
if (verbose) printf("MBI @ %p\n", mb_info_ptr);
addr_t mb_info_addr = kip->user_ptr;
if (verbose) printf("MBI @ %lx\n", mb_info_addr);
/* parse memory descriptors - look for virtual memory configuration */
/* XXX we support only one VM region (here and also inside RM) */
@ -413,8 +414,8 @@ void Platform::_setup_basics()
/* remove KIP and MBI area from region and IO_MEM allocator */
remove_region(Region((addr_t)kip, (addr_t)kip + L4_PAGESIZE), _region_alloc);
remove_region(Region((addr_t)kip, (addr_t)kip + L4_PAGESIZE), _io_mem_alloc);
remove_region(Region((addr_t)mb_info_ptr, (addr_t)mb_info_ptr + _mb_info.size()), _region_alloc);
remove_region(Region((addr_t)mb_info_ptr, (addr_t)mb_info_ptr + _mb_info.size()), _io_mem_alloc);
remove_region(Region(mb_info_addr, mb_info_addr + _mb_info.size()), _region_alloc);
remove_region(Region(mb_info_addr, mb_info_addr + _mb_info.size()), _io_mem_alloc);
/* remove core program image memory from region and IO_MEM allocator */
addr_t img_start = (addr_t) &_prog_img_beg;
@ -468,6 +469,7 @@ Platform::Platform() :
_ram_alloc(nullptr), _io_mem_alloc(core_mem_alloc()),
_io_port_alloc(core_mem_alloc()), _irq_alloc(core_mem_alloc()),
_region_alloc(core_mem_alloc()), _cap_id_alloc(core_mem_alloc()),
_mb_info(sigma0_map_kip()->user_ptr, true),
_sigma0(cap_map()->insert(_cap_id_alloc.alloc(), Fiasco::L4_BASE_PAGER_CAP))
{
/*

View File

@ -35,12 +35,6 @@ static const bool verbose = false;
#define VPRINTF(fmt...) if (verbose) printf(fmt); else {}
void Multiboot_info::print_debug()
{
printf("TODO Multiboot_info does not support print_debug.");
}
unsigned Multiboot_info::num_modules()
{
using namespace Pistachio;
@ -48,8 +42,8 @@ unsigned Multiboot_info::num_modules()
unsigned int i = 0;
L4_Word_t entries;
L4_BootRec_t *rec;
for (entries = L4_BootInfo_Entries(_mb_info),
rec = L4_BootInfo_FirstEntry(_mb_info);
for (entries = L4_BootInfo_Entries(reinterpret_cast<void *>(Mmio::base)),
rec = L4_BootInfo_FirstEntry(reinterpret_cast<void *>(Mmio::base));
entries > 0;
entries--, rec = L4_Next(rec))
{
@ -71,8 +65,8 @@ Rom_module Multiboot_info::get_module(unsigned num)
unsigned int i = 0;
L4_Word_t entries;
L4_BootRec_t *rec;
for (entries = L4_BootInfo_Entries(_mb_info),
rec = L4_BootInfo_FirstEntry(_mb_info);
for (entries = L4_BootInfo_Entries(reinterpret_cast<void *>(Mmio::base)),
rec = L4_BootInfo_FirstEntry(reinterpret_cast<void *>(Mmio::base));
entries > 0;
entries--, rec = L4_Next(rec))
{
@ -116,47 +110,3 @@ Rom_module Multiboot_info::get_module(unsigned num)
Rom_module ret = Rom_module(start, size, name);
return ret;
}
bool Multiboot_info::check_module(unsigned num, addr_t *start, addr_t *end)
{
panic("TODO Who calls check_module?");
return false;
}
Multiboot_info::Multiboot_info(void *mb_info)
: _mb_info(mb_info)
{
using namespace Pistachio;
if (!L4_BootInfo_Valid(mb_info))
panic("Invalid BootInfo.");
/* some debug info, can probably be removed */
unsigned int i;
L4_Word_t entries;
L4_BootRec_t *rec;
for (entries = L4_BootInfo_Entries(mb_info),
rec = L4_BootInfo_FirstEntry(mb_info),
i = 0;
entries > 0;
entries--, i++, rec = L4_Next(rec)) {
VPRINTF("Entry[%d]\n", i);
switch (L4_Type(rec)) {
case L4_BootInfo_Module:
VPRINTF(" Type: Module\n");
VPRINTF(" Cmd : %s\n", L4_Module_Cmdline(rec));
break;
case L4_BootInfo_SimpleExec:
VPRINTF(" Type: SimpleExec (ignored)\n");
VPRINTF(" Cmd : %s\n", L4_SimpleExec_Cmdline(rec));
break;
case L4_BootInfo_EFITables:
VPRINTF(" Type: EFITables (ignored)\n"); break;
case L4_BootInfo_Multiboot:
VPRINTF(" Type: Multiboot (ignored)\n"); break;
}
}
}

View File

@ -466,15 +466,23 @@ void Platform::_setup_preemption()
}
void Platform::_setup_basics()
static Pistachio::L4_KernelInterfacePage_t *init_kip()
{
using namespace Pistachio;
/* completely map program image */
addr_t beg = trunc_page((addr_t)&_prog_img_beg);
addr_t end = round_page((addr_t)&_prog_img_end);
for ( ; beg < end; beg += get_page_size())
L4_Sigma0_GetPage(get_sigma0(), L4_Fpage(beg, get_page_size()));
for ( ; beg < end; beg += Pistachio::get_page_size())
L4_Sigma0_GetPage(get_sigma0(), L4_Fpage(beg, Pistachio::get_page_size()));
return get_kip();
}
void Platform::_setup_basics()
{
using namespace Pistachio;
/* store mapping base from received mapping */
L4_KernelInterfacePage_t *kip = get_kip();
@ -515,7 +523,6 @@ void Platform::_setup_basics()
/* done magic */
_mb_info = Multiboot_info(mb_info_ptr);
if (verbose) printf("MBI @ %p\n", mb_info_ptr);
/* get UTCB memory */
@ -627,7 +634,8 @@ Platform_pd *Platform::core_pd()
Platform::Platform() :
_ram_alloc(nullptr), _io_mem_alloc(core_mem_alloc()),
_io_port_alloc(core_mem_alloc()), _irq_alloc(core_mem_alloc()),
_region_alloc(core_mem_alloc())
_region_alloc(core_mem_alloc()),
_mb_info(init_kip()->BootInfo)
{
/*
* We must be single-threaded at this stage and so this is safe.

View File

@ -1,11 +1,12 @@
/**
* \brief GRUB multi-boot information handling
/*
* \brief Multiboot handling
* \author Christian Helmuth
* \author Alexander Boettcher
* \date 2006-05-09
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
* Copyright (C) 2006-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@ -14,56 +15,78 @@
#ifndef _CORE__INCLUDE__MULTIBOOT_H_
#define _CORE__INCLUDE__MULTIBOOT_H_
/* base includes */
#include <util/mmio.h>
/* core includes */
#include <rom_fs.h>
#include <base/stdint.h>
namespace Genode { class Multiboot_info; }
namespace Genode {
class Genode::Multiboot_info : Mmio
{
private:
class Multiboot_info
{
private:
struct Flags : Register<0x00, 32> {
struct Mem_map : Bitfield<6, 1> { };
};
struct Mods_count : Register<0x14, 32> { };
struct Mods_addr : Register<0x18, 32> { };
/* Location of MBI in memory */
void *_mb_info;
struct Mmap_length: Register<0x2c, 32> { };
struct Mmap_addr : Register<0x30, 32> { };
public:
public:
/** Standard constructor creates invalid object */
Multiboot_info() : _mb_info(0) { }
Multiboot_info(addr_t mbi) : Mmio(mbi) { }
Multiboot_info(addr_t mbi, bool strip);
Multiboot_info(void *mb_info);
struct Mmap : Genode::Mmio {
struct Size : Register <0x00, 32> { };
struct Addr : Register <0x04, 64> { };
struct Length : Register <0x0c, 64> { };
struct Type : Register <0x14, 8> {
struct Memory : Bitfield<0, 1> { };
struct Reserved : Bitfield<1, 1> { };
};
/**
* Number of boot modules
*/
unsigned num_modules();
Mmap(addr_t mmap = 0) : Mmio(mmap) { }
};
/**
* Use boot module num
*
* The module is marked as invalid in MBI and cannot be gotten again
*/
Rom_module get_module(unsigned num);
struct Mods : Genode::Mmio {
struct Start : Register <0x00, 32> { };
struct End : Register <0x04, 32> { };
struct Cmdline : Register <0x08, 32> { };
struct Padding : Register <0x0c, 32> { };
/**
* Read module info
*/
bool check_module(unsigned num, addr_t *start, addr_t *end);
Mods(addr_t mods) : Mmio(mods) { }
};
/**
* Debugging (may be removed later)
*/
void print_debug();
private:
/**
* Check validity
*/
bool valid() { return _mb_info ? true : false; }
Mods _get_mod(unsigned i) {
Genode::addr_t mods_addr = read<Mods_addr>();
/* Accessors */
size_t size() const { return 0x1000; }
};
}
enum { MODS_SIZE_OF = 16 };
return Mods(mods_addr + i * MODS_SIZE_OF);
}
public:
/**
* Number of boot modules
*/
unsigned num_modules();
/* Accessors */
size_t size() const { return 0x1000; }
/**
* Use boot module num
*
* The module is marked as invalid in MBI and cannot be gotten again
*/
Rom_module get_module(unsigned num);
};
#endif /* _CORE__INCLUDE__MULTIBOOT_H_ */

View File

@ -1,175 +0,0 @@
/**
* \brief Multiboot info structure as defined by GRUB
* \author Christian Helmuth
* \date 2006-05-09
*
* This is a stripped down version. Original code in
* l4/pkg/l4util/include/ARCH-x86/mb_info.h.
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _MB_INFO_H_
#define _MB_INFO_H_
#include <base/stdint.h>
/**
* Multi-boot module
*/
typedef struct
{
uint32_t mod_start; /* starting address of module in memory. */
uint32_t mod_end; /* end address of module in memory. */
uint32_t cmdline; /* module command line */
uint32_t pad; /* padding to take it to 16 bytes */
} mb_mod_t;
/** VBE controller information. */
typedef struct
{
uint8_t signature[4];
uint16_t version;
uint32_t oem_string;
uint32_t capabilities;
uint32_t video_mode;
uint16_t total_memory;
uint16_t oem_software_rev;
uint32_t oem_vendor_name;
uint32_t oem_product_name;
uint32_t oem_product_rev;
uint8_t reserved[222];
uint8_t oem_data[256];
} __attribute__((packed)) mb_vbe_ctrl_t;
/** VBE mode information. */
typedef struct
{
/* all VESA versions */
uint16_t mode_attributes;
uint8_t win_a_attributes;
uint8_t win_b_attributes;
uint16_t win_granularity;
uint16_t win_size;
uint16_t win_a_segment;
uint16_t win_b_segment;
uint32_t win_func;
uint16_t bytes_per_scanline;
/* >= VESA version 1.2 */
uint16_t x_resolution;
uint16_t y_resolution;
uint8_t x_char_size;
uint8_t y_char_size;
uint8_t number_of_planes;
uint8_t bits_per_pixel;
uint8_t number_of_banks;
uint8_t memory_model;
uint8_t bank_size;
uint8_t number_of_image_pages;
uint8_t reserved0;
/* direct color */
uint8_t red_mask_size;
uint8_t red_field_position;
uint8_t green_mask_size;
uint8_t green_field_position;
uint8_t blue_mask_size;
uint8_t blue_field_position;
uint8_t reserved_mask_size;
uint8_t reserved_field_position;
uint8_t direct_color_mode_info;
/* >= VESA version 2.0 */
uint32_t phys_base;
uint32_t reserved1;
uint16_t reversed2;
/* >= VESA version 3.0 */
uint16_t linear_bytes_per_scanline;
uint8_t banked_number_of_image_pages;
uint8_t linear_number_of_image_pages;
uint8_t linear_red_mask_size;
uint8_t linear_red_field_position;
uint8_t linear_green_mask_size;
uint8_t linear_green_field_position;
uint8_t linear_blue_mask_size;
uint8_t linear_blue_field_position;
uint8_t linear_reserved_mask_size;
uint8_t linear_reserved_field_position;
uint32_t max_pixel_clock;
uint8_t reserved3[189];
} __attribute__ ((packed)) mb_vbe_mode_t;
/**
* Multi-boot information
*/
typedef struct
{
uint32_t flags; /* MultiBoot info version number */
uint32_t mem_lower; /* available memory below 1MB */
uint32_t mem_upper; /* available memory starting from 1MB [kB] */
uint32_t boot_device; /* "root" partition */
uint32_t cmdline; /* Kernel command line */
uint32_t mods_count; /* number of modules */
uint32_t mods_addr; /* module list */
union
{
struct
{
/* (a.out) Kernel symbol table info */
uint32_t tabsize;
uint32_t strsize;
uint32_t addr;
uint32_t pad;
} a;
struct
{
/* (ELF) Kernel section header table */
uint32_t num;
uint32_t size;
uint32_t addr;
uint32_t shndx;
} e;
} syms;
uint32_t mmap_length; /* size of memory mapping buffer */
uint32_t mmap_addr; /* address of memory mapping buffer */
uint32_t drives_length; /* size of drive info buffer */
uint32_t drives_addr; /* address of driver info buffer */
uint32_t config_table; /* ROM configuration table */
uint32_t boot_loader_name; /* Boot Loader Name */
uint32_t apm_table; /* APM table */
uint32_t vbe_ctrl_info; /* VESA video contoller info */
uint32_t vbe_mode_info; /* VESA video mode info */
uint16_t vbe_mode; /* VESA video mode number */
uint16_t vbe_interface_seg; /* VESA segment of prot BIOS interface */
uint16_t vbe_interface_off; /* VESA offset of prot BIOS interface */
uint16_t vbe_interface_len; /* VESA lenght of prot BIOS interface */
} mb_info_t;
/**
* Flags to be set in the 'flags' parameter above
*/
/** is the command-line defined? */
#define MB_CMDLINE 0x00000004
/** Is there video information? */
#define MB_VIDEO_INFO 0x00000800
/** If we are multiboot-compliant, this value is present in the eax register */
#define MB_VALID 0x2BADB002
#endif

View File

@ -11,75 +11,23 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
#include <multiboot.h>
#include <util/misc_math.h>
using namespace Genode;
namespace Mb_info {
#include "mb_info.h"
}
static const bool verbose = false;
void Multiboot_info::print_debug()
{
Mb_info::mb_info_t *mbi = (Mb_info::mb_info_t *)_mb_info;
printf(" flags = %x %s\n", mbi->flags,
mbi->flags & MB_CMDLINE ? "CMDLINE" : "");
printf(" mem_lower = %xu\n", mbi->mem_lower);
printf(" mem_upper = %xu\n", mbi->mem_upper);
printf(" boot_device = %x\n", mbi->boot_device);
printf(" mods_count = %d\n", mbi->mods_count);
printf(" mods_addr = %xu\n", mbi->mods_addr);
unsigned i = 0;
Mb_info::mb_mod_t *mods = reinterpret_cast<Mb_info::mb_mod_t*>(mbi->mods_addr);
for (i = 0; i < mbi->mods_count; i++)
printf(" mod[%02d] [%xu,%xu) %s\n", i,
mods[i].mod_start, (mods[i].mod_end),
reinterpret_cast<char*>(mods[i].cmdline));
printf(" mmap_length = %x\n", mbi->mmap_length);
printf(" mmap_addr = %x\n", mbi->mmap_addr);
printf(" drives_length = %x\n", mbi->drives_length);
printf(" drives_addr = %x\n", mbi->drives_addr);
printf(" config_table = %x\n", mbi->config_table);
printf(" boot_loader_name = %x\n", mbi->boot_loader_name);
printf(" apm_table = %x\n", mbi->apm_table);
printf(" vbe_ctrl_info = %xu\n", mbi->vbe_ctrl_info);
printf(" vbe_mode_info = %xu\n", mbi->vbe_mode_info);
printf(" vbe_mode = %x\n", mbi->vbe_mode);
printf(" vbe_interface_seg = %x\n", mbi->vbe_interface_seg);
printf(" vbe_interface_off = %x\n", mbi->vbe_interface_off);
printf(" vbe_interface_len = %x\n", mbi->vbe_interface_len);
}
unsigned Multiboot_info::num_modules()
{
Mb_info::mb_info_t *mbi = (Mb_info::mb_info_t *)_mb_info;
return mbi->mods_count;
}
unsigned Multiboot_info::num_modules() { return read<Mods_count>(); }
Rom_module Multiboot_info::get_module(unsigned num)
{
Mb_info::mb_info_t *mbi = reinterpret_cast<Mb_info::mb_info_t*>(_mb_info);
Mb_info::mb_mod_t *mods = reinterpret_cast<Mb_info::mb_mod_t*>(mbi->mods_addr);
if (num >= num_modules()) return Rom_module();
/* num exceeds number of modules */
if (!(num < mbi->mods_count)) return Rom_module();
Mods mods = _get_mod(num);
char *cmdline = reinterpret_cast<char*>(mods.read<Mods::Cmdline>());
/* invalid module -- maybe returned earlier */
if (!mods[num].cmdline) return Rom_module();
char *cmdline = reinterpret_cast<char*>(mods[num].cmdline);
if (!cmdline) return Rom_module();
/* skip everything in front of the base name of the file */
for (unsigned i = 0; cmdline[i]; i++) {
@ -94,49 +42,30 @@ Rom_module Multiboot_info::get_module(unsigned num)
i = 0;
}
Rom_module ret = Rom_module(mods[num].mod_start,
mods[num].mod_end - mods[num].mod_start,
Rom_module ret = Rom_module(mods.read<Mods::Start>(),
mods.read<Mods::End>() - mods.read<Mods::Start>(),
cmdline);
/* mark module as invalid */
mods[num].cmdline = 0;
mods.write<Mods::Cmdline>(0);
return ret;
}
bool Multiboot_info::check_module(unsigned num, addr_t *start, addr_t *end)
{
Mb_info::mb_info_t *mbi = reinterpret_cast<Mb_info::mb_info_t*>(_mb_info);
Mb_info::mb_mod_t *mods = reinterpret_cast<Mb_info::mb_mod_t*>(mbi->mods_addr);
/* num exceeds number of modules */
if (!(num < mbi->mods_count)) return false;
*start = mods[num].mod_start;
*end = mods[num].mod_end;
return true;
}
/**
* Constructor
*/
Multiboot_info::Multiboot_info(void *mb_info)
: _mb_info(mb_info)
Multiboot_info::Multiboot_info(addr_t mbi, bool path_strip)
: Mmio(mbi)
{
Mb_info::mb_info_t *mbi = reinterpret_cast<Mb_info::mb_info_t*>(_mb_info);
Mb_info::mb_mod_t *mods = reinterpret_cast<Mb_info::mb_mod_t*>(mbi->mods_addr);
if (!path_strip)
return;
/* strip path and arguments from module name */
for (unsigned i = 0; i < mbi->mods_count; i++) {
char *cmdline = reinterpret_cast<char*>(mods[i].cmdline);
mods[i].cmdline = (addr_t)commandline_to_basename(cmdline);
}
if (verbose) {
printf("Multi-boot info with %d modules @ %p.\n",
mbi->mods_count, _mb_info);
print_debug();
for (unsigned i = 0; i < num_modules(); i++) {
Mods mods = _get_mod(i);
char *cmdline = reinterpret_cast<char*>(mods.read<Mods::Cmdline>());
mods.write<Mods::Cmdline>((addr_t)commandline_to_basename(cmdline));
}
}