编译 Linux 固件(GPT)

前言

本 SDK 开发环境是在 Ubuntu 上开发测试的。我们推荐使用 Ubuntu 16.04 的系统进行编译。其他的 Linux 版本可能需要对软件包做相应调整。 除了系统要求外,还有其他软硬件方面的要求。

准备工作

硬件要求:

64 位系统,硬盘空间大于 40G。如果您进行多个构建,将需要更大的硬盘空间。

软件要求:编译环境初始化

  • Ubuntu 14.04 软件包安装:

$ sudo apt-get install git gnupg flex bison gperf build-essential \
zip tar curl libc6-dev libncurses5-dev:i386 x11proto-core-dev \
libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 \
libgl1-mesa-dev g++-multilib mingw32 cmake tofrodos \
python-markdown libxml2-utils xsltproc zlib1g-dev:i386 lzop lib32stdc++6
$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so
  • Ubuntu 16.04 软件包安装

sudo apt-get install git gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler mtools \
parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools linaro-image-tools libssl-dev \
autotools-dev libsigsegv2 m4 libdrm-dev curl sed make binutils build-essential gcc g++ bash \
patch gzip bzip2 perl tar cpio python unzip rsync file bc wget libncurses5 libglib2.0-dev openssh-client lib32stdc++6
  • 安装 ARM 交叉编译工具链和编译内核相关软件包

$ sudo apt-get install gcc-arm-linux-gnueabihf \
gcc-aarch64-linux-gnu device-tree-compiler lzop libncurses5-dev \
libssl1.0.0 libssl-dev

下载 Firefly_Linux_SDK

Firefly_Linux_SDK 源码包比较大,可以通过如下方式获取 Firefly_Linux_SDK源码包:下载链接

下载完成后先验证一下 MD5 码:

$ md5sum firefly-sdk-20200629.7z
d8c52272725ff8a2216fc2be7a92ffc4  firefly-sdk-20200629.7z

确认无误后,就可以解压:

7z x firefly-sdk-20200629.7z
cd firefly-sdk
git reset --hard
  • 更新

注意:解压后务必要先更新下远程仓库。以下为从 github 处更新的方法:

#1. 进入SDK根目录
cd firefly-sdk

#2. 下载远程bundle仓库
git clone https://github.com/FireflyTeam/bundle.git -b rk3399-linux-bundle

#3. 若clone失败,可以前往github下载bundle.zip:

#4. 更新SDK,并且后续更新不需要再次拉取远程仓库,直接执行以下命令即可
./bundle/update rk3399-linux-bundle

#5. 按照提示已经更新内容到 FETCH_HEAD,同步FETCH_HEAD到firefly分支
git rebase FETCH_HEAD

#6 更新共用仓库
./bundle/update common-linux-bundle
git rebase FETCH_HEAD

Linux_SDK 目录

$ tree -L 1
.
├── app
├── buildroot
├── build.sh -> device/rockchip/common/build.sh
├── bundle
├── debian
├── device
├── distro
├── docs
├── envsetup.sh -> buildroot/build/envsetup.sh
├── external
├── kernel
├── Makefile -> buildroot/build/Makefile
├── mkfirmware.sh -> device/rockchip/common/mkfirmware.sh
├── prebuilts
├── rkbin
├── rkflash.sh -> device/rockchip/common/rkflash.sh
├── tools
├── u-boot
└── yocto

编译SDK

编译前配置:

device/rockchip/rk3328/目录下,选择对应的板型的配置文件

本文以编译Ubuntu固件为例子:使用roc-rk3328-cc-ubuntu.mk配置文件

注意: 编译Buildroot固件使用roc-rk3328-cc-buildroot.mk配置文件

配置文件使用source命令包含其它文件的方式,一些配置选项在其包含的文件中。

相关配置介绍:

# Target arch
export RK_ARCH=arm64                                            64位ARM架构
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=firefly-rk3328                        u-boot配置文件
# Kernel defconfig
export RK_KERNEL_DEFCONFIG=firefly-rk3328_defconfig             kernel配置文件
# Kernel dts
export RK_KERNEL_DTS=rk3328-roc-cc                              dts文件
# parameter for GPT table
export RK_PARAMETER=parameter-ubuntu.txt                        分区表(关键)
# rootfs image path
export RK_ROOTFS_IMG=ubuntu_rootfs/rk3328_ubuntu_rootfs.img     根文件系统路径

重点:

配置Rootfs

