在家学习嵌入式3--使用Buildroot构建编译系统

前言

新冠疫情期间在家里无事可做,奈何手上没有现成的开发板,又想调试学习linux内核,于是就有了这一系列的文章。本系列文章包含以下内容:


编译系统

在前面的文章中,我们分别下载编译uboot、下载编译kernel、下载busybox制作ramdisk、下载toolchain、制作SD卡等。这些步骤比较繁琐,有没有一种方法一键生成所需的镜像并且打包到一起呢?我们先看一下嵌入式系统编译的输入和输出,输入源码,输出二进制镜像。其中就需要Embedded Linux build system来整合这些步骤,一键就需要依赖这里的build system(编译系统)来实现。目前的编译系统有Yocto/OpenEmbedded, PTXdist, Buildroot, OpenWRT。回想一下,SOC厂商发布BSP的时候,不可能一个个给你发布uboot、kernel的,而是将整个编译系统发布出来,据我所知NXP/MTK是通过Yocto发布,Pana通过Buildroot发布。
在家学习嵌入式-1

本文将使用buildroot作为编译系统,将我们之前使用qemu搭建的虚拟开发环境统一起来,实现一键编译打包。在这之前,我们先介绍一下buildroot。


buildroot介绍

buildroot官方的介绍如下,翻译下来就是buildroot是一个简单以及自动化的工具,可以使用交叉编译为嵌入式系统构建一个完整的linux系统。为了实现这个功能,buildroot可以生成交叉工具链,rootfs,linux kernel镜像和bootloader。buildroot可以独立地用于这些选项的任何组合(例如,您可以使用现有的交叉编译工具链,并仅通过Buildroot来构建根文件系统)。

Buildroot is a tool that simplifies and automates the process of building a complete Linux system for an embedded system, using cross-compilation. In order to achieve this, Buildroot is able to generate a cross-compilation toolchain, a root filesystem, a Linux kernel image and a bootloader for your target. Buildroot can be used for any combination of these options, independently (you can for example use an existing cross-compilation toolchain, and build only your root filesystem with Buildroot).

以下内容将一步步介绍如何配置buildroot作为我们自己的qemu vexpress虚拟开发板的编译系统。


拷贝配置

configs/qemu_arm_vexpress_defconfig有关于qemu vexpress-a9的buildroot配置,我们以此为基础,将其拷贝为configs/wowothink_qemu_arm_vexpress_defconfig文件,然后根据这个文件进行buildroot的配置。在make menuconfig之前,我们先通过make wowothink_qemu_arm_vexpress_defconfig生成.config文件。


配置Target options

这部分内容为默认的,在我们使用qemu_arm_vexpress_defconfig的配置的时候就已经默认好了,所以无需配置。

Target options配置
1
2
3
4
5
6
7
8
     Target Architecture (ARM (little endian))  --->
Target Binary Format (ELF) --->
Target Architecture Variant (cortex-A9) --->
[ ] Enable NEON SIMD extension support
[ ] Enable VFP extension support
Target ABI (EABI) --->
Floating point strategy (Soft float) --->
ARM instruction set (ARM) --->


配置Build options

这部分内容有一个需要配置的就是Location to save buildroot config选项,将其指定为我们wowothink_qemu_arm_vexpress_defconfig配置文件的路径即可。这样子我们每次执行make savedefconfig就会自动将其保存到该文件。

Build options配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    Commands  --->
(/home/victor/work/buildroot/buildroot/configs/wowothink_qemu_arm_vexpress_defconfig) Location to save buildroot config
($(TOPDIR)/dl) Download dir
($(BASE_DIR)/host) Host dir
Mirrors and Download locations --->
(0) Number of jobs to run simultaneously (0 for auto)
[ ] Enable compiler cache
[ ] build packages with debugging symbols
[*] strip target binaries
() executables that should not be stripped
() directories that should be skipped when stripping
gcc optimization level (optimize for size) --->
[ ] Enable google-breakpad support
libraries (shared only) --->
($(CONFIG_DIR)/local.mk) location of a package override file
() global patch directories
Advanced --->
*** Security Hardening Options ***
[ ] Build code with PIC/PIE
Stack Smashing Protection (None) --->
RELRO Protection (None) --->
Buffer-overflow Detection (FORTIFY_SOURCE) (None) --->

