fw_printenv 不显示来自 uboot.env 的环境变量

fw_printenv Not showing env variables from uboot.env

我正在开发 OrangePi Zero,试图让 fw_printenv 正常工作。到目前为止,我不知所措。预先感谢大家可能提供的任何帮助。

我运行在引导内核之前使用以下 u-boot 脚本:

fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs

test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "A B"
test -n "${BOOT_A_LEFT}" || setenv BOOT_A_LEFT 3
test -n "${BOOT_B_LEFT}" || setenv BOOT_B_LEFT 3
test -n "${BOOT_DEV}" || setenv BOOT_DEV "mmc 0:1"

setenv bootpart
setenv raucslot

for BOOT_SLOT in "${BOOT_ORDER}"; do
  if test "x${bootpart}" != "x"; then
    # skip remaining slots
  elif test "x${BOOT_SLOT}" = "xA"; then
    if test ${BOOT_A_LEFT} -gt 0; then
      setexpr BOOT_A_LEFT ${BOOT_A_LEFT} - 1
      echo "Found valid RAUC slot A"
      setenv bootpart "/dev/mmcblk0p2"
      setenv raucslot "A"
      setenv BOOT_DEV "mmc 0:2"
    fi
  elif test "x${BOOT_SLOT}" = "xB"; then
    if test ${BOOT_B_LEFT} -gt 0; then
      setexpr BOOT_B_LEFT ${BOOT_B_LEFT} - 1
      echo "Found valid RAUC slot B"
      setenv bootpart "/dev/mmcblk0p3"
      setenv raucslot "B"
      setenv BOOT_DEV "mmc 0:3"
    fi
  fi
done

setenv bootcmd_pxe ""

if test -n "${bootpart}"; then
  setenv bootargs console=${console} console=tty1 root=/dev/${rootdev} rootwait panic=10 ${extra}
  setenv bootargs "${bootargs} root=${bootpart} rauc.slot=${raucslot}"
  saveenv
else
  echo "No valid RAUC slot found. Resetting tries to 3"
  setenv BOOT_A_LEFT 3
  setenv BOOT_B_LEFT 3
  saveenv
  reset
fi

fatload mmc 0:1 ${kernel_addr_r} @@KERNEL_IMAGETYPE@@
if test ! -e mmc 0:1 uboot.env; then saveenv; fi;

load mmc 0:1 ${fdt_addr_r} ${fdtfile} || load mmc 0:1 ${fdt_addr_r} boot/${fdtfile}
load mmc 0:1 ${kernel_addr_r} zImage || load mmc 0:1 ${kernel_addr_r} boot/zImage || load mmc 0:1 ${kernel_addr_r} uImage || load mmc 0:1 ${kernel_addr_r} boot/uImage
bootz ${kernel_addr_r} - ${fdt_addr_r} || bootm ${kernel_addr_r} - ${fdt_addr_r}

此脚本在 运行 看来没有问题,它设置的环境变量已保存到 /boot/uboot.env。 /boot 分区在我的设备上是 mmcblk0p1。我的 uboot.env 文件如下所示:

