From dbef9ff15d2270479bd484d23dcc9359e6336cfd Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sat, 7 Sep 2024 15:13:20 -0700 Subject: [PATCH] [platform][qemu-m68k] expand the bootinfo parsing code Break into a separate .c file. --- platform/qemu-virt-m68k/bootinfo.c | 91 ++++++++++++++++++++++++++++++ platform/qemu-virt-m68k/bootinfo.h | 64 +++++++++++++++++++++ platform/qemu-virt-m68k/platform.c | 49 +++++----------- platform/qemu-virt-m68k/rules.mk | 1 + 4 files changed, 170 insertions(+), 35 deletions(-) create mode 100644 platform/qemu-virt-m68k/bootinfo.c create mode 100644 platform/qemu-virt-m68k/bootinfo.h diff --git a/platform/qemu-virt-m68k/bootinfo.c b/platform/qemu-virt-m68k/bootinfo.c new file mode 100644 index 00000000..36b00ccf --- /dev/null +++ b/platform/qemu-virt-m68k/bootinfo.c @@ -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 +#include +#include +#include + +#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; + } +} + diff --git a/platform/qemu-virt-m68k/bootinfo.h b/platform/qemu-virt-m68k/bootinfo.h new file mode 100644 index 00000000..c426b625 --- /dev/null +++ b/platform/qemu-virt-m68k/bootinfo.h @@ -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 + +// 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; +}; \ No newline at end of file diff --git a/platform/qemu-virt-m68k/platform.c b/platform/qemu-virt-m68k/platform.c index bc1a78b2..405fb033 100644 --- a/platform/qemu-virt-m68k/platform.c +++ b/platform/qemu-virt-m68k/platform.c @@ -25,60 +25,39 @@ #include #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) { diff --git a/platform/qemu-virt-m68k/rules.mk b/platform/qemu-virt-m68k/rules.mk index b7a1f8e4..4298d4c8 100644 --- a/platform/qemu-virt-m68k/rules.mk +++ b/platform/qemu-virt-m68k/rules.mk @@ -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