- Published on
uboot从sd卡启动kernel
- Authors
- Name
- JiGu
- @crypto20x
qemu启动uboot
qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot -nographic -no-reboot
下面是uboot加载的日志
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
U-Boot 2024.07 (Sep 02 2024 - 17:26:56 +0800)
DRAM: 512 MiB
WARNING: Caches not enabled
Core: 23 devices, 11 uclasses, devicetree: embed
Flash: 128 MiB
MMC: mmci@5000: 0
Loading Environment from Flash... *** Warning - bad CRC, using default environment
In: uart@9000
Out: uart@9000
Err: uart@9000
Net: eth0: ethernet@3,02000000
Hit any key to stop autoboot: 0
MMC Device 1 not found
no mmc device at slot 1
Card did not respond to voltage select! : -110
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (3 ms)
*** Warning: no boot file name; using '0A00020F.img'
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename '0A00020F.img'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
missing environment variable: pxefile_addr_r
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (0 ms)
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename 'boot.scr.uimg'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (1 ms)
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename 'boot.scr.uimg'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
cp - memory copy
Usage:
cp [.b, .w, .l] source target count
Wrong Image Type for bootm command
ERROR -91: can't get kernel image!
从log看到,uboot通过tftp网络读取kernel镜像,但是找不到。uboot可以从sd卡读取,制作一SD卡,将kernel,rootfs,dtb文件放到sd卡, 在uboot中将sd卡文件载入到DDR,从DDR启动内核。
创建sd卡
创建sd卡文件
dd if=/dev/zero of=./sd_scard bs=1M count=512
给sd卡分区
sudo fdisk /home/victor/work/sd_card
# 键入 o n w
# n的时候有几个参数,全部default即可
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xb0076014.
Command (m for help): o
Created a new DOS disklabel with disk identifier 0x34a29c34.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-1048575, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1048575, default 1048575):
Created a new partition 1 of type 'Linux' and of size 511 MiB.
Command (m for help): w
The partition table has been altered.
Syncing disks.
创建vfat文件系统
sudo mkfs.vfat sd_scard
file sd_scard
sd_scard: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "mkfs.fat", sectors/cluster 8, Media descriptor 0xf8, sectors/track 63, heads 255, sectors 1048576 (volumes > 32 MB), FAT (32 bit), sectors/FAT 1024, serial number 0xe3792218, unlabeled
制作uramdisk.img
下载最新的busybox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
make defconfig #加载默认配置
make CROSS_COMPILE=arm-linux-gnueabi- #编译
make install CROSS_COMPILE=arm-linux-gnueabi- #安装
编译的bin文件生成在_install/
路径下
- 创建根目录
mkdir -p rootfs/{dev,etc/init.d,lib}
- 拷贝bin文件到rootfs
cp -rf _install/* rootfs/
- 拷贝库文件到lib目录下
cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/
- 创建proc和sys目录
mkdir rootfs/proc
mkdir rootfs/sys
mkdir rootfs/config
mkdir rootfs/debug
之所以要创建这两个目录,因为后面需要挂载procfs和sysfs两个文件系统。当然,这两个目录也可以在启动脚本中创建。
- 修改为root
sudo chown -R root:root rootfs/
- 创建4个tty终端设备
sudo mknod rootfs/dev/tty1 c 4 1
sudo mknod rootfs/dev/tty2 c 4 2
sudo mknod rootfs/dev/tty3 c 4 3
sudo mknod rootfs/dev/tty4 c 4 4
- 制作根文件系统
dd if=/dev/zero of=a9rootfs.ext4 bs=1M count=32
- 格式化成ext4格式
mkfs.ext4 a9rootfs.ext4
```git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git
- ext4格式uboot无法引导,重新制作`initramfs`格式镜像
initrd 是一种较早的机制,使用 cpio 归档文件格式,作为临时根文件系统挂载。
initramfs 是 initrd 的现代替代方案,直接在内存中以文件系统形式存在,提供更高的灵活性和功能。
现代 Linux 系统通常使用 initramfs,因为它提供了更好的性能和更简化的操作方式。
```sh
cd rootfs/
find . |cpio -ov -H newc |gzip > ../ramdisk.img
newc
表示initramfs格式
制作的ramdisk.img uboot是无法识别的,需转换成uImage,uImage就是在头部加上64字节的信息,才能通过bootz去启动。
mkimage -A arm -O linux -C none -T ramdisk -a 0x00000000 -e 0x00000000 -n "Jcob's Root Filesystem" -d ramdisk.img uramdisk.img
Image Name: Jcob's Root Filesystem
Created: Wed Sep 4 17:48:25 2024
Image Type: ARM Linux RAMDisk Image (uncompressed)
Data Size: 6284950 Bytes = 6137.65 KiB = 5.99 MiB
Load Address: 00000000
Entry Point: 00000000
mkimage如果交叉编译工具链没有带,在编译好的u-boot/tools下有。
复制到sd卡
将sd卡挂载到 card/
mkdir card
sudo mount -tvfat sd_scard card/
拷贝uboot的image到sd卡
cp busybox-1.36.1/uramdisk.img card/
编译kernel
git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git
# 全部拉取太慢,拉取指定的版本
git clone -b v6.9 --single-branch https://mirrors.tuna.tsinghua.edu.cn/git/linux.git
编译个最新的内核试试
配置
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm -j4 # 或指定 make zImage dtbs
...
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
看到zImage is ready,编译完成了。
复制内核文件到sd卡
sudo cp linux/arch/arm/boot/zImage card/
sudo cp linux/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb card/
sudo umount card/
修改uboot配置
修改启动命令
vim configs/vexpress_ca9x4_defconfig
## CONFIG_BOOTCOMMAND="run distro_bootcmd; run bootflash"
CONFIG_BOOTCOMMAND="run bootsd"
改为bootsd
添加zImage和uramdisk配置
vim include/configs/vexpress_common.h
~/code/embeded/u-boot-2024.07/include/configs$ diff vexpress_common.h vexpress_common.h_bak
151,159d150
< "kernel_name=zImage\0" \
< "ramdisk_name=uramdisk.img\0" \
< "dtb_name=vexpress-v2p-ca9.dtb\0" \
< "kernel_jcob_addr=0x60000000\0" \
< "ramdisk_jcob_addr=0x70000000\0" \
< "dtb_jcob_addr=0x61000000\0" \
< "load_kernel=fatload mmc 0:0 ${kernel_jcob_addr} ${kernel_name}\0 " \
< "load_ramdisk=fatload mmc 0:0 ${ramdisk_jcob_addr} ${ramdisk_name}\0 "\
< "load_dtb=fatload mmc 0:0 ${dtb_jcob_addr} ${dtb_name}\0 " \
165c156
< "root=/dev/mmcblk0 rw\0" \
---
> "root=/dev/sda1 rw\0" \
171d161
< "sdargs=setenv bootargs rdinit=/sbin/init root=${root} console=${console}\0" \
175,179d164
< "bootsd=run sdargs; "\
< "run load_kernel; "\
< "run load_ramdisk; "\
< "run load_dtb; " \
< "bootz ${kernel_jcob_addr} ${ramdisk_jcob_addr} ${dtb_jcob_addr}\0"\
重新编译uboot
启动
qemu-system-arm -M vexpress-a9 -m 1024M -kernel u-boot-2024.07/u-boot -dtb linux/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb -sd sd_scard -nographic -no-reboot
报VFS错误,找不到根文件系统。提示“root=”,这里可以看到需要设定root启动设备,之前uboot启动参数漏了root=${root}
,加上。
先从qemu直接启动kernel
生成一个init程序
#include <stdio.h>
void main()
{
printf("Hello World!\n");
while(1);
}
因为init程序不能退出,所以加while
静态编译 arm-linux-gnueabi-gcc -static test.c -o test
echo test | cpio -o --format=newc > rootfs
生成一个简单的文件系统,启动kernel
qemu-system-arm -M vexpress-a9 -m 1024M -kernel linux/arch/arm/boot/zImage -dtb linux/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb -initrd rootfs -nographic -append "root=/dev/ram rdinit=/test console=ttyAMA0"
启动kernel,可以看到hello owrld就成功了,这样可以先排除kernel和设备树的问题。
启动成功
最新6.9内核,完成。