參考資訊:
https://gitlab.com/qemu-project/qemu
hw/arm/f1c100s.c
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/datadir.h"
#include "qemu/units.h"
#include "qemu/f1c100s_log.h"
#include "hw/sysbus.h"
#include "hw/arm/boot.h"
#include "hw/ssi/ssi.h"
#include "hw/misc/unimp.h"
#include "hw/boards.h"
#include "hw/usb/hcd-ohci.h"
#include "hw/loader.h"
#include "hw/firmware/smbios.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "target/arm/cpu.h"
#define TYPE_F1C100S "f1c100s"
OBJECT_DECLARE_SIMPLE_TYPE(f1c100s_soc_state, F1C100S)
int f1c100s_debug_level = TRACE_LEVEL;
enum {
BOOTROM_BASE
};
struct f1c100s_soc_state {
DeviceState parent_obj;
ARMCPU cpu;
const hwaddr *memmap;
MemoryRegion bootrom;
};
static const hwaddr f1c100s_memmap[] = {
[BOOTROM_BASE] = 0xffff0000
};
static struct arm_boot_info f1c100s_binfo = { 0 };
static void f1c100s_soc_realize(DeviceState *dev, Error **errp)
{
f1c100s_soc_state *s = F1C100S(dev);
trace("call %s()\n", __func__);
qdev_realize(DEVICE(&s->cpu), NULL, errp);
}
static void f1c100s_soc_instance_init(Object *obj)
{
f1c100s_soc_state *s = F1C100S(obj);
trace("call %s()\n", __func__);
s->memmap = f1c100s_memmap;
object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("f1c100s"));
}
static void f1c100s_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
trace("call %s()\n", __func__);
dc->realize = f1c100s_soc_realize;
}
static const TypeInfo f1c100s_soc_type_info = {
.name = "f1c100s",
.parent = TYPE_DEVICE,
.instance_size = sizeof(f1c100s_soc_state),
.instance_init = f1c100s_soc_instance_init,
.class_init = f1c100s_soc_class_init,
};
static void f1c100s_soc_register_types(void)
{
trace("call %s()\n", __func__);
type_register_static(&f1c100s_soc_type_info);
}
type_init(f1c100s_soc_register_types)
static void f1c100s_soc_board_init(MachineState *machine)
{
f1c100s_soc_state *s = NULL;
trace("call %s()\n", __func__);
s = F1C100S(object_new(TYPE_F1C100S));
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
object_unref(OBJECT(s));
qdev_realize(DEVICE(s), NULL, &error_abort);
memory_region_init_rom(&s->bootrom, NULL, "f1c100s.bootrom", 64 * KiB, &error_fatal);
memory_region_add_subregion(get_system_memory(), s->memmap[BOOTROM_BASE], &s->bootrom);
char *fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
if (fname) {
trace("loading... \"%s\"\n", fname);
load_image_targphys(fname, s->memmap[BOOTROM_BASE], 64 * KiB);
g_free(fname);
f1c100s_binfo.entry = s->memmap[BOOTROM_BASE];
}
f1c100s_binfo.ram_size = machine->ram_size;
CPUARMState *env = &s->cpu.env;
env->boot_info = &f1c100s_binfo;
arm_load_kernel(&s->cpu, machine, &f1c100s_binfo);
};
static void f1c100s_soc_init(MachineClass *mc)
{
trace("call %s()\n", __func__);
mc->desc = "Allwinner F1C100S (ARM926EJ-S)";
mc->init = f1c100s_soc_board_init;
mc->min_cpus = 1;
mc->max_cpus = 1;
mc->default_cpus = 1;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("f1c100s");
mc->default_ram_size = 32 * MiB;
mc->default_ram_id = "f1c100s.ram";
};
DEFINE_MACHINE("f1c100s", f1c100s_soc_init)
編譯、測試
$ make -j4
$ ./build/qemu-system-arm -M f1c100s -bios main.bin
[TRACE] call f1c100s_soc_register_types()
[TRACE] call f1c100s_soc_init()
[TRACE] call f1c100s_soc_class_init()
[TRACE] call f1c100s_soc_board_init()
[TRACE] call f1c100s_soc_instance_init()
[TRACE] call f1c100s_soc_realize()
[TRACE] loading... "main.bin"