[platform][qemu-m68k] expand the bootinfo parsing code
Break into a separate .c file.
This commit is contained in:
91
platform/qemu-virt-m68k/bootinfo.c
Normal file
91
platform/qemu-virt-m68k/bootinfo.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
64
platform/qemu-virt-m68k/bootinfo.h
Normal file
64
platform/qemu-virt-m68k/bootinfo.h
Normal 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;
|
||||
};
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user