有个小的注意事项,在执行make的时候,buildroot有可能会从网络上下载包,有些会提示如下的错误:

1
2
3
错误: 无法验证 releases.linaro.org 的由 “CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US” 颁发的证书:
颁发的证书还未生效。
要以不安全的方式连接至 releases.linaro.org,使用“--no-check-certificate”。

解决办法是在wget命令中加入--no-check-certificate的参数,在下面的选项中加入即可。

1
Build options  --->Commands  --->(wget --passive-ftp -nd -t 3 --no-check-certificate) Wget command


配置Toolchain

下面的toolchain是我最终的配置,我尝试使用Buildroot toolchain的配置,但是由于网络的原因总是下载断开。后面我使用系统自带的arm-linux-gnueabi,也就是之前安装的交叉工具链,但是在编译的时候会提示以下的错误:

系统自带的toolchain错误
1
2
3
4
Distribution toolchains are unsuitable for use by Buildroot,
as they were configured in a way that makes them non-relocatable,
and contain a lot of pre-built libraries that would conflict with
the ones Buildroot wants to build.

最终,我不得不预先从https://releases.linaro.org/components/toolchain/binaries/ 下载5.4版本的交叉工具链,然后通过Toolchain path指定其路径。注意,在buildroot中,所有路径相关的,最后都不能带/,因为buildroot会自动将其加上。

Toolchain最终配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    Toolchain type (External toolchain)  --->
*** Toolchain External Options ***
Toolchain (Custom toolchain) --->
Toolchain origin (Pre-installed toolchain) --->
(/home/victor/work/toolchain/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi) Toolchain path
($(ARCH)-linux-gnueabi) Toolchain prefix
External toolchain gcc version (5.x) --->
External toolchain kernel headers series (4.0.x) --->
External toolchain C library (glibc/eglibc) --->
[*] Toolchain has SSP support?
[*] Toolchain has RPC support?
[*] Toolchain has C++ support?
[ ] Toolchain has D support?
[ ] Toolchain has Fortran support?
[ ] Toolchain has OpenMP support?
[ ] Copy gdb server to the Target
*** Host GDB Options ***
[ ] Build cross gdb for the host
*** Toolchain Generic Options ***
[ ] Copy gconv libraries
() Extra toolchain libraries to be copied to target
[*] Enable MMU support
() Target Optimizations
() Target linker options


配置System configuration

这里主要配置为busybox为Init system,并设置运行一个getty,这样子系统启动后会有一个console,并且这个console是/bin/sh,用户名和登陆密码为root.

