CVE-2024-20154 技术分析文章
分类: CWE-121 — 基于栈的缓冲区溢出
严重性: 关键(联发科公告)· 8.8 高,攻击向量:邻近(CISA-ADP)
类型: 远程代码执行 — 无需用户交互,无需预先关联
披露: 联发科安全公告,2025 年 1 月 6 日 https://corp.mediatek.com/product-security-bulletin/January-2025
分析目标: 三星 Galaxy A14 SM-A145R — MT6769 系列(Helio G80),属于联发科受影响芯片组列表 - 固件在安全条件下仿真。
状态: 已修复。
这是我首次公开发布的基带研究。我原先的背景与电信基础设施、合法拦截中介层、Stingray 和 IMSI 捕获器分析以及嵌入式设备安全相距甚远——此前我并未对蜂窝调制解调器进行深入的固件逆向工程。我想向自己证明,一种结构化的分析方法能够跨目标适应,并且对特定平台的熟悉程度可以通过严格的链条追踪来替代。NB-IoT 之所以引人注目,是因为它处于一个真正危险的交叉点:该协议是为受限的物联网设备设计的,攻击面在预关联阶段,而无论手机用户在做什么,调制解调器堆栈都会处理它。
当分析已修补的固件并确认易受攻击的模式已不存在时,用于在定位特定功能前对固件进行大规模分析的 AI 系统独立地将重构的漏洞类别、条件和受影响的固件系列与 CVE-2024-20154 的描述相匹配。
技术结论为分析师本人所持有。
你口袋里的手机至少包含两台独立的计算机。你与之交互的那台运行 Android。另一台——基带——完全独立运行,处理所有无线电通信,并且对其上方的操作系统几乎不可见。Android 可能已完全修补。浏览器可能已被沙盒化。用户可能从未点击恶意链接。但如果易受攻击的代码位于应用处理器介入之前处理无线电信号的调制解调器固件中,那么所有这些都无关紧要。
CVE-2024-20154 正是这类漏洞。
一个畸形的 NB-IoT 系统信息广播会导致联发科调制解调器固件接受攻击者控制的调度计数,将该计数通过 RRC 到 L1 的配置路径传递而不进行任何钳位,并最终将其用作 NB-IoT 广播信道处理程序中栈写入循环的循环边界。当计数超过目标数组的容量时,循环写入超出它们,到达栈上保存的寄存器,并覆盖保存的返回地址。该函数随后将损坏的值恢复到返回地址寄存器并跳转至该地址。
其严重性在于:
该漏洞已在联发科 2025 年 1 月 6 日的安全公告中以关键严重性评级发布,影响 LR12A 调制解调器系列及其他。三星已将其修复纳入其 2025 年 2 月的安全维护版本。
本文不会发布可武器化的漏洞利用代码,也无法通过此处公开的内容复现漏洞。 目标是展示链条在何处断裂,每一层为何未能阻止它,以及在无法将调试器连接到实时调制解调器的情况下,负责任地验证基带漏洞所需的工作。
主要目标:三星 Galaxy A14(SM-A145R)。无线电子系统由 MT6769 芯片组系列(Helio G80)中的联发科基带处理器驱动。MT6769 系列已明确列在联发科针对 CVE-2024-20154 的受影响芯片组列表中。``` AP/CP firmware: A145RXXU1AWD1 Modem software: MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5 Build date: 2023-04-18
基带固件并非 Android 代码。它是 SoC 射频子系统上一个独立的嵌入式系统,拥有自己的 CPU、自己的 RTOS 以及自己的内存空间,完全位于 Android 进程沙箱之外。
### 2.2 调制解调器架构
对提取的二进制文件进行分析后显示,调制解调器处理器运行在 MIPS32 架构上,并使用 MIPS16e2 压缩指令集,采用小端模式。MIPS16e2 是一种用于嵌入式代码尺寸缩减的 16 位编码扩展——这与联发科在 Helio 系列基带上的做法一致,并且已有针对该 SoC 系列的独立已发布基带研究加以证实。
操作系统为 Nucleus RTOS,提供任务调度、IPC 消息队列以及基于内存池的分配器。任务之间没有内核/用户权限分离、没有内存保护单元强制措施,也没有硬件堆栈保护机制。
本文中所有地址均为虚拟地址,在 Ghidra 中以基址 `0x90000000` 加载。
### 2.3 缓解措施(针对所分析构建版本观察到的结果)
| 缓解措施 | 状态 | 影响 |
|---|---|---|
| ASLR | 缺失 | 固件地址是静态的,可根据镜像预测 |
| 栈金丝雀 | 缺失 | `SAVE`/`RESTORE` 存储被调用者保存的寄存器时没有保护值 |
| NX / W^X | 缺失 | 栈内存可执行 |
| CFI | 缺失 | 返回地址未根据任何策略进行验证 |
### 2.4 分析方法
并行三条路径:
**静态分析。** Samsung 固件包 → CP 分区提取 → `md1img.img` → Ghidra(MIPS LE 32 位,基址 `0x90000000`),并使用 NCC Group 的 `mtk_bp` 工具集从固件调试段恢复出来的联发科工程符号。
**动态验证。** 使用 Unicorn Engine(MIPS32 仿真)分两个阶段隔离执行特定固件例程。第一阶段尝试通过原生指令对证明 `si_count` 未经钳制便复制到通道上下文中。第二阶段在实际固件字节上执行了该脆弱循环,并确认固件自身指令破坏了已保存的返回地址。由于 CPHY 分发路径所需的 RTOS 服务对象环境未能重建,第一阶段无法完全原生执行,故在全部输出中对该副作用进行了建模并加以标注。
**射频侧验证。** 使用带 ZMQ 回环的 srsRAN 4G(纯软件,无射频发射)确认了测试载荷能够通过 NB-IoT PHY 编码及传输块交付。
---
## 3. 攻击面:NB-IoT 与 SIB1-NB
### 3.1 预关联攻击面
NB-IoT(窄带物联网)是 3GPP Release 13 标准,旨在利用现有授权 LTE 频谱连接受限物联网设备。它在包括消费级智能手机在内的多种现代蜂窝 SoC 中均有实现。
在 RRC_IDLE 状态下,在建立任何 RRC 连接之前,正在搜索服务的设备将执行以下操作:
1. 与小区的时间信号(NPSS/NSSS)同步
2. 通过 NPBCH 解码主信息块(640 毫秒传输窗口)
3. 通过 NPDSCH 解码 SIB1-NB(2560 毫秒调度周期)
4. 利用 SIB1-NB 中的调度信息定位其他系统信息块
在第 3 步中,调制解调器会在任何连接或用户交互之前,处理来自一个它尚未认证的实体的消息。满足正常小区选择条件的恶意发射机将被处理。```
+------------------+ +---------------------+
| Rogue Base Stn | | Target UE (Modem) |
+--------+---------+ +----------+----------+
| |
| NPSS/NSSS sync |
|--------------------------------------->|
| MIB-NB (640 ms cycle) |
|--------------------------------------->|
| SIB1-NB (malformed, si_count > 8) |
|--------------------------------------->| ← vulnerability triggered
| [no RRC connection established] |
SIB1-NB 定义于 3GPP TS 36.331。其 schedulingInfoList 字段携带小区广播的系统信息消息数量,规范约束最多为 8 个条目(1..maxSI-Message-NB-r13 = 8)。这是一个协议层约束。内存安全约束——即列表长度不得超过目标数组的容量——必须由固件单独强制执行。
但事实并非如此。
固件从三星 CP 包中获取,并使用 NCC Group 的 mtk_bp 工具集进行提取:```
md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image)
→ 017_md1_dbginfo (XZ-compressed CATI debug symbols)
CATI调试部分通过 `mtk_dbg_extract.py symbols` 解压并解析,然后通过 `ImportSymbolsScript.py` 导入到 Ghidra 中。结果为整个调制解调器栈提供了完整的内部函数名称——包括 ERRC 层、L1 信道管理、IPC 子系统以及 NB-IoT BCCH 处理链——从而支持语义引导的链重构。
本文中所有函数名称均来自从固件镜像中提取的联发科自有嵌入式调试符号。
---
## 5. 漏洞
### 5.1 漏洞循环
`el1_ch_nbcch_resume_req` (`0x90213940`) 处理 NB-IoT 广播信道恢复事件。其 MIPS16e2 函数序言:```asm
90213940: save 0xE8, ra, s0-s1
SAVE 指令将 sp 递减 0xE8,并将被调用者保存的寄存器向下存储:```
old_sp (= new_sp + 0xE8)
new_sp + 0xE4 saved ra ← overflow target
new_sp + 0xE0 saved s1
new_sp + 0xDC saved s0
new_sp + 0x98 si_sched_arr [34 halfwords = 68 bytes]
new_sp + 0x78 si_type_arr [32 bytes]
new_sp + 0x00 ← stack pointer after SAVE
来自 Ghidra 对实际固件二进制文件的反编译:```c
for (uVar6 = 0; uVar6 < (byte)param_2[0x40a]; uVar6 = uVar6 + 1) {
si_type_arr[uVar6] = /* SI type byte */; // 1 byte/iter, base new_sp+0x78
si_sched_arr[uVar6] = /* SI schedule halfword */; // 2 bytes/iter, base new_sp+0x98
}
param_2[0x40a] 是 ch_ctx[+0x40A] — 通道上下文 BSS 结构体中的一个持久字节。
循环边界直接使用,没有事先与数组容量进行比较。
Stream A(半字 sh 写入)从 new_sp+0x98 开始,每次迭代前进 2 字节。
它在第 38 次迭代时到达 new_sp+0xE4 处的保存的 RA:```
new_sp + 0x98 + i×2 = new_sp + 0xE4
i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38
流B (字节 `sb` 写入) 起始于 `new_sp+0x78` 并且需要 iteration 108 才能到达 RA 槽位:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108
With si_count = 40(演示值,选择它来超过 38 的溢出阈值)
循环运行了 40 次迭代。流 B 从未到达 RA 槽。RA 损坏完全来自流 A。
经过 40 次迭代后,MIPS16e2 RESTORE 指令从堆栈中将损坏的值重新加载到 $ra,然后 jrc ra 转移控制。
ch_ctx[+0x40A] 由 el1_ch_nbcch_start 在 0x90213444 写入。两条连续的 MIPS 指令之间没有任何内容:```asm
; el1_ch_nbcch_start @ 0x90213444
lbu v0, 0x99(s0) ; read IPC_msg[+0x99] = si_count from CPHY_CFG_REQ
sb v0, 0x40A(s1) ; write to ch_ctx[+0x40A] — no clamp, no mask, no compare
### 5.4 ERRC 构建器 — Layer A
CPHY_CFG_REQ 缓冲区在 ERRC 层中由解码后的 SIB1-NB 构建。函数 `errc_chm_l1_set_bcch_si_reception` 写入 `IPC_msg[+0x99]`:```c
// errc_chm_l1_set_bcch_si_reception — Layer A
// Loop bound: decoded schedulingInfoList entry count from SIB1-NB
while (bVar3 < *(byte *)(param_3 + 0x44) && (param_2 != 0)) {
bVar3++;
if (uVar2 != param_2) {
*param_5 = *param_5 + 1; // CPHY_CFG_REQ[+0x99]++ — no upper bound check
}
}
循环边界是来自SIB1-NB的解码条目计数。计数器每解码一个条目递增一次,一直递增到所有解码条目,没有上限保护。
一旦CPHY_CFG_REQ缓冲区被填充,ERRC就将它分发给L1,路由键为sap_id = 0x501F:```
el1_ch_rcv_ilm (sap 0x501F)
→ el1_chmgm_errc_cfg_req_in_idle ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C]
→ el1_chmgm_nbcch_handler
→ el1_ch_nbcch_main
→ el1_ch_nbcch_cphy_cfg_req_process ← validates cell identity, no si_count check
→ el1_ch_nbcch_start @ 0x90213444 ← Layer B: lbu + sb, no clamp
### 5.6 三层缺失钳位
| 层 | 函数 | 地址 | 是否存在钳位? |
|---|---|---|---|
| A — ERRC 构建器 | `errc_chm_l1_set_bcch_si_reception` | ERRC 范围 | **无** |
| B — L1 复制 | `el1_ch_nbcch_start` | `0x90213444` | **无** |
| C — L1 循环 | `el1_ch_nbcch_resume_req` | `0x90213940` | **无** |
任何一层添加单个检查都会破坏该链条。
### 5.7 根本原因
一条被违反的不变量:
> SI 调度条目数绝不能超过目标数组容量。
3GPP 提供了预期的协议上限(8 个条目)。固件需要在每一层——当该计数值成为索引或循环上限时——强制执行内存安全边界。在该有漏洞的构建中,该计数值从 SIB1-NB 广播字段穿过 ERRC 解码器,进入 CPHY_CFG_REQ 消息,越过 IPC 边界进入 L1 任务,进入信道上下文 BSS,最后进入一个栈写入循环——期间没有任何一层对其进行钳位。
---
## 6. 调用链——如何发现的
### 6.1 两条路径的混淆
两条结构相似但不同的路径可以将一个 0x760 字节的配置缓冲区传递到 `el1_ch_nbcch_main`:
| 路径 | 来源 | `[+0x99]` 值 | 相关性 |
|---|---|---|---|
| 路径 A(ERRC → L1 IPC) | ERRC 从解码的 SIB1-NB 构建 CPHY_CFG_REQ | 来自空口的 `schedulingInfoList.count` | **受影响路径** |
| 路径 B(L1 内部) | `el1_ch_scs_ind_send` 构建内部 IPC 体 | 硬编码的 `1` | 无漏洞 |
路径 B 确认了消息格式——字节 `+0x99` 是 `el1_ch_nbcch_start` 消耗的 SI 计数值。由于其计数值始终硬编码为 1,因此无法溢出。受外部影响的路径是路径 A。
### 6.2 写入者搜索
在固件中模式搜索任何写入偏移 `+0x99` 的指令产生了大量噪声:T1(直接 `sb`,约 100 条)、T2(拆分基址,5 条)、T3(计算偏移,0 条)、T4(重叠 `sh`/`sw`,约 465 条)。ERRC 信道管理函数未出现在 `msg_send6` 交叉引用列表中,因为 ERRC 使用 `errc_com_send_msg`。仿真探测确认写入发生在 ERRC 端:从 L1 调度器运行 Unicorn 测试框架并监视对缓冲区 `+0x99` 偏移的写入,未从 L1 端捕获到任何操作。```
[RUN] dispatcher=0x90214418 watching IPC_msg+0x99
NO writes to IPC_msg+0x99 caught from dispatcher.
Write happened before el1_ch_nbcch_main — confirmed ERRC-side.
在 errc_com_send_msg 中按 sap_id = 0x501F 进行路由导向至 el1_chmgm_errc_cfg_req_in_idle,后者将 CPHY_CFG_REQ 指针存储于 L1_ctx[+0x323C] 处,并开始下游分发。
SIB1-NB schedulingInfoList.count (demonstrator: 40) │ ▼ [ERRC task] errc_chm_ch_ctrl_req_hdlr → errc_chm_call_ctrl → errc_chm_l1_main → errc_chm_l1_call_ctrl → errc_chm_l1_snd_cphy_cfg_req ← allocates 0x760-byte CPHY_CFG_REQ → errc_chm_l1_set_cphy_req_nbcch_cfg → errc_chm_l1_set_bcch_inf → errc_chm_l1_set_bcch_si_reception ← Layer A: CPHY_CFG_REQ[+0x99] = 40 → errc_com_send_msg(sap=0x501F) ← IPC to L1 │ ▼ [L1 task] el1_ch_rcv_ilm (sap 0x501F) → el1_chmgm_errc_cfg_req_in_idle ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C] → el1_chmgm_nbcch_handler → el1_ch_nbcch_main → el1_ch_nbcch_cphy_cfg_req_process ← no si_count validation → el1_ch_nbcch_start @ 0x90213444 ← Layer B: lbu + sb, no clamp │ ▼ ch_ctx[0x40A] = 40 (persists in BSS) │ ▼ [state machine advances to 0x0B, event 0x2C] el1_ch_nbcch_resume_req @ 0x90213940 ← Layer C: loop bound from ch_ctx[0x40A] │ ▼ stack overflow → jrc ra → PC = attacker-controlled
---
## 7. 验证
这款特定的 SM-A145R 型号在正常的出厂固件运行中似乎并未触发存在漏洞的 NB-IoT 代码路径,这也是为何采用混合仿真与静态分析而非直接硬件复现的原因。
**静态证明。** 固件二进制文件中包含存在漏洞的指令对。调用链通过符号、交叉引用及反编译函数体重建。
**模拟环境原生执行。** `el1_ch_nbcch_resume_req` 内部的循环在 Unicorn Engine(MIPS32)中直接执行真实的联发科固件字节。固件自身的 `sh` 指令(位于 `0x90213B02`)向保存的返回地址槽写入数据。`RESTORE` 指令将篡改后的值加载至 `$ra`,随后 `jrc ra` 执行控制流跳转。
**显式建模。** `el1_ch_nbcch_start` 中的 `lbu`/`sb` 拷贝操作无法完全原生执行,因为 `el1_ch_nbcch_cphy_cfg_req_process` 内的 RTOS 回调表分发路径需要真实的 Nucleus 堆对象,而扁平模拟器无法提供。阶段 2 中的恢复处理程序(`el1_ch_nbcch_resume_req`)仅从 BSS 驻留的信道上下文中读取数据,且不经过相同分发路径,因此阶段 2 无需额外脚手架即可原生运行。阶段 1 的副作用——将 `IPC_msg[+0x99]` 的一个字节写入 `ch_ctx[+0x40A]`——已直接建模并标记为 `[PHASE1-MODEL]`。
**未声称。** 完整的端到端空口硬件复现。
### 7.1 防篡改
测试框架强制执行一条规则:任何钩子均不得向保存的返回地址槽写入证明标记。所有非固件内存写入操作均被追踪。```
[PROOF-W] saved_RA write: pc=0x90213b02 addr=new_sp+0xE4 value=0xbeef
[PROOF-W] saved_RA write: pc=0x90213b02 addr=new_sp+0xE6 value=0xdead
[ANTI-TAMPER] no hook wrote RA=0xDEADBEEF — firmware only
anti_tamper_fail = False
0x90213B02 是循环体内的 sh 指令。固件将这些字节放置在预测的栈偏移处。在小端序存储中,位于 new_sp+0xE4 和 new_sp+0xE6 的半字 0xBEEF 和 0xDEAD 组合成 [ef be ad de] = 0xDEADBEEF。
[REGS] RA = 0xdeadbeef ← firmware wrote this; decisive proof PC = 0x00000000 ← Unicorn unmapped-fetch artifact, not a hardware exception vector
[STACK] new_sp+0xE4: [ef be ad de] ← little-endian 0xDEADBEEF
[PC-EXPLAIN] PC=0 is an unmapped-fetch artifact; decisive proof is RA=0xDEADBEEF + stack bytes [ef be ad de] + [PROOF-JRC] CONFIRMED: saved RA = 0xDEADBEEF
### 7.3 ZMQ 交付
为了确认测试载荷能够经受 NB-IoT PHY 编码和传输块交付,使用了带有 ZMQ 环回(无射频发射)的 srsRAN 4G。载荷是一个故意不符合规范的向量——放宽了 `schedulingInfoList` 上的 ASN.1 SIZE 约束,允许 40 个条目,并通过 pycrate 往返解码确认字节 14 处的计数字段。```
SIB1 received
SIB2 activated
exit 0
这确认了传输层交付。固件侧的ASN.1行为由Layer A静态分析确立。
el1_ch任务有一个栈。Phase 1和Phase 2是由同一任务顺序处理的两个独立IPC事件,它们之间栈完全展开。计数持久保存在通道上下文BSS中,而不是在栈上:```
EVENT: CPHY_CFG_REQ (Phase 1)
el1_ch_nbcch_start
lbu v0, 0x99(s0)
sb v0, 0x40A(s1) ← ch_ctx[0x40A] = attacker value, written to BSS
returns — stack fully unwound
EVENT: resume (state 0x0B, msg 0x2C) (Phase 2) el1_ch_nbcch_resume_req ← frame 0xE8, reads ch_ctx[0x40A] as loop bound loop × 40 → saved RA corrupted jrc ra → attacker-controlled PC
`ch_ctx[0x40A]` 位于 BSS,并保留攻击者的值,直到调制解调器重置或后续通道配置覆盖它。
### 8.2 栈帧```
old_sp (= new_sp + 0xE8)
new_sp + 0xE4 saved ra
new_sp + 0xE0 saved s1
new_sp + 0xDC saved s0
new_sp + 0x98 si_sched_arr [34 halfwords = 68 bytes]
new_sp + 0x78 si_type_arr [32 bytes]
通过仿真测量确认帧大小。仿真结果确认数组位置——RA 在第38次迭代时写入,与 si_sched_arr 起始于 new_sp+0x98 一致。
| 构建版本 | 调制解调器固件 | 构建日期 |
|---|---|---|
| 易受攻击版本 | A145RXXU1AWD1, MOLY LR12A...V1.P5 | 2023-04-18 |
| 已修补版本 | A145RXXUDDZC2, MOLY LR12A...V3.P8 | 2025-04-23 |
通过从两个镜像中提取 md1_dbginfo 元数据确认构建日期。补丁 ID:MOLY00720348 · 问题 ID:MSV-2392。
el1_ch_nbcch_start(易受攻击二进制文件中的 0x90213444): lbu/sb 指令对缺失。IPC_msg[+0x99] 直接复制到 ch_ctx[+0x40A] 的操作已被移除。
el1_ch_nbcch_resume_req(易受攻击二进制文件中的 0x90213940): 遍历 ch_ctx[0x40A] 进行栈写入的循环已不存在。那种将不可信字节直接作为固定大小栈数组循环边界的架构不再存在。该函数体已被替换为不同的分发结构。
errc_chm_l1_set_bcch_si_reception: 无界计数器循环已被替换为面向验证的辅助函数调用。
已修补二进制文件中出现而易受攻击二进制文件中缺失的两个函数:``` el1_ch_nbcch_param_check el1_ch_scell_param_check
单行边界检查看起来是在同一地址的现有函数内部添加几条指令。但补丁后的二进制文件显示的是架构性的修订:NBCCH 调度路径被重新设计,使得 `si_count` 作为循环边界的模式不再存在于该路径的任何位置。
### 10.4 CVE 归属
这里描述的漏洞与 MediaTek 于2025年1月6日发布的 CVE-2024-20154 相符。确认依据如下:
- 受影响的固件系列 (LR12A) 与 MediaTek 公告相符。
- 漏洞类别——栈溢出、缺失边界检查、来自恶意基站的远程代码执行、无需用户交互——与 CVE 描述和 NVD 记录相符。
- 修复后的固件精确移除了被识别为存在漏洞的代码结构。
- 补丁 ID MOLY00720348 已从 MediaTek 公告和 Android 安全公告 (A-376809176) 中确认。
- AI 辅助分析在手动确认之前,独立地将重构的模式与 CVE-2024-20154 匹配。
---
## 11. 伦理与负责任披露
### 11.1 本文不包含的内容
没有武器化的漏洞利用代码。没有固件二进制内容。没有畸形的负载字节。没有针对真实设备触发漏洞的逐步操作步骤。重现可行攻击所需的信息——特定调制解调器解码器的完整负载构造、完整第一阶段模拟的 RTOS 堆对象脚手架、空中无线电配置——被有意省略。
### 11.2 为什么 ZMQ 回环和模拟是合乎伦理的方法
ZMQ 回环意味着从未通过空中传输任何信号。没有针对真实设备。没有涉及运营商网络。证明过程完全在分析人员拥有的硬件上的隔离软件环境中运行。这是验证预关联无线电漏洞的正确方法——传输畸形广播会影响范围内的任何设备。
Unicorn 模拟表明,漏洞行为存在于固件二进制本身,且可重现,独立于任何特定的设备状态或无线电环境。这比单次硬件崩溃在技术上更强有力,且避免了在空中部署任何内容。
### 11.3 MediaTek 知识产权
所有分析均基于从消费设备合法获取的固件以及三星公开发布的固件包进行。未使用任何专有文档。内部 MediaTek 结构体定义和 IPC 消息格式仅在解释内存安全故障所需的范围内进行描述。它们并未作为规范发布。
---
| 迭代 | sh 写入位置 | 效果 |
|---|
| 0–33 | si_sched_arr[0..33] | 在范围内 |
| 34–35 | new_sp+0xDC — 保存的 s0 | s0 被损坏 |
| 36–37 | new_sp+0xE0 — 保存的 s1 | s1 被损坏 |
| 38 | new_sp+0xE4 — 保存的 ra [15:0] | RA 低半字 |
| 39 | new_sp+0xE6 — 保存的 ra [31:16] | RA 高半字 |
| 门控 | 条件 | 检查位置 |
|---|
| NB-IoT 激活路径 | cfg_type == 1 | el1_ch_nbcch_cphy_cfg_req_process |
| 信道未完成 | done_flag == 0 | ch_ctx[0x438] |
状态机 0x0B | NBCCH 处于恢复状态 | el1_ch_nbcch_main 分发 |
| si_count 非零 | ch_ctx[0x40A] > 0 | 循环条件 |
| 频段等级 ≤ 2 | 有效的 NB-IoT 模式 | 进入 el1_ch_nbcch_resume_req |
el1_chmgm_cell_info_get 非零 | 小区在服务表中 | 在 el1_ch_nbcch_start 中调用 |
| 函数 | 地址 | 作用 | 钳制? |
|---|
errc_chm_l1_set_bcch_si_reception | ERRC 范围 | 写入 CPHY_CFG_REQ[+0x99] | 无 |
el1_ch_nbcch_cphy_cfg_req_process | 0x90213F80 | 将 CPHY 配置路由到 L1 | N/A — 不读取 si_count |
el1_chmgm_cell_info_get | 0x9020E0D0 | 验证 EARFCN/PCI | N/A |
el1_ch_nbcch_start | 0x90213444 | 将计数复制到 BSS | 无 |
el1_ch_nbcch_resume_req | 0x90213940 | 使用计数作为循环边界 | 无 |