ARM Chromebook/U-Boot Environment

From Linux Exynos
Jump to: navigation, search

Contents

Introduction

Note by Wizzup: this document mostly applies to the Chrome OS u-boot. The load addresses are also off for peach boards.

In this guide we will discuss tweaking the U-Boot environment variables to customise the behaviour of U-Boot and have it do some fancy stuff for us. We will be mostly working in a file env.txt that ought to be written to the boot partition (it doesn't really matter that much, as long as the partition is accesible by U-Boot, i.e. as long as it is formatted as FAT32 or Ext2). Let's start off by telling U-Boot where to find the boot files and the root filesystem, and in addition to that the memory addresses where it should be loading the files to. The partition lay-out is assumed to be the following:

  • 1st partition: ChromeOS kernel partition with nv u-boot.
  • 2nd partition: boot partition with kernel images, flat device trees, etc.
  • 3rd partition: root partition with the root filesystem.

/boot/env.txt:

boot_part=2
root_part=3

loadaddr=0x42000000
dtaddr=0x43000000
scriptaddr=0x44000000
initrdaddr=0x45000000

Importing an environment

The first thing you'll want for testing purposes when using U-Boot is the ability to quickly load and test an environment from a file. The code below attempts to read env.txt from the boot partition, first assuming it has been formatted as FAT, then assuming it has been formatted as Ext2. If the file has been loaded successfully, it will be imported as a U-Boot environment. Furthermore, the import_env, import_sd_env and import_usb_env variables can be used to import an env.txt file from various storage devices (e.g. to import env.txt from a SD-card use: run import_sd_env).

/boot/env.txt:

env_path=/env.txt

load_env_txt=fatload ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${env_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${env_path}

import_env_txt=if run load_env_txt; then env import -t ${loadaddr} ${filesize} fi;

import_env=setenv dev_num 0; run mmc_setup; run load_env
import_sd_env=load_env=setenv dev_num 1; run mmc_setup; run load_env
import_usb_env=run usb_setup; run load_env

Booting a kernel

The following command will be used to boot from a given storage device. It will first attempt to boot a script image named boot.scr. If that fails, it will fall back to booting a kernel.

/boot/env.txt:

boot=run boot_script; run boot_kernel

Boot arguments

Before booting into the default kernel, the following commands will ensure that the boot arguments that are to be passed to the kernel have been set up properly.

/boot/env.txt:

common_bootargs=cros_legacy console=ttySAC3,115200 console=tty1 debug earlyprintk clk_ignore_unused
dev_extras=daisy

regen_bootargs=setenv bootargs ${common_bootargs} ${dev_extras} ${extra_bootargs} ${dev_bootargs}
regen_dev_bootargs=setenv dev_bootargs root=/dev/${dev_name}${root_part} rootwait ro; run regen_bootargs

Loading a default kernel

Similar to importing the environment, we'll have commands to load each of the files. These are then used to load the files, and to boot the kernel using the bootm command.

/boot/env.txt:

kernel_path=/uImage
initrd_path=/initrd
dtb_path=/exynos5250-snow.dtb

load_kernel=fatload ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${kernel_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${kernel_path}
load_initrd=fatload ${dev_type} ${dev_num}:${boot_part} ${initrdaddr} ${initrd_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${initrdaddr} ${initrd_path}
load_dtb=fatload ${dev_type} ${dev_num}:${boot_part} ${dtaddr} ${dtb_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${dtaddr} ${dtb_path}

boot_kernel=run regen_dev_bootargs; run load_kernel; run load_dtb; \
if run load_initrd; then bootm ${loadaddr} ${initrdaddr} ${dtaddr}; else bootm ${loadaddr} - ${dtaddr}; fi

Loading a boot script

There are times when the defaults just aren't good enough, and when you don't really want to fiddle with the environment variables. For that U-Boot offers the feature of sourcing boot scripts. The following commands will attempt to load boot.scr, which can be made using mkimage:

/boot/env.txt:

script_path=/boot.scr

load_script=fatload ${dev_type} ${dev_num}:${boot_part} ${scriptaddr} ${script_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${scriptaddr} ${script_path}

boot_script=if run load_script; then source ${scriptaddr} fi;

Changing the boot order

If the boot command has been invoked from the U-Boot shell, or if the amount of seconds specified in the bootdelay variable have been passed, U-Boot will proceed with booting. In order to do that it will run the commands in the bootcmd variable. We will be using that to configure the boot order. For instance, the code below will use the following boot order:

  1. USB-device.
  2. SD-card.
  3. SSD.

/boot/env.txt:

bootdelay=3
bootcmd=run usb_boot; run mmc1_boot; run mmc0_boot

Booting from MMC

The following commands can then be used to boot from a SD-card or from the SSD.

/boot/env.txt:

mmc_setup=mmc dev ${dev_num}; mmc rescan ${dev_num}; setenv dev_type mmc; setenv dev_name mmcblk${dev_num}p
mmc_boot=run mmc_setup; run boot
mmc0_boot=setenv dev_num 0; run mmc_boot
mmc1_boot=setenv dev_num 1; run mmc_boot

Booting from USB

The following commands can be used to boot from a USB-device.

/boot/env.txt:

usb_setup=usb start; setenv dev_type usb; setenv dev_num 0; setenv dev_name sda;
usb_boot=run usb_setup; run boot

Saving the environment

When you have finished editing env.txt, and once you have written nv u-boot to a partition, you can boot up the Chromebook. Whilst doing that interrupt the boot process by pressing any key, so that you will enter the U-Boot shell. There you can type the following commands to load the environment (from a SD-card):

mmc dev 1
mmc rescan
ext2load mmc 1:2 ${loadaddr} /env.txt
env import -t ${loadaddr} ${filesize}

Confirm that the environment is correct by printing it:

printenv

If everything is all right, you can save it to the Flash ROM:

saveenv

Result

/boot/env.txt:

boot_part=2
root_part=3

loadaddr=0x42000000
dtaddr=0x43000000
scriptaddr=0x44000000
initrdaddr=0x45000000

env_path=/env.txt
script_path=/boot.scr
kernel_path=/uImage
initrd_path=/initrd
dtb_path=/exynos5250-snow.dtb

common_bootargs=cros_legacy console=ttySAC3,115200 console=tty1 debug earlyprintk clk_ignore_unused
dev_extras=daisy

bootdelay=3
bootcmd=run usb_boot; run mmc1_boot; run mmc0_boot

load_env_txt=fatload ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${env_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${env_path}

import_env_txt=if run load_env_txt; then env import -t ${loadaddr} ${filesize} fi;

import_env=setenv dev_num 0; run mmc_setup; run load_env
import_sd_env=load_env=setenv dev_num 1; run mmc_setup; run load_env
import_usb_env=run usb_setup; run load_env

regen_all=setenv bootargs ${common_bootargs} ${dev_extras} ${extra_bootargs} ${dev_bootargs}
regen_bootargs=setenv dev_bootargs root=/dev/${dev_name}${root_part} rootwait ro; run regen_all

load_kernel=fatload ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${kernel_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${loadaddr} ${kernel_path}
load_initrd=fatload ${dev_type} ${dev_num}:${boot_part} ${initrdaddr} ${initrd_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${initrdaddr} ${initrd_path}
load_dtb=fatload ${dev_type} ${dev_num}:${boot_part} ${dtaddr} ${dtb_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${dtaddr} ${dtb_path}

boot_kernel=run regen_bootargs; run load_kernel; run load_dtb; if run load_initrd; then bootm ${loadaddr} ${initrdaddr} ${dtaddr}; else bootm ${loadaddr} - ${dtaddr}; fi

load_script=fatload ${dev_type} ${dev_num}:${boot_part} ${scriptaddr} ${script_path} || ext2load ${dev_type} ${dev_num}:${boot_part} ${scriptaddr} ${script_path}

boot_script=if run load_script; then source ${scriptaddr} fi;

boot=run boot_script; run boot_kernel

mmc_setup=mmc dev ${dev_num}; mmc rescan; setenv dev_type mmc; setenv dev_name mmcblk${dev_num}p
mmc_boot=run mmc_setup; run boot
mmc0_boot=setenv dev_num 0; run mmc_boot
mmc1_boot=setenv dev_num 1; run mmc_boot

usb_setup=usb start; setenv dev_type usb; setenv dev_num 0; setenv dev_name sda;
usb_boot=run usb_setup; run boot