前言:
代码实现不一定正确, 因为MTK不公开SOC内部的实现细节,这个模拟器的实现依据是我的对此芯片的了解程度以及Linux/Uboot/NetBSD里面的驱动代码.
项目地址: https://github.com/newluhux/qemu-mt7628
下载QEMU 应用PATCH 然后构建
git clone https://gitlab.com/qemu-project/qemu git clone https://github.com/newluhux/qemu-mt7628 cd ./qemu/ git branch mt7628 git switch mt7628 for i in ../qemu-mt7628/000*.patch do git am < $i done ./configure --cc=gcc --cxx=g++ --target-list=mipsel-softmmu make -j$(nproc) make check
启动主线uboot
wget http://musl.cc/mipsel-linux-muslsf-cross.tgz tar xf mipsel-linux-muslsf-cross.tgz cd mipsel-linux-muslsf-cross/bin/ export PATH=$PATH:$(pwd) cd - git clone https://github.com/u-boot/u-boot cd u-boot cp ./configs/linkit-smart-7688_defconfig ./.config make ARCH=mips CROSS_COMPILE=mipsel-linux-musl- menuconfig # you need select: # CONFIG_REMAKE_ELF=y make ARCH=mips CROSS_COMPILE=mipsel-linux-musl- -j$(nproc) # create a blank flash image dd if=/dev/zero of=flash_16M.bin count=16 bs=1M ../qemu/qemu-system-mipsel -M mt7628 \ -serial telnet:localhost:4000,server \ -serial telnet:localhost:4001,server \ -serial telnet:localhost:4002,server \ -drive if=mtd,file=flash_16M.bin,type=raw \ -usb \ -kernel ./u-boot.elf
使用telnet连接串口:
$ telnet localhost 4002 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. U-Boot 2022.04 (Feb 14 2023 - 15:32:34 +0000) CPU: MediaTek MT7628A ver:1 eco:2 Boot: DDR2, SPI-NOR 3-Byte Addr, CPU clock from XTAL Clock: CPU: 575MHz, Bus: 191MHz, XTAL: 25MHz Model: LinkIt-Smart-7688 DRAM: 256 MiB Core: 54 devices, 15 uclasses, devicetree: separate Loading Environment from SPIFlash... SF: Detected w25q128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB Net: Warning: eth@10110000 (eth0) using random MAC address - 96:0d:9e:0d:3f:ea eth0: eth@10110000 =>
现在你可以使用tftp或者fatload命令来加载固件到内存,然后使用sf写入到 spi flash
最后使用bootm来启动固件
启动OpenWRT固件
在此之前你需要构建一个主线的uboot用于启动uImage,然后执行:
cp /path/to/uboot/uboot.elf ./uboot.elf wget https://downloads.openwrt.org/releases/22.03.3/targets/ramips/mt76x8/openwrt-22.03.3-ramips-mt76x8-vocore_vocore2-squashfs-sysupgrade.bin dd if=/path/to/uboot/uboot-with-spl.bin of=flash.bin dd if=/dev/zero bs=1M count=1 >> flash.bin truncate -s 327680 flash.bin dd if=./openwrt-22.03.3-ramips-mt76x8-vocore_vocore2-squashfs-sysupgrade.bin >> flash.bin dd if=/dev/zero bs=1M count=16 >> flash.bin truncate -s 16M flash.bin /path/to/qemu-build/qemu-system-mipsel -M mt7628 \ -serial telnet:localhost:4000,server,nowait \ -serial telnet:localhost:4001,server,nowait \ -serial telnet:localhost:4002,server \ -kernel ./uboot.elf \ -drive if=mtd,file=flash_16M.bin,type=raw \ -usb
使用telnet 连接串口
$ telnet localhost 4002 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. U-Boot 2022.04 (Feb 14 2023 - 15:32:34 +0000) CPU: MediaTek MT7628A ver:1 eco:2 Boot: DDR2, SPI-NOR 3-Byte Addr, CPU clock from XTAL Clock: CPU: 575MHz, Bus: 191MHz, XTAL: 25MHz Model: LinkIt-Smart-7688 DRAM: 256 MiB Core: 54 devices, 15 uclasses, devicetree: separate Loading Environment from SPIFlash... SF: Detected w25q128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB Net: Warning: eth@10110000 (eth0) using random MAC address - 96:0d:9e:0d:3f:ea eth0: eth@10110000
使用 `bootm 0x1c050000` 来启动 openwrt
启动主线NetBSD
ref: https://www.netbsd.org/docs/guide/en/chap-build.html
NetBSD在8.0以及之后的版本加入了mt7628支持,你可以使用Linux/NetBSD/Other UNIX 来交叉编译 NetBSD,构建NetBSD内核是十分容易的(在我的Slackware Linux 机器上):
mkdir ./netbsd/ cd ./netbsd/ wget https://ftp.NetBSD.org/pub/NetBSD/NetBSD-release-9/tar_files/src.tar.gz tar -zxf src.tar.gz cd ./src/ ./build.sh -U -O ~/obj -j$(nproc) -m evbmips -a mipsel tools cd sys/arch/evbmips/conf/ ~/obj/tooldir.HOST/bin/nbconfig LINKITSMART7688 cd ../compile/LINKITSMART7688/ ~/obj/tooldir.HOST/bin/nbmake-evbmips depend ~/obj/tooldir.HOST/bin/nbmake-evbmips
构建成功后你会获得一个 './netbsd' 的文件
file ./netbsd netbsd: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, for NetBSD 9.3, with debug_info, not stripped
运行它:
/path/to/qemu-build/qemu-system-mipsel -M mt7628 \ -serial telnet:localhost:4000,server,nowait \ -serial telnet:localhost:4001,server,nowait \ -serial telnet:localhost:4002,server \ -kernel ./netbsd
连接串口,你可以看到netbsd内核的启动日志:
telnet localhost 4002 Trying ::1... telnet: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. [ 1.0000000] MIPS32/64 params: cpu arch: 128 [ 1.0000000] MIPS32/64 params: TLB entries: 16 [ 1.0000000] MIPS32/64 params: Icache: line=16, total=2048, ways=2, sets=64, colors=0 [ 1.0000000] MIPS32/64 params: Dcache: line=16, total=2048, ways=2, sets=64, colors=0 [ 1.0000000] phys segment: 0x8000000 @ 0 [ 1.0000000] adding 0xe000 @ 0x2000 to freelist 0 [ 1.0000000] adding 0x797e000 @ 0x682000 to freelist 0 [ 1.0000000] Enabled early console [ 1.0000000] Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, [ 1.0000000] 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, [ 1.0000000] 2018, 2019, 2020, 2021, 2022 [ 1.0000000] The NetBSD Foundation, Inc. All rights reserved. [ 1.0000000] Copyright (c) 1982, 1986, 1989, 1991, 1993 [ 1.0000000] The Regents of the University of California. All rights reserved. [ 1.0000000] NetBSD 9.3 (LINKITSMART7688) #0: Wed Mar 15 20:37:27 HKT 2023 [ 1.0000000] luhui@x230.luhui:/home/luhui/pub/netbsd/src/sys/arch/evbmips/compile/LINKITSMART7688 [ 1.0000000] MT7628 [ 1.0000000] total memory = 128 MB [ 1.0000000] avail memory = 120 MB [ 1.0000000] mainbus0 (root): Mediatek MT7628 System Bus [ 1.0000000] cpu0 at mainbus0: 580.00MHz (hz cycles = 2900000, delay divisor = 290) [ 1.0000000] cpu0: MIPS 24KE (0x19600) Rev. 0 with software emulated floating point
从flash镜像启动
我了解了一下mt7628的启动流程,发现从flash启动的流程很简单,但是会遇到一些问题:
取指令太慢, 因为QEMU没有实现cache, 所以启动时的指令是从flash反复读取的,延迟很大.
导致DRAM test和 LZMA解压会很慢, 建议使用hexedit修改镜像来跳过这些指令,或者直接拷贝他们到DRAM上,设置pc寄存器跳过去执行
你需要从真实的板子上dump flash镜像,然后执行:
./qemu/qemu-system-mipsel -M mt7628 \ -serial telnet:localhost:4000,server \ -serial telnet:localhost:4001,server \ -serial telnet:localhost:4002,server \ -drive if=mtd,file=flash_16M.bin,type=raw \ -usb
本文为项目原作者投稿,原文: https://newluhux.github.io/2023-02-14-qemu-emulate-mt7628.html
本文章由作者:佐须之男 整理编辑,原文地址: 使用qemu模拟mt7628 并成功运行uboot、OpenWrt、NetBSD