[platform][pc] move the multiboot header into generic space

Share the header with arch/x86 code
Clean up the use of the boot flags
Add code to print the framebuffer information, if present
This commit is contained in:
Travis Geiselbrecht
2022-08-07 23:04:23 -07:00
parent 8643334914
commit 62e2e7dba0
5 changed files with 165 additions and 104 deletions

View File

@@ -10,19 +10,7 @@
#include <lk/asm.h>
#include <arch/x86/descriptor.h>
#include <arch/x86/mmu.h>
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#if defined(__ELF__) && 0
#define MULTIBOOT_HEADER_FLAGS 0x00000002
#else
#define MULTIBOOT_HEADER_FLAGS 0x00010002
#endif
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#include <hw/multiboot.h>
#define PHYS_LOAD_ADDRESS (MEMBASE + KERNEL_LOAD_OFFSET)
#define PHYS_ADDR_DELTA (KERNEL_BASE + KERNEL_LOAD_OFFSET - PHYS_LOAD_ADDRESS)
@@ -35,6 +23,9 @@ _start:
.align 4
/* flags for multiboot header */
#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE)
.type multiboot_header,STT_OBJECT
multiboot_header:
/* magic */
@@ -44,7 +35,6 @@ multiboot_header:
/* checksum */
.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#if !defined(__ELF__) || 1
/* header_addr */
.int PHYS(multiboot_header)
/* load_addr */
@@ -55,7 +45,6 @@ multiboot_header:
.int PHYS(__bss_end)
/* entry_addr */
.int PHYS(real_start)
#endif
real_start:
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax

View File

@@ -10,19 +10,7 @@
#include <lk/asm.h>
#include <arch/x86/descriptor.h>
#include <arch/x86/mmu.h>
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#if defined(__ELF__) && 0
#define MULTIBOOT_HEADER_FLAGS 0x00000002
#else
#define MULTIBOOT_HEADER_FLAGS 0x00010002
#endif
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#include <hw/multiboot.h>
#define MSR_EFER 0xc0000080
#define EFER_LME 0x00000100
@@ -39,6 +27,9 @@ _start:
.align 8
/* flags for multiboot header */
#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE)
.type multiboot_header,STT_OBJECT
multiboot_header:
/* magic */
@@ -48,7 +39,6 @@ multiboot_header:
/* checksum */
.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#if !defined(__ELF__) || 1
/* header_addr */
.int PHYS(multiboot_header)
/* load_addr */
@@ -59,7 +49,6 @@ multiboot_header:
.int PHYS(__bss_end)
/* entry_addr */
.int PHYS(real_start)
#endif
real_start:
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax

View File

@@ -25,7 +25,7 @@ uint8_t _kstack[PAGE_SIZE] __ALIGNED(8);
/* save a pointer to the multiboot information coming in from whoever called us */
/* make sure it lives in .data to avoid it being wiped out by bss clearing */
__SECTION(".data") void *_multiboot_info;
__SECTION(".data") uint32_t _multiboot_info;
/* main tss */
static tss_t system_tss;

View File