如果编译Buildroot固件,跳过此步,如果编译的是Ubuntu固件,需要通过以下步骤来配置:

以Ubuntu18.04为例

1、 下载根文件系统:Ubuntu18.04 根文件系统,放到SDK路径下。

2、 该文件为7z压缩包,解压该文件。

7z x rk3328-ubuntu1804-arm64-rootfs.7z

3、 完成上述后,得到rk3328-ubuntu1804-arm64-rootfs.img,拷贝根文件系统到ubuntu_rootfs目录下。

mkdir ubuntu_rootfs
cp rk3328-ubuntu1804-arm64-rootfs.img ubuntu_rootfs/

4、 在 device/rockchip/rk3328/firefly-rk3328-ubuntu.mk 中,将“# rootfs image path”修改为以下的配置选项或者在 device/rockchip/rk3328/roc-rk3328-cc-ubuntu.mk 中添加该配置选项。

export RK_ROOTFS_IMG=ubuntu_rootfs/rk3328-ubuntu1804-arm64-rootfs.img

编译配置文件:

./build.sh roc-rk3328-cc-ubuntu.mk

运行完上述脚本后,在 device/rockchip/ 目录下,生成.BoardConfig.mk 软链接 device/rockchip/rk3328/roc-rk3328-cc-ubuntu.mk.

完全编译

./build.sh

注意:若用户需要用的根文件系统是Debian或者Ubuntu时,请!先!将!对应的根文件系统准备好,不然在执行该build.sh脚本时,会在整理分区镜像、打包固件时出错,这部分操作在以下的“部分编译”中“编译rootfs”有详细说明,按照操作执行即可!

build.sh脚本运行完成后,会将分区镜像和统一固件放在rockdev/目录下,同时创建IMAGE/目录备份。

模块化编译:

编译u-boot:

./build.sh uboot

编译kernel:

./build.sh kernel

编译rootfs:

本SDK支持三种根文件系统,分别是Buildroot、Debian、Ubuntu;

  • Buildroot

编译 Buildroot 文件系统前请在编译前配置中选择roc-rk3328-cc-buildroot.mk为配置文件。

编译 Buildroot 环境搭建所依赖的软件包安装命令如下:

sudo apt-get install repo git-core gitk git-gui gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler \
gcc-aarch64-linux-gnu mtools parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools linaro-image-tools \
autoconf autotools-dev libsigsegv2 m4 intltool libdrm-dev curl sed make binutils build-essential gcc g++ bash \
patch gzip bzip2 perl tar cpio python unzip rsync file bc wget libncurses5 libqt4-dev libglib2.0-dev libgtk2.0-dev \
libglade2-dev cvs git mercurial rsync openssh-client subversion asciidoc w3m dblatex graphviz python-matplotlib \
libc6:i386 libssl-dev texinfo liblz4-tool genext2fs expect

搭建环境完成后,编译Buildroot,执行如下命令:

./build.sh rootfs
  • Debian

编译 Debian 环境搭建所依赖的软件包安装命令如下:

sudo apt-get install repo git-core gitk git-gui gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler \
gcc-aarch64-linux-gnu mtools parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools linaro-image-tools \
gcc-4.8-multilib-arm-linux-gnueabihf gcc-arm-linux-gnueabihf libssl-dev gcc-aarch64-linux-gnu g+conf autotools-dev \
libsigsegv2 m4 intltool libdrm-dev curl sed make binutils build-essential gcc g++ bash patch gzip bzip2 perl \
tar cpio python unzip rsync file bc wget libncurses5 libqt4-dev libglib2.0-dev libgtk2.0-dev libglade2-dev cvs \
git mercurial rsync openssh-client subversion asciidoc w3m dblatex graphviz python-matplotlib libc6:i386 \
libssl-dev texinfo liblz4-tool genext2fs 

搭建环境完成后,编译Debian,按照自身需求,执行如下命令:

cd rootfs/

