QEMU ARM64 Uboot

QEMU ARM64 Uboot
以virt machine 为例,
export ARCH=arm64 
export CROSS_COMPILE=aarch64-linux-gnu-
make qemu_arm64_defconfig
make -j16 
make CROSS_COMPILE=aarch64-linux-gnu- -j2 
QEMU启动

qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-smp 2 \
-m 2048M \
-kernel u-boot \
-nographic

qemu-system-aarch64: unable to find CPU model 'cortex-a72'

qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 2 -m 2048M -kernel u-boot -nographic

qemu-system-aarch64 -M virt -cpu cortex-a53  -m 2048M -kernel u-boot -nographic
qemu quit:
ctrl+A -> wait a moment ->+X


/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * relocate - common relocation function for AArch64 U-Boot
 *
 * (C) Copyright 2013
 * Albert ARIBAUD <albert.u.boot@aribaud.net>
 * David Feng <fenghua@phytium.com.cn>
 */

#include <asm-offsets.h>
#include <config.h>
#include <elf.h>
#include <linux/linkage.h>
#include <asm/macro.h>


//ARM64 有34个寄存器,包括31个通用寄存器,SP,PC,CPSR.
//x0-x30 64bit 通用寄存器,如果有需要可以当做32bit使用:W0-W30.
//其中x0 - x7:这 8 个寄存器主要用来存储传递参数.如果参数超过 8 个,
//则会通过栈来传递; x0 也用来存放上文方法的返回值.
//FP(x29) 64bit 保存栈帧地址(栈底指针),指向当前方法栈的底部。
//LR(x30) 64bit 通常称x30为程序链接寄存器,因为这个寄存器会记录着当前方法的调用方地址 ,
//即当前方法调用完成时应该返回的位置。例如我们遇到 Crash 要获取方法堆栈,
//其本质就是不断的向上递归每一个 x30 寄存器的记录状态(也就是栈上 X30 寄存器的内容) 
//来找到上层调用方。
//SP 64bit 保存栈指针,使用 SP/WSP来进行对SP寄存器的访问。
//指向当前方法栈的顶部。
//PC 64bit 程序计数器,俗称PC指针,总是指向即将要执行的下一条指令,
//在arm64中,软件是不能改写PC寄存器的。
//CPSR 64bit 状态寄存器

