添加 niubi board
根据上一节,已知 -M help 代码执行在:
qemu-6.0.0/softmmu/vl.c : machine_parse
我们看看源码:
c
static MachineClass *machine_parse(const char *name, GSList *machines)
{
MachineClass *mc;
GSList *el;
if (is_help_option(name)) {
printf("Supported machines are:\n");
printf("yoooooo!!!\n");
machines = g_slist_sort(machines, machine_class_cmp);
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
if (mc->alias) {
printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name);
}
printf("%-20s %s%s%s\n", mc->name, mc->desc,
mc->is_default ? " (default)" : "",
mc->deprecation_reason ? " (deprecated)" : "");
}
exit(0);
}
mc = find_machine(name, machines);
if (!mc) {
error_report("unsupported machine type");
error_printf("Use -machine help to list supported machines\n");
exit(1);
}
return mc;
}
连蒙带猜,这个参数 name 应该就是跟在选项 -M 后边的东西。
is_help_option 就是判断 name == "help" 是否成立
如果成立,就打印 Supported machine list
不成立,找到 name 所指的机器,存到变量 mc 里,然后返回 mc (mc 类型是 MachineClass)
阅读源码,很容易发现 Supported machine list 是存放在第二个参数 machines 里的。
在上一节,我们知道调用 machine_parse 的调用栈是:
#0 machine_parse (machines=0x5555566143a0 = {...}, name=0x55555647fde0 "help") at ../softmmu/vl.c:1540
#1 select_machine () at ../softmmu/vl.c:1630
#2 qemu_init (argc=argc@entry=3, argv=argv@entry=0x7fffffffde28, envp=envp@entry=0x7fffffffde48) at ../softmmu/vl.c:3546
#3 0x000055555581044b in main (argc=3, argv=0x7fffffffde28, envp=0x7fffffffde48) at ../softmmu/main.c:50
往上追溯,看 vl.c : select_macine 函数:
c
static MachineClass *select_machine(void)
{
GSList *machines = object_class_get_list(TYPE_MACHINE, false);
...
会发现 machines 列表是 object_class_get_list 函数返回的。
深入下去看 object_class_get_list 的实现,会发现功能是 "遍历 QOM 全局注册的类型哈希表,把所有满足过滤条件的 ObjectClass 收集成一个单链表 GSList 返回"。
这个过滤参数就在参数上,TYPE_MACHINE 是类型过滤条件,false 表示不包含抽象类。
深入读下去,会发现包含各个板子硬件类型的 QOM 已经初始化好了。object_class_get_list 并没有初始化这些板子,而是把已经初始化完毕的 QOM 按照过滤条件收集起来,变成一个单链表返回。
说明板子硬件类型的 QOM 初始化发生在更早阶段。