@@ -7,23 +7,39 @@
*/
#pragma once
#include <sys/types.h>
/* from https://www.gnu.org/software/grub/manual/multiboot/multiboot.html */
/* magic number for multiboot header */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* flags for multiboot header */
#ifdef __ELF__
#define MULTIBOOT_HEADER_FLAGS 0x00000003
#else
#define MULTIBOOT_HEADER_FLAGS 0x00010003
#endif
/* magic number passed by multiboot-compliant boot loaders */
#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
#ifndef ASSEMBLY
#include <sys/types.h>
#include <assert.h>
/* multiboot header */
typedef struct multiboot_header {
uint32_t magic;
@@ -65,8 +81,46 @@ typedef struct multiboot_info {
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
uint32_t mmap_length;
uint32_t mmap_addr;
uint32_t drives_length;
uint32_t drives_addr;
uint32_t config_table;
uint32_t boot_loader_name;
uint32_t apm_table;
uint32_t vbe_control_info;
uint32_t vbe_mode_info;
uint16_t vbe_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
uint64_t framebuffer_addr;
uint32_t framebuffer_pitch;
uint32_t framebuffer_width;
uint32_t framebuffer_height;
uint8_t framebuffer_bpp;
uint8_t framebuffer_type;
union {
struct {
uint32_t framebuffer_palette_addr;
uint16_t framebuffer_palette_num_colors;
};
struct {
uint8_t framebuffer_red_field_position;
uint8_t framebuffer_red_mask_size;
uint8_t framebuffer_green_field_position;
uint8_t framebuffer_green_mask_size;
uint8_t framebuffer_blue_field_position;
uint8_t framebuffer_blue_mask_size;
};
};
} multiboot_info_t;
enum {
@@ -111,5 +165,12 @@ enum {
MB_MMAP_TYPE_BADRAM = 0x05,
};
#endif
/* framebuffer types */
enum {
MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED = 0,
MULTIBOOT_FRAMEBUFFER_TYPE_RGB = 1,
MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT = 2,
};
#endif // ASSEMBLY

View File

@@ -15,10 +15,10 @@
#include <platform.h>
#include "platform_p.h"
#include <platform/pc.h>
#include <platform/multiboot.h>
#include <platform/console.h>
#include <platform/keyboard.h>
#include <dev/uart.h>
#include <hw/multiboot.h>
#include <arch/x86.h>
#include <arch/mmu.h>
#include <malloc.h>
@@ -38,7 +38,7 @@
#define LOCAL_TRACE 0
/* multiboot information passed in, if present */
extern multiboot_info_t *_multiboot_info;
extern uint32_t _multiboot_info;
#define DEFAULT_MEMEND (16*1024*1024)
@@ -91,81 +91,102 @@ static pmm_arena_t mem_arena[NUM_ARENAS];
/* Walk through the multiboot structure and attempt to discover all of the runs
* of physical memory to bootstrap the pmm areas.
* Returns number of arenas initialized (or error).
* Returns number of arenas initialized in passed in pointer
*/
static int platform_parse_multiboot_info(void) {
int count = 0;
static status_t platform_parse_multiboot_info(size_t *found_mem_arenas) {
*found_mem_arenas = 0;
LTRACEF("_multiboot_info %p\n", _multiboot_info);
if (_multiboot_info) {
/* bump the multiboot pointer up to the kernel mapping */
_multiboot_info = (void *)((uintptr_t)_multiboot_info + KERNEL_BASE);
if (_multiboot_info->flags & MB_INFO_MEM_SIZE) {
LTRACEF("memory lower %#x\n", _multiboot_info->mem_lower * 1024U);
LTRACEF("memory upper %#" PRIx64"\n", _multiboot_info->mem_upper * 1024ULL);
}
dprintf(SPEW, "PC: multiboot address %#" PRIx32 "\n", _multiboot_info);
if (_multiboot_info == 0) {
return ERR_NOT_FOUND;
}
if (_multiboot_info->flags & MB_INFO_MMAP) {
memory_map_t *mmap = (memory_map_t *)(uintptr_t)_multiboot_info->mmap_addr;
mmap = (void *)((uintptr_t)mmap + KERNEL_BASE);
/* bump the multiboot pointer up to the kernel mapping */
/* TODO: test that it's within range of the kernel mapping */
const multiboot_info_t *multiboot_info = (void *)((uintptr_t)_multiboot_info + KERNEL_BASE);
LTRACEF("memory map, length %u:\n", _multiboot_info->mmap_length);
for (uint i = 0; i < _multiboot_info->mmap_length / sizeof(memory_map_t); i++) {
dprintf(SPEW, "\tflags %#x\n", multiboot_info->flags);
uint64_t base = mmap[i].base_addr_low | (uint64_t)mmap[i].base_addr_high << 32;
uint64_t length = mmap[i].length_low | (uint64_t)mmap[i].length_high << 32;
if (multiboot_info->flags & MB_INFO_MEM_SIZE) {
dprintf(SPEW, "PC: multiboot memory lower %#x upper %#" PRIx64 "\n",
multiboot_info->mem_lower * 1024U, multiboot_info->mem_upper * 1024ULL);
}
LTRACEF("\ttype %u addr %#" PRIx64 " len %#" PRIx64 "\n",
mmap[i].type, base, length);
if (mmap[i].type == MB_MMAP_TYPE_AVAILABLE) {
if (multiboot_info->flags & MB_INFO_MMAP) {
const memory_map_t *mmap = (const memory_map_t *)(uintptr_t)multiboot_info->mmap_addr;
mmap = (void *)((uintptr_t)mmap + KERNEL_BASE);
/* do some sanity checks to cut out small arenas */
if (length < PAGE_SIZE * 2) {
continue;
}
dprintf(SPEW, "PC: multiboot memory map, length %u:\n", multiboot_info->mmap_length);
for (uint i = 0; i < multiboot_info->mmap_length / sizeof(memory_map_t); i++) {
/* align the base and length */
uint64_t oldbase = base;
base = PAGE_ALIGN(base);
if (base > oldbase) {
length -= base - oldbase;
}
length = ROUNDDOWN(length, PAGE_SIZE);
uint64_t base = mmap[i].base_addr_low | (uint64_t)mmap[i].base_addr_high << 32;
uint64_t length = mmap[i].length_low | (uint64_t)mmap[i].length_high << 32;
/* ignore memory < 1MB */
if (base < 1*MB) {
/* skip everything < 1MB */
continue;
}
dprintf(SPEW, "\ttype %u addr %#" PRIx64 " len %#" PRIx64 "\n",
mmap[i].type, base, length);
if (mmap[i].type == MB_MMAP_TYPE_AVAILABLE) {
/* ignore everything that extends past max memory */
if (base >= MAX_PHYSICAL_RAM) {
continue;
}
uint64_t end = base + length;
if (end > MAX_PHYSICAL_RAM) {
end = MAX_PHYSICAL_RAM;
DEBUG_ASSERT(end > base);
length = end - base;
dprintf(INFO, "PC: trimmed memory to %" PRIu64 " bytes\n", MAX_PHYSICAL_RAM);
}
/* do some sanity checks to cut out small arenas */
if (length < PAGE_SIZE * 2) {
continue;
}
/* initialize a new pmm arena */
mem_arena[count].name = "memory";
mem_arena[count].base = base;
mem_arena[count].size = length;
mem_arena[count].priority = 1;
mem_arena[count].flags = PMM_ARENA_FLAG_KMAP;
count++;
if (count == countof(mem_arena)) {
break;
}
/* align the base and length */
uint64_t oldbase = base;
base = PAGE_ALIGN(base);
if (base > oldbase) {
length -= base - oldbase;
}
length = ROUNDDOWN(length, PAGE_SIZE);
/* ignore memory < 1MB */
if (base < 1*MB) {
/* skip everything < 1MB */
continue;
}
/* ignore everything that extends past max memory */
if (base >= MAX_PHYSICAL_RAM) {
continue;
}
uint64_t end = base + length;
if (end > MAX_PHYSICAL_RAM) {
end = MAX_PHYSICAL_RAM;
DEBUG_ASSERT(end > base);
length = end - base;
dprintf(INFO, "PC: trimmed memory to %" PRIu64 " bytes\n", MAX_PHYSICAL_RAM);
}
/* initialize a new pmm arena */
mem_arena[*found_mem_arenas].name = "memory";
mem_arena[*found_mem_arenas].base = base;
mem_arena[*found_mem_arenas].size = length;
mem_arena[*found_mem_arenas].priority = 1;
mem_arena[*found_mem_arenas].flags = PMM_ARENA_FLAG_KMAP;
(*found_mem_arenas)++;
if (*found_mem_arenas == countof(mem_arena)) {
break;
}
}
}
}
return count;
if (multiboot_info->flags & MB_INFO_FRAMEBUFFER) {
dprintf(SPEW, "PC: multiboot framebuffer info present\n");
dprintf(SPEW, "\taddress %#" PRIx64 " pitch %u width %u height %u bpp %hhu type %u\n",
multiboot_info->framebuffer_addr, multiboot_info->framebuffer_pitch,
multiboot_info->framebuffer_width, multiboot_info->framebuffer_height,
multiboot_info->framebuffer_bpp, multiboot_info->framebuffer_type);
if (multiboot_info->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
dprintf(SPEW, "\tcolor bit layout: R %u:%u G %u:%u B %u:%u\n",
multiboot_info->framebuffer_red_field_position, multiboot_info->framebuffer_red_mask_size,
multiboot_info->framebuffer_green_field_position, multiboot_info->framebuffer_green_mask_size,
multiboot_info->framebuffer_blue_field_position, multiboot_info->framebuffer_blue_mask_size);
}
}
return NO_ERROR;
}
void platform_early_init(void) {
@@ -182,7 +203,8 @@ void platform_early_init(void) {
platform_init_timer();
/* look at multiboot to determine our memory size */
int found_arenas = platform_parse_multiboot_info();
size_t found_arenas;
platform_parse_multiboot_info(&found_arenas);
if (found_arenas <= 0) {
/* if we couldn't find any memory, initialize a default arena */
mem_arena[0] = (pmm_arena_t){
@@ -196,11 +218,11 @@ void platform_early_init(void) {
printf("PC: WARNING failed to detect memory map from multiboot, using default\n");
}
DEBUG_ASSERT(found_arenas > 0 && found_arenas <= (int)countof(mem_arena));
DEBUG_ASSERT(found_arenas > 0 && found_arenas <= countof(mem_arena));
/* add the arenas we just set up to the pmm */
uint64_t total_mem = 0;
for (int i = 0; i < found_arenas; i++) {
for (size_t i = 0; i < found_arenas; i++) {
pmm_add_arena(&mem_arena[i]);
total_mem += mem_arena[i].size;
}