rk3568 的 bootrom 在 0xffff0000 处,hexdump 出来一段。
0000000000000000 <.data>:
0: d53800a0 mrs x0, mpidr_el1
4: 92403c00 and x0, x0, #0xffff
8: f100001f cmp x0, #0x0
c: 540001a0 b.eq 0x40
10: 58000680 ldr x0, 0xe0
14: 52800021 mov w1, #0x1 // #1
18: b9000001 str w1, [x0]
1c: d503205f wfe
20: 18000682 ldr w2, 0xf0
24: 580005e0 ldr x0, 0xe0
28: b9400001 ldr w1, [x0]
2c: 6b02003f cmp w1, w2
30: 54ffff61 b.ne 0x1c
34: 580005a1 ldr x1, 0xe8
38: b9400020 ldr w0, [x1]
3c: d61f0000 br x0
40: aa1f03e0 mov x0, xzr
44: aa1f03e1 mov x1, xzr
48: aa1f03e2 mov x2, xzr
4c: aa1f03e3 mov x3, xzr
50: aa1f03e4 mov x4, xzr
54: aa1f03e5 mov x5, xzr
58: aa1f03e6 mov x6, xzr
5c: aa1f03e7 mov x7, xzr
60: aa1f03e8 mov x8, xzr
64: aa1f03e9 mov x9, xzr
68: aa1f03ea mov x10, xzr
.........
通过 mpidr_el1 判断主从核心,
低16位为0, 表明当前CPU核心是主核,然后跳到 0x40处的代码继续运行。
否则表明当前核心是从核,运行如下指令:
10: 58000680 ldr x0, 0xe0
14: 52800021 mov w1, #0x1 // #1
18: b9000001 str w1, [x0]
1c: d503205f wfe
20: 18000682 ldr w2, 0xf0
24: 580005e0 ldr x0, 0xe0
28: b9400001 ldr w1, [x0]
2c: 6b02003f cmp w1, w2
30: 54ffff61 b.ne 0x1c
34: 580005a1 ldr x1, 0xe8
38: b9400020 ldr w0, [x1]
3c: d61f0000 br x0
将内在 0x000000e0 处的32位数据写成1
然后就 wfe => Wait for event,即让当前核心进入 low-power standby state 模式,
直到被事件唤醒,请参考 ARM WFI和WFE指令_自由的天空-CSDN博客_arm wfi
如果wfe失败,就判断内在 0x000000e0 处是否为0xf0,如果不是就继续跳到1c处,
继续wfe,如果 0x000000e0 处为 0xf0,就从内存 0x000000e8 处取目标地址,
并用 br 指令跳转过去运行。
由此可知, 如果没触发条件, 从核心都处于不工作状态。
dfsdf主核心跳到 0x40 处后执行流程:
首先就是把 31 个通用寄存器清0,
.........
ac: aa1f03fb mov x27, xzr
b0: aa1f03fc mov x28, xzr
b4: aa1f03fd mov x29, xzr
b8: aa1f03fe mov x30, xzr
bc: 580000a0 ldr x0, 0xd0
c0: 9100001f mov sp, x0
c4: 580000a0 ldr x0, 0xd8
c8: d51ec000 msr vbar_el3, x0
cc: 14000567 b 0x1668
d0: fdcc1000 .inst 0xfdcc1000 ; undefined
d4: 00000000 .inst 0x00000000 ; undefined
d8: ffff7800 .inst 0xffff7800 ; undefined
dc: 00000000 .inst 0x00000000 ; undefined
e0: fdcc0004 .inst 0xfdcc0004 ; undefined
e4: 00000000 .inst 0x00000000 ; undefined
e8: fdcc0008 .inst 0xfdcc0008 ; undefined
ec: 00000000 .inst 0x00000000 ; undefined
f0: deadbeaf .inst 0xdeadbeaf ; undefined
f4: 00000000 .inst 0x00000000 ; undefined
然后设置栈寄存器:取 0xd0 处的 unsigned int 做为 sp
其后设置 vbar_el3(el3 的 vertor base addr)为 0xFFFF7800,
然后 b 0x1668 跳到 0x1668 处继续运行。
1668: f81f0ffe str x30, [sp,#-16]!
166c: f0fee668 adrp x8, 0xfffffffffdcd0000
1670: 528794a9 mov w9, #0x3ca5 // #15525
1674: f0fee66a adrp x10, 0xfffffffffdcd0000
1678: 1280000b mov w11, #0xffffffff // #-1
167c: f0fee66c adrp x12, 0xfffffffffdcd0000
1680: f0fee66d adrp x13, 0xfffffffffdcd0000
1684: b9000d09 str w9, [x8,#12]
1688: b902714b str w11, [x10,#624]
168c: f0fee668 adrp x8, 0xfffffffffdcd0000
1690: 3900f19f strb wzr, [x12,#60]
1694: 3900d1bf strb wzr, [x13,#52]
1698: b900111f str wzr, [x8,#16]
169c: 321d07e0 orr w0, wzr, #0x18
16a0: 94000dfb bl 0x4e8c
16a4: 94000dfd bl 0x4e98
16a8: 94000cb8 bl 0x4988
mem@0xfdcd000c = 0x3ca5
mem@0xfdcd0270 = 0xffffffff // #-1
mem@0xfdcd003c = 0 (byte)
mem@0xfdcd0034 = 0 (byte)
mem@0xfdcd0010 = 0 (byte)
都是PMU_SRAM 内存( 0xFDCD0000 8KB)
然后 bl 0x4e8c
因为只dump了前19kb的bootrom, 暂时看不到 0x4e8c 处的代码。
汇编也不是强项, 放弃 bootrom 代码分析。