Machine ID问题

问题背景

以前的一个旧产品需要升级SDK,包括loader、uboot、kernel、sdk等。
在升级kennel的时候遇到下面一个machine ID的问题:

1
2
3
4
5
6
7
8
9
10
11
12
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

1
#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,譬如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	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              
1
2
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          
1
它的 .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

Donate comment here