System configuration配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    Root FS skeleton (default target skeleton)  --->
(wowothink) System hostname
(Welcome to Buildroot) System banner
Passwords encoding (sha-256) --->
Init system (BusyBox) --->
/dev management (Dynamic using devtmpfs only) --->
(system/device_table.txt) Path to the permission tables
[ ] support extended attributes in device tables
[*] Use symlinks to /usr for /bin, /sbin and /lib
[*] Enable root login with password
(root) Root password
/bin/sh (busybox' default shell) --->
[*] Run a getty (login prompt) after boot --->
[ ] remount root filesystem read-write during boot
() Network interface to configure through DHCP
(/bin:/sbin:/usr/bin:/usr/sbin) Set the system's default PATH
[*] Purge unwanted locales
(C en_US) Locales to keep
() Generate locale data
[ ] Enable Native Language Support (NLS)
[ ] Install timezone info
() Path to the users tables
() Root filesystem overlay directories
() Custom scripts to run before creating filesystem images
() Custom scripts to run inside the fakeroot environment
() Custom scripts to run after creating filesystem images


配置Kernel

linux kernel配置其从gitee上下载,并且切换到v4.4的branch上面,使用的kernel的defconfig名字为vexpress(改名字无需加上_defconfig的后缀),dtb名字为vexpress-v2p-ca9。这样子,在编译linux kernel的时候,buildroot就会自动去使用vexpress _defconfig的配置,并且会去编译生成vexpress-v2p-ca9.dtb。这样子最终在out/images/会生成一个zImagevexpress-v2p-ca9.dtb的文件。注意事项:有时候国内的网络不稳定,kernel无法clone下来,经常断开。如果之前有下载过linux kernel,就可以将URL of custom repository配置为之前linux kernel的路径。

Kernel配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[*] Linux Kernel
Kernel version (Custom Git repository) --->
(https://mirrors.tuna.tsinghua.edu.cn/git/linux.git) URL of custom repository
(v4.4) Custom repository version
() Custom kernel patches
Kernel configuration (Using an in-tree defconfig file) --->
(vexpress) Defconfig name
() Additional configuration fragment files
() Custom boot logo file path
Kernel binary format (zImage) --->
Kernel compression format (gzip compression) --->
[*] Build a Device Tree Blob (DTB)
[ ] DTB is built by kernel itself
(vexpress-v2p-ca9) In-tree Device Tree Source file names
() Out-of-tree Device Tree Source file paths
[ ] Build Device Tree with overlay support
[ ] Install kernel image to /boot in target
[ ] Needs host OpenSSL
[ ] Needs host libelf
Linux Kernel Extensions --->
Linux Kernel Tools --->

配置Filesystem images

这一步主要配置生成的rootfs是什么格式的,在前面,我们使用了uramdisk.imgcpio加上gzip并且带上uboot头的文件格式,那么这里就必须配置上cpio/gzip/uboot image的格式。这样子最终在out/images/会生成一个rootfs.cpio.uboot的文件。为了保证名称的一致性,需要将我们前面打入uboot中的patch里面的ramdisk_name=uramdisk.img\0修改为ramdisk_name=rootfs.cpio.uboot\0

Filesystem images的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[ ] axfs root filesystem                                            
[ ] btrfs root filesystem
[ ] cloop root filesystem for the target device
[*] cpio the root filesystem (for use as an initial RAM filesystem)
Compression method (gzip) --->
[*] Create U-Boot image of the root filesystem
[ ] cramfs root filesystem
[ ] ext2/3/4 root filesystem
[ ] f2fs root filesystem
[ ] initial RAM filesystem linked into linux kernel
[ ] jffs2 root filesystem
[ ] romfs root filesystem
[ ] squashfs root filesystem
[ ] tar the root filesystem
[ ] ubi image containing an ubifs root filesystem
[ ] ubifs root filesystem
[ ] yaffs2 root filesystem

配置Bootloaders

这一步主要配置编译uboot,配置uboot源码从gitee上下载,使用v2017.01的分支,并且使用vexpress_ca9x4作为uboot的配置文件。Custom U-Boot patches这个路径是配置uboot的patch路径,如果没有patch打入到uboot中,可以不用配置。

Bootloaders配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[ ] afboot-stm32
[ ] ARM Trusted Firmware (ATF)
[ ] Barebox
[ ] grub2
[ ] mxs-bootlets
[ ] optee_os
[ ] s500-bootloader
[*] U-Boot
Build system (Kconfig) --->
U-Boot Version (Custom Git repository) --->
(https://gitee.com/wowothink/u-boot.git) URL of custom repository
(v2017.01) Custom repository version
(/home/victor/work/buildroot/buildroot/board/qemu/arm-versatile/patches/uboot) Custom U-Boot patches
U-Boot configuration (Using an in-tree board defconfig file) --->
(vexpress_ca9x4) Board defconfig
() Additional configuration fragment files
[ ] U-Boot needs dtc
[ ] U-Boot needs pylibfdt
[ ] U-Boot needs pyelftools
[ ] U-Boot needs OpenSSL
[ ] U-Boot needs lzop
U-Boot binary format --->
[ ] produce a .ift signed image (OMAP)
[ ] Install U-Boot SPL binary image
[ ] Environment image ----
[ ] Generate a U-Boot boot script
() Device Tree Source file paths
() Custom make options

配置uboot的二进制文件为u-boot.elf,由于qemu使用的是elf文件格式的uboot,因此这里必须配置上。

U-Boot binary format
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[ ] u-boot.ais
[*] u-boot.bin
[ ] u-boot-dtb.bin
[ ] u-boot-dtb.img
[ ] u-boot-dtb.imx
[ ] u-boot.img
[ ] u-boot.itb
[ ] u-boot.imx
[ ] u-boot-nand.bin
[ ] u-boot.kwb (Marvell)
[*] u-boot.elf
[ ] u-boot.sb (Freescale i.MX28)
[ ] u-boot.sd (Freescale i.MX28)
[ ] u-boot.nand (Freescale i.MX28)
[ ] Custom (specify below)


配置自动生成sdcard.img

在前面的文章中,我们制作了一个vfat格式的sdcard,将所需的zImageuramdisk.imgvexpress-v2p-ca9.dtb拷贝到该sdcard中,然后再uboot启动的时候从sdcard将其load到DDR中并且启动linux。这个几步在buildroot中可以自动执行完成,需要在System configuration配置以下两个选项:

配置自动生成sdcard.img
1
2
(support/scripts/genimage.sh) Custom scripts to run after creating filesystem images
(-c board/qemu/arm-vexpress/arm-vexpress-genimage.cfg) Extra arguments passed to custom scripts

前者表示创建文件系统后去执行genimage.sh脚本,后者表示该脚本使用的配置文件,配置文件的内容如下,表示创建一个vfat格式的sdcard.img,大小为512M,里面包含3个文件。

arm-vexpress-genimage.cfg
1
2
3
4
5
6
7
8
9
10
11
12
# Minimal SD card image for the qemu arm vexpress board
#
image sdcard.img {
vfat {
files = {
"zImage",
"vexpress-v2p-ca9.dtb",
"rootfs.cpio.uboot"
}
}
size = 512M
}


一键编译生成

  • 首先从https://releases.linaro.org/components/toolchain/binaries/ 下载5.4版本的交叉工具链;
  • 下载我配置好的buildroot源码:git clone https://gitee.com/wowothink/buildroot.git
  • 修改configs/wowothink_qemu_arm_vexpress_defconfig文件以下两个宏为自己本地的绝对路径,分别是toolchain的路径以及uboot patch的路径:

    1
    2
    BR2_TOOLCHAIN_EXTERNAL_PATH="/home/victor/work/toolchain/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi"
    BR2_TARGET_UBOOT_PATCH="/home/victor/work/buildroot/buildroot/board/qemu/arm-vexpress/patches/uboot"
  • 一键编译生成

    一键编译生成
    1
    2
    make wowothink_qemu_arm_vexpress_defconfig
    make

最终在output/images/会生成如下文件,qemu就可以用sdcard.imgu-boot

生成的镜像
1
2
3
4
5
6
7
8
9
10
11
12
victor@victor-linux:~/work/temp/buildroot$ ll output/images/
总用量 21216
drwxr-xr-x 2 victor victor 4096 3月 25 14:32 .
drwxrwxr-x 6 victor victor 4096 3月 25 14:32 ..
-rw-r--r-- 1 victor victor 5231616 3月 25 14:32 rootfs.cpio
-rw-r--r-- 1 victor victor 2445179 3月 25 14:32 rootfs.cpio.gz
-rw-r--r-- 1 victor victor 2445243 3月 25 14:32 rootfs.cpio.uboot
-rw-r--r-- 1 victor victor 536870912 3月 25 14:32 sdcard.img
-rwxr-xr-x 1 victor victor 1668600 3月 25 14:32 u-boot
-rwxr-xr-x 1 victor victor 273016 3月 25 14:32 u-boot.bin
-rw-r--r-- 1 victor victor 14360 3月 25 10:46 vexpress-v2p-ca9.dtb
-rw-r--r-- 1 victor victor 3465600 3月 25 10:46 zImage

  • 使用qemu-system-arm启动
    1
    qemu-system-arm -M vexpress-a9 -m 1024M -kernel /home/victor/work/temp/buildroot/output/images/u-boot -nographic -no-reboot -sd /home/victor/work/temp/buildroot/output/images/sdcard.img

参考资料

Title:在家学习嵌入式3--使用Buildroot构建编译系统

Author:Victor Huang

Time:2020-03-27 / 18:03

Link:http://wowothink.com/14c7c84a/

License: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)