Linux下 修改访问uboot环境变量分区内容

关于Linux下 修改访问uboot环境变量分区内容补充!

时间:2018年03-21

背景:项目需要在Linux下也能修改flash分区中的env环境变量

一、引言

问:uboot下可以通过命令访问和修改环境变量,在Linux系统下该怎样访问这些数据?

答:用uboot提供的fw_printenv工具


二、该怎么做?

1、下载新版本的uboot,在uboot/tools/下可看见env/ 目录,里面存放的就是该工具的源码

2、编译fw_printenv工具

在uboot顶层目录下编译该工具: make CROSS_COMPILE=arm-linux- env

3、安装fw_printenv工具
  到/tools/env目录中,将编译好的fw_printenv拷贝到目标机的文件系统中/bin/,并通过"ln -s fw_printenv fw_setenv",创建一个fw_setenv到fw_printenv的软链接。

4、配置fw_env.config文件

    请将uboot/tools/env/fw_env.config文件拷贝到目标机的文件系统的/etc目录下。然后结合uboot配置中定义的ENV区和Linux下mtd分区的情况修改配置文件。具体的修改方法见fw_env.config文件中的说明及/tools/env/README文件。

    说明:在使用此工具时,需要注意fw_env.config很重要,如果配置不对,那么将出现错误!!因为我用的mmc卡,而不是传统的nand flash或norflash,因此在/tools/env/README中的说明对于我便有点出入,不太合适。为此,在认真阅读fw_printenv代码之后才发现原来是因为fw_env.config配置有点问题。下面给出对于mmc卡作为存储设备的,fw_env.config配置:

# Configuration file for fw_(printenv/setenv) utility.
# Up to two entries are valid, in this case the redundant
# environment sector is assumed present.
# Notice, that the "Number of sectors" is not required on NOR and SPI-dataflash.
# Futhermore, if the Flash sector size is ommitted, this value is assumed to
# be the same as the Environment size, which is valid for NOR and SPI-dataflash

# NOR example
# MTD device name       Device offset   Env. size       Flash sector size       Number of sectors
#/dev/mtd1              0x0000          0x4000          0x4000
#/dev/mtd2              0x0000          0x4000          0x4000

# MTD SPI-dataflash example
# MTD device name       Device offset   Env. size       Flash sector size       Number of sectors
#/dev/mtd5              0x4200          0x4200
#/dev/mtd6              0x4200          0x4200

# NAND example
#/dev/mtd0              0x4000          0x4000          0x20000                 2

# Block device example
# device name           env_offset      Env.bin_size    Env.bin_size    Env_partition_sectors        
/dev/mmcblk0            0x3000000       0x20000         0x20000         0x8000
请注意最后/dev/mmcblk0部分。


三、fw_printenv工具的使用

fw_printenv使用起来和uboot下的printenv和setenv指令是一模一样的。


四、问题补充!

1、在进行fw_printenv操作时,发现fw_printenv工具在读取env分区时,env分区的第一个uint32为env的crc32的校验码存放区间

2、fw_printenv在读取env分区时,如果env.cfg一开始有注释,如下图


那么其生成的env.bin在crc32校验码后面为0,此时fw_printenv在读env内容时,没有任何内容打印出来,这个是其工具代码没有做好,其原代码如下:

if (fw_env_open())
		return -1;

	if (argc == 1) {		/* Print all env variables  */
		for (env = environment.data; *env; env = nxt + 1) { //如果crc32校验码后面为0,那么*env会为0,则循环会直接退出
			for (nxt = env; *nxt; ++nxt) {                //所以就不会打印任何内容,解决办法是,找到0以后的位置,从那里开始
				if (nxt >= &environment.data[ENV_SIZE]) {//就可以了
					fprintf (stderr, "## Error: "
						"environment not terminated\n");
					return -1;
				}
			}

			printf ("%s\n", env);
		}
		return 0;
	}

替换代码:

if (argc == 1) {
		for(j=0,env = environment.data;!(*env);j++)
			env = environment.data + j;
		/* Print all env variables  */
		for (; *env; env = nxt + 1) {
			for (nxt = env; *nxt; ++nxt) {
				if (nxt >= &environment.data[ENV_SIZE]) {
					fprintf (stderr, "## Error: "
						"environment not terminated\n");
					return -1;
				}
			}
			printf ("%s\n", env);
		}
		return 0;
	}

3、fw_setenv 时提示Warning: Bad CRC, using default environment

这个就是配置文件没配好的结果。





### 如何在 U-Boot 中通过修改具体文件来配置 `bootcmd` 环境变量 为了在 U-Boot 中设置 `bootcmd` 环境变量,可以通过编辑特定的头文件实现这一目标。通常情况下,这些环境变量是在编译阶段被硬编码到 U-Boot 的二进制镜像中的。 #### 文件位置 对于大多数开发板而言,`bootcmd` 及其他环境变量的初始值通常是通过 `CFG_EXTRA_ENV_SETTINGS` 宏定义的。此宏一般位于与开发板对应的配置文件中,路径类似于 `/include/configs/` 下的相关 `.h` 文件[^3]。 例如,在 RK3399 平台上,该宏可能定义在以下文件中: ```c /include/configs/rk3399_common.h ``` #### 修改方法 以下是具体的修改方式: 1. **定位并打开配置文件** 找到对应开发板的配置文件(如上述提到的 `rk3399_common.h`),这是定义 `CFG_EXTRA_ENV_SETTINGS` 的地方。 2. **编辑 `CFG_EXTRA_ENV_SETTINGS` 宏** 在这个宏中添加或修改 `bootcmd` 的定义。例如,如果希望将 `bootcmd` 设置为执行某个脚本命令,则可以在宏中加入如下内容: ```c #define CFG_EXTRA_ENV_SETTINGS \ ENV_MEM_LAYOUT_SETTINGS \ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \ "partitions=" PARTS_DEFAULT "\0" \ "bootcmd=run load_image; run boot_from_mmc\0" \ ROCKCHIP_DEVICE_SETTINGS \ "boot_targets=" BOOT_TARGETS "\0" ``` 上述代码片段展示了如何重新定义 `bootcmd` 环境变量。这里将其设为运行两个子命令:`load_image` 和 `boot_from_mmc`。 3. **保存更改并重新编译** 编辑完成后,保存文件并重新构建 U-Boot 镜像。这一步骤会将新的环境变量嵌入到最终生成的固件中。 4. **验证效果** 将新生成的 U-Boot 映像烧录至设备后,进入 U-Boot 命令行界面并通过以下命令确认 `bootcmd` 是否已更新成功: ```bash printenv bootcmd ``` #### 注意事项 需要注意的是,虽然可以直接通过这种方式静态设定 `bootcmd`,但在某些场景下也可以动态调整它。例如,用户可通过串口或其他接口临时改变其值,或者利用外部工具写回闪存永久生效[^2]。 --- ### 示例代码 假设需要让 `bootcmd` 支持从 eMMC 启动,默认加载指定分区上的内核映像,可按如下形式编写: ```c #define CFG_EXTRA_ENV_SETTINGS \ ENV_MEM_LAYOUT_SETTINGS \ "bootcmd=mmc dev ${mmcdev}; mmc part; setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rw earlyprintk; fatload mmc ${mmcdev}:${mmcpart} ${kernel_addr_r} Image.gz-dtb; booti ${kernel_addr_r}\0" \ "bootargs=console=ttyS0,115200 rootwait panic=10\0" ``` 以上示例实现了自动检测 eMMC 设备、读取 FAT 分区内的压缩内核以及传递必要的引导参数给 Linux 内核的功能。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值