ENTRY( fuck_code )
    LDR    X10, =0x42000000
    MOV             W0, #21
    CMP             W0, #20
    MOV             W1, #20
    CSEL         W0, W0, W1, LS
    STR    W0, [X10, #0x00]
    STR    W1, [X10, #0x08]
    MOV             W1, #0xA
    CMP             W0, W1
    CSEL         W0, W0, W1, CS

    STR    W0, [X10, #0x10]
    STR    W1, [X10, #0x18]
    UDIV         W0, W0, W1

    //ADRL         X1, fuck_codexxx  IDA

ADR         X1, fuck_codexxx     

//加L编译会报错   unknown mnemonic `adrl' -- `adrl X1,fuck_codexxx'


    SUB             W0, W0, #1
    LDR             X0, [X1,X0,LSL#3]

    mov    x1, 0x9000000
    STRb    W0, [X1]
    STR    W0, [X1]

    RET


    


ENDPROC(fuck_code)

fuck_codexxx:
    .ascii    "123456789abcdef444444445555557778888"


ENTRY( fuck_code1 )
    LDR    X10, =0x42000000
    STR    X29, [X10, #0x00]
    STR    lr,  [X10, #0x08]
    MOV    X8, SP                   
    STR    x8,  [X10, #0x10]
    mov    x9, 0
    STR    x9, [X10, #0x18]
    
    STP    X29, X30, [SP,#-0x100]!
    MOV    X29, SP
    STR    X29, [X10, #0x20]
    MOV    W0, #0xFFFFFFf0
    STR    W0, [X29,#0x38]
loc_1:
    LDR    W1, [X29,#0x38]
    TBZ    W1, #0x1F, loc_3718a
    ADD    W2, W1, #8
    ADD    x9, x9, 1
    STR    W2, [X29,#0x38]
    CMP    W2, #0
    B.LE   loc_1
loc_3718a:    
    LDR    X4, =0x1234
    STR    W1, [X10, #0xa0]
    STR    X1, [X10, #0xb0]
    STR    W2, [X10, #0xc0]
    STR    X2, [X10, #0xd0]
    B      quit    
loc_3728a:                   
    LDR    X4, =0x55aa     
quit:                        
    STR    X4, [X10, #0xe0]
    STR    X9, [X10, #0xf0]
    LDP    X29, X30, [SP], 0x100

    MOV    X29, SP
    STR    X29, [X10, #0x28]
    
    ret
ENDPROC(fuck_code1)

    

ENTRY( fuck_log1 )           
    STP             X29, X30, [SP,#-0x100]!
    //变量sp+0x00  存储 X29, X30 的原始值
    MOV             X29, SP
    LDR    X10, =0x42000000
    STR    X10, [x10, #0x00]
          
    ADD             X0,  X29, #0x100   
    //x0 栈顶指针 指向函数调用之前的堆栈sp
    //函数的参数如果是8个以内(包含8个) 用x0-x7来传递  (param0-param7)
    //超过8个的部分 从此sp开始依次先储存好 比如超过3个
    //sp+0x00->param8 sp+0x08->param9 sp+0x10->param10

    STR             X19, [SP,#0x10]
    //变量sp+0x10  存储 x19 的原始值
    ldr             X19, =0x42000200   //"xoutputx: %s.\n" printf的第一个参数 x0

    mov    X11, X0
    STR    X11, [x10, #0x08]                                  
    ldr    X12, [X11]
    STR    X12, [x10, #0x10] 
    
    add    X11, x11, #0x08
    STR    X11, [x10, #0x18]
    ldr    X12, [X11]
    STR    X12, [x10, #0x20] 
    
    add    X11, x11, #0x08
    STR    X11, [x10, #0x28]
    ldr    X12, [X11]
    STR    X12, [x10, #0x30] 
    
    add    X11, x11, #0x08
    STR    X11, [x10, #0x38]
    ldr    X12, [X11]
    STR    X12, [x10, #0x40] 

    //add    X11, x11, #0x08
    STR    X7, [x10, #0x48]
    ldr    X12, [X7]
    STR    X12, [x10, #0x50] 

    STR    X6, [x10, #0x58]
    ldr    X12, [X6]
    STR    X12, [x10, #0x60] 

    

    STP             X0, X0, [X29, #0x20] 
    //变量sp+0x20 sp+0x28 存储 x0 栈顶指针

    ADD             X0, X29, #0xC0
    STR             X0, [X29,#0x30]
    //变量sp+0x30 = sp+0xc0

    MOV             W0, #0xFFFFFFC8
    STR             W0, [X29,#0x38]
    //变量sp+0x38 = 0xFFFFFFC8  4字节

    MOV             W0, #0xFFFFFF80
    STR             W0, [X29,#0x3C]
    //变量sp+0x3C = 0xFFFFFF80  4字节

       
    STP             X1, X2, [X29,#0xC8] 
    STP             X3, X4, [X29,#0xD8]
    STP             X5, X6, [X29,#0xE8]
    STR             X7, [X29,#0xF8]
    //传递进来的参数 依次压入堆栈 x1-x7 c8-d8-e8-f8-0x100-[x0 栈顶指针的位置]


    STR             Q0, [X29,#0x40]
    STR             Q1, [X29,#0x50]
    STR             Q2, [X29,#0x60]
    STR             Q3, [X29,#0x70]
    STR             Q4, [X29,#0x80]
    STR             Q5, [X29,#0x90]
    STR             Q6, [X29,#0xA0]
    STR             Q7, [X29,#0xB0]
    //0x40-0xc0 用0填充这块区域 没有用到

loc_36FC:
    LDR             W1, [X29,#0x38]
    //变量sp+0x38 = 0xFFFFFFC8  4字节
    LDR             X0, [X29,#0x20]
    //栈顶指针
    TBZ             W1, #0x1F, loc_3718
    //测试 sp+0x38 0xFFFFFFC8 & 0x1F 是否等于0,等于0的话跳转到loc_3718
    //否则执行下一条指令
    ADD             W2, W1, #8
    //[sp+0x38] & 0x1f 不等于0, 自加8 
    CMP             W2, #0
    STR             W2, [X29,#0x38]
    B.LE            loc_3728
    //不等于0 跳转

loc_3718:     
    //等于0 说明经过7次循环 x1-x7已经用完了 
    ADD             X1, X0, #0xF
    AND             X1, X1, #0xFFFFFFFFFFFFFFF8
    STR             X1, [X29,#0x20]
    B               loc_3730

loc_3728:                                
    LDR             X0, [X29,#0x28]
    //sp+0x28 存储 x0 栈顶指针
    ADD             X0, X0, W1,SXTW
    //x0+w1 w1符号扩展 此例是一个负数 
    //传递进来的参数 依次压入堆栈 x1-x7 c8-d8-e8-f8-0x100-[x0 栈顶指针的位置]
    //栈顶指针的位置 + 负数 精确计算好了 第一次是定位到 x1 
    //7*8=56 0x38 0xFFFFFFC8 + 0x38 = 0x00000000 即-0x38
    //下一次循环就是 -0x30 总共循环7次

loc_3730:                              
    LDR             X1, [X0]
    //取得压入堆栈的x1的值 第二次是x2 ...
    CBZ             X1, loc_3744
    //等于空退出函数
    MOV             X0, X19 
    BL              printf
    B               loc_36FC

loc_3744:                              
    LDR             X19, [SP,#0x10]
    //变量sp+0x10   恢复 x19 的原始值
    LDP             X29, X30, [SP],#0x100
    //恢复 X29, X30 的原始值,sp堆栈平衡
    RET
    //程序返回
    
ENDPROC(fuck_log1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值