[platform][qemu-m68k] expand the bootinfo parsing code

Break into a separate .c file.
This commit is contained in:
Travis Geiselbrecht
2024-09-07 15:13:20 -07:00
parent d9362e4dd5
commit dbef9ff15d
4 changed files with 170 additions and 35 deletions

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2024 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include "bootinfo.h"
#include <lk/compiler.h>
#include <lk/trace.h>
#include <lk/debug.h>
#include <stdio.h>
#define LOCAL_TRACE 0
extern uint8_t __bss_end;
static const char *bootinfo_tag_to_string(enum BOOTINFO_TAGS tag) {
switch (tag) {
case BOOTINFO_TAG_END: return "END";
case BOOTINFO_TAG_MACHTYPE: return "MACHTYPE";
case BOOTINFO_TAG_CPUTYPE: return "CPUTYPE";
case BOOTINFO_TAG_FPUTYPE: return "FPUTYPE";
case BOOTINFO_TAG_MMUTYPE: return "MMUTYPE";
case BOOTINFO_TAG_MEMCHUNK: return "MEMCHUNK";
case BOOTINFO_TAG_RAMDISK: return "RAMDISK";
case BOOTINFO_TAG_COMMAND_LINE: return "COMMAND_LINE";
case BOOTINFO_TAG_RNG_SEED: return "RNG_SEED";
case BOOTINFO_TAG_VIRT_QEMU_VERSION: return "VIRT_QEMU_VERSION";
case BOOTINFO_TAG_VIRT_GF_PIC_BASE: return "VIRT_GF_PIC_BASE";
case BOOTINFO_TAG_VIRT_GF_RTC_BASE: return "VIRT_GF_RTC_BASE";
case BOOTINFO_TAG_VIRT_GF_TTY_BASE: return "VIRT_GF_TTY_BASE";
case BOOTINFO_TAG_VIRT_VIRTIO_BASE: return "VIRT_VIRTIO_BASE";
case BOOTINFO_TAG_VIRT_CTRL_BASE: return "VIRT_CTRL_BASE";
default: return "UNKNOWN";
}
}
static void dump_bootinfo_record(const struct bootinfo_item *item) {
printf("item %p: tag %hx (%s), size %hu\n", item, item->tag, bootinfo_tag_to_string(item->tag), item->size);
if (item->size > 4) {
hexdump8(item->data, item->size - 4);
}
}
void dump_all_bootinfo_records(void) {
const uint8_t *ptr = &__bss_end;
printf("bootinfo records at %p:\n", ptr);
for (;;) {
const struct bootinfo_item *item = (const struct bootinfo_item *)ptr;
if (item->tag == BOOTINFO_TAG_END) {
break;
}
dump_bootinfo_record(item);
// move to the next field
ptr += item->size;
}
}
// look for tags that qemu left at the end of the kernel that hold various
// pieces of system configuration info.
const void *bootinfo_find_record(uint16_t id, uint16_t *size_out) {
const uint8_t *ptr = &__bss_end;
*size_out = 0;
for (;;) {
const struct bootinfo_item *item = (const struct bootinfo_item *)ptr;
if (item->tag == BOOTINFO_TAG_END) {
return NULL;
}
if (LOCAL_TRACE > 2) {
dump_bootinfo_record(item);
}
if (item->tag == id) {
*size_out = item->size - 4;
return item->data;
} else if (item->tag == 0) { // end token
return NULL;
}
// move to the next field
ptr += item->size;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2024 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#pragma once
#include <stdint.h>
// parse bootinfo
struct bootinfo_item {
uint16_t tag;
uint16_t size;
uint32_t data[0];
};
// bootinfo tags (from QEMU)
enum BOOTINFO_TAGS {
BOOTINFO_TAG_END = 0,
BOOTINFO_TAG_MACHTYPE = 1,
BOOTINFO_TAG_CPUTYPE = 2,
BOOTINFO_TAG_FPUTYPE = 3,
BOOTINFO_TAG_MMUTYPE = 4,
BOOTINFO_TAG_MEMCHUNK = 5,
BOOTINFO_TAG_RAMDISK = 6,
BOOTINFO_TAG_COMMAND_LINE = 7,
BOOTINFO_TAG_RNG_SEED = 8,
BOOTINFO_TAG_VIRT_QEMU_VERSION = 0x8000,
BOOTINFO_TAG_VIRT_GF_PIC_BASE = 0x8001,
BOOTINFO_TAG_VIRT_GF_RTC_BASE = 0x8002,
BOOTINFO_TAG_VIRT_GF_TTY_BASE = 0x8003,
BOOTINFO_TAG_VIRT_VIRTIO_BASE = 0x8004,
BOOTINFO_TAG_VIRT_CTRL_BASE = 0x8005,
};
void dump_all_bootinfo_records(void);
const void *bootinfo_find_record(uint16_t id, uint16_t *size_out);
// for BOOTINFO_TAG_*TYPE tags
struct bootinfo_item_type {
uint32_t type;
};
// for BOOTINFO_TAG_VIRT_QEMU_VERSION
struct bootinfo_item_qemu_version {
uint8_t major;
uint8_t minor;
uint8_t micro;
uint8_t unused__;
};
// for BOOTINFO_TAG_MEMCHUNK
struct bootinfo_item_memchunk {
uint32_t base;
uint32_t size;
};
// for VIRT_*_BASE tags
struct bootinfo_item_device {
uint32_t base;
uint32_t irq_base;
};

View File

@@ -25,60 +25,39 @@
#include <kernel/novm.h>
#endif
#include "bootinfo.h"
#include "platform_p.h"
#define LOCAL_TRACE 0
extern uint8_t __bss_end;
// parse bootinfo
struct bootinfo_item {
uint16_t tag;
uint16_t size;
uint32_t data[0];
};
// look for tags that qemu left at the end of the kernel that hold various
// pieces of system configuration info.
static void *bootinfo_find_record(uint16_t id, uint16_t *size_out) {
uint8_t *ptr = &__bss_end;
*size_out = 0;
for (;;) {
struct bootinfo_item *item = (struct bootinfo_item *)ptr;
LTRACEF_LEVEL(2, "item %p: tag %hx, size %hu\n", item, item->tag, item->size);
if (item->tag == id) {
*size_out = item->size - 4;
return item->data;
} else if (item->tag == 0) { // end token
return NULL;
}
// move to the next field
ptr += item->size;
}
}
void platform_early_init(void) {
goldfish_tty_early_init();
pic_early_init();
goldfish_rtc_early_init();
// Dump the bootinfo structure
if (LK_DEBUGLEVEL >= INFO) {
dump_all_bootinfo_records();
}
// look for tag 0x5, which describes the memory layout of the system
uint16_t size;
void *ptr = bootinfo_find_record(0x5, &size);
const void *ptr = bootinfo_find_record(BOOTINFO_TAG_MEMCHUNK, &size);
if (!ptr) {
panic("68K VIRT: unable to find MEMCHUNK BOOTINFO record\n");
}
if (size < 8) {
panic("68K VIRT: MEMCHUNK BOOTINFO record too small\n");
}
LTRACEF("MEMCHUNK ptr %p, size %hu\n", ptr, size);
uint32_t membase = *(uint32_t *)ptr;
uint32_t memsize = *(uint32_t *)((uintptr_t)ptr + 4);
uint32_t membase = *(const uint32_t *)ptr;
uint32_t memsize = *(const uint32_t *)((uintptr_t)ptr + 4);
dprintf(INFO, "VIRT: memory base %#x size %#x\n", membase, memsize);
novm_add_arena("mem", membase, memsize);
// TODO: read the rest of the device bootinfo records and dynamically locate devices
}
void platform_init(void) {

View File

@@ -11,6 +11,7 @@ MODULE_DEPS += dev/virtio/block
MODULE_DEPS += dev/virtio/gpu
MODULE_DEPS += dev/virtio/net
MODULE_SRCS += $(LOCAL_DIR)/bootinfo.c
MODULE_SRCS += $(LOCAL_DIR)/goldfish_rtc.c
MODULE_SRCS += $(LOCAL_DIR)/goldfish_tty.c
MODULE_SRCS += $(LOCAL_DIR)/pic.c