通过qemu模拟ATF的启动,即启动流程为:
其中bl33为uboot。
apt方式下载
# 不推荐以apt-get方式安装,版本较低
# 后续启动kernel可能失败
sudo apt-get install qemu
# 查看ARM64平台版本
qemu-system-aarch64 --version
源码安装
去官网下载最新的版本,这里下载qemu-7.1.0,并解压
# 下载
wget https://download.qemu.org/qemu-7.1.0.tar.xz
# 解压
xz -d qemu-7.1.0.tar.xz
tar xvf qemu-7.1.0.tar
相关库安装
sudo apt-get install libcap-dev
sudo apt-get install pkg-config
sudo apt-get install zlib1g-dev libglib2.0-dev
sudo apt-get install libpixman-1-dev
sudo apt install python3-pip
pip3 install --user meson
# ninja
sudo apt-get install re2c
git clone https://github.com/ninja-build/ninja.git
cd ninja && ./configure.py --bootstrap
sudo cp ./ninja /usr/bin/
ninja --version
问题解决
virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel
wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/libcap-ng/0.7.7-3.1/libcap-ng_0.7.7.orig.tar.gz
cd libcap-ng-0.7.7
./autogen.sh
./configure
make
sudo make install
编译安装
./configure --target-list=x86_64-softmmu,x86_64-linux-user,arm-softmmu,arm-linux-user,aarch64-softmmu,aarch64-linux-user --enable-kvm
make -j16
sudo make install
# 查看版本
qemu-system-aarch64 --version
下载uboot
git clone https://source.denx.de/u-boot/u-boot.git
编译uboot
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make qemu_arm64_defconfig
make -j16
uboot位置
./u-boot.bin
下载kernel
进入官网,下载稳定版本的,这里下载linux-5.19.6.tar.xz,并解压
# 下载
https://www.kernel.org/
# 解压
xz -d linux-5.19.6.tar.xz
tar xvf linux-5.19.6.tar
编译kernel
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make defconfig
make -j16
Image位置
./arch/arm64/boot/Image
下载buildroot
进入官网,下载稳定版本,这里下载buildroot-2022.05.2.tar.xz,并解压
# 下载
https://buildroot.org/download.html
# 解压
xz -d xz -d buildroot-2022.05.2.tar.xz
tar xvf buildroot-2022.05.2.tar
配置
make ARCH=arm64 menuconfig
如出现Unable to find the ncurses libraries or the required header files,需要安装以下库
sudo apt-get install libncurses5-dev libncursesw5-dev
Target Options
Target Architecture:AArch64(little endian)
Target Architecture Variant:cortex-A53
其他默认不变。
Toolchain
这里让buildroot自己去下载适配的工具链
System configuration
这里默认不变
Filesystem images
ext2/3/4 root filesystem:y
编译
注意不能-j进行多核编译
sudo make
下载ATF
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
编译
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make PLAT=qemu all DEBUG=1
TIPS:默认调试版本日志等级为40(INFO),发布版本中为20(NOTICE),可加LOG_LEVEL=50参数开启VERBOSE日志。
bin文件位置
build/qemu/debug
生成bl1.bin,bl2.bin,bl31.bin等文件
新建qemu_test文件夹,并进入。
qemu启动u-boot
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-smp 2 \
-m 2048M \
-kernel ../u-boot-master/u-boot \
-nographic
TIPS:
解决qemu启动输出参数较多,添加启动选项保存到配置文件中,如下
-writeconfig qemu-test.conf
下次启动时,直接加载该配置文件即可
qemu-system-aarch64 –readconfig qemu-test.conf
退出qemu,按住Ctrl+A,松开后再输入X即可。
qemu启动kernel
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-smp 2 \
-m 2048M \
-kernel ../linux-5.19.6/arch/arm64/boot/Image \
-append "console=ttyAMA0 root=/dev/vda" \
-nographic
这里由于缺少根文件系统rootfs,会打印end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)。
qemu启动rootfs(kernel)
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-smp 2 \
-m 2048M \
-kernel ../linux-5.19.6/arch/arm64/boot/Image \
-drive file=../buildroot-2022.05.2/output/images/rootfs.ext4,if=none,id=blk1,format=raw \
-device virtio-blk-device,drive=blk1 \
-append "console=ttyAMA0 root=/dev/vda" \
-nographic
使用root的password登陆进去。
qemu通过u-boot启动kernel
uboot下载kernel镜像和设备数dtb有两种方式:
我们这里使用后者,但是需要编译uboot时,在configs/qemu_arm64_defconfig中添加以下配置CONFIG_SEMIHOSTING=y。重新编译后,运行:
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-smp 2 \
-m 2048M \
-kernel ../u-boot-master/u-boot \
-semihosting-config enable=on,target=native \
-nographic
然后通过semihosting方式添加kernel
smhload ../linux-5.19.6/arch/arm64/boot/Image
最后设置bootargs并启动内核
setenv bootargs " console=ttyAMA0 root=/dev/vda"
booti 0x40000000 - 0x43000000
TODO:这里没有添加成功smhload命令
qemu通过ATF启动u-boot
拷贝bl1.bin、bl2.bin、bl31.bin到当前目录下,拷贝u-boot.bin到当前目录下并重命名为bl33.bin
cp ../arm-trusted-firmware-2.7.0/build/qemu/debug/*.bin ./
cp ../u-boot-master/u-boot.bin ./bl33.bin
qemu-system-aarch64 \
-nographic -machine virt,secure=on \
-cpu cortex-a53 \
-smp 2 -m 2048 \
-d unimp \
-bios bl1.bin \
-semihosting-config enable=on,target=native
注意:qemu默认使用FIP方式加载,原始镜像存在memmap中,如果memmap没有镜像,会打印Firmware Image Package header check failed.FIP校验头失败。然后就会使用半主机的方式读取镜像Using Semi-hosting IO,直接半主机方式读取原始镜像到内存地址中(实际上是通过读文件的方式),即不会在校验FIP方式的头这些,因此如果需要FIP方式加载,需要将镜像事先加载到memmap中。
可以使用gdb的restore命令用来将文件中的数据加载到内容中,使用方法如下,详见第5点
restore file binary start_addr end_addr
qemu通过gdb调试目标镜像
在启动qemu时添加-s –S选项。
-S:表示QEMU虚拟机会冻结CPU,直到远程的GDB输入相应控制命令
-s:表示在1234端口接受GDB的调试连接,其与-gdb tcp::1234参数相同
qemu-system-aarch64 \
-nographic -machine virt,secure=on \
-cpu cortex-a53 \
-smp 2 -m 2048 \
-d unimp \
-bios bl1.bin \
-semihosting-config enable=on,target=native -s -S
启动GDB,apt-get安装的交叉工具链没有gdb(可以安装gdb-multiarch的gdb),我们这里使用自己下载的工具链。在另一窗口下通过gdb从atf的bl1开始启动:
~/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb ../arm-trusted-firmware-2.7.0/build/qemu/debug/bl1/bl1.elf
gdb通过tcp方式attach到qemu的目标板上
target remote localhost:1234
就开始调试了,执行N,C,B等gdb命令。
TIPS1:默认ATF编译时开优化,需要打开调试
CFLAGS='-O0 -gdwarf-2'
make PLAT=qemu all DEBUG=1
TIPS2:默认我们开始使用的是bl1的符号表,因此如果要调试bl2,bl31,kernel等,需要在gdb中添加对应的符号表,如下:
add-symbol-file ../arm-trusted-firmware-2.7.0/build/qemu/debug/bl2/bl2.elf
qemu使用FIP方式加载ATF
编译生成FIP包,需要指定BL33镜像的位置,默认会生成fip.bin
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make PLAT=qemu BL33=../u-boot-master/u-boot.bin all fip DEBUG=1 LOG_LEVEL=50
下面的命令在build/qemu/debug目录下执行。
启动qemu
qemu-system-aarch64 \
-nographic -machine virt,secure=on \
-cpu cortex-a53 \
-smp 2 -m 2048 \
-d unimp \
-bios bl1.bin \
-semihosting-config enable=on,target=native -s -S
启动gdb调试
~/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb bl1/bl1.elf
连接目标板
target remote localhost:1234
加载fip.bin到内存
restore fip.bin binary 0x00040000
这里的开始地址和最大大小就是qemu平台配置的
#define PLAT_QEMU_FIP_BASE 0x00040000
#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
全速运行
c
如果开启VERBOSE打印,可以看到每个镜像加载时会打印如下内容
VERBOSE: FIP header looks OK.
VERBOSE: Using FIP
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame
假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho
我想用Capistrano启动sidekiq。下面是代码namespace:sidekiqdotask:startdorun"cd#{current_path}&&bundleexecsidekiq-c10-eproduction-Llog/sidekiq.log&"pcapture("psaux|grepsidekiq|awk'{print$2}'|sed-n1p").strip!endend它执行成功但sidekiq仍然没有在服务器上启动。输出:$capsidekiq:starttriggeringloadcallbacks*2014-06-0315:03:01executing`
我有一个rspec模拟对象,一个值赋给了属性。我正在努力在我的rspec测试中满足这种期望。只是想知道语法是什么?代码:defcreate@new_campaign=AdCampaign.new(params[:new_campaign])@new_campaign.creationDate="#{Time.now.year}/#{Time.now.mon}/#{Time.now.day}"if@new_campaign.saveflash[:status]="Success"elseflash[:status]="Failed"endend测试it"shouldabletocreat
我正在尝试测试命令行工具的输出。如何使用rspec来“伪造”命令行调用?执行以下操作不起作用:it"shouldcallthecommandlineandreturn'text'"do@p=Pig.new@p.should_receive(:run).with('my_command_line_tool_call').and_return('resulttext')end如何创建stub? 最佳答案 使用newmessageexpectationsyntax:规范/虚拟规范.rbrequire"dummy"describeDummy
我有一个正在升级到Rails3的Rails2.3.5应用程序。我做了所有我需要做的升级以及当我使用启动Rails服务器时要做的事情railsserver它给了我这个PleaseswitchtoRuby1.9'sstandardCSVlibrary.It'sFasterCSVplussupportforRuby1.9'sm17nencodingengine.我正在使用ruby-1.9.2-p0并安装了fastercsv(1.5.3)gem。在puts语句的帮助下,我能够追踪到错误发生的位置。我发现执行在这一行停止了Bundler.require(:default,Rails.env)if