QEMUでu-bootを利用し、仮想SDカードからLinuxを起動する
- 実施環境:Ubuntu 22.04.3 LTS
- ボード:vexpress-a9(QEMU)
- ブートローダー:u-boot-2023.10
- カーネル:linux-5.15.141
- ファイルシステム:busybox-1.36.1
〇事前準備:
1.必要なソフトウェアのインストール
①クロスコンパイル環境の構築
sudo apt install gcc-arm-linux-gnueabi
②QEMUのインストール
sudo apt install qemu-system-arm
2.必要なライブラリのインストール
①opensslのライブラリをインストールする(u-bootをコンパイルする時の必要なライブラリ)
sudo apt-get install libssl-dev
②カーネルをコンパイルする時の必要なライブラリをインストールする
sudo apt-get install flex sudo apt-get install bison -y
※flexとbisonをインストールしないと、コンパイルパラメータを設定する時、「flex:not found」のエラーメッセージが出て来る。
sudo apt-get install u-boot-tools
※u-boot-toolsをインストールしないと、uImageをコンパイルする時、「"mkimage" command not found - uboot image will not be built」のエラーメッセージが出て来る。
③menuconfigを実施する必要なcursesライブラリをインストールする
sudo opt-get install libncurses5-dev
〇Bootloaderの構築:
1.u-bootをダウンロードする
https://ftp.denx.de/pub/u-boot/u-boot-2023.10.tar.bz2
2.u-bootを解凍する
zhou@zhou-Vostro-3480:~/ker-arm$ tar -xf u-boot-2023.10.tar.bz2 zhou@zhou-Vostro-3480:~/ker-arm$
3.下記の様に、u-boot-2023.10フォルダのMakefileにCROSS_COMPILEとARCHを指定する
zhou@zhou-Vostro-3480:~/ker-arm$ cd u-boot-2023.10/ zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$ vim Makefile # SPDX-License-Identifier: GPL-2.0+ VERSION = 2023 PATCHLEVEL = 10 SUBLEVEL = EXTRAVERSION = NAME = CROSS_COMPILE = arm-linux-gnueabi- ARCH = arm # *DOCUMENTATION*
4.u-bootをコンパイルする
①コンパイルパラメータの設定
zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$ make vexpress_ca9x4_defconfig HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o YACC scripts/kconfig/zconf.tab.c LEX scripts/kconfig/zconf.lex.c HOSTCC scripts/kconfig/zconf.tab.o HOSTLD scripts/kconfig/conf # # configuration written to .config # zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$
zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$ make -j8 ・・・ AR lib/built-in.o LD u-boot OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin SYM u-boot.sym COPY u-boot.bin ===================== WARNING ====================== CONFIG_OF_EMBED is enabled. This option should only be used for debugging purposes. Please use CONFIG_OF_SEPARATE for boards in mainline. See doc/develop/devicetree/control.rst for more info. ==================================================== ===================== WARNING ====================== This board does not use CONFIG_DM_SERIAL (Driver Model for Serial drivers). Please update the board to use CONFIG_DM_SERIAL before the v2023.04 release. Failure to update by the deadline may result in board removal. See doc/develop/driver-model/migration.rst for more info. ==================================================== OFCHK .config zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$
※QEMUにu-boot.binを使用できない為、u-bootを利用し、SDカードからカーネル、DTBとルートファイルシステムを読み込む
5.ボードの情報を確認する
zhou@zhou-Vostro-3480:~/ker-arm/u-boot-2023.10$ qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel u-boot pulseaudio: set_sink_input_volume() failed pulseaudio: Reason: Invalid argument pulseaudio: set_sink_input_mute() failed pulseaudio: Reason: Invalid argument ・・・ DRAM: 512 MiB WARNING: Caches not enabled Core: 18 devices, 10 uclasses, devicetree: embed Flash: 64 MiB MMC: mmci@5000: 0 Loading Environment from Flash... *** Warning - bad CRC, using default environment ・・・ Usage: cp [.b, .w, .l, .q] source target count Wrong Image Format for bootm command ERROR: can't get kernel image! => bdinfo boot_params = 0x60002000 DRAM bank = 0x00000000 -> start = 0x60000000 -> size = 0x20000000 ・・・ Early malloc usage: 370 / 400 =>
※上記より、ボードのメモリ開始アドレスは0x60000000など情報が分かれるが、それはuImageを構築する時の必要なパラメータである。
1.カーネルをダウンロードする
wget https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/snapshat/linux-5.15.141.tar.gz
2.カーネルを解凍する
zhou@zhou-Vostro-3480:~/ker-arm$ tar -xf linux-5.15.141.tar.gz
zhou@zhou-Vostro-3480:~/ker-arm$
3.コンパイルパラメータを設定する
zhou@zhou-Vostro-3480:~/ker-arm$ cd linux-5.15.141
zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.[ch]
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/menu.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTCC scripts/kconfig/util.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$
3.コンパイルする
zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- LOADADDR=0x60008000 uImage -j8 ・・・ Kernel: arch/arm/boot/Image is ready Kernel: arch/arm/boot/zImage is ready UIMAGE arch/arm/boot/uImage Image Name: Linux-5.15.141 Created: Wed Jan 10 23:03:41 2024 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 5023752 Bytes = 4906.01 KiB = 4.79 MiB Load Address: 60008000 Entry Point: 60008000 Kernel: arch/arm/boot/uImage is ready zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$
※u-bootの情報より、メモリ開始アドレスは0x60000000であることが分かるが、カーネルを実行する時、ページング用のページテーブル情報の保存も必要だったので、ロードアドレスに0x8000のオフセットを設定する(具体的なオフセットのサイズはトプフォルダのMakefileに記載されている)
zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs DTC arch/arm/boot/dts/vexpress-v2p-ca5s.dtb DTC arch/arm/boot/dts/vexpress-v2p-ca9.dtb DTC arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb DTC arch/arm/boot/dts/vexpress-v2p-ca15_a7.dtb zhou@zhou-Vostro-3480:~/ker-arm/linux-5.15.141$
〇ルートファイルシステムの構築:
1.Busyboxのダウンロード
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
2.Busyboxの解凍
zhou@zhou-Vostro-3480:~/ker-arm$ tar -xf busybox-1.36.1.tar.bz2 zhou@zhou-Vostro-3480:~/ker-arm$
zhou@zhou-Vostro-3480:~/ker-arm$ cd busybox-1.36.1 zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
メニュー画面にてSetting->Buildoptions->Build static binaryの先頭に*を付与する(どこでも使えるように)。設定が完了したら、続いてコンパイルを実施する
zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8 SPLIT include/autoconf.h -> include/config/* ・・・ zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$
5.ルートファイルを作成する
zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install ./_install//bin/arch -> busybox ./_install//bin/ash -> busybox ・・・ -------------------------------------------------- You will probably need to make your busybox binary setuid root to ensure all configured applets will work properly. -------------------------------------------------- zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$ ls applets examples networking applets_sh findutils NOFORK_NOEXEC.lst arch include NOFORK_NOEXEC.sh archival init printutils AUTHORS _install procps busybox INSTALL qemu_multiarch_testing busybox_ldscript.README.txt klibc-utils README busybox.links libbb runit busybox_unstripped libpwdgrp scripts busybox_unstripped.map LICENSE selinux busybox_unstripped.out loginutils shell Config.in mailutils size_single_applets.sh configs Makefile sysklogd console-tools Makefile.custom testsuite coreutils Makefile.flags TODO debianutils Makefile.help TODO_unicode docs make_single_applets.sh util-linux e2fsprogs miscutils editors modutils zhou@zhou-Vostro-3480:~/ker-arm/busybox-1.36.1$
※上記コマンドを実行すると、_installフォルダーを作成され、中身に必要なルートファイルが保存される。
〇仮想SDカードの作成:
説明:uImageのサイズは10Mが足りるが、FSは32Mもできる為、64Mの仮想SDカードが有余です。仮想SDカードをパーティション分割し、パート1は16Mで、uImageとディバイスツリーを格納し、パート2は48Mで、ルートファイルシステムを格納する。
1.仮想SDカードを作成する
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ dd if=/dev/zero of=sdImage bs=1M count=64
记录了64+0 的读入
记录了64+0 的写出
67108864字节(67 MB,64 MiB)已复制,0.0512024 s,1.3 GB/s
zhou@zhou-Vostro-3480:~/ker-arm/qemu$
2.使用可能のループバックデバイスを確認する
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ losetup -f
/dev/loop16
zhou@zhou-Vostro-3480:~/ker-arm/qemu$
3.仮想SDカードをループバックデバイスに関連付ける
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo losetup /dev/loop16 sdImage
[sudo] zhou 的密码:
zhou@zhou-Vostro-3480:~/ker-arm/qemu$
4.仮想SDカードのパーティションを変更し、新たなパーティションを作成する
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo sgdisk -n 0:0:+16M -c 0:ker sdImage Creating new GPT entries in memory. Setting name! partNum is 0 Warning: The kernel is still using the old partition table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8) The operation has completed successfully. zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo sgdisk -n 0:0:0 -c 0:rootfs sdImage Setting name! partNum is 1 Warning: The kernel is still using the old partition table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8) The operation has completed successfully. zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo sgdisk -p sdImage Disk sdImage: 131072 sectors, 64.0 MiB Sector size (logical): 512 bytes Disk identifier (GUID): B7DE305C-4510-4353-BB6F-A5C5FDB21D88 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 131038 Partitions will be aligned on 2048-sector boundaries Total free space is 2014 sectors (1007.0 KiB) Number Start (sector) End (sector) Size Code Name 1 2048 34815 16.0 MiB 8300 ker 2 34816 131038 47.0 MiB 8300 rootfs zhou@zhou-Vostro-3480:~/ker-arm/qemu$
5.ディスクパーティション情報を再読み込む
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo partprobe /dev/loop16 zhou@zhou-Vostro-3480:~/ker-arm/qemu$ ls /dev | grep loop16 loop16 loop16p1 loop16p2 zhou@zhou-Vostro-3480:~/ker-arm/qemu$
6.SDカードの各パーティションにファイルシステムを作成する
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo mkfs.ext4 /dev/loop16p1 mke2fs 1.46.5 (30-Dec-2021) 丢弃设备块: 完成 创建含有 4096 个块(每块 4k)和 4096 个 inode 的文件系统 正在分配组表: 完成 正在写入 inode表: 完成 创建日志(1024 个块): 完成 写入超级块和文件系统账户统计信息: 已完成 zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo mkfs.ext4 /dev/loop16p2 mke2fs 1.46.5 (30-Dec-2021) 丢弃设备块: 完成 创建含有 12027 个块(每块 4k)和 12032 个 inode 的文件系统 正在分配组表: 完成 正在写入 inode表: 完成 创建日志(1024 个块): 完成 写入超级块和文件系统账户统计信息: 已完成 zhou@zhou-Vostro-3480:~/ker-arm/qemu$
7.SDカードをマウントし、作成したカーネル、デバイスツリー、ルートファイルシステムをSDカードにロードする
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo mount -t ext4 /dev/loop16p1 tmp zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo cp ../linux-5.15.141/arch/arm/boot/uImage tmp/ zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo cp ../linux-5.15.141/arch/arm/boot/dts/*.dtb tmp/ zhou@zhou-Vostro-3480:~/ker-arm/qemu$ zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo umount /dev/loop16p1 zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo mount -t ext4 /dev/loop16p2 tmp zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo cp -r ../busybox-1.36.1/_install/* /tmp zhou@zhou-Vostro-3480:~/ker-arm/qemu$ zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo cp -rf ../busybox-1.36.1/_install/* tmp/ zhou@zhou-Vostro-3480:~/ker-arm/qemu$ ls tmp/ bin linuxrc lost+found sbin usr zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo umount /dev/loop16p2 zhou@zhou-Vostro-3480:~/ker-arm/qemu$ sudo losetup -d /dev/loop16 zhou@zhou-Vostro-3480:~/ker-arm/qemu$
〇Linuxの起動テスト:
1.U-BOOTを起動する
zhou@zhou-Vostro-3480:~/ker-arm/qemu$ qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel ../u-boot-2023.10/u-boot -sd sdImage WARNING: Image format was not specified for 'sdImage' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. Specify the 'raw' format explicitly to remove the restrictions. pulseaudio: set_sink_input_volume() failed pulseaudio: Reason: Invalid argument pulseaudio: set_sink_input_mute() failed pulseaudio: Reason: Invalid argument U-Boot 2023.10 (Jan 08 2024 - 00:05:18 +0900) DRAM: 512 MiB WARNING: Caches not enabled Core: 18 devices, 10 uclasses, devicetree: embed Flash: 64 MiB MMC: mmci@5000: 0 Loading Environment from Flash... *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: eth0: ethernet@3,02000000 Hit any key to stop autoboot: 0 MMC Device 1 not found no mmc device at slot 1 switch to partitions #0, OK mmc0 is current device Scanning mmc 0:1... 14081 bytes read in 13 ms (1 MiB/s) No EFI system partition No EFI system partition Failed to persist EFI variables BootOrder not defined EFI boot manager: Cannot load any image 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) *** 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, .q] source target count Wrong Image Format for bootm command ERROR: can't get kernel image! =>
=> load mmc 0:1 0x60008000 uImage 5023816 bytes read in 810 ms (5.9 MiB/s) => load mmc 0:1 0x60800000 vexpress-v2p-ca9.dtb 14081 bytes read in 11 ms (1.2 MiB/s) =>
3.起動パラメータを設定する
=> setenv bootargs 'root=/dev/mmcblk0p2 rw rootfstype=ext4 console=ttyAMA0' =>
4.カーネルを起動する
〇Linuxの起動を完璧にする: