使用qemu虚拟arm硬件比较合适。
步骤如下:
- 安装qemu
apt install qemu-system
- 安装aarch64-none-elf-gcc
需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf.tar.xz?rev=a05df3001fa34105838e6fba79ee1b23&hash=DCB97F9E407955B162E4652F4E78B6CCDF75E4FF
下载后无需编译。下载完虎,执行如下命令设置编译环境:
vim ~/.bashrc
export PATH=$PATH:/home/ljg/aarch/arm-gnu-toolchain-13.2.Rel1-x86_64-aarch64-none-elf/aarch64-none-elf/bin
source ~/.bashrc
- 编译uart.c源文件
代码:
void outputstr(char * str){
int * base = (int*)0x9000000;
while(*str){
*base = (int)*str;
str++;
}
}
int main(){
outputstr("hello world!\r\n");
return 0x12345678;
}
命令:
aarch64-none-elf-gcc -I -include -c uart.c -o uart.o
- 编写start.s汇编源文件
代码:
.global _start
_start:
ldr x30,=stack_top
mov sp,x30
bl main
b .
命令:
aarch64-none-elf-as -c start.s -o start.o
- 链接
链接脚本文件:
ENTRY(_start)
SECTIONS
{
. = 0x40000000;
.startup . : {start.o(.text)}
.text :{*(.text)}
.data : {*(.data)}
.bss : {*(.bss COMMON)}
. = ALIGN(8);
. = .+0x1000;
stack_top = .;
}
命令:
aarch64-none-elf-ld -Tlink.ld uart.o start.o -o hello.elf
- 制作镜像文件。
aarch64-none-elf-objcopy -O binary hello.elf hello.bin
- 运行测试
qemu-system-aarch64 -M virt -cpu cortex-a710 -monitor none -kernel hello.bin
或者:
qemu-system-aarch64 -M virt -cpu cortex-a710 -monitor none -nographic -serial stdio -kernel hello.bin
virt虚拟机设备树:
Working FDT set to 6000000
/ {
interrupt-parent = <0x00008002>;
model = "linux,dummy-virt";
#size-cells = <0x00000002>;
#address-cells = <0x00000002>;
compatible = "linux,dummy-virt";
psci {
migrate = <0xc4000005>;
cpu_on = <0xc4000003>;
cpu_off = <0x84000002>;
cpu_suspend = <0xc4000001>;
method = "hvc";
compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
};
memory@40000000 {
reg = <0x00000000 0x40000000 0x00000000 0x80000000>;
device_type = "memory";
};
platform-bus@c000000 {
interrupt-parent = <0x00008002>;
ranges = <0x00000000 0x00000000 0x0c000000 0x02000000>;
#address-cells = <0x00000001>;
#size-cells = <0x00000001>;
compatible = "qemu,platform", "simple-bus";
};
fw-cfg@9020000 {
dma-coherent;
reg = <0x00000000 0x09020000 0x00000000 0x00000018>;
compatible = "qemu,fw-cfg-mmio";
};
virtio_mmio@a000000 {
dma-coherent;
interrupts = <0x00000000 0x00000010 0x00000001>;
reg = <0x00000000 0x0a000000 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000200 {
dma-coherent;
interrupts = <0x00000000 0x00000011 0x00000001>;
reg = <0x00000000 0x0a000200 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000400 {
dma-coherent;
interrupts = <0x00000000 0x00000012 0x00000001>;
reg = <0x00000000 0x0a000400 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000600 {
dma-coherent;
interrupts = <0x00000000 0x00000013 0x00000001>;
reg = <0x00000000 0x0a000600 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000800 {
dma-coherent;
interrupts = <0x00000000 0x00000014 0x00000001>;
reg = <0x00000000 0x0a000800 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000a00 {
dma-coherent;
interrupts = <0x00000000 0x00000015 0x00000001>;
reg = <0x00000000 0x0a000a00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000c00 {
dma-coherent;
interrupts = <0x00000000 0x00000016 0x00000001>;
reg = <0x00000000 0x0a000c00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a000e00 {
dma-coherent;
interrupts = <0x00000000 0x00000017 0x00000001>;
reg = <0x00000000 0x0a000e00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001000 {
dma-coherent;
interrupts = <0x00000000 0x00000018 0x00000001>;
reg = <0x00000000 0x0a001000 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001200 {
dma-coherent;
interrupts = <0x00000000 0x00000019 0x00000001>;
reg = <0x00000000 0x0a001200 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001400 {
dma-coherent;
interrupts = <0x00000000 0x0000001a 0x00000001>;
reg = <0x00000000 0x0a001400 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001600 {
dma-coherent;
interrupts = <0x00000000 0x0000001b 0x00000001>;
reg = <0x00000000 0x0a001600 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001800 {
dma-coherent;
interrupts = <0x00000000 0x0000001c 0x00000001>;
reg = <0x00000000 0x0a001800 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001a00 {
dma-coherent;
interrupts = <0x00000000 0x0000001d 0x00000001>;
reg = <0x00000000 0x0a001a00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001c00 {
dma-coherent;
interrupts = <0x00000000 0x0000001e 0x00000001>;
reg = <0x00000000 0x0a001c00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a001e00 {
dma-coherent;
interrupts = <0x00000000 0x0000001f 0x00000001>;
reg = <0x00000000 0x0a001e00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002000 {
dma-coherent;
interrupts = <0x00000000 0x00000020 0x00000001>;
reg = <0x00000000 0x0a002000 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002200 {
dma-coherent;
interrupts = <0x00000000 0x00000021 0x00000001>;
reg = <0x00000000 0x0a002200 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002400 {
dma-coherent;
interrupts = <0x00000000 0x00000022 0x00000001>;
reg = <0x00000000 0x0a002400 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002600 {
dma-coherent;
interrupts = <0x00000000 0x00000023 0x00000001>;
reg = <0x00000000 0x0a002600 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002800 {
dma-coherent;
interrupts = <0x00000000 0x00000024 0x00000001>;
reg = <0x00000000 0x0a002800 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002a00 {
dma-coherent;
interrupts = <0x00000000 0x00000025 0x00000001>;
reg = <0x00000000 0x0a002a00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002c00 {
dma-coherent;
interrupts = <0x00000000 0x00000026 0x00000001>;
reg = <0x00000000 0x0a002c00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a002e00 {
dma-coherent;
interrupts = <0x00000000 0x00000027 0x00000001>;
reg = <0x00000000 0x0a002e00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003000 {
dma-coherent;
interrupts = <0x00000000 0x00000028 0x00000001>;
reg = <0x00000000 0x0a003000 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003200 {
dma-coherent;
interrupts = <0x00000000 0x00000029 0x00000001>;
reg = <0x00000000 0x0a003200 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003400 {
dma-coherent;
interrupts = <0x00000000 0x0000002a 0x00000001>;
reg = <0x00000000 0x0a003400 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003600 {
dma-coherent;
interrupts = <0x00000000 0x0000002b 0x00000001>;
reg = <0x00000000 0x0a003600 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003800 {
dma-coherent;
interrupts = <0x00000000 0x0000002c 0x00000001>;
reg = <0x00000000 0x0a003800 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003a00 {
dma-coherent;
interrupts = <0x00000000 0x0000002d 0x00000001>;
reg = <0x00000000 0x0a003a00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003c00 {
dma-coherent;
interrupts = <0x00000000 0x0000002e 0x00000001>;
reg = <0x00000000 0x0a003c00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
virtio_mmio@a003e00 {
dma-coherent;
interrupts = <0x00000000 0x0000002f 0x00000001>;
reg = <0x00000000 0x0a003e00 0x00000000 0x00000200>;
compatible = "virtio,mmio";
};
gpio-keys {
compatible = "gpio-keys";
poweroff {
gpios = <0x00008004 0x00000003 0x00000000>;
linux,code = <0x00000074>;
label = "GPIO Key Poweroff";
};
};
pl061@9030000 {
phandle = <0x00008004>;
clock-names = "apb_pclk";
clocks = <0x00008000>;
interrupts = <0x00000000 0x00000007 0x00000004>;
gpio-controller;
#gpio-cells = <0x00000002>;
compatible = "arm,pl061", "arm,primecell";
reg = <0x00000000 0x09030000 0x00000000 0x00001000>;
};
pcie@10000000 {
interrupt-map-mask = <0x00001800 0x00000000 0x00000000 0x00000007>;
interrupt-map = <0x00000000 0x00000000 0x00000000 0x00000001 0x00008002 0x00000000 0x00000000 0x00000000 0x00000003 0x00000004 0x00000000 0x00000000 0x00000000 0x00000002 0x00008002 0x00000000 0x00000000 0x00000000 0x00000004 0x00000004 0x00000000 0x00000000 0x00000000 0x00000003 0x00008002 0x00000000 0x00000000 0x00000000 0x00000005 0x00000004 0x00000000 0x00000000 0x00000000 0x00000004 0x00008002 0x00000000 0x00000000 0x00000000 0x00000006 0x00000004 0x00000800 0x00000000 0x00000000 0x00000001 0x00008002 0x00000000 0x00000000 0x00000000 0x00000004 0x00000004 0x00000800 0x00000000 0x00000000 0x00000002 0x00008002 0x00000000 0x00000000 0x00000000 0x00000005 0x00000004 0x00000800 0x00000000 0x00000000 0x00000003 0x00008002 0x00000000 0x00000000 0x00000000 0x00000006 0x00000004 0x00000800 0x00000000 0x00000000 0x00000004 0x00008002 0x00000000 0x00000000 0x00000000 0x00000003 0x00000004 0x00001000 0x00000000 0x00000000 0x00000001 0x00008002 0x00000000 0x00000000 0x00000000 0x00000005 0x00000004 0x00001000 0x00000000 0x00000000 0x00000002 0x00008002 0x00000000 0x00000000 0x00000000 0x00000006 0x00000004 0x00001000 0x00000000 0x00000000 0x00000003 0x00008002 0x00000000 0x00000000 0x00000000 0x00000003 0x00000004 0x00001000 0x00000000 0x00000000 0x00000004 0x00008002 0x00000000 0x00000000 0x00000000 0x00000004 0x00000004 0x00001800 0x00000000 0x00000000 0x00000001 0x00008002 0x00000000 0x00000000 0x00000000 0x00000006 0x00000004 0x00001800 0x00000000 0x00000000 0x00000002 0x00008002 0x00000000 0x00000000 0x00000000 0x00000003 0x00000004 0x00001800 0x00000000 0x00000000 0x00000003 0x00008002 0x00000000 0x00000000 0x00000000 0x00000004 0x00000004 0x00001800 0x00000000 0x00000000 0x00000004 0x00008002 0x00000000 0x00000000 0x00000000 0x00000005 0x00000004>;
#interrupt-cells = <0x00000001>;
ranges = <0x01000000 0x00000000 0x00000000 0x00000000 0x3eff0000 0x00000000 0x00010000 0x02000000 0x00000000 0x10000000 0x00000000 0x10000000 0x00000000 0x2eff0000 0x03000000 0x00000080 0x00000000 0x00000080 0x00000000 0x00000080 0x00000000>;
reg = <0x00000040 0x10000000 0x00000000 0x10000000>;
msi-map = <0x00000000 0x00008003 0x00000000 0x00010000>;
dma-coherent;
bus-range = <0x00000000 0x000000ff>;
linux,pci-domain = <0x00000000>;
#size-cells = <0x00000002>;
#address-cells = <0x00000003>;
device_type = "pci";
compatible = "pci-host-ecam-generic";
};
pl031@9010000 {
clock-names = "apb_pclk";
clocks = <0x00008000>;
interrupts = <0x00000000 0x00000002 0x00000004>;
reg = <0x00000000 0x09010000 0x00000000 0x00001000>;
compatible = "arm,pl031", "arm,primecell";
};
pl011@9000000 {
clock-names = "uartclk", "apb_pclk";
clocks = <0x00008000 0x00008000>;
interrupts = <0x00000000 0x00000001 0x00000004>;
reg = <0x00000000 0x09000000 0x00000000 0x00001000>;
compatible = "arm,pl011", "arm,primecell";
};
pmu {
interrupts = <0x00000001 0x00000007 0x00000104>;
compatible = "arm,armv8-pmuv3";
};
intc@8000000 {
phandle = <0x00008002>;
reg = <0x00000000 0x08000000 0x00000000 0x00010000 0x00000000 0x08010000 0x00000000 0x00010000>;
compatible = "arm,cortex-a15-gic";
ranges;
#size-cells = <0x00000002>;
#address-cells = <0x00000002>;
interrupt-controller;
#interrupt-cells = <0x00000003>;
v2m@8020000 {
phandle = <0x00008003>;
reg = <0x00000000 0x08020000 0x00000000 0x00001000>;
msi-controller;
compatible = "arm,gic-v2m-frame";
};
};
flash@0 {
bank-width = <0x00000004>;
reg = <0x00000000 0x00000000 0x00000000 0x04000000 0x00000000 0x04000000 0x00000000 0x04000000>;
compatible = "cfi-flash";
};
cpus {
#size-cells = <0x00000000>;
#address-cells = <0x00000001>;
cpu-map {
socket0 {
cluster0 {
core0 {
cpu = <0x00008001>;
};
};
};
};
cpu@0 {
phandle = <0x00008001>;
reg = <0x00000000>;
compatible = "arm,cortex-a57";
device_type = "cpu";
};
};
timer {
interrupts = <0x00000001 0x0000000d 0x00000104 0x00000001 0x0000000e 0x00000104 0x00000001 0x0000000b 0x00000104 0x00000001 0x0000000a 0x00000104>;
always-on;
compatible = "arm,armv8-timer", "arm,armv7-timer";
};
apb-pclk {
phandle = <0x00008000>;
clock-output-names = "clk24mhz";
clock-frequency = <0x016e3600>;
#clock-cells = <0x00000000>;
compatible = "fixed-clock";
};
chosen {
stdout-path = "/pl011@9000000";
rng-seed = <0x36ea9704 0x0df0b009 0x5a442122 0x709ca37a 0x3beb236b 0x1fed8df1 0xef91ac7e 0x653b2401>;
kaslr-seed = <0xc809d522 0xf3a4a8e0>;
};
};
参考链接:
- https://blog.csdn.net/jingyu_1/article/details/135631512
- https://zhuanlan.zhihu.com/p/16952747762
- https://stdrc.cc/post/2021/02/23/u-boot-qemu-virt/
- https://zhuanlan.zhihu.com/p/708166648
- https://www.qemu.org/docs/master/system/arm/virt.html