因为需要4.19的内核,需要制作树莓派的img镜像,因此,就顺便编译一下树莓派3B+的内核,并制作成树莓派镜像。
树莓派镜像制作
一、树莓派介绍
树莓派介绍
树莓派由注册于英国的慈善组织“Raspberry Pi 基金会”开发,Eben·Upton/埃·厄普顿为项目带头人。2012年3月,英国剑桥大学埃本·阿普顿(Eben Epton)正式发售世界上最小的台式机,又称卡片式电脑,外形只有信用卡大小,却具有电脑的所有基本功能,这就是Raspberry Pi电脑板,中文译名"树莓派"。
二、基础环境
- 使用X86交叉编译
- 需要10G的硬盘空间
本文使用的是ubuntu 16.04的系统
三、基础环境安装
3.1 编译内核用的工具gcc
3.1.1下载并配置gcc
- 64位下载
root@ubuntu16:~# wget https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/aarch64-linux-gnu/gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu.tar.xz
# 下载64位gcc
root@ubuntu16:~# mkdir ~/toolchains
# 创建文件夹
root@ubuntu16:~# tar xf gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu.tar.xz -C ~/toolchains/
# 解压缩
root@ubuntu16:~# cd ~/toolchains/gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu/
root@ubuntu16:~# echo 'export PATH=${PATH}:$(pwd)/bin' > env.sh
# 创建环境变量
root@ubuntu16:~# source env.sh
# 让环境变量在当前终端生效
- 32位下载
root@ubuntu16:~# wget https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/aarch64-linux-gnu/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu.tar.xz
# 下载32位gcc
root@ubuntu16:~# mkdir ~/toolchains
# 创建文件夹
root@ubuntu16:~# tar xf gcc-linaro-4.9-2017.01-i686_aarch64-linux-gnu.tar.xz -C ~/toolchains/
# 解压缩
root@ubuntu16:~# cd ~/toolchains/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/
root@ubuntu16:~# echo 'export PATH=${PATH}:$(pwd)/bin' > env.sh
# 配置环境变量
root@ubuntu16:~# source env.sh
# 让环境变量在当前终端生效
3.2 安装依赖环境
依赖环境安装
root@ubuntu16:~# sudo apt install build-essential bison make debootstrap qemu-user-static kpartx util-linux vim git libncurses5-dev bc git dosfstools -y
# 安装依赖
root@ubuntu16:~# sudo service binfmt-support start
# 启动binfmt服务
3.3 下载内核并配置
3.3.1 下载内核
root@ubuntu16:~# mkdir ~/kernel
root@ubuntu16:~# cd ~/kernel
# 创建文件夹并进入
root@ubuntu16:~# git clone https://github.com/raspberrypi/linux.git
# 下载linux内核
3.4 下载树莓派的启动文件
root@ubuntu16:~# git clone --depth=1 https://github.com/raspberrypi/firmware/
# git上下载boot文件
3.5 配置树莓派固件
- wifi固件
- 树莓派3b
1.1 固件1:brcmfmac43430-sdio.bin
root@ubuntu16:~# mkdir ~/wifi
root@ubuntu16:~# cd ~/wifi
# 新建文件夹并进入
root@ubuntu16:~# wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac43430-sdio.bin
# 下载brcmfmac43430-sdio.bin
1.2 固件2:brcmfmac43430-sdio.txt
root@ubuntu16:~# wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.txt
# 下载tree/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.txt
root@ubuntu16:~# cp brcmfmac43430-sdio.raspberrypi,3-model-b.txt brcmfmac43430-sdio.txt
# 复制并改名
- 树莓派3b+
2.1 固件1:brcmfmac43455-sdio.bin
root@ubuntu16:~# mkdir ~/wifi
root@ubuntu16:~# cd ~/wifi
# 创建文件夹并进入
root@ubuntu16:~# https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac43455-sdio.bin
# 下载brcmfmac43455-sdio.bin
2.2 固件2:brcmfmac43455-sdio.txt
root@ubuntu16:~# https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt
# 下载brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt
root@ubuntu16:~# cp brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt brcmfmac43455-sdio.txt
# 复制并改名
- 蓝牙固件
- 树莓派3b
1.1 固件:BCM43430A1.hcd
root@ubuntu16:~# mkdir ~/bluetooth
root@ubuntu16:~# cd ~/bluetooth
root@ubuntu16:~# wget https://github.com/RPi-Distro/bluez-firmware/raw/master/broadcom/BCM43430A1.hcd
- 树莓派3b+
2.1 固件:BCM4345C0.hcd
root@ubuntu16:~# mkdir ~/bluetooth
root@ubuntu16:~# cd ~/bluetooth
root@ubuntu16:~# wget https://github.com/RPi-Distro/bluez-firmware/raw/master/broadcom/BCM4345C0.hcd
四、编译内核
4.1 检查环境变量
root@ubuntu16:~# which aarch64-linux-gnu-gcc
4.2 创建内核编译环境变量并检查
root@ubuntu16:~# echo 'export ARCH=arm64' >> env.sh
root@ubuntu16:~# echo 'export CROSS_COMPILE=aarch64-linux-gnu-' >> env.sh
# 创建环境变量
root@ubuntu16:~# source env.sh
# 初始化环境变量
root@ubuntu16:~# echo "${ARCH}"
# 检查ARCH
root@ubuntu16:~# echo "${CROSS_COMPILE}"
# 检查CROSS_COMPILE
# 如果ARCH为arm64,CROSS_COMPILE为aarch64-linux-gnu-,环境配置正确
4.3 编译内核
4.3.1 内核编译1
root@ubuntu16:~# cd ~/kernel/linux
root@ubuntu16:~# make bcmrpi3_defconfig
# 生成默认配置文件
root@ubuntu16:~# make menuconfig
# 修改默认配置文件
4.3.2 内核配置
默认为配置如下图所示:
- 如果需要虚拟化支持,请选择
[*] Virtualization ---
[*] Kernel-based Virtual Machine (KVM) support
<M> Host kernel accelerator for virtio net
[*] Cross-endian support for vhost
# 在Virtualization下的所有选项选中
# 然后按住左右按键找到save保存一下
- 如果需要cgroup支持,请选择
General setup --->
-*- Control Group support --->
[*] Memory controller
[*] Swap controller
[*] Swap controller enabled by default (NEW)
[*] IO controller
-*- CPU controller --->
[*] CPU bandwidth provisioning for FAIR_GROUP_SCHED
[*] Group scheduling for SCHED_RR/FIFO
[*] PIDs controller
[*] RDMA controller
[*] Freezer controller
[*] Cpuset controller
[*] Include legacy /proc/<pid>/cpuset file
[*] Device controller
[*] Simple CPU accounting controller
- 如果需要Checkpoint/restore支持,请选择:
使用CRIU必须开启
General setup --->
[*] Checkpoint/restore support
- 在内核里选择你需要的驱动
例如usb网卡驱动
Device Drivers --->
[*] Network device support --->
[*] Wireless LAN --->
[*] Realtek devices
<M> Realtek 8187 and 8187B USB support
<M> Realtek rtlwifi family of devices --->
<M> Realtek 8192C USB WiFi
<M> RTL8723AU/RTL8188[CR]U/RTL819[12]CU (mac80211) support
选择完成后选择save后按exit钮退出即可
4.3.3 内核编译
root@ubuntu16:~# make -j 4
# 编译内核
五、制作rootfs
- 首先创建rootfs文件夹
root@ubuntu16:~# mkdir ~/rootfs/
请从以下地址选取rootfs
基本rootfs镜像
- Archlinux 64 位官方rootfs:
http://mirrors.ustc.edu.cn/archlinuxarm/os/ArchLinuxARM-aarch64-latest.tar.gz - Gentoo 64 位官方rootfs:
http://distfiles.gentoo.org/experimental/arm64/ - Ubuntu 64 位官方rootfs:
- xenial:
http://mirrors.ustc.edu.cn/ubuntu-cdimage/ubuntu-base/releases/xenial/release/ubuntu-base-16.04.5-base-arm64.tar.gz - bionic:
http://mirrors.ustc.edu.cn/ubuntu-cdimage/ubuntu-base/releases/bionic/release/ubuntu-base-18.04.1-base-arm64.tar.gz
- 我选取的位ubuntu16.04版本
root@ubuntu16:~# mkdir -p ~/rootfs/4.19/
# 创建文件夹
root@ubuntu16:~# cd rootfs/4.19
# 进入
root@ubuntu16:~# cp /usr/bin/qemu-aarch64-static usr/bin
# 拷贝qemu-aarch64-static到usr/bin
- 挂载文件并进入
root@ubuntu16:~# sudo mount -o bind /dev/ dev
root@ubuntu16:~# sudo mount -o bind /dev/pts dev/pts
root@ubuntu16:~# sudo mount -o bind /proc proc
root@ubuntu16:~# sudo mount -o bind /sys sys
root@ubuntu16:~# $ sudo cp etc/hosts etc/hosts.bak
# 备份原HOSTS
root@ubuntu16:~# sudo cp etc/resolv.conf etc/resolv.conf.bak
#备份原resolv.conf
root@ubuntu16:~# sudo cp /etc/hosts etc/hosts
# 复制系统文件
root@ubuntu16:~# sudo cp /etc/resolv.conf etc/resolv.conf
# 复制系统文件
root@ubuntu16:~# sudo chroot ./ /bin/sh
# 使用chroot进入
- 安装依赖
chroot #
# 进入后
chroot # passwd root
# 更改密码,注意登入需要
chroot # apt update
# 更新
chroot # apt install vim wpasupplicant net-tools openssh-server bash-com* netbase iproute2 iputils-ping git
# 安装依赖
chroot # exit
# 退出
- 卸载文件系统并恢复网络配置
root@ubuntu16:~# sudo umount dev/pts
root@ubuntu16:~# sudo umount dev
root@ubuntu16:~# sudo umount proc
root@ubuntu16:~# sudo umount sys
# 卸载文件系统
root@ubuntu16:~# sudo mv etc/hosts.bak etc/hosts
root@ubuntu16:~# sudo mv etc/resolv.conf.bak etc/resolv.conf
# 恢复网络配置
- 计算一下rootfs大小
root@ubuntu16:~# sudo du -sh ./
# 有用
- 镜像大小计算公式
镜像大小= rootfs大小 + 300M + 200M
五、制作镜像文件
5.1 分区
首先创建images文件
- 创建images文件
root@ubuntu16:~# mkdir ~/images/
root@ubuntu16:~# cd ~/images/
root@ubuntu16:~# dd bs=1M count=545 if=/dev/zero of=ubuntu.img
# 根据镜像大小计算公式计算出的镜像大小来创建,本文创建的大小位545M
为镜像分区
- 为镜像分区
root@ubuntu16:~# cfdisk ubuntu.img
分区表选择dos
- 分区表选择dos
┌ Select label type ───┐
│ gpt │
│ dos * │
│ sgi │
│ sun │
└──────────────────────┘
Device does not contain a recognized partition table.
Select a type to create a new label or press 'L' to load script file.
选 new 创建分区,分区大小为100M,并且选择主分区,分区如下所示
Disk: ubuntu.img
Size: 545 MiB, 571473920 bytes, 1116160 sectors
Label: dos, identifier: 0xd5f9f036
Device Boot Start End Sectors Size Id Type
>> ubuntu.img1 * 2048 206847 204800 100M 83 Linux
Free space 206848 1116159 909312 444M
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│Partition type: Linux (83) │
│ Attributes: 80 │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
[ * Bootable] [ Delete ] [ Resize ] [ Quit ] [ Type ] [ Help ] [ Write ] [ Dump ]
选bootable使刚才创建的分区设定为可启动,Boot下,有一个星号代表设置完成
Device Boot Start End Sectors Size Id Type
>> ubuntu.img1 * 2048 206847 204800 100M 83 Linux
Free space 206848 1116159 909312 444M
选“type”改变分区标识,找到“W95 FAT32” 并回车,成功之后“Id Type”显示“b W95 FAT32”字样
Device Boot Start End Sectors Size Id Type
>> ubuntu.img1 * 2048 206847 204800 100M 83 Linux b W95 FAT32
Free space 206848 1116159 909312 444M
按方向健下,切换到空余空间.选择new新健一个分区,分区使用所有空余空间,选择primary 主分区,成功之后如下显示
Device Boot Start End Sectors Size Id Type
>> ubuntu.img1 * 2048 206847 204800 100M 83 Linux b W95 FAT32
ubuntu.img2 206848 1116159 909312 444M
选择Write 将更改写入镜像
5.2 写入内容到img文件
5.2.1用kpartx挂载镜像到loop
root@ubuntu16:~/images# kpartx -av ubuntu.img
add map loop0p1 (252:2): 0 204800 linear 7:0 2048
add map loop0p2 (252:3): 0 909312 linear 7:0 206848
# 输出的信息就是需要挂载的文件
# loop0p1 为第一个分区
# loop0p2 为第二个分区
5.2.2 格式化分区
- 格式化为ext4
root@ubuntu16:~/images# sudo mkfs.vfat /dev/mapper/loop0p1
# 格式化第一个分区
root@ubuntu16:~/images# sudo mkfs.ext4 /dev/mapper/loop0p2
# 格式化第二个分区
- 格式化为f2fs【如果你想把第二个分区格式化为f2fs】
root@ubuntu16:~/images# sudo apt install f2fs-tools
root@ubuntu16:~/images# sudo mkfs.f2fs -f /dev/mapper/loop0p2
# 格式化第二个分区
5.2.3挂载镜像
root@ubuntu16:~/images# sudo mkdir /mnt/loop0p1
# 创建文件夹
root@ubuntu16:~/images# sudo mount /dev/mapper/loop0p1 /mnt/loop0p1
# 挂载loop0p1
root@ubuntu16:~/images# sudo mkdir /mnt/loop0p2
# 创建文件夹
root@ubuntu16:~/images# sudo mount /dev/mapper/loop0p2 /mnt/loop0p2
# 挂载loop0p2
5.2.4向镜像里写入内容
向第一个分区写入内容
向第一个分区写入内容
本节内容是向第一个分区写入启动引导。
- 为第一个分区写入内容
root@ubuntu16:~/images# cp -r /root/firmware/boot/* /mnt/loop0p1/
# 复制boot文件到loop0p1
root@ubuntu16:~/images# cd ~/kernel/linux/
# 进入编译的内核的工作目录
root@ubuntu16:~/kernel/linux# sudo cp ./arch/arm64/boot/Image /mnt/loop0p1/kernel8.img
# 复制编译好的内核
root@ubuntu16:~/kernel/linux# sudo mv /mnt/loop0p1/bcm2710-rpi-3-b.dtb /mnt/loop0p1/bcm2710-rpi-3-b.dtb_32
root@ubuntu16:~/kernel/linux# sudo mv /mnt/loop0p1/bcm2710-rpi-3-b-plus.dtb /mnt/loop0p1/bcm2710-rpi-3-b-plus.dtb_32
# 将32位的dtb文件更名
root@ubuntu16:~/kernel/linux# sudo cp ./arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /mnt/loop0p1/bcm2710-rpi-3-b.dtb
root@ubuntu16:~/kernel/linux# sudo cp ./arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dtb /mnt/loop0p1/bcm2710-rpi-3-b-plus.dtb
# 复制64位的dtb文件
- 写cmdline.txt
root@ubuntu16:~/kernel/linux# sudo vim /mnt/loop0p1/cmdline.txt
写入内容
root=/dev/sda2 rootfstype=ext4 rw rootwait fsck.repair=yes program_usb_boot_mode=1
注意:“program_usb_boot_mode=1”为u盘启动,如果内存卡启动请删除“program_usb_boot_mode=1”这行代码
- 其他说明
1.1 root=/dev/sda2 将第二分区设置为根分区
1.2 rootfstype=ext4 根分区类型 f2fs应更换为f2fs
1.3 rw 可写挂载跟分区
1.4 rootwait 等待内核识别根分区设备后再挂载
1.5 fsck.repair=yes 启动时自动检查修复文件系统错误
向第二个分区写入内容
向第二个分区写入内容
本节主要内容是安装内核模块、固件和rootfs系统到镜像的第二个分区。
- 1.安装内核模块
root@ubuntu16:~/kernel/linux# cd ~/kernel/linux
#进入编译内核的工作目录
root@ubuntu16:~/kernel/linux# make modules_install INSTALL_MOD_PATH=/mnt/loop0p2
- 2.放入wifi和蓝牙固件
root@ubuntu16:~/kernel/linux# mkdir -p /mnt/loop0p2/lib/firmware/brcm
root@ubuntu16:~/kernel/linux# cp -r ~/wifi/* /mnt/loop0p2/lib/firmware/brcm/
root@ubuntu16:~/kernel/linux# cp -r ~/bluetooth/* /mnt/loop0p2/lib/firmware/brcm/
root@ubuntu16:~/kernel/linux# sync
# 同步写入
- 3.写入rootfs系统
root@ubuntu16:~# sudo apt install rsync
# 安装rsync同步工具
root@ubuntu16:~# sudo rsync -HPavz -q ./ /mnt/loop0p2
# 使用rsync同步到loop0p2分区
root@ubuntu16:~# sync
# 同步一下
- 4.卸载分区
root@ubuntu16:~/kernel/linux# sudo umount /dev/mapper/loop0p1
root@ubuntu16:~/kernel/linux# sudo umount /dev/mapper/loop0p2
root@ubuntu16:~/kernel/linux# sudo kpartx -dv /dev/loop0
root@ubuntu16:~/kernel/linux# sudo losetup -d /dev/loop0
六、测试
请自己进行测试,如果按照我的步骤来,应该不会出错,本人已经实验完成。
滴!访客卡!请上车的乘客系好安全带,现在是:Fri Mar 06 2020 14:15:09 GMT+0800 (中国标准时间)