Pass a U-boot Environment Variable Though Kernel Command Line
Contents
Introduction
Sometimes it might come in handy to stash a parameter in the non-partitioned area and make use of it from user space. Normally the u-boot utilities fw_setenv and fw_getenv handle this. The problem is that we don't have u-boot source code and the enviroment location may still change -- making a hack risky. u-boot does checksum the variable values and if you just poked a value in, the checksum would fail and u-boot would revert to default environment values.
u-boot knows how to pass the boot arguments to the kernel. All we need to do is piggy-back on that. This works writing in u-boot and reading from user space -- but we still do not have a way to write from user space to the u-boot environment.
Prerequisites
Overview
We are going to:
Steps
Abort the boot in u-boot. You can hit a key while rebooting (easier) or while powering up (you have to be fast). This is the (current) u-boot prompt:
Exynos4412 #
Hint: you can cause u-boot to wait longer, but subsequent boots will take a bit longer and a window is open to where you could abort booting due to noise on the serial port. (optional step)
set bootdelay 3
We set our own u-boot environment variable and save it. It is stored on the SD Card in the non-partitioned space.
set magic_cookie 1 save
Boot to Linux with u-boot command, or you can power-cycle.
run bootcmd
Now, with Linux up. Make sure the boot partition is mounted.
test -d /boot || mkdir /boot mountpoint /boot >/dev/null || mount /dev/mmcblk0p1 /boot cd /boot
Take a look at our current boot script.
cat boot.txt
setenv initrd_high "0xffffffff" setenv fdt_high "0xffffffff" setenv bootcmd "fatload mmc 0:1 0x40008000 zImage; fatload mmc 0:1 0x42000000 uInitrd; bootm 0x40008000 0x42000000" setenv bootargs "console=tty1 console=ttySAC1,115200n8 root=/dev/mmcblk0p2 rootwait ro mem=2047M" boot
Insert some text and create a new boot script. You could do this with your favorite editor. We are just inserting the magic_cookie=${magic_cookie} text. The kernel commandline parameter will be magic_cookie and it will have the persistent value we set in u-boot. We have a new boot script called boot-magic_cookie.txt
cat boot.txt | sed -i s/root=/" magic_cookie=\${magic_cookie} root="/ > boot-magic_cookie.txt
Compile the new boot script
mkimage -T script -A arm -C none -n 'odroid-u2.Boot SD Card with a magic cookie' -d boot-magic_cookie.txt boot-magic_cookie.scr
Replace original boot script with the new one
cp boot.scr boot.scr.bak cp boot-magic_cookie.scr boot.scr sync
And reboot
reboot
Once Linux comes up, Look for our cookie:
cat /proc/cmdline
console=ttySAC1,115200n8 androidboot.console=ttySAC1 mem=2047M console=tty1 console=ttySAC1,115200n8 magic_cookie=1 root=/dev/mmcblk0p2 rootwait ro mem=2047M
See? magic_cookie comes through with the value we set in u-boot.
We can put it in our environment:
export magic_cookie=$(cat /proc/cmdline | awk -F"magic_cookie=" '{print $2}' | awk -F" " '{ print $1 }' )
Or put its value to a file:
cat /proc/cmdline | awk -F"magic_cookie=" '{print $2}' | awk -F" " '{ print $1 }' > /root/.magic_cookieNow we can use the magic_cookie value programmatically.