mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-02 14:23:19 +08:00
RT-Thread BSP Static Build Check / 🔍 Summary of Git Diff Changes (push) Has been cancelled
RT-Thread BSP Static Build Check / ${{ matrix.legs.RTT_BSP }} (push) Has been cancelled
RT-Thread BSP Static Build Check / collect-artifacts (push) Has been cancelled
pkgs_test / change (push) Has been cancelled
utest_auto_run / A9 :components/dfs.cfg (push) Has been cancelled
utest_auto_run / A9 :components/lwip.cfg (push) Has been cancelled
utest_auto_run / A9 :components/netdev.cfg (push) Has been cancelled
utest_auto_run / A9 :components/sal.cfg (push) Has been cancelled
utest_auto_run / A9 :cpp11/cpp11.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :default.cfg (push) Has been cancelled
utest_auto_run / A9-smp :default.cfg (push) Has been cancelled
utest_auto_run / RISCV :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :kernel/mem.cfg (push) Has been cancelled
ToolsCI / Tools (push) Has been cancelled
doc_doxygen / doxygen_doc generate (push) Has been cancelled
doc_doxygen / deploy (push) Has been cancelled
Signed-off-by: GuEe-GUI <2991707448@qq.com>
396 lines
12 KiB
Python
Executable File
396 lines
12 KiB
Python
Executable File
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
import os, sys, re, shutil
|
|
|
|
with open('rtconfig.h', 'r') as file:
|
|
rtconfig_header = file.read()
|
|
|
|
if os.getenv('RTT_QEMU_ROOT'):
|
|
RTT_QEMU_ROOT = os.getenv('RTT_QEMU_ROOT')
|
|
else:
|
|
RTT_QEMU_ROOT = ""
|
|
|
|
if os.getenv('RTT_ROOT'):
|
|
RTT_ROOT = os.getenv('RTT_ROOT')
|
|
else:
|
|
RTT_ROOT = os.path.join(os.getcwd(), '..', '..')
|
|
|
|
sys.path.append(RTT_ROOT + '/tools')
|
|
|
|
from building import *
|
|
import dtc
|
|
|
|
# WSL?
|
|
is_windows = sys.platform.startswith('win') or \
|
|
os.popen('which qemu-system-aarch64 | xargs file').read().find('PE') >= 0 or \
|
|
(os.system("readlink `which qemu-system-aarch64` > /dev/null") == 0 and \
|
|
os.popen('readlink `which qemu-system-aarch64` | xargs file').read().find('PE') >= 0)
|
|
|
|
class QEMU_VERSION:
|
|
def __init__(self):
|
|
cmd = os.popen(RTT_QEMU_ROOT + "qemu-system-aarch64 --version").readlines()[0]
|
|
version = cmd[cmd.find("version ") + 8: -1].split('.')
|
|
|
|
self.major = version[0]
|
|
self.minor = version[1]
|
|
self.revision = version[2]
|
|
# ==
|
|
def __eq__(self, version_in):
|
|
version = version_in.split('.')
|
|
return self.major == version[0] and self.minor == version[1] and self.revision == version[2]
|
|
# >=
|
|
def __ge__(self, version_in):
|
|
return self.__gt__(version_in) or self.__eq__(version_in)
|
|
# >
|
|
def __gt__(self, version_in):
|
|
version = version_in.split('.')
|
|
return int(self.major) > int(version[0]) or \
|
|
(int(self.major) == int(version[0]) and int(self.minor) > int(version[1])) or \
|
|
(int(self.major) == int(version[0]) and int(self.minor) == int(version[1]) and int(self.revision) > int(version[2]))
|
|
# <=
|
|
def __le__(self, version_in):
|
|
return self.__lt__(version_in) or self.__eq__(version_in)
|
|
# <
|
|
def __lt__(self, version_in):
|
|
return not self.__ge__(version_in)
|
|
# !=
|
|
def __ne__(self, version_in):
|
|
return not self.__eq__(version_in)
|
|
|
|
def toString(self):
|
|
return self.major + '.' + self.minor + '.' + self.revision
|
|
|
|
qemu_version = QEMU_VERSION()
|
|
|
|
opt = sys.argv
|
|
|
|
graphic_cfg = """ \
|
|
-device ramfb \
|
|
-device virtio-keyboard-device \
|
|
-device virtio-tablet-device \
|
|
"""
|
|
|
|
smmu_cfg = ""
|
|
iommu_cfg = ""
|
|
cdrom_cfg = ""
|
|
virtfs_cfg = ""
|
|
ufs_cfg = ""
|
|
camera_cfg = ""
|
|
amp_cfg = ""
|
|
|
|
q_gic = 2
|
|
q_dumpdtb = ""
|
|
q_el = 1
|
|
q_smp = int(re.findall(r'#define\s+RT_CPUS_NR\s+(\d+)', rtconfig_header)[0])
|
|
q_mem = 128
|
|
q_graphic = "-nographic"
|
|
q_debug = ""
|
|
q_bootargs = "console=ttyAMA0 earlycon cma=8M coherent_pool=2M root=vda0 rootfstype=elm rootwait rw"
|
|
q_initrd = ""
|
|
q_block = "virtio"
|
|
q_net = "user"
|
|
q_ssh = 12055
|
|
q_scsi = "scsi"
|
|
q_cdrom = ""
|
|
q_flash = "flash"
|
|
q_emmc = "emmc"
|
|
q_nvme = "nvme"
|
|
q_ahci = "ahci"
|
|
q_sound = "hda"
|
|
q_gl = None
|
|
q_9p = ""
|
|
q_ufs = "ufs"
|
|
q_camera = ""
|
|
q_dtbo = []
|
|
q_dtb = ""
|
|
|
|
def is_opt(key, inkey):
|
|
if str("-" + key) == inkey:
|
|
return True
|
|
return False
|
|
|
|
for i in range(len(opt)):
|
|
if i == 0:
|
|
continue
|
|
inkey = opt[i]
|
|
|
|
if is_opt("gic", inkey): q_gic = int(opt[i + 1])
|
|
if is_opt("dumpdtb", inkey): q_dumpdtb = str(",dumpdtb=" + opt[i + 1])
|
|
if is_opt("el", inkey): q_el = int(opt[i + 1])
|
|
if is_opt("smp", inkey): q_smp = int(opt[i + 1])
|
|
if is_opt("mem", inkey): q_mem = int(opt[i + 1])
|
|
if is_opt("debug", inkey): q_debug = "-S -s"
|
|
if is_opt("bootargs", inkey): q_bootargs = opt[i + 1]
|
|
if is_opt("initrd", inkey): q_initrd = str("-initrd " + opt[i + 1])
|
|
if is_opt("graphic", inkey): q_graphic = graphic_cfg
|
|
if is_opt("virtio-block", inkey): q_block = opt[i + 1]
|
|
if is_opt("tap", inkey): q_net = "tap,ifname=tap0"
|
|
if is_opt("ssh", inkey): q_ssh = int(opt[i + 1])
|
|
if is_opt("cdrom", inkey): q_cdrom = opt[i + 1]
|
|
if is_opt("flash", inkey): q_flash = opt[i + 1]
|
|
if is_opt("emmc", inkey): q_emmc = opt[i + 1]
|
|
if is_opt("nvme", inkey): q_nvme = opt[i + 1]
|
|
if is_opt("sound", inkey): q_sound = opt[i + 1]
|
|
if is_opt("gl", inkey): q_gl = "-device virtio-gpu-gl-pci -display {},gl=on ".format(opt[i + 1])
|
|
if is_opt("9p", inkey): q_9p = opt[i + 1]
|
|
if is_opt("ufs", inkey): q_ufs = opt[i + 1]
|
|
if is_opt("camera", inkey): q_camera = opt[i + 1]
|
|
if is_opt("dtb", inkey): q_dtb = "-dtb " + opt[i + 1]
|
|
if is_opt("dtbo", inkey): q_dtbo += [opt[i + 1]]
|
|
|
|
# SMP
|
|
if q_smp > 8:
|
|
q_gic = 3
|
|
|
|
# Exception Level
|
|
if q_el == 1:
|
|
q_el = ""
|
|
elif q_el == 2:
|
|
q_el = ",virtualization=on"
|
|
if q_gic == 3:
|
|
q_gic = "max"
|
|
elif q_el == 3:
|
|
q_el = ",secure=on"
|
|
else:
|
|
print("Error: Invalid -el {}".format(q_el))
|
|
exit(-1)
|
|
|
|
# Display
|
|
# --enable-opengl --enable-virglrenderer
|
|
if q_graphic != "-nographic":
|
|
if q_gl:
|
|
q_graphic += q_gl
|
|
else:
|
|
q_graphic += "-device virtio-gpu-device "
|
|
elif q_gl != None:
|
|
print("Error: GL should in graphic mode")
|
|
exit(-1)
|
|
|
|
# Sound
|
|
if q_sound == "hda":
|
|
q_sound = "-device intel-hda -device hda-duplex "
|
|
elif q_sound == "virtio":
|
|
if qemu_version < '8.2.0':
|
|
print("Error: VirtIO Sound is not in this version: {}".format(qemu_version.toString()))
|
|
exit(-1)
|
|
q_sound = "-device virtio-sound-pci,audiodev=vsnd -audiodev alsa,id=vsnd "
|
|
else:
|
|
print("Error: Invalid -sound {}".format(q_sound))
|
|
exit(-1)
|
|
|
|
# Net
|
|
# --enable-slirp
|
|
# Enable TAP in example (not support in Windows, Maybe WSL2):
|
|
# ETH0=`/sbin/route -n | awk '$1 == "0.0.0.0" {print $NF}'`
|
|
# ip link add br0 type bridge
|
|
# ip link set br0 up
|
|
# echo 1 | tee /proc/sys/net/ipv4/ip_forward > /dev/null
|
|
# ip link set ${ETH0} up
|
|
# ip link set ${ETH0} master br0
|
|
# dhclient br0
|
|
# ip tuntap add dev tap0 mode tap
|
|
# ip link set dev tap0 up
|
|
# ip link set tap0 master br0
|
|
#
|
|
# Disable TAP in example (not support in Windows, Maybe WSL2):
|
|
# ip link set tap0 down
|
|
# ip tuntap del dev tap0 mod tap
|
|
# echo 0 | tee /proc/sys/net/ipv4/ip_forward > /dev/null
|
|
# ip link set br0 down
|
|
# ip link del br0 type bridge
|
|
if q_net.find("user") >= 0:
|
|
q_net += ",hostfwd=tcp::{}-:22".format(q_ssh)
|
|
else:
|
|
if not is_windows:
|
|
q_net += ",script=no,downscript=no"
|
|
print("Warning: SSH not set in TAP")
|
|
|
|
# Storage
|
|
# pflash have pflash0 and pflash1, pflash0 is used for BootROMs such as UEFI
|
|
# if we load file to pflash0, QEMU will boot from it, so we only use pflash1.
|
|
# Well, we can R/W in pflash0 by CFI driver, but the data will lost after QEMU exits.
|
|
#
|
|
# partitions (not support in Windows, Maybe WSL2):
|
|
# modprobe nbd max_part=12
|
|
# qemu-nbd --connect=/dev/nbdX ABC.qcow2
|
|
# fdisk /dev/nbdX
|
|
# ...
|
|
# qemu-nbd --disconnect /dev/nbdX
|
|
disk_list = [q_block, q_scsi, q_flash, q_emmc, q_nvme, q_ahci]
|
|
|
|
if qemu_version >= '8.2.0':
|
|
disk_list += [q_ufs]
|
|
ufs_cfg = """ \
|
|
-drive if=none,file={}.qcow2,format=qcow2,id=ufs \
|
|
-device ufs,serial=deadbeef \
|
|
-device ufs-lu,drive=ufs \
|
|
""".format(q_ufs)
|
|
|
|
for disk in disk_list:
|
|
disk += ".qcow2"
|
|
if not os.path.exists(disk):
|
|
os.system("qemu-img create -f qcow2 {} 64M".format(disk))
|
|
|
|
if len(q_cdrom) > 0:
|
|
cdrom_cfg = """ \
|
|
-device scsi-cd,channel=0,scsi-id=0,lun=1,drive=scsi1 \
|
|
-drive file={},format=raw,if=none,id=scsi1 \
|
|
""".format(q_cdrom)
|
|
|
|
# Share File System
|
|
# --enable-virtfs
|
|
if len(q_9p) > 0:
|
|
p9_tag = "hostshare"
|
|
virtfs_cfg = """ \
|
|
-fsdev local,security_model=passthrough,id=fsdev0,path={} \
|
|
-device virtio-9p-device,fsdev=fsdev0,mount_tag={} \
|
|
""".format(q_9p, p9_tag)
|
|
q_bootargs += " 9p.tag={} 9p.mount=host".format(p9_tag)
|
|
|
|
# Camera (Linux only)
|
|
if len(q_camera) > 0:
|
|
if is_windows:
|
|
print("Camera is supported only on Linux")
|
|
exit(-1)
|
|
camera_cfg = """ --device '{"driver": "vfio-user-pci","socket": {"path": "/tmp/qemu-device-camera.sock", "type": "unix"}}'"""
|
|
|
|
# Note
|
|
# Hot-plug / Hot-unplug in QEMU monitor:
|
|
# (qemu) chardev-add socket,host=127.0.0.1,port=4323,server=on,wait=off,telnet=on,id=console2
|
|
# (qemu) device_add virtserialport,chardev=console2,name=org.rt-thread.port,id=port2
|
|
# (qemu) device_del port2
|
|
# (qemu) chardev-remove console2
|
|
#
|
|
# VirtIO version disable legacy to set version >= 1.0:
|
|
# -global virtio-mmio.force-legacy=false
|
|
#
|
|
# VirtIO used virtqueue packed (version >= 1.0)
|
|
# -device virtio-XYZ-device,packed=on
|
|
#
|
|
# VirtIO used PCI/PCIe bus (version >= 1.0)
|
|
# -device virtio-XYZ-pci,disable-legacy=on
|
|
|
|
cmd_base = """
|
|
{}qemu-system-aarch64 \
|
|
-M virt,acpi=on,its=on,gic-version={}{}{} \
|
|
-cpu max \
|
|
-smp {} \
|
|
-m {} \
|
|
-kernel rtthread.bin \
|
|
-append "{}" \
|
|
{} \
|
|
{} \
|
|
-serial mon:stdio \
|
|
{} \
|
|
{} \
|
|
-drive if=none,file={}.qcow2,format=qcow2,id=blk0 \
|
|
-device virtio-blk-device,drive=blk0 \
|
|
-netdev {},id=net0 \
|
|
-device virtio-net-device,netdev=net0,speed=800000 \
|
|
-device virtio-rng-device \
|
|
-device virtio-scsi-pci,disable-legacy=on \
|
|
-device scsi-hd,channel=0,scsi-id=0,lun=0,drive=scsi0 \
|
|
-drive file={}.qcow2,format=qcow2,if=none,id=scsi0 \
|
|
{} \
|
|
{} \
|
|
-device virtio-crypto-device,cryptodev=vcrypto0 \
|
|
-object cryptodev-backend-builtin,id=vcrypto0 \
|
|
-device virtio-serial-device \
|
|
-chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 \
|
|
-device virtserialport,chardev=console0,name=org.rt-thread.console \
|
|
{} \
|
|
-drive if=pflash,file={}.qcow2,format=qcow2,index=1 \
|
|
-device pci-serial,chardev=console1 \
|
|
-chardev socket,host=127.0.0.1,port=4322,server=on,wait=off,telnet=on,id=console1 \
|
|
-device sdhci-pci -device sd-card,drive=emmc0 \
|
|
-drive if=none,file={}.qcow2,format=qcow2,id=emmc0 \
|
|
-device nvme,id=nvme-ctrl-0,serial=deadbeef \
|
|
-drive if=none,file={}.qcow2,format=qcow2,id=nvme0 \
|
|
-device nvme-ns,drive=nvme0 \
|
|
-device ahci,id=ahci-ctrl-0 \
|
|
-drive if=none,file={}.qcow2,format=qcow2,id=ahci0 \
|
|
-device ide-hd,drive=ahci0 \
|
|
-device i6300esb -watchdog-action reset \
|
|
{} \
|
|
{} \
|
|
{} \
|
|
-device edu,dma_mask=0xffffffff
|
|
"""
|
|
def cmd():
|
|
return cmd_base.format(RTT_QEMU_ROOT, q_gic, q_dumpdtb, q_el, q_smp, q_mem, q_bootargs, q_dtb, q_initrd,
|
|
q_graphic, q_debug, q_block, q_net, q_scsi, cdrom_cfg, virtfs_cfg,
|
|
q_sound, q_flash, q_emmc, q_nvme, q_ahci, ufs_cfg, camera_cfg, amp_cfg)
|
|
|
|
def dumpdtb():
|
|
dtb = q_dumpdtb.split('=')[-1]
|
|
dtc.dtb_to_dts(RTT_ROOT, dtb)
|
|
|
|
if len(q_camera) > 0:
|
|
shell = os.environ.get('SHELL', '/bin/bash')
|
|
os.system("{} ./qemu-device-camera.c {} &".format(shell, q_camera))
|
|
|
|
import time
|
|
start_time = time.time()
|
|
while not os.path.exists("/tmp/qemu-device-camera.sock"):
|
|
if time.time() - start_time > 5:
|
|
print("qemu-device-camera timeout")
|
|
exit(-1)
|
|
time.sleep(1)
|
|
|
|
if len(q_dtbo) > 0:
|
|
amp_mode = False
|
|
q_bootargs = "rpmsg.mode=master " + q_bootargs
|
|
# Read all dtbo
|
|
with open("qemu.run.dtsi", 'w') as run_dtsi:
|
|
for dtsi in q_dtbo:
|
|
with open(dtsi) as dtsi:
|
|
dts_content = dtsi.read()
|
|
if not amp_mode and len(re.findall('amp_soc', dts_content)) > 0:
|
|
amp_cfg += " -device loader,file=amp.dtb,addr={}".format(re.findall(r'dtb-entry\s*=\s*<(\S+)>;', dts_content)[0])
|
|
amp_cfg += " -device loader,file=rtthread.bin,addr={}".format(re.findall(r'kernel-entry\s*=\s*<(\S+)>;', dts_content)[0])
|
|
q_smp += 1
|
|
amp_mode = True
|
|
run_dtsi.write(dts_content)
|
|
# Add Console for AMP
|
|
amp_cfg += " -serial telnet:localhost:4323,server,nowait"
|
|
# Add Storage for AMP
|
|
q_amp_block = q_block + ".amp.qcow2"
|
|
if not os.path.exists(q_amp_block):
|
|
shutil.copyfile(q_block + ".qcow2", q_amp_block)
|
|
amp_cfg += " -drive if=none,file={},format=qcow2,id=blk1 -device virtio-blk-device,drive=blk1".format(q_amp_block)
|
|
# Keep vda0 is root
|
|
cmd_base = cmd_base.replace(",drive=blk0", ",drive=blk0,bus=virtio-mmio-bus.0")
|
|
# Build AMP dtb
|
|
with open("amp.dt.h", 'w') as gic_inc:
|
|
gic_inc.write("#define GIC_VERSION {}\n\r".format(q_gic))
|
|
gic_inc.write("#define CPU_ID {}\n\r".format(q_smp - 1))
|
|
dtc.dts_to_dtb(RTT_ROOT, ["amp.dts"], ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"])
|
|
os.remove("amp.dt.h")
|
|
# Dump raw QEMU dts
|
|
q_dumpdtb = ",dumpdtb=qemu.run.dtb"
|
|
os.system(cmd())
|
|
dumpdtb()
|
|
os.remove("qemu.run.dtb")
|
|
q_dumpdtb = ""
|
|
# Merge all dtsi
|
|
with open("qemu.run.dts", 'a') as dts:
|
|
with open("qemu.run.dtsi", 'r') as dtsi:
|
|
dts.write(dtsi.read())
|
|
os.remove("qemu.run.dtsi")
|
|
# Build runtime dtb
|
|
dtc.dts_to_dtb(RTT_ROOT, ["qemu.run.dts"], ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"])
|
|
os.remove("qemu.run.dts")
|
|
# Run QEMU
|
|
q_dtb = "-dtb qemu.run.dtb"
|
|
os.system(cmd())
|
|
os.remove("amp.dtb")
|
|
os.remove("qemu.run.dtb")
|
|
else:
|
|
os.system(cmd())
|
|
|
|
if len(q_dumpdtb) != 0:
|
|
dumpdtb()
|
|
|
|
if len(q_camera) > 0:
|
|
os.system("kill -15 `pidof qemu-device-camera`")
|