Machine ID问题
问题背景
以前的一个旧产品需要升级SDK,包括loader、uboot、kernel、sdk等。
在升级kennel的时候遇到下面一个machine ID
的问题:
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Error: unrecognized/unsupported machine ID (r1 = 0x00000778).
Available machine support:
ID (hex) NAME
ffffffff VATICS vienna SoC (Flattened Device Tree)
Please check your kernel config and/or bootloader
解决
后面通过修改读取DTB的内存地址解决了,就是下面的0x1400000
。
CONFIG_BOOTCOMMAND bootcmd
#define CONFIG_BOOTCOMMAND_NET "tftp 0xa00000 zImage;tftp 0x3000000 rootfs;sf probe;sf read 0x1400000 0x60000 0x10000;bootz 0xa00000 - 0x1400000"
扩展
【引入 DTS 之前】:
过去,ARM Linux 针对不同的电路板会建立由 MACHINE_START 和 MACHINE_END包围起来的针对这个
machine 的一系列 callback,譬如:
MACHINE_START(VEXPRESS, "ARM-Versatile Express")
.atag_offset = 0x100,
.smp = smp_ops(vexpress_smp_ops),
.map_io = v2m_map_io,
.init_early = v2m_init_early,
.init_irq = v2m_init_irq,
.timer = &v2m_timer,
.handle_irq = gic_handle_irq,
.init_machine = v2m_init,
.restart = vexpress_restart,
MACHINE_END
```
这些不同的 machine 会有不同的 MACHINE ID,Uboot 在启动 Linux 内核时会将 MACHINE ID 存放在 r1寄存器,Linux 启动时会匹配 Bootloader 传递的 MACHINE ID 和 MACHINE_START 声明的 MACHINE ID,然后执行相应 machine 的一系列初始化函数。
【引入 DTS 之后】:
引入 Device Tree 之后,MACHINE_START 变更为DT_MACHINE_START,其中含有一个.dt_compat 成员,用于表明相关的 machine 与 .dts 中 root 结点的 compatible 属性兼容关系。如果 Bootloader 传递给内核的 Device Tree 中 root 结点的 compatible 属性出现在某 machine 的 .dt_compat 表中,相关的 machine就与对应的 Device Tree 匹配,从而引发这一 machine 的一系列初始化函数被执行。
static const char * const v2m_dt_match[] __initconst = {
"arm,vexpress",
"xen,xenvm",
NULL,
};
DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
.dt_compat = v2m_dt_match,
.smp = smp_ops(vexpress_smp_ops),
.map_io = v2m_dt_map_io,
.init_early = v2m_dt_init_early,
.init_irq = v2m_dt_init_irq,
.timer = &v2m_dt_timer,
.init_machine = v2m_dt_init,
.handle_irq = gic_handle_irq,
.restart = vexpress_restart,
MACHINE_END
Linux 倡导针对多个 SoC、多个电路板的通用 DT machine,即一个 DT machine 的 .dt_compat 表含多个电路板 .dts 文件的 root 结点 compatible 属性字符串。之后,如果的电路板的初始化序列不一样,可以透过`int of_machine_is_compatible(const char *compat)` API 判断具体的电路板是什么。
譬如 arch/arm/mach-exynos/mach-exynos5-dt.c 的 EXYNOS5_DT machine 同时兼容 "samsung,exynos5250"和 "samsung,exynos5440":
static char const *exynos5_dt_compat[] __initdata = {
"samsung,exynos5250",
"samsung,exynos5440",
NULL
};
DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
// Maintainer: Kukjin Kim <kgene.kim@samsung.com>
.init_irq = exynos5_init_irq,
.smp = smp_ops(exynos_smp_ops),
.map_io = exynos5_dt_map_io,
.handle_irq = gic_handle_irq,
.init_machine = exynos5_dt_machine_init,
.init_late = exynos_init_late,
.timer = &exynos4_timer,
.dt_compat = exynos5_dt_compat,
.restart = exynos5_restart,
.reserve = exynos5_reserve,
MACHINE_END
它的 .init_machine 成员函数就针对不同的 machine 进行了不同的分支处理:
static void __init exynos5_dt_machine_init(void)
{
…
if (of_machine_is_compatible("samsung,exynos5250"))
of_platform_populate(NULL, of_default_bus_match_table,
exynos5250_auxdata_lookup, NULL);
else if (of_machine_is_compatible("samsung,exynos5440"))
of_platform_populate(NULL, of_default_bus_match_table,
exynos5440_auxdata_lookup, NULL);
}
原文链接:[https://blog.csdn.net/wangjun7121/article/details/88133331](https://blog.csdn.net/wangjun7121/article/details/88133331)
评论