## Usage for 32bit Debian
Building a base debian system by ubuntu-build-service from linaro.

    sudo apt-get install binfmt-support qemu-user-static
    sudo dpkg -i ubuntu-build-service/packages/*
    sudo apt-get install -f
    RELEASE=stretch TARGET=desktop ARCH=armhf ./mk-base-debian.sh

Building the rk-debain rootfs with debug:

    VERSION=debug ARCH=armhf ./mk-rootfs-stretch.sh

Creating the ext4 image(linaro-rootfs.img):

    ./mk-image.sh
------------------------------------------------------------------

## Usage for 64bit Debian
Building a base debian system by ubuntu-build-service from linaro.

    sudo apt-get install binfmt-support qemu-user-static
    sudo dpkg -i ubuntu-build-service/packages/*
    sudo apt-get install -f
    RELEASE=stretch TARGET=desktop ARCH=arm64 ./mk-base-debian.sh

Building the rk-debain rootfs with debug:

    VERSION=debug ARCH=arm64 ./mk-rootfs-stretch-arm64.sh

Creating the ext4 image(linaro-rootfs.img):

    ./mk-image.sh

完成上述后,会在rootfs目录下,生成linaro-rootfs.img.修改device/rockchip/.BoardConfig.mk中的根文件系统路径即可,参考配置前编译中的“配置Rootfs”.

  • Ubuntu

以Ubuntu18.04为例

1、 下载根文件系统:Ubuntu18.04 根文件系统,放到SDK路径下。

2、 该文件为7z压缩包,解压该文件。

7z x rk3328-ubuntu1804-arm64-rootfs.7z

3、 完成上述后,得到rk3328_ubuntu_18.04.img,拷贝根文件系统到rootfs目录下。

mkdir ubuntu_rootfs
cp rk3328-ubuntu1804-arm64-rootfs.img ubuntu_rootfs/

编译recovery:

./build.sh recovery

补充说明:

Usage: build.sh [OPTIONS]
Available options:
*.mk               -switch to specified board config
uboot              -build uboot
spl                -build spl
kernel             -build kernel
modules            -build kernel modules
toolchain          -build toolchain
extboot            -build extlinux boot.img, boot from EFI partition
rootfs             -build default rootfs, currently build buildroot as default
buildroot          -build buildroot rootfs
ramboot            -build ramboot image
multi-npu_boot     -build boot image for multi-npu board
yocto              -build yocto rootfs
debian             -build debian9 stretch rootfs
distro             -build debian10 buster rootfs
pcba               -build pcba
recovery           -build recovery
all                -build uboot, kernel, rootfs, recovery image
cleanall           -clean uboot, kernel, rootfs, recovery
firmware           -pack all the image we need to boot up system
sdupdateimg        -pack sdupdate image
updateimg [-p]     -pack update image; [-p] compress
sdbootimg [-p]     -pack sdboot image; [-p] compress
otapackage         -pack ab update otapackage image
save               -save images, patches, commands used to debug
allsave            -build all & firmware & updateimg & save

Default option is 'allsave'.

打包固件

parameter分区表

parameter.txt文件中包含了固件的重要信息,如以rk3288为例: 路径:device/rockchip/rk3328/parameter-ubuntu.txt

FIRMWARE_VER: 8.1
MACHINE_MODEL: RK3328
MACHINE_ID: 007
MANUFACTURER: RK3328
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3328
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00010000@0x0000a000(boot),0x00010000@0x0001a000(recovery),0x00010000@0x0002a000(backup),0x00600000@0x0005a000(rootfs),-@0x0065a000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9

CMDLINE属性是我们关注的地方,以uboot为例 0x00002000@0x00004000(uboot)中0x00004000为uboot分区的起始位置0x00002000为分区的大小,后面相同,用户可以根据自己需要增减或者修改分区信息,但是请最少保留uboot,trust,boot,rootfs分区,这是机器能正常启动的前提条件。

  • 分区介绍:

uboot    分区:  uboot编译出来的 uboot.img.
trust    分区:  uboot编译出来的 trust.img
misc     分区:  misc.img开机检测进入recovery模式.
boot     分区:  编译出来的 boot.img包含kernel和设备树信息.
recovery 分区:  烧写 recovery.img.
backup   分区:  预留,暂时没有用。后续跟 android 一样作为 recovery 的 backup 使用.
oem      分区:  给厂家使用,存放厂家的 app 或数据,只读,代替原来音箱的 data 分区,挂载在/oem 目录.(可省略)
rootfs   分区:  存放 buildroot 或者 debian 编出来的rootfs.img只读.
userdata 分区:  存放app临时生成的文件或者是给最终用户使用。可读写,挂载在/userdata目录下.(可省略)

注意:若发现根文件分区大小异常时,执行如下命令:

resize2fs /dev/mmcblk2p5

package-file

package-file文件用于打包统一固件时确定需要的分区镜像和镜像路径,同时它需要与parameter.txt文件保持一致。 路径tools/linux/Linux_Pack_Firmware/rockdev/目录下,以package-file为例:

# NAME          Relative path
#
#HWDEF          HWDEF
package-file    package-file
bootloader  Image/MiniLoaderAll.bin
parameter   Image/parameter.txt
trust       Image/trust.img
uboot       Image/uboot.img
boot        Image/boot.img
misc        Image/misc.img
recovery    Image/recovery.img
rootfs      Image/rootfs.img
userdata:grow RESERVED
backup      RESERVED

打包

  • 整理分区镜像到rockdev/目录下

./mkfirmware.sh

每次打包固件前先确保 rockdev/ 目录下文件链接是否正确:

$ tree -L 1 rockdev/
rockdev/
├── boot.img -> ../kernel/boot.img
├── MiniLoaderAll.bin -> ../u-boot/rk3328_loader_v1.16.250.bin
├── misc.img -> ../device/rockchip/rockimg/wipe_all-misc.img
├── oem.img
├── pack
├── parameter.txt -> ../device/rockchip/rk3328/parameter-buildroot.txt
├── recovery.img -> ../buildroot/output/rockchip_rk3328_recovery/images/recovery.img
├── rootfs.ext4 -> ../buildroot/output/rockchip_rk3328/images/rootfs.ext2
├── rootfs.img -> ../buildroot/output/rockchip_rk3328/images/rootfs.ext2
├── trust.img -> ../u-boot/trust.img
├── uboot.img -> ../u-boot/uboot.img
└── userdata.img
  • 整合统一固件

./build.sh updateimg

输入该命令后将会提醒是否需要重命名,输入y可以将固件重新命名,输入n使用默认的固件名字,在rockdev/pack目录下生成该固件。

注意:每次打包固件前,需要运行mkfirmware.sh脚本更新rockdev/下的分区镜像。

烧写固件

工具下载

Windows升级

下载 AndroidTool2.58后,解压,运行里面的 AndroidTool.exe(注意,如果是 Windows 7/8,需要按鼠标右键,选择以管 理员身份运行),如下图: _images/linux_compile1.png

前提:设备烧写固件或分区镜像时,需处于Loader模式或Maskrom模式,参考设备模式

烧写统一固件 update.img

烧写统一固件 update.img 的步骤如下:

  1. 切换至”升级固件”页。

  2. 按”固件”按钮,打开要升级的固件文件。升级工具会显示详细的固件信息

  3. 按”升级”按钮开始升级。

  4. 如果升级失败,可以尝试先按”擦除Flash”按钮来擦除 Flash,然后再升级。

注意:如果你烧写的固件loader版本与原来的机器的不一致,请在升级固件前先执行”擦除Flash”。 _images/linux_compile2.png

烧写分区映像

烧写分区映像时,请使用对应SDK下的FFTools/AndroidTool.rar烧写。步骤如下:

  1. 切换至”下载镜像”页。

  2. 勾选需要烧录的分区,可以多选。

  3. 确保映像文件的路径正确,需要的话,点路径右边的空白表格单元格来重新选择。

  4. 点击”执行”按钮开始升级,升级结束后设备会自动重启。 _images/linux_compile3.png

Linux升级

下载Upgrade_tool1.34.zip后,解压,将upgrade_tool拷贝到/usr/local/bin/目录下,操作如下:

unzip Linux_Upgrade_Tool_v1.34.zip
cd Linux_Upgrade_Tool
sudo mv upgrade_tool /usr/local/bin
sudo chown root:root /usr/local/bin/upgrade_tool

统一固件烧写

  • 使用upgrade_tool工具烧写:

sudo upgrade_tool uf update.img
  • 使用SDK脚本烧写:

./rkflash.sh firmware

分区镜像烧写

  • 使用upgrade_tool工具烧写:

sudo upgrade_tool ul $LOADER
sudo upgrade_tool di -p $PARAMETER
sudo upgrade_tool di -uboot $UBOOT
sudo upgrade_tool di -trust $TRUST
sudo upgrade_tool di -misc $MISC
sudo upgrade_tool di -b $BOOT
sudo upgrade_tool di -recovery $RECOVERY
sudo upgrade_tool di -rootfs $ROOTFS
  • 使用脚本烧写:

#全自动烧写
./rkflash.sh
#分区镜像烧写
./rkflash.sh loader
./rkflash.sh parameter
./rkflash.sh uboot
./rkflash.sh trust
./rkflash.sh misc
./rkflash.sh boot
./rkflash.sh recovery
./rkflash.sh rootfs

说明:rkflash.sh该脚本文件的原理便是使用upgrade_tool工具烧写