Pass a U-boot Environment Variable Though Kernel Command Line

From odroid US
Jump to: navigation, search

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

  • You MUST have access to the serial console -- use the USB/Serial adapter [check actual Hardkernel name]. This is the only way to drive u-boot console.

    Overview

    We are going to:

  • Set a u-boot environment variable
  • Create a new boot script that extracts the value of the variable and forwards it to Linux
  • See some example uses

    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_cookie 
    
    Now we can use the magic_cookie value programmatically.