[[PageOutline]] = Buildroot A Linux kernel without a root filesystem (aka rootfs) is useless. There are many sources for root filesystems including complete Linux distributions like Ubuntu (often too big, or limited in arch availability), pre-built root filesystems from vendors (often too limited), root filesystems built manually with Busybox (still often too limited) and more. There are Embedded Linux build systems which try to be more flexible like !OpenEmbedded, Yocto, and OpenWrt but these tend to be not easy to understand or quick to setup. Buildroot tends to be a much more simplistic approach using standard makefiles, can produce a root filesystem in minutes, and has 1000+ userspace libs/apps available. Using a buildroot rootfs is extremely useful for: * small fast booting self-contained systems (the default busybox rootfs is typically ~1.5MB) * kernel development (using [#initrd initrd] or [#initramfs initramfs] options * using its toolchain externally suggested tools to include for kernel development: * dropbear for SSH * benchmarksiozone, bonnie++, LTP, netperf, ramspeed, stress, lmbench, iostat, memtester, etc * debug tools; evtest, i2c-tools, devmem2, pciutils, usbutils, libv4l, alsa-utils, linux-firmware, mii-diag, iperf, iw * filesystem tools: resize2fs (BR2_PACKAGE_E2FSPROGS_RESIZE2FS) adds 1.2MB for 2.4MB cpio Building: {{{#!bash git clone https://github.com/buildroot/buildroot.git cd buildroot make menuconfig # configure make -j8 ls output/images }}} * Note that like many build systems sources will be downloaded from the network during the build process * The .config file contains all the configuration options from the {{{make menuconfig}}} * see sections below on configuration tips for various platforms For platform specific notes see below: * [#ventana Gateworks Ventana (imx6)] * [#newport Gateworks Newport (cn80xx)] References: * https://buildroot.org * https://buildroot.org/downloads/manual/manual.html * http://free-electrons.com/pub/conferences/2013/kernel-recipes/rootfs-kernel-developer/rootfs-kernel-developer.pdf [=#initrd] == initrd (initial ramdisk) The initial RAM disk (initrd) is an initial root file system that is mounted prior to when the real root file system is available. The initrd is bound to the kernel and loaded as part of the kernel boot procedure. An {{{initrd}}} is a 'cpio' image (an archive created with the Unix {{{cpio}}} tool) thus you need to have BR2_TARGET_ROOTFS_CPIO enabled and optionally one of the compression formats supported by your kernel). If using U-Boot 'bootm' be sure to enable BR2_TARGET_ROOTFS_CPIO_UIMAGE which runs 'mkimage' on output/images/rootfs.cpio to create a 'uramdisk'. Example booting Linux kernel with device-tree and initrd using U-Boot 'bootm': * Bootloader: {{{#!bash setexpr fdt_addr $loadaddr setexpr linux_addr $fdt_addr + 0x20000 # allow 128KB for FDT setexpr rd_addr $linux_addr + 0x4000000 # allow 64MB for kernel setenv bootargs "console=${console},${baudrate}" setenv fsload tftpboot # for network load $fsload $fdt_addr $fdt_file2 && $fsload $linux_addr uImage && $fsload $rd_addr uramdisk && bootm $linux_addr $rd_addr $fdt_addr }}} - In the above example you can modify fsload to load for your storage interface, device, and filesystem (ie "setenv fsload 'fatload mmc 0:1'" for loading from fist mmc controller first partition fatfs filesystem) [=#initramfs] == initramfs The buildroot root filesystem can also be built statically into a kernel eliminating the need to have a separate kernel and ramdisk as in the [#initrd initrd] option above. To build a rootfs suitable for use as an initramfs: - Select target arch - Configure toolchain or point to external toolchain - System configuration - select devtmpfs /dev management method and ensure serial port for the getty is correct - Filesystem images - select cpio format - use {{{make}}} to build - your rootfs will be in output/images/rootfs.cpio and will build within minutes - a default config using busybox will be about 1.5MiB Make sure your kernel has the following: - CONFIG_DEVTMPFS=y - to get devtmpfs support, to provide a dynamic /dev - CONFIG_INITRAMFS_SOURCE="/path/to/buildroot/output/images/rootfs.cpio" - path to your cpio - CONFIG_INITRAMFS_COMPRESSION_GZIP=y - compression algorithm - CONFIG_INITRAMFS_ROOT_UID=0 - root user id - CONFIG_INITRAMFS_ROOT_GID=0 - root group id If using buildbot to build kernel add the following to automatically build a kernel using to buildroot rootfs as an initramfs: * BR2_TARGET_ROOTFS_INITRAMFS=y See also: * [wiki:linux/initramfs linux/initramfs] [=#toolchain] == Using Buildroot toolchain externally Buildroot builds its own GCC toolchain and using this externally can be useful. The toolchain generated by Buildroot is located by default in {{{output/host/}}} and the simplest way to use it to to add {{{output/host/bin/}}} to your PATH then and use the version of gcc tools there. For example: {{{#!bash export PATH=$PWD/output/host/bin:$PATH export CROSS_COMPILE=arm-linux- export ARCH=arm }}} It is possible to relocate this toolchain making it easy for distribution using {{{make sdk}}} which prepares the toolchain to be relocatable and creates a tarball in the {{{output/host/}}} directory. The {{{relocate-sdk.sh}}} script in the tarball can be used to update paths. See the full documentation in docs/manual/using-buildroot-toolchain.txt [=#busybox] == Busybox config Busybox is used by default for all of the tools in the rootfs built by buildroot. If you want to alter the default configuration of busybox itself you can access it via {{{make menuconfig}}}: * Target packages -> !BusyBox -> !BusyBox configuration file to use * defaults to package/busybox/busybox.config [=#newport] == Newport (CN80XX) The following details pertain to buildroot 2017.11 although newer versions will likely be similar if not the same. To configure buildroot for the Cavium CN80XX/CN81XX SoC found on the Newport product family: * Target options -> Target Architecture -> AArch64 (little endian) (BR2_aarch64) * Filesystem images -> tar the root filesystem -> Compression method (xz) (BR2_TARGET_ROOTFS_CPIO_XZ) * Filesystem images -> cpio the root filesystem (BR2_TARGET_ROOTFS_CPIO) * Filesystem images -> Compression method (xz) (BR2_TARGET_ROOTFS_TAR_XZ) This builds a ~500KiB output/images/root.tar.xz in less than 5 minutes on a typical Linux desktop. If you also want buildroot to build a kernel provided from buildroot using the buildroot rootfs embedded as an initramfs then enable the following to create a kernel suitable for aarch64 and booting via U-Boot {{{booti}}}: * Kernel -> Linux Kernel (BR2_LINUX_KERNEL) * Kernel -> Kernel configuration (Using a custom (def)config file) -> newport_defconfig * Filesystem images -> initial RAM filesystem linked into linux kernel Adding the kernel build produces a ~21MB Image in less than 10 minutes on a typical Linux desktop. To boot this on a Newport bootloader: {{{#!bash tftpboot ${kernel_addr_r} newport/buildroot/Image && booti ${kernel_addr_r} - ${fdtcontroladdr} }}} Now you have a minimal Linux OS that booted in about 6 seconds. A prebuilt image can be found [http://dev.gateworks.com/buildroot/newport/minimal here] which contains: * Linux 4.14 kernel with ThunderX periperhals enabled * resize2fs (BR2_PACKAGE_E2FSPROGS_RESIZE2FS) * screen (BR2_PACKAGE_SCREEN) * pciutils (BR2_PACKAGE_PCIUTILS) * libusb (BR2_PACKAGE_LIBUSB) * eudev (BR2_PACKAGE_HAS_UDEV) * usbutils (BR2_PACKAGE_USBUTILS) * disk partitioning tools === Building .ext4 filesystem and compressed disk image In the event you choose to use Buildroot but wish to avoid the drawbacks of a ramdisk you can install it to a block storage device. For this you will need to create a .ext4 filesystem image. This example will utilize the Linux-Newport branch of the mainline 4.14.4 kernel. Prerequisite for this procedure you will need to have: * Downloaded and configured the [wiki:/newport/bsp Newport BSP], many of the tools used will be provided by it. * The [http://dev.gateworks.com/newport/kernel/linux-newport.tar.xz linux-newport.tar.xz] kernel tarball. * The latest [http://dev.gateworks.com/newport/boot_firmware/firmware-newport.img firmware-newport.img] boot firmware if you would like to create a compressed disk image. With the Newport BSP installed, and Buildroot cloned, configure Buildroot in make menuconfig with the two following options: {{{#!bash cd buildroot make menuconfig }}} * Target options -> Target Architecture -> AArch64 (little endian) (BR2_aarch64) * Filesystem images -> tar the root filesystem -> Compression method (xz) (BR2_TARGET_ROOTFS_CPIO_XZ) Save the .config and exit. Now: {{{#!bash make -j8 }}} After the build completes: * Export the location of the rootfs.tar located in your buildroot/output/images folder. {{{#!bash ROOTFS=${PWD}/output/images/rootfs.tar }}} * Create a tmp_mnt directory at a location of your discression, this is your temporary mounting point for compiling the filesystem. {{{#!bash mkdir tmp_mnt TMP_MNT=${PWD}/tmp_mnt }}} * Create a filesystem of a specific size. It will be expandable later using resize2fs, make it large enough to fit what you have in your current build. {{{#!bash OUT=buildroot-newport.ext4 SIZEMB=1536 # 1.5GB truncate -s ${SIZEMB}M ${OUT} mkfs.ext4 -q -F -L rootfs ${OUT} }}} * Mount this file to your 'tmp_mnt' directory {{{#!bash sudo mount ${OUT} ${TMP_MNT} }}} * Extract the Buildroot rootfs.tar and linux-newport.tar.xz which was downloaded to this mount point. {{{#!bash sudo tar -C ${TMP_MNT} -xf ${ROOTFS} sudo tar -C ${TMP_MNT} -xf linux-newport.tar.xz }}} * Convert the kernel 'Image' (uncompressed Kernel) to a fit image. For this you will need a tool from your Newport BSP directory, in this example the path to the BSP directory is named ${NEWPORT_BSP}. {{{#!bash mv ${TMP_MNT}/boot/Image vmlinux gzip -f vmlinux ${NEWPORT_BSP}/newport/mkits.sh -o kernel.its -k vmlinux.gz -C gzip -v "buldroot-newport" mkimage -f kernel.its tmp_mnt/boot/kernel.itb #adds header }}} * Create U-Boot bootscript using the existing Ubuntu one from the Newport BSP, use mkimage to add the u-boot header. {{{#!bash mkimage -A arm64 -T script -C none -d ${NEWPORT_BSP}/newport/ubuntu.scr ${TMP_MNT}/boot/newport.scr }}} * Unmount temporary mount point, and compress the .ext4 file to be used with the u-boot command 'gzwrite'. {{{#!bash umount ${TMP_MNT} rm -rf ${TMP_MNT}eh gzip -k -f ${OUT} }}} To load this root file system without disturbing the existing boot firmware tftpboot can be used: * Boot your Newport SBC, at the prompt "Hit any key to stop autoboot" press a key. * Execute the following commands. {{{#!bash setenv ipaddr setenv serverip setenv dev 0 setenv image buildroot-newport.ext4.gz run update_rootfs }}} To create a disk image from the .ext4 file: * Creating a disk image is useful if you would like to overwrite the existing boot firmware when the image is flashed. {{{#!bash # http://dev.gateworks.com/newport/boot_firmware/firmware-newport.img cp firmware-newport.img buildroot-newport.img # copy buildroot rootfs .ext4 filesystem to image with an offset dd if=buildroot-newport.ext4 of=buildroot-newport.img bs=16M seek=1 # compress it gzip -k -f buildroot-newport.img }}} [=#ventana] == Ventana (IMX6) The following details pertain to buildroot 2017.08 although newer versions will likely be similar if not the same. To configure buildroot for the i.MX6 SoC found on the Ventana product family: * Target options -> Target Architecture -> ARM (little endian) * Target options -> Target Architecture Variant -> cortex-A9 (BR2_GCC_TARGET_CPU) * Target options -> Enable NEON SIMD extension support (BR2_ARM_ENABLE_NEON=y) * Target options -> Enable VFP extension support (BR2_ARM_ENABLE_VFP=y) * Target options -> Floating point strategy (NEON) (BR2_ARM_FPU_NEON=y) * Filesystem images -> tar the root filesystem -> Compression method (xz) This builds a ~500KiB output/images/rootfs.tar.xz in less than 5 minutes on a typical Linux desktop. If you also want buildroot to build a kernel provided from buildroot using the buildroot rootfs embedded as an initramfs then enable the following to create a kernel suitable for imx_v6_v7 and booting via U-Boot {{{bootm}}}: * Kernel -> Linux Kernel (BR2_LINUX_KERNEL) * Kernel -> Defconfig name (imx_v6_v7) (BR2_LINUX_KERNEL_DEFCONFIG) * Kernel -> Kernel binary format (uImage) * Kernel -> load address (0x10008000) (BR2_LINUX_KERNEL_UIMAGE_LOADADDR) * Kernel -> Device Tree Source file names (imx6dl-gw54xx imx6q-gw54xx imx6dl-gw53xx imx6q-gw53xx imx6dl-gw52xx imx6q-gw52xx imx6dl-gw51xx imx6q-gw51xx imx6dl-gw551x imx6q-gw551x imx6dl-gw552x imx6q-gw552x imx6dl-gw553x imx6q-gw553x) (BR2_LINUX_KERNEL_INTREE_DTS_NAME) * Filesystem images -> initial RAM filesystem linked into linux kernel Adding the kernel build produces a ~6MB uImage in less than 10 minutes on a typical Linux desktop. To boot this on a Ventana bootloader: {{{#!bash tftpboot ${loadaddr} ventana/uImage && tftpboot ${fdt_addr} ventana/${fdt_file2} && bootm ${loadaddr} - ${fdt_addr} }}} Now you have a minimal Linux OS that booted in about 6 seconds. A prebuilt image of this can be found at: http://dev.gateworks.com/buildroot/ventana/minimal Additional tools: * resize2fs * screen * ubi/ubifs tools * pciutils usb-utils * disk partitioning tools