root@orange-pi-zero:~# cat /boot/uboot.env 
�5�`BOOT_A_LEFT=3OOT_B_LEFT=3BOOT_DEV=mmc 0:2BOOT_ORDER=A Barch=armbaudrate=115200board=sunxiboard_name=sunxiboot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}boot_efi_binary=if fdt addr ${fdt_addr_r}; then bootefi bootmgr ${fdt_addr_r};else bootefi bootmgr ${fdtcontroladdr};fi;load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} efi/boot/bootarm.efi; if fdt addr ${fdt_addr_r}; then bootefi ${kernel_addr_r} ${fdt_addr_r};else bootefi ${kernel_addr_r} ${fdtcontroladdr};fiboot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}boot_net_usb_start=usb startboot_prefixes=/ /boot/boot_script_dhcp=boot.scr.uimgboot_scripts=boot.scr.uimg boot.scrboot_syslinux_conf=extlinux/extlinux.confboot_targets=fel mmc0 usb0 pxe dhcp bootargs=console=ttyS0,115200 console=tty1 root=/dev/ rootwait panic=10 root=/dev/mmcblk0p2 rauc.slot=Abootcmd=run distro_bootcmdbootcmd_dhcp=run boot_net_usb_start; if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; fi; setenv efi_old_vci ${bootp_vci};setenv efi_old_arch ${bootp_arch};setenv bootp_vci PXEClient:Arch:00010:UNDI:003000;setenv bootp_arch 0xa;if dhcp ${kernel_addr_r}; then tftpboot ${fdt_addr_r} dtb/${efi_fdtfile};if fdt addr ${fdt_addr_r}; then bootefi ${kernel_addr_r} ${fdt_addr_r}; else bootefi ${kernel_addr_r} ${fdtcontroladdr};fi;fi;setenv bootp_vci ${efi_old_vci};setenv bootp_arch ${efi_old_arch};setenv efi_fdtfile;setenv efi_old_arch;setenv efi_old_vci;bootcmd_fel=if test -n ${fel_booted} && test -n ${fel_scriptaddr}; then echo '(FEL boot)'; source ${fel_scriptaddr}; fibootcmd_mmc0=devnum=0; run mmc_bootbootcmd_pxe=bootcmd_usb0=devnum=0; run usb_bootbootdelay=2bootfstype=fatbootm_size=0xa000000bootpart=/dev/mmcblk0p2console=ttyS0,115200cpu=armv7devplist=1dfu_alt_info_ram=kernel ram 0x42000000 0x1000000;fdt ram 0x43000000 0x100000;ramdisk ram 0x43300000 0x4000000distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; doneefi_dtb_prefixes=/ /dtb/ /dtb/current/eth1addr=12:42:0f:ba:44:2eethaddr=02:42:0f:ba:44:2efdt_addr_r=0x43000000fdtcontroladdr=5bf59080fdtfile=sun8i-h2-plus-orangepi-zero.dtbfileaddr=43100000filesize=77ckernel_addr_r=0x42000000load_efi_dtb=load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${efi_fdtfile}mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fimmc_bootdev=0partitions=name=loader1,start=8k,size=32k,uuid=${uuid_gpt_loader1};name=loader2,size=984k,uuid=${uuid_gpt_loader2};name=esp,size=128M,bootable,uuid=${uuid_gpt_esp};name=system,size=-,uuid=${uuid_gpt_system};preboot=usb startpxefile_addr_r=0x43200000ramdisk_addr_r=0x43300000raucslot=Ascan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;run scan_dev_for_efi;scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done; setenv devplistscan_dev_for_efi=setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; fi; for prefix in ${efi_dtb_prefixes}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${efi_fdtfile}; then run load_efi_dtb; fi;done;if test -e ${devtype} ${devnum}:${distro_bootpart} efi/boot/bootarm.efi; then echo Found EFI removable media binary efi/boot/bootarm.efi; run boot_efi_binary; echo EFI LOAD FAILED: continuing...; fi; setenv efi_fdtfilescan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo SCRIPT FAILED: continuing...;��scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; donescriptaddr=0x43100000serial#=02c000420fba442esoc=sunxistderr=serialstdin=serial,usbkbdstdout=serialusb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fiuuid_gpt_esp=c12a7328-f81f-11d2-ba4b-00a0c93ec93buuid_gpt_system=69dad710-2ce4-4e3c-b16c-21a1d49abed3

考虑到这一点,当我 运行 fw_printenv 时返回以下内容:

root@orange-pi-zero:~# fw_printenv
BOOT_A_LEFT=3

奇怪的是,好像只输出了第一个变量。以下是 strace 的相关部分:

openat(AT_FDCWD, "/etc/fw_env.config", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=30, ...}) = 0
read(3, "/boot/uboot.env 0x0000 0x4000\n", 4096) = 30
lstat64("/boot", {st_mode=S_IFDIR|0755, st_size=16384, ...}) = 0
lstat64("/boot/uboot.env", {st_mode=S_IFREG|0755, st_size=131072, ...}) = 0
stat64("/boot/uboot.env", {st_mode=S_IFREG|0755, st_size=131072, ...}) = 0
openat(AT_FDCWD, "/boot/uboot.env", O_RDONLY) = 4
close(4)                                = 0
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/var/lock/fw_printenv.lock", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
flock(3, LOCK_EX)                       = 0
openat(AT_FDCWD, "/boot/uboot.env", O_RDONLY) = 4
read(4, "657`BOOT_A_LEFT=3[=15=][=15=]OOT_B_LEFT=3[=15=]"..., 16384) = 16384
close(4)                                = 0
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x4, 0x40), ...}) = 0
ioctl(1, TCGETS, {B115200 opost isig icanon echo ...}) = 0
write(1, "BOOT_A_LEFT=3\n", 14BOOT_A_LEFT=3
)         = 14
flock(3, LOCK_UN)                       = 0
close(3)                                = 0
exit_group(0)                           = ?

因此,根据该堆栈跟踪(并且因为它似乎读取了其中的第一个变量),它似乎可以毫无问题地找到我的 uboot.env 文件。至于为什么它好像看不懂其他的,我有点不知所措。

uboot.env 文件似乎在 BOOT_A_LEFT=3 值之后包含一个双 NUL 终止符:

read(4, "657`BOOT_A_LEFT=3[=10=][=10=]OOT_B_LEFT=3[=10=]"..., 16384) = 16384

我怀疑该文件可能已被覆盖一次或多次,并且您看到的是旧内容(奇怪命名的 OOT_B_LEFT 值及其后面的所有内容)和新内容(a单个 BOOT_A_LEFT 值)。

catfw_printenv 输出不同的原因是 cat 将打印整个文件的内容,而 fw_printenv 将停止打印变量遇到双 NUL 终止后,表示环境块结束。

所以,我找到了问题的关键。这似乎最终是由于在我的 fw_env.config 文件中使用了不正确的配置造成的。在我之前发布的内容中,它看起来如下:

/boot/uboot.env 0x0000 0x4000

然而,第二个值(0x4000)是指环境的大小。就我而言,在 OrangePi Zero 上,我的环境是 0x20000.

当我的 fw_env.config 看起来如下所示时,一切正常。

/boot/uboot.env 0x0000 0x20000