Emulating ARM with QEMU on Debian/Ubuntu
To use QEMU (Quick EMUlator) to start a Ubuntu ARM Linux
$ sudo apt install qemu-system-armGet a list of ARM CPU models supported by qemu-system-arm:
$ qemu-system-arm -machine help Supported machines are: akita Sharp SL-C1000 (Akita) PDA (PXA270) ast2500-evb Aspeed AST2500 EVB (ARM1176) ast2600-evb Aspeed AST2600 EVB (Cortex-A7) borzoi Sharp SL-C3100 (Borzoi) PDA (PXA270) canon-a1100 Canon PowerShot A1100 IS (ARM946) cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310) collie Sharp SL-5500 (Collie) PDA (SA-1110) connex Gumstix Connex (PXA255) cubieboard cubietech cubieboard (Cortex-A8) emcraft-sf2 SmartFusion2 SOM kit from Emcraft (M2S010) fp5280g2-bmc Inspur FP5280G2 BMC (ARM1176) fuji-bmc Facebook Fuji BMC (Cortex-A7) g220a-bmc Bytedance G220A BMC (ARM1176) highbank Calxeda Highbank (ECX-1000) imx25-pdk ARM i.MX25 PDK board (ARM926) integratorcp ARM Integrator/CP (ARM926EJ-S) kudo-bmc Kudo BMC (Cortex-A9) kzm ARM KZM Emulation Baseboard (ARM1136) lm3s6965evb Stellaris LM3S6965EVB (Cortex-M3) lm3s811evb Stellaris LM3S811EVB (Cortex-M3) mainstone Mainstone II (PXA27x) mcimx6ul-evk Freescale i.MX6UL Evaluation Kit (Cortex-A7) mcimx7d-sabre Freescale i.MX7 DUAL SABRE (Cortex-A7) microbit BBC micro:bit (Cortex-M0) midway Calxeda Midway (ECX-2000) mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3 mps2-an386 ARM MPS2 with AN386 FPGA image for Cortex-M4 mps2-an500 ARM MPS2 with AN500 FPGA image for Cortex-M7 mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33 mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3 mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33 mps3-an524 ARM MPS3 with AN524 FPGA image for dual Cortex-M33 mps3-an547 ARM MPS3 with AN547 FPGA image for Cortex-M55 musca-a ARM Musca-A board (dual Cortex-M33) musca-b1 ARM Musca-B1 board (dual Cortex-M33) musicpal Marvell 88w8618 / MusicPal (ARM926EJ-S) n800 Nokia N800 tablet aka. RX-34 (OMAP2420) n810 Nokia N810 tablet aka. RX-44 (OMAP2420) netduino2 Netduino 2 Machine (Cortex-M3) netduinoplus2 Netduino Plus 2 Machine (Cortex-M4) none empty machine npcm750-evb Nuvoton NPCM750 Evaluation Board (Cortex-A9) nuri Samsung NURI board (Exynos4210) orangepi-pc Orange Pi PC (Cortex-A7) palmetto-bmc OpenPOWER Palmetto BMC (ARM926EJ-S) quanta-gbs-bmc Quanta GBS (Cortex-A9) quanta-gsj Quanta GSJ (Cortex-A9) quanta-q71l-bmc Quanta-Q71l BMC (ARM926EJ-S) rainier-bmc IBM Rainier BMC (Cortex-A7) raspi0 Raspberry Pi Zero (revision 1.2) raspi1ap Raspberry Pi A+ (revision 1.1) raspi2b Raspberry Pi 2B (revision 1.1) realview-eb ARM RealView Emulation Baseboard (ARM926EJ-S) realview-eb-mpcore ARM RealView Emulation Baseboard (ARM11MPCore) realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8 realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9 romulus-bmc OpenPOWER Romulus BMC (ARM1176) sabrelite Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9) smdkc210 Samsung SMDKC210 board (Exynos4210) sonorapass-bmc OCP SonoraPass BMC (ARM1176) spitz Sharp SL-C3000 (Spitz) PDA (PXA270) stm32vldiscovery ST STM32VLDISCOVERY (Cortex-M3) supermicrox11-bmc Supermicro X11 BMC (ARM926EJ-S) swift-bmc OpenPOWER Swift BMC (ARM1176) (deprecated) sx1 Siemens SX1 (OMAP310) V2 sx1-v1 Siemens SX1 (OMAP310) V1 tacoma-bmc OpenPOWER Tacoma BMC (Cortex-A7) terrier Sharp SL-C3200 (Terrier) PDA (PXA270) tosa Sharp SL-6000 (Tosa) PDA (PXA255) verdex Gumstix Verdex (PXA270) versatileab ARM Versatile/AB (ARM926EJ-S) versatilepb ARM Versatile/PB (ARM926EJ-S) vexpress-a15 ARM Versatile Express for Cortex-A15 vexpress-a9 ARM Versatile Express for Cortex-A9 virt-2.10 QEMU 2.10 ARM Virtual Machine virt-2.11 QEMU 2.11 ARM Virtual Machine virt-2.12 QEMU 2.12 ARM Virtual Machine virt-2.6 QEMU 2.6 ARM Virtual Machine virt-2.7 QEMU 2.7 ARM Virtual Machine virt-2.8 QEMU 2.8 ARM Virtual Machine virt-2.9 QEMU 2.9 ARM Virtual Machine virt-3.0 QEMU 3.0 ARM Virtual Machine virt-3.1 QEMU 3.1 ARM Virtual Machine virt-4.0 QEMU 4.0 ARM Virtual Machine virt-4.1 QEMU 4.1 ARM Virtual Machine virt-4.2 QEMU 4.2 ARM Virtual Machine virt-5.0 QEMU 5.0 ARM Virtual Machine virt-5.1 QEMU 5.1 ARM Virtual Machine virt-5.2 QEMU 5.2 ARM Virtual Machine virt-6.0 QEMU 6.0 ARM Virtual Machine virt-6.1 QEMU 6.1 ARM Virtual Machine virt QEMU 6.2 ARM Virtual Machine (alias of virt-6.2) virt-6.2 QEMU 6.2 ARM Virtual Machine witherspoon-bmc OpenPOWER Witherspoon BMC (ARM1176) xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9 z2 Zipit Z2 (PXA27x) $ qemu-system-arm -machine virt -cpu help Available CPUs: arm1026 arm1136 arm1136-r2 arm1176 arm11mpcore arm926 arm946 cortex-a15 cortex-a7 cortex-a8 cortex-a9 cortex-m0 cortex-m3 cortex-m33 cortex-m4 cortex-m55 cortex-m7 cortex-r5 cortex-r5f max pxa250 pxa255 pxa260 pxa261 pxa262 pxa270-a0 pxa270-a1 pxa270 pxa270-b0 pxa270-b1 pxa270-c0 pxa270-c5 sa1100 sa1110 ti925t
Install Ubuntu ARM Linux
Download Ubuntu ARM (ISO) Image on the official Ubuntu website. Mount the ISO:$ mkdir ubuntu_iso_mount $ sudo mount -o loop /home/jerry/data/ubuntu-22.04.4-live-server-arm64.iso ubuntu_iso_mountStart QEMU with the mounted ISO:
$ qemu-system-arm -machine virt -cpu cortex-a7 -m 1024 -cdrom /home/jerry/work-2/ubuntu_iso_mount -boot d
Emulating ARM with QEMU on Debian/Ubuntu
Install the ARM cross compiler toolchain on your Linux Ubuntu PC
Cross-compiling user programs needs GCC-ARM toolchain.Install the Cross Compilers, utilities, etc.
- ARM C compiler
sudo apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev build-essential bison flex libssl-dev bc sudo apt-get install gcc-arm-linux-gnueabihf gcc-arm-linux-gnueabi g++-arm-linux-gnueabihf
- ARM
sudo apt-get install g++-arm-linux-gnueabihf libstdc++-4.8-dev-armhf-cross
sudo apt-get install g++-aarch64-linux-gnu libstdc++-4.8-dev-arm64-cross
Try the cross C compiler
This is the example:cat > hello.c << EOF #include <stdio.h> int main(void) { return printf("Hello ARM!\n"); } EOFCompile it:
arm-linux-gnueabihf-gcc hello.c -o hello
Try the cross C++ compiler
#include "iostream" using namespace std; int main(int argc, char *argv[]) { cout << "Hello world !" << endl; return 0; }Compile it:
arm-linux-gnueabihf-g++ hello.cc -o hello
Running the ARM program:
install qemu-arm-static so that you can run ARM executables directly on your build machine.
Chroot into ARMv8 64bit (AARCH64) distribution
- Install required packages
sudo apt install \ build-essential \ binfmt-support \ daemonize \ libarchive-tools \ qemu-system \ qemu-user \ qemu-user-static \ gcc-aarch64-linux-gnu \ g++-aarch64-linux-gnu
wget https://cloud-images.ubuntu.com/releases/server/focal/release/ubuntu-20.04-server-cloudimg-arm64-wsl.rootfs.tar.gz
$ mkdir arm64.rootfs $ sudo tar xzf ubuntu-20.04-server-cloudimg-arm64-wsl.rootfs.tar.gz -C arm64.rootfs
sudo cp /usr/bin/qemu-aarch64-static arm64.rootfs/usr/bin/
sudo daemonize \ /usr/bin/unshare -fp --mount-proc \ /lib/systemd/systemd --system-unit=basic.target
$ ls /proc/sys/fs/binfmt_misc/qemu-a* /proc/sys/fs/binfmt_misc/qemu-aarch64 /proc/sys/fs/binfmt_misc/qemu-arm /proc/sys/fs/binfmt_misc/qemu-alpha /proc/sys/fs/binfmt_misc/qemu-armeb
sudo mount -o bind /proc arm64.rootfs/proc sudo mount -o bind /dev arm64.rootfs/dev sudo chroot arm64.rootfs qemu-aarch64-static /bin/bash
QemuARMVexpress
Running ARM programs under linux (without starting QEMU VM!)
QEMU disk image utility
qemu-img allows you to create, convert and modify images offline.It can handle all image formats supported by QEMU.
Install qemu
sudo apt install qemu qemu-system-armCreate a hard disk for your virtual machine with required capacity.
$ qemu-img create -f raw armdisk.img 8G Formatting 'armdisk.img', fmt=raw size=8589934592Get a list of all supported machines
$ qemu-system-arm -machine help | grep ARMThen get a list pf CPUs supported by the machine:
$ qemu-system-arm -machine virt-4.2 -cpu help ... cortex-a9 ...
在 x86 下 chroot 到 ARM 平台的 rootfs
Chroot into Raspberry Pi ARMv7 Image with Qemu on Linux
- Install dependecies
$ sudo apt-get install qemu qemu-user-static binfmt-support
$ wget https://downloads.raspberrypi.org/raspbian_latest $ unzip raspbian_latest
dd if=/dev/zero bs=1M count=1024 >> 2016-05-27-raspbian-jessie.img
losetup /dev/loop0 2016-05-27-raspbian-jessie.img
e2fsck -f /dev/loop0p2
resize2fs /dev/loop0p2
mount -o rw /dev/loop0p2 /mnt mount -o rw /dev/loop0p1 /mnt/boot
mount --bind /dev /mnt/dev/ mount --bind /sys /mnt/sys/ mount --bind /proc /mnt/proc/ mount --bind /dev/pts /mnt/dev/pts
sed -i 's/^/#/g' /mnt/etc/ld.so.preload
cp /usr/bin/qemu-arm-static /mnt/usr/bin/
chroot /mnt /bin/bash
sed -i 's/^#//g' /mnt/etc/ld.so.preload
umount /mnt/{dev/pts,dev,sys,proc,boot,}
losetup -d /dev/loop0
Raspberry Pi Emulation Using qemu-user-static
These are some notes for how to mount a Raspberry Pi disk image, and use qemu-user-static to modify the image.This example shows Raspbian.
Overview
We'll mount the disk image, chroot in to it, then use QemuUserEmulation to update the image and execute the ARM code.qemu-user-static
qemu-user-static is the package provides the user mode emulation binaries, built statically.In this mode QEMU can launch Linux processes compiled for one CPU on another CPU.
If binfmt-support package is installed, qemu-user-static package will register binary formats which the provided emulators can handle, so that it will be possible to run foreign binaries directly."
Set up Host
Install the qemu-user-static and binfmt-support packages.sudo apt install qemu qemu-user-static binfmt-supportAfter installed, you can check your ability to emulate the binary formats by checking for ARM support by executing:
$ update-binfmts --display | grep arm qemu-arm (enabled): interpreter = /usr/bin/qemu-arm-static qemu-armeb (enabled): interpreter = /usr/bin/qemu-armeb-static
Get and mount the image
Download and extract the Raspbian disk imagemkdir ~/rpi_image cd ~/rpi_image $ wget https://downloads.raspberrypi.org/raspbian_latest $ unzip raspbian_latest $ rm raspbian_latest
Resize the image
To increase the size of the disk image so it is more useful.- check out your disk image
$ fdisk -lu 2020-02-13-raspbian-buster.img Disk 2020-02-13-raspbian-buster.img: 3.54 GiB, 3787456512 bytes, 7397376 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xea7d04d6 Device Boot Start End Sectors Size Id Type 2020-02-13-raspbian-buster.img1 8192 532479 524288 256M c W95 FAT32 (LBA) 2020-02-13-raspbian-buster.img2 532480 7397375 6864896 3.3G 83 LinuxThe first partition is boot (kernel and binary blobs), the second is the filesystem.
We want to add space to the disk image, then expand that second partition.
$ dd if=/dev/zero bs=1M count=1024 >> 2020-02-13-raspbian-buster.img 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.68891 s, 636 MB/s
To mount and work with the image, it needs to be attached to a loop device. To do so, losetup(8) can be used.
$ sudo losetup -f -P --show 2020-02-13-raspbian-buster.img /dev/loop8
- The -f option will search for the next free loop device to attach the image to.
- The -P option will trigger a scan for partitions on the attached image and create devices for each partition detected.
$ lsblk | grep loop8 loop8 7:18 0 4.5G 0 loop ├─loop8p1 259:2 0 256M 0 part └─loop8p2 259:3 0 3.3G 0 partThis should set up /dev/loop8 as the whole image and /dev/loop8p2 as the partition we're expanding
$ sudo parted /dev/loop8 [sudo] password for jerry: GNU Parted 3.3 Using /dev/loop8 Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: Loopback device (loopback) Disk /dev/loop8: 4861MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 4194kB 273MB 268MB primary fat32 lba 2 273MB 3787MB 3515MB primary ext4 (parted) rm 2 (parted) mkpart primary 273 4861 (parted) print Model: Loopback device (loopback) Disk /dev/loop8: 4861MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 4194kB 273MB 268MB primary fat32 lba 2 273MB 4861MB 4589MB primary lba (parted) quit
$ sudo e2fsck -f /dev/loop8p2 e2fsck 1.45.5 (07-Jan-2020) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information rootfs: 106314/214704 files (0.2% non-contiguous), 724571/858112 blocks $ sudo resize2fs -f /dev/loop8p2 resize2fs 1.45.5 (07-Jan-2020) Resizing the filesystem on /dev/loop8p2 to 1120256 (4k) blocks. The filesystem on /dev/loop8p2 is now 1120256 (4k) blocks long.
$ sudo losetup -d /dev/loop8
Mount the image
A bind mount is an alternate view of a directory tree.For example, after issuing the Linux command-
mount --bind /some/where /else/wherethe directories /some/where and /else/where have the same content, which is the content of /some/where. (If /else/where was not empty, its previous content is now hidden.)
Here, the “device” /some/where is not a disk partition like in the case of an on-disk filesystem, but an existing directory.
Mount the file system to be modified
$ sudo losetup -f -P --show 2020-02-13-raspbian-buster.img /dev/loop8 $ sudo mount /dev/loop8p2 -o rw rpi_mnt
Before chrooting in
You need to comment out everything in rpi_mnt/etc/ld.so.preload$ cat rpi_mnt/etc/ld.so.preload /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so $ sudo sed -i 's/^/#/g' rpi_mnt/etc/ld.so.preload$ cat rpi_mnt/etc/ld.so.preload #/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so
Copy qemu binary
For ARCH=arm64,$ sudo cp /usr/bin/qemu-aarch64-static rpi_mnt/usr/bin/
Test chroot
$ cd rpi_mnt $ sudo chroot . bin/bash # uname -av 43~20.04.1-Ubuntu SMP Tue Jan 12 16:39:47 UTC 2021 armv7l GNU/Linux #
Revert the ld.so.preload fix
# sed -i 's/^#//g' etc/ld.so.preload # cat etc/ld.so.preload /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so # sed -i 's/^#//g' /mnt/etc/ld.so.preload # exit exit
Unmount everything
$ sudo umount /mnt/{dev/pts,dev,sys,proc,boot,}
Unmount loop device
$ sudo losetup -d /dev/loop8
留言