Command line 使用设备树时将内核参数从U-Boot传递到ARM Linux
我一直在研究一些嵌入式软件的变化,因为我们希望U-Boot能够将特定的命令行参数传递给内核,这些参数不一定事先就知道 这样内核就可以知道它是由哪个U-Boot分区启动的(我们有两个副本,一个在Command line 使用设备树时将内核参数从U-Boot传递到ARM Linux,command-line,parameters,linux-kernel,arm,u-boot,Command Line,Parameters,Linux Kernel,Arm,U Boot,我一直在研究一些嵌入式软件的变化,因为我们希望U-Boot能够将特定的命令行参数传递给内核,这些参数不一定事先就知道 这样内核就可以知道它是由哪个U-Boot分区启动的(我们有两个副本,一个在/dev/mmc3boot0和/dev/mmc3boot1中,它们都共享一个(冗余)环境空间,所以我们不能单独使用它来唯一地标识实例) 一种想法是简单地让每个U-Boot在启动时将其ID写入共享环境,但这有一个缺点,即目前有一些变体不这样做。因此,如果我们从一个有ID的启动,它将写入其ID,如果我们从一个没
/dev/mmc3boot0
和/dev/mmc3boot1
中,它们都共享一个(冗余)环境空间,所以我们不能单独使用它来唯一地标识实例)
一种想法是简单地让每个U-Boot在启动时将其ID写入共享环境,但这有一个缺点,即目前有一些变体不这样做。因此,如果我们从一个有ID的启动,它将写入其ID,如果我们从一个没有ID的启动,它将不会将ID更改回空白,如果我们依赖它,将导致错误的信息
这就是为什么我们想使用内核参数——因为老式的U-Boot实例从不提供ID,我们知道它在boot0
中运行。较新的样式将提供它们的实际ID,这样我们就可以搜索两个boot
分区,查看它在哪个分区中
为此,我修改了U-Boot,以便它设置ATAG来传递所需的额外参数。具体而言:
- 我在
中定义了arch\arm\include\asm\CONFIG.h
,以便调用CONFIG\u SYS\u BOOT\u GET\u CMDLINE
BOOT\u GET\u CMDLINE()
- 我修改了
函数,以便在附加正常参数之前设置特定参数。换句话说,我们现在得到的不是boot\u get\u cmdline()
,而是plugh=xyzy
uboot\u实例=42 plugh=xyzy
plugh=xyzy
在进一步的研究中,我们似乎遇到了调用内核的两种可能方式的冲突。其中一个是ATAGs,另一个是扁平设备树(FDT),它们似乎是互斥的(内核启动代码根据引用ATAGs或FDT结构的指针传入的签名选择一个或另一个)
所以我的问题是。假设设备树是您正在描述的设备的固定结构,那么当引导加载程序调用内核时,如何传递任意内核命令行参数(在运行时计算)?您可以在
include/configs/.h
中为平台使用虚拟环境变量
例如,假设您有以下(简化的)UBoot环境变量用于引导:
bootcmd=run mmcargs
run loadimage loadfdt
bootz ${loadaddr} - ${fdt_addr}
mmcargs=setenv bootargs blah=blah
这使用mmcargs
设置要使用的内核命令行。我们需要做的是以当前UBoot实例不提供任何内容而新实例提供实际ID的方式插入虚拟环境变量。这只需进行以下更改即可完成:
mmcargs=setenv bootargs ${uboot_id_stanza} blah=blah
然后,在板的初始化过程中,您可以使用env_set
API设置此变量,特别是通过在board/.c
中编写自己的自定义board_late_init
板初始化代码来设置此变量
以下行应放在board\u late\u init
函数的末尾:
setenv("uboot_id_stanza", "uboot_id=<uniqueId>");
setenv(“uboot_id_节”,“uboot_id=”);
通过这种方式,
uboot\u id
变量设置被添加到内核命令行中,但是,由于您没有执行saveenv
,因此它不会变得持久。每个UBoot实例都将设置正确的ID(包括未设置ID的旧实例)。您可以在include/configs/.h
中为平台使用虚拟环境变量
例如,假设您有以下(简化的)UBoot环境变量用于引导:
bootcmd=run mmcargs
run loadimage loadfdt
bootz ${loadaddr} - ${fdt_addr}
mmcargs=setenv bootargs blah=blah
这使用mmcargs
设置要使用的内核命令行。我们需要做的是以当前UBoot实例不提供任何内容而新实例提供实际ID的方式插入虚拟环境变量。这只需进行以下更改即可完成:
mmcargs=setenv bootargs ${uboot_id_stanza} blah=blah
然后,在板的初始化过程中,您可以使用env_set
API设置此变量,特别是通过在board/.c
中编写自己的自定义board_late_init
板初始化代码来设置此变量
以下行应放在board\u late\u init
函数的末尾:
setenv("uboot_id_stanza", "uboot_id=<uniqueId>");
setenv(“uboot_id_节”,“uboot_id=”);
通过这种方式,
uboot\u id
变量设置被添加到内核命令行中,但是,由于您没有执行saveenv
,因此它不会变得持久。每个UBoot实例都将设置正确的ID(包括未设置ID的旧实例)。@sawdust。问题实际上是共享环境,再加上我们将拥有传统U-Boots。我们可以让新样式的总是写他们的ID,但是,如果我们随后恢复到旧样式,它们中没有任何东西可以清除这些数据,因此这将是不准确的。我已经更新了问题,使之更清楚。使用一个单独的内核参数很简单,因为旧的样式将不提供任何东西,而新的样式将提供我们可以搜索的东西。最终我们可能不得不咬紧牙关,拒绝切换回旧式。您可以在include/configs/board.h
中为您的平台使用虚拟环境变量。例如,bootconf=“uboot\u instance=X”
作为默认值,并将其附加到bootargs中。在电路板初始化过程中,您可以使用env_set
API设置此变量,特别是通过在board/vendor/start_.c
中编写自己的自定义board_late_init
中的board init代码来设置此变量。这样,您就不需要ATAGS了。对不起,我的评论有误。