diff --git a/README.md b/README.md index 17e999f..100425c 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,241 @@ -# U-571 -This github repository contains a collection of u-boot macros which make the u-boot usage more beneficial. Almost every SBC vendor introduces his very own way how u-boot is going to be used. I've tried to consolidate these different approaches into one consistent way how a device can be started with u-boot. +# U-Boot-Dock -# Warning -Installing this collection of u-boot macros will change the stored u-boot environment on your device. This might render your SBC unusable. Especially when the u-boot environment is saved on a non-removable storage device (e.g. the Utilite) you might brick your device. - -# Motivation -When I started development on my different SBC, I was quite unhappy with the existing boot mechanisms I've found. I missed the ability to choose between different configurations during boot. For example I wanted to test a newly build Linux kernel without overwriting the existing one. Or I wanted to boot various Linux flavours stored on different partitions on the same storage device instead of swapping a bunch of µSD cards. - -# Single partition layout -Many 'standard' images provided by the SBC vendors come with a two partition layout: One partition containing the Linux root filesystem and one small vfat partition carrying the Linux kernel image. In the very first days this boot partition was necessary due to u-boot's limitation being able to read files from fat filesystems only. Nowadays u-boot supports reading files from ext4 partitons, so I've decided to skip the boot partition in favour of a single ext4 partition layout, yielding a relocatable and self-contained root filesystem. Multiboot environments are easier to implement since they won't have side effects outside their root file system. Furthermore the directory layout inside `/boot` makes use of symbolic links which aren't supported by vfat filesystems. - -# `/boot` directory layout -I've decided to tune up the `/boot` directory a little bit: -- `/boot/kernel.d/` is used to store different kernel images in separate directories, including - - kernel image binary (`[z|u]Image`) - - device tree binary (`*.dtb`) - - initial ramdisk image (`[u]Initrd`) - - additions like `System.map` or `config` (not needed for boot) -- `/boot/conf.d` is used to store different u-boot configurations in subdirectories: - - `/boot/conf.d/default/`, the default u-boot configuration - - `/boot/conf.d/test/`, for testing a new kernel or uEnv.txt or whatever - - `/boot/conf.d/failsafe/`, the fail safe configuration which is supposed to boot under any circumstances +This github repository contains a collection of u-boot macros which make +the u-boot usage more beneficial. Almost every SBC vendor introduces his +very own way how u-boot is going to be used. This project tries to consolidate +these different approaches with a new consistent, flexibel and clean structure. -Each configuration has its own overlay for the default u-boot environment(`uEnv.txt`), a `kernel` directory (usually a link to a directory in `/boot/kernel.d/...`) and a pre-compiled u-boot script (`boot.scr`, optional). The configuration directory itself can be a symbolic link, so resetting `/boot/conf.d/default/` will change the default u-boot configuration. - -For compatibility reasons a `config-$(make kernelrelease)` might be still present in `/boot` (needed for tools like `update-initramfs`). - -# Custom u-boot environment (`uEnv.txt`) -U-Boot loads it's persistent environment during startup. There is a particular initial default environment for each board which already contains all necessary settings to boot up the default configuration, i.e. the board will boot even if the `uEnv.txt` is not present or has been accidentally deleted. If this file is present in the configuration directory, it's contents will be merged on the fly into the actual u-boot environment (but not be written back to the persistent u-boot environment). - -# Some conventions about u-boot variables - -1. There are two different ways to define a variable in the u-boot shell / monitor: +# Warning - 1. `setenv foo bar`: adds the variable `foo` to the u-boot environment - 1. `foo=bar`: sets the shell-only variable `foo` which is not part of the u-boot environment (might be helpful if the environment size is rather small), but cannot be used for calling macros. -1. Shell-only variables are used for passing parameters to macros (`p_...`) and local variables (`v_...`) -2. I've decided to use the prefix `m_` for all u-boot variables containing macros which helps to distinguish code parts from 'real' u-boot variables. -3. All variables using the naming prefix `k_` are used by the macro `m_set_bootargs` to compose the kernel command line (aka `bootargs`). So instead of altering `bootargs` directly you might only want to change `k_rootfs`. +Installing this collection of u-boot macros will change the stored u-boot +environment on your device. This might render your SBC unusable. Especially +when the u-boot environment is saved on a non-removable storage device +(e.g. the Utilite) you might brick your device. -# Default u-boot variables +# Motivation -The following u-boot variables are defined in the initial default environment and can be overwritten: +When I started development on my different SBC, I was quite unhappy with +the existing boot mechanisms I've found. I missed the ability to choose +between different configurations during boot. For example I wanted to test +a newly build Linux kernel without overwriting the existing one. Or I +wanted to boot various Linux flavours stored on different partitions on the +same storage device instead of swapping a bunch of µSD cards. + +# Lifting Constraints + +Many SBC vendors deployed boot images require a two partition layout: + +* Boot: a small vat partition carrying the Linux kernel image +* Root: containing the Linux root filesystem + +In the very first days this partitioning was necessary due to u-boot's +limitation being able to read files from fat filesystems only. Nowadays +u-boot supports reading files from other filesystems (e.g. ext4, btrfs) +no matter which partition they reside. + +A `single partition layout` can lift old burdons. + +Because `u-boot` does not force the usage of vfat (unlike UEFI based +approaches) we can lift burdons using other filesystems: + +* take advantage of a relocatable, self-contained root filesystem. +* implement multiboot environments, without side effects outside their root +* take advantage of symbolic links inside the `/boot` structure + +# Restructure `/boot` directory layout + +The design goal of a simple, thus intuitive directory layout for `U-Boot` +should isolate object-structures. + +* kernels can be coupled with different inital ram disks +* different SBC boards need their corresponding device tree blobs +* distros may rely on given metadata. For compatibility reasons a +`config-$(make kernelrelease)` might be still present in `/boot` (needed +for tools like `update-initramfs`). +* each configuration may have its own overlay for the default U-Boot +environment(`uEnv.txt`) +* a pre-compiled U-Boot script (`boot.scr`, optional). + +This leads to following flat design proposal: + +* /boot + * ./conf.d + * ./conf.d/default + * ./conf.d/default/uImage + * ./conf.d/default/uInitrd + * ./conf.d/default/board.dtb + * ./conf.d/default/uEnv.txt + * ./conf.d/test + * ./conf.d/test/vmlinuz-amlogic-5.4 + * ./conf.d/test/initramfs-amlogic-5.4-.img + * ./conf.d/test/meson-sm1-khadas-vim3l.dtb + * ./conf.d/default/uEnv.txt + +Or a complex implementation using symbolic links: + +* /boot + * ./conf.d + * ./conf.d/default -> ../../default + * ./conf.d/rescue -> ../../rescue + * ./conf.d/arch-5.5 -> ../../arch-5.5 + * ./conf.d/vim3l -> ../../vim3l + * ./conf.d/cubieboard4 -> ../../cubieboard4 + * ./conf.d/arch-mainline -> ../../arch-5.4 + * ./conf.d/android-pie -> ../../kernel.d/android + * ./default + * ./default/uImage -> ../../kernel.d/ubuntu/vmlinuz + * ./default/uInitrd -> ../../kernel.d/ubuntu/Initrd + * ./default/board.dtb -> ../../kernel.d/ubuntu/board.dtb + * ./default/uEnv.txt + * ./rescue + * ./rescue/uImage -> ../../kernel.d/ubuntu/vmlinuz + * ./rescue/uInitrd -> ../../kernel.d/ubuntu/Initrd-failsave + * ./rescue/board.dtb -> ../../kernel.d/ubuntu/board.dtb + * ./rescue/uEnv.txt + * ./arch-5.4 + * ./arch-5.4/vmlinuz-amlogic-5.4 -> ../../kernel.d/arch/vmlinuz-amlogic-5.4 + * ./arch-5.4/initramfs-amlogic-5.4.img -> ../../kernel.d/arch/initramfs-amlogic-5.4.img + * ./arch-5.4/meson-sm1-khadas-vim3l.dtb -> ../../kernel.d/arch/meson-sm1-khadas-vim3l.dtb + * ./arch-5.4/uEnv.txt + * ./arch-5.5 + * ./arch-5.5/vmlinuz-amlogic-5.5-rc1 -> ../../kernel.d/arch/vmlinuz-amlogic-5.5-rc1 + * ./arch-5.5/initramfs-amlogic-5.5-rc1.img -> ../../kernel.d/arch/initramfs-amlogic-5.5-rc1.img + * ./arch-5.5/meson-sm1-khadas-vim3l.dtb -> ../../kernel.d/arch/meson-sm1-khadas-vim3l.dtb + * ./arch-5.5/uEnv.txt -> ../../kernel.d/arch/uEnv.txt + * ./arch-5.5-vim3 + * ./arch-5.5-vim3/vmlinuz-amlogic-5.5-rc1 -> ../../../kernel.d/arch/vmlinuz-amlogic-5.5-rc1 + * ./arch-5.5-vim3/initramfs-amlogic-5.5-rc1.img -> ../../kernel.d/arch/initramfs-amlogic-5.5-rc1.img + * ./arch-5.5-vim3/meson-sm1-khadas-vim3l.dtb -> ../../kernel.d/arch/meson-sm1-khadas-vim3l.dtb + * ./arch-5.5-vim3/uEnv.txt -> ../../kernel.d/arch/uEnv.txt + * ./cubieboard4 + * ./ubuntu/vmlinuz -> ../../../kernel.d/ubuntu/vmlinuz-amlogic-5.5-rc1 + * ./ubuntu/Initrd.img -> ../../kernel.d/ubuntu/initramfs-amlogic-5.5-rc1.img + * ./ubuntu/cubieboard4.dtb -> ../../kernel.d/ubuntu/cubieboard4.dtb + * ./ubuntu/uEnv.txt + * ./vim3l + * ./vim3l/vmlinuz-amlogic-5.4 -> ../../kernel.d/arch/vmlinuz-amlogic-5.4 + * ./vim3l/initramfs-amlogic-5.4.img -> ../../kernel.d/arch/ubuntu/initramfs-amlogic-5.4.img + * ./vim3l/meson-sm1-khadas-vim3l.dtb -> ../../kernel.d/arch/meson-sm1-khadas-vim3l.dtb + * ./vim3l/uEnv.txt + * ./kernel.d + * ./dtfs + * ./dtbs/amlogic + * ./dtbs/amlogic/meson-g12b-odroid-n2.dtb + * ./dtbs/amlogic/meson-g12b-a311d-khadas-vim3.dtb + * ./dtbs/amlogic/meson-sm1-khadas-vim3l.dtb + * ./dtbs/sunxi + * ./dtbs/sunxi/sun7i-a20-bananapro.dtb + * ./dtbs/sunxi/sun9i-a80-cubieboard4.dtb + * ./kernel.d/ubuntu + * ./kernel.d/ubuntu/vmlinuz + * ./kernel.d/ubuntu/Initrd + * ./kernel.d/ubuntu/Initrd-failsave + * ./kernel.d/ubuntu/bananapro.dtb -> ../dtbs/sunxi/sun7i-a20-bananapro.dtb + * ./kernel.d/ubuntu/cubieboard4.dtb -> ../dtbs/sunxi/sun9i-a80-cubieboard4.dtb + * ./kernel.d/arch + * ./kernel.d/arch/vmlinuz-amlogic-5.4 + * ./kernel.d/arch/vmlinuz-amlogic-5.5-rc1 + * ./kernel.d/arch/initramfs-amlogic-5.5-rc1.img + * ./kernel.d/arch/initramfs-amlogic-5.4-fallback.img + * ./kernel.d/arch/initramfs-amlogic-5.4.img + * ./dtfs/amlogic/meson-g12b-odroid-n2.dtb -> ../../dtfs/amlogic/meson-g12b-odroid-n2.dtb + * ./dtfs/amlogic/meson-g12b-a311d-khadas-vim3.dtb -> ../../dtfs/amlogic/meson-g12b-a311d-khadas-vim3.dtb + * ./kernel.d/arch/meson-sm1-khadas-vim3l.dtb -> ../../dtfs/amlogic/meson-sm1-khadas-vim3l.dtb + * ./kernel.d/arch/uEnv.txt + * ./kernel.d/android + * ./kernel.d/android/kernel.img + * ./kernel.d/android/SYSTEM + * ./kernel.d/android/dtb.img + * ./kernel.d/android/boot.ini + * ./kernel.d/android/aml_autoscript + +## Substructure `/boot/kernel.d/` + +Create as subdirectory for any supported kernel architecture. Inside the +subdirectory save the vendor supported blobs + + * kernel image binary (`[z|u]Image`) + * device tree binary (`*.dtb`) + * initial ramdisk image (`[u]Initrd`) + * additions like `System.map` or `config` (not needed for boot) + +## Substructure `/boot/conf.d/` + +This directory will store different, selectable `U-Boot` configurations. +You are free to save the needed binary blobs itself or create symbolic links to +the structured vendor/system blobs. + + * symlinks to saved in the kernel.d structure + * symlinks to saved arch structure referencing the kernel.d + +Usualy you will implement + +* `/boot/conf.d/default/`, the default U-Boot configuration +* `/boot/conf.d/test/`, for testing a new kernel or uEnv.txt or whatever +* `/boot/conf.d/failsafe/`, the fail safe configuration which is supposed + to boot under any circumstances + + The configuration directory itself can be a +symbolic link, so resetting `/boot/conf.d/default/` will change the default +U-Boot configuration. + + +# Custom U-Boot environment (`uEnv.txt`) + +U-Boot loads it's persistent environment during startup. There is a +particular initial default environment for each board which already +contains all necessary settings to boot up the default configuration, +i.e. the board will boot even if the `uEnv.txt` is not present or has been +accidentally deleted. If this file is present in the configuration +directory, it's contents will be merged on the fly into the actual U-Boot +environment (but not be written back to the persistent U-Boot environment). + +# Some conventions about U-Boot variables + +`U-Boot` can significantly gain much more flexiblilty while using +macros and environment variables. + +There are two different ways to define a variable in the U-Boot shell / monitor: + +* `setenv foo bar`: adds the variable `foo` to the U-Boot environment +* `foo=bar`: sets the shell-only variable `foo` which is not part of the + U-Boot environment (might be helpful if the environment size is + rather small), but cannot be used for calling macros. + +This proposel will structure the variable names pepending following +constants to the variable name: + + +* `p_`: Shell-only variables passing parameters to macros +* `v_`: local variables inside the shell +* `m_`: all U-Boot variables containing macros. This helps to + distinguish code parts from 'real' U-Boot variables. +* `k_`). Suggestion + - /boot/conf.d/u0p1/ for USB0 Partiton 1 - /boot/conf.d/s0p2/ for SATA0 Partition 2 -- on the first partition , usually eMMC or uSD - +- on the first partition , usually eMMC or µSD ## Permanent Changes (affecting the default configuration) + ### boot a different kernel -Let `/boot/conf.d/default/kernel` point to a different directory within `/boot/kernel.d/` -### boot with different kernel settings +Let `/boot/conf.d/default/kernel` point to a different directory within +`/boot/kernel.d/` + +### Boot with different kernel settings + Modify `/boot/conf.d/default/uEnv.txt`. -### boot from the 2nd partition -Modify the u-boot environment variable `mmcdev`, `satadev` or `usbdev` from `0:1` to `0:2` and make sure that `/boot/...` is populated accordingly on `0:2`. +### Boot from the 2nd partition + +Modify the U-Boot environment variable `mmcdev`, `satadev` or `usbdev` from +`0:1` to `0:2` and make sure that `/boot/...` is populated accordingly on +`0:2`. ## boot from USB device first -Modify the u-boot environment variable `m_autoboot` in a way that `... run m_autoboot_usb ...` is called first. +Modify the U-Boot environment variable `m_autoboot` in a way that `... run +m_autoboot_usb ...` is called first. -# Installation +# Target installation ## Toolset -I've built a small toolset into the [Makefile](https://github.com/umiddelb/u-571/blob/master/macro/Makefile) targets aiming to make the u-boot macro coding a little bit more convenient. U-boot macros are stored as one large character string into an u-boot environment variable which makes editing not very intuitive, e.g. no line feeds, no indentation, no comments. You will find all this elements in the input files (`*.uboot`). The make procedure will remove them in order to produce a clean u-boot macro. -## Userland access to the u-boot environment -The u-boot environment is stored on dedicated space outside the filesystem. The u-boot-tools package contains the tool fw_setenv/fw_printenv to access the u-boot environment from the userland. This tool needs to be configured to your specific board, otherwise the make target `install` will fail. Please refer to [this article](https://github.com/umiddelb/armhf/wiki/Get-more-out-of-%22Das-U-Boot%22) for more details. +To ease the use of `U-Boot-Dock` a small toolset is provided. + +[Makefile](https://github.com/umiddelb/u-571/blob/master/macro/Makefile) +targets are called to resolve your presets, which are board specific. This +board specific definitions are structured in a the `board\` +subdirectory. + +U-Boot will handle macros as one large character string. This makes editing +not very intuitive, since you can't use line feeds, indentation, nor +comments. `U-Boot-Dock's` defines its macro definitions in sources files +(`*.uboot`) inside the subdirectory `macros`. When Makefile targets are +executed, they take care to remove comments, line feeds and identation. All +macro resultions be will combine combine and the final U-Boot complient +environment will be saved. + +Please adapt following files inside the board subdirectory: + +* board_init.env (board defaults) +* uEnv.txt (runtime adaptions) + +## Userland access to the U-Boot environment + +The U-Boot environment is stored on dedicated space outside the +filesystem. The U-Boot-tools package contains the tool + +* fw_setenv +* fw_printenv + +to access the U-Boot environment from the userland. You need to configure +this tools according to your specific board. If the tools can't access your +target device the macro call from the Toolset (target `install`) will +fail. + +Please refer to [this +article](https://github.com/umiddelb/armhf/wiki/Get-more-out-of-%22Das-U-Boot%22) +for more details. + +## Flashing your U-Boot environment + +First you need to select your SBC for the given board subirectory. You are +welcome to create an entry for a non listed board and expand the given selection. + +Please choose your [board](https://github.com/umiddelb/u-571/tree/master/board) + +As a second step, open a terminal and change into the choosen board config. +Adapt your `board_init.env`. When ready, flash the config to your boot +media by calling + +`make install` + +You may create a `bundle.Env` file, that will reflact the U-Boot +environment that the previoas flash call will store on your target device. + +## License + + +[Logo-CC_BY]: https://i.creativecommons.org/l/by/4.0/88x31.png "Creative Common Logo" +[License-CC_BY]: https://creativecommons.org/licenses/by/4.0/legalcode "Creative Common License" + +This work is licensed under a [Creative Common License 4.0][License-CC_BY] -## [Choose your board](https://github.com/umiddelb/u-571/tree/master/board) +![Creative Common Logo][Logo-CC_BY] -## `make install` +© 2016, 2019 Uli Middelberg; +© 2019 Ralf Zerres diff --git a/macro/Makefile b/macro/Makefile index b2ca65f..91e6f03 100644 --- a/macro/Makefile +++ b/macro/Makefile @@ -1,4 +1,3 @@ - .PHONY: clean all install all: $(patsubst %.uboot,%.env,$(wildcard *.uboot)) @@ -9,12 +8,19 @@ install: all install.ext4: all cat *.env | sed -e 's/ext2/ext4/g' | sudo fw_setenv -s - +install.btrfs: all + cat *.env | sed -e 's/ext2/btrfs/g' | sudo fw_setenv -s - + macro.uEnv: $(patsubst %.uboot,%.uEnv,$(wildcard *.uboot)) cat *.uEnv | sort > $@ macro.ext4.uEnv: $(patsubst %.uboot,%.uEnv,$(wildcard *.uboot)) cat *.uEnv | sed -e 's/ext2/ext4/g' | sort > $@ +macro.btrfs.uEnv: $(patsubst %.uboot,%.uEnv,$(wildcard *.uboot)) + cat *.uEnv | sed -e 's/ext2/btrfs/g' | sort > $@ + + clean: rm -f *.sh *.env *.uEnv uEnv.txt uEnv.ext4.txt diff --git a/macro/m_load_fdt.uboot b/macro/m_load_fdt.uboot index 467785e..9f20825 100644 --- a/macro/m_load_fdt.uboot +++ b/macro/m_load_fdt.uboot @@ -17,18 +17,18 @@ if test "${fdt}" != ""; then v_success=false; for v_fdt in ${fdt}; do if test ${v_success} = false; then - p_filename=${prefix}/${p_conf}/kernel/${v_fdt}; + p_filename=${prefix}/${p_conf}/${v_fdt}; p_loadaddr=${fdt_addr_r}; if run m_load; then - if test ${dbglevel} -gt 0; then - echo [m_load_fdt]Device Tree loaded from ${p_class}:${p_device}:${p_filename}, size ${filesize}; - fi; - v_success=true; + if test ${dbglevel} -gt 0; then + echo [m_load_fdt]Device Tree loaded from ${p_class}:${p_device}:${p_filename}, size ${filesize}; + fi; + v_success=true; else - if test ${errlevel} -gt 0; then - echo [m_load_fdt]Loading device tree from ${p_class}:${p_device}:${p_filename} failed!; - fi; - v_success=false; + if test ${errlevel} -gt 0; then + echo [m_load_fdt]Loading device tree from ${p_class}:${p_device}:${p_filename} failed!; + fi; + v_success=false; fi; fi; done; diff --git a/macro/m_load_kernel.uboot b/macro/m_load_kernel.uboot index 9563a4c..2fd52e6 100644 --- a/macro/m_load_kernel.uboot +++ b/macro/m_load_kernel.uboot @@ -13,7 +13,7 @@ # return value # - true: success / false: error -p_filename=${prefix}/${p_conf}/kernel/${kernel}; +p_filename=${prefix}/${p_conf}/${kernel}; p_loadaddr=${kernel_addr_r}; if run m_load; then if test ${dbglevel} -gt 0; then @@ -24,6 +24,6 @@ else if test ${errlevel} -gt 0; then echo [m_load_kernel]Loading kernel image from ${p_class}:${p_device}:${p_filename} failed!; fi; - false; + false; fi; # vim:ft=sh