- 固件
- 嵌入式
- 操作系统
- 驱动开发
【免费下载链接】coreboot
Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.
本文围绕 coreboot 仓库中 Documentation/northbridge/intel/sandybridge/index.md 及其子文档,系统讲解 Intel 第二代(Sandy Bridge)与第三代(Ivy Bridge)酷睿处理器内存控制器(北桥)的初始化原理、原生内存初始化(Native RAM Initialization)的实现细节、频率选择策略、读取训练算法、MCHBAR 寄存器布局,以及如何通过 me_cleaner 缩减 Intel ME 固件以回收 Flash 空间。读完本文,你将掌握 coreboot 在 Sandy/Ivy Bridge 平台上"如何不依赖闭源 mrc.bin 完成内存初始化"的完整技术脉络,并能落地配置USE_NATIVE_RAMINIT、XMP/熔丝覆盖、MRC cache 复用、S3 恢复与 ME 分区裁剪等实战操作。
一、章节导航与文档总览
Documentation/northbridge/intel/sandybridge/index.md是 coreboot 中关于 Intel Sandy Bridge 北桥的官方文档入口,其目录树指向三份核心文档:
- Native RAM Initialization(
nri.md) - RAM initialization feature matrix(
nri_features.md) - ME Cleaner(
me_cleaner.md)
其中nri.md又通过 toctree 展开四份深度子文档:寄存器文档(nri_registers.md)、频率选择(nri_freq.md)、读取训练(nri_read.md)。这些文档构成了 coreboot 在 Sandy/Ivy Bridge 平台上开源内存初始化的第一手技术资料。
需要特别强调的是,这套文档的撰写背景是:Intel 的内存控制器属于闭源硬件,coreboot 社区通过逆向工程梳理出了可编程寄存器与训练算法,并在 src/northbridge/intel/sandybridge 下实现了完整的开源 raminit 代码(核心文件为raminit.c、raminit_native.c、raminit_common.c、raminit_iosav.c)。
二、内存初始化的职责范围
在 Sandy Bridge / Ivy Bridge 上,内存初始化代码必须承担大量工作(见nri.md),主要包括:
- 选择工作频率(Operating frequency)
- 选择公共时序(Common timings)
- 施加频率相关的补偿值
- 对所有已插 DIMM 的通道执行读取训练(Read training)
- 对所有已插 DIMM 的通道执行写入训练(Write training)
- 调整地址与命令信号的延迟网络
- 对所有已插 DIMM 的通道执行 DQS 训练
- 编程内存映射(Memory map)
- 上报 DRAM 配置
- 错误处理
这些职责与源码结构一一对应:raminit.c中的init_dram_ddr3()(src/northbridge/intel/sandybridge/raminit.c)是训练总入口,内部依次完成 SPD 探测、频率/CAS 选择、通道训练、ECC scrub、正常模式切换与report_memory_config()上报。
2.1 符号定义约定
nri.md与nri_freq.md、nri_read.md共用一套术语表,理解后续内容前必须先掌握:
| 符号 | 含义 | 单位 | 有效范围 |
|---|---|---|---|
| SCK | DRAM 系统时钟周期时间 | s | — |
| tCK | DRAM 系统时钟周期时间(定点表示) | 1/256 ns | — |
| DCK | 数据时钟周期时间(两个 SCK 沿之间的时间) | s | — |
| timA | IO 相位(IO 信号的相位延迟) | 1/64 DCK | [0-512) |
| SPD | 每条 DIMM 上 EEPROM 中厂商预置的时序 | bytes | — |
| REFCK | 参考时钟,100 或 133 | MHz | 100, 133 |
| MULT | DRAM PLL 倍频器 | — | [3-12] |
| XMP | 极限内存配置文件(Extreme Memory Profiles) | — | — |
在读取训练章节还会引入 DQS(Data Strobe,用于采样各 lane DQ 信号的数据选通信号)。
三、Native Raminit 与 mrc.bin 两条路线
nri_features.md开篇对比了内存初始化的两条可选路线,这在 Kconfig 中对应USE_NATIVE_RAMINIT开关(src/northbridge/intel/sandybridge/Kconfig):
路线一:Native raminit(开源)
- 完全开源,代码就在
src/northbridge/intel/sandybridge/raminit_native.c等文件中; - 对大多数板卡的大多数频率都能工作,但仍可能存在需要修复的错误;
- 对在 romstage 中的位置没有要求。
路线二:mrc.bin raminit(闭源 blob)
- 使用 Intel System Agent 二进制(默认路径
3rdparty/blobs/northbridge/intel/sandybridge/systemagent-r6.bin,见MRC_FILE配置,src/northbridge/intel/sandybridge/Kconfig); - 没有已知错误,但必须被放置在 romstage 中的固定偏移处(
raminit_mrc.c负责该路径)。
USE_NATIVE_RAMINIT默认值为y,即 coreboot 默认推荐使用开源实现。选择 mrc.bin 路径时,DCACHE_RAM_MRC_VAR_SIZE默认变为0x9000,用于给 MRC 预留变量空间。
3.1 已实现功能矩阵
nri_features.md给出了一份非常详尽的特性矩阵,这里完整转述并补充 Kconfig 佐证:
通道与容量
- 单通道与双通道:支持、已实现、可用;
- 最多 4 个插槽:支持、已实现、可用;
- 每通道最多 4 个 rank:支持、已实现、可用。
从源码看,通道数、每通道槽位数的探测来自CAPID0_A寄存器(src/northbridge/intel/sandybridge/raminit.c 中的nb_slots_per_channel()与nb_number_of_channels())。
支持频率
- DDR3-1066(533 MHz):支持、已实现、可用;
- DDR3-1600(800 MHz):支持、已实现、可用;
- DDR3-1866(933 MHz):支持、已实现、可用;
- DDR3-2133(1066 MHz):支持、已实现、可用;
- DDR3-1400(700 MHz)、DDR3-1800(900 MHz)、DDR3-2000(1000 MHz)、DDR3-2200(1100 MHz)、DDR3-2400(1200 MHz):Ivy Bridge 独占,自 coreboot 4.6 起支持、已实现、可用。
支持 CAS 延迟(CL)
- CL6、CL7、CL8、CL9:支持且已实现,可用性存疑(矩阵中标为
?); - CL10、CL11:支持、已实现、可用;
- CL12、CL13、CL14、CL15:自 coreboot 4.6 起支持且已实现(CL13 标记为可用,其余标
?)。
MRC cache(上次训练的时序缓存)
- S3 恢复:支持、已实现、可用;
- 正常启动:支持、已实现、可用,CRC16 差异时重置。
XMP 支持
- XMP Profile 1:支持、已实现、可用(仅 1.5V 电压配置档);
- XMP Profile 2:支持、已实现,但未激活(not activated)。
ECC 支持
- ECC:自 coreboot 4.13 起支持、已实现、可用;对应 Kconfig 的
RAMINIT_ENABLE_ECC(src/northbridge/intel/sandybridge/Kconfig)。
四、频率选择机制
nri_freq.md详细描述了频率选择的全过程,这是内存初始化中最先确定、影响全局的决策。
4.1 SPD 与 XMP
每条 DIMM 的 SPD(Serial Presence Detect)由厂商出厂烧录了多种时序,其中之一规定该 DIMM 的最大工作时钟频率,以定点值 tCK 存储,并被向下取整到最接近的支持频率。部分 SPD 还包含可选的 XMP 数据,宣告更高频率的"性能模式"。
XMP 生效条件:当前 raminit 能解析 XMP Profile 1 与 Profile 2,但只有XMP Profile 1在同时满足以下条件时才会被采用:
- 宣告 1.5V 工作电压;
- 通道内已安装 DIMM 数不超过 XMP 编码的限制。
否则回退到常规 SPD 时序。源码dram_find_spds_ddr3()中依次判断 XMP profile 有效性、dimms_per_channel限制与电压(src/northbridge/intel/sandybridge/raminit.c),条件不满足时调用spd_decode_ddr3()回落。
对应的 Kconfig 覆盖选项:
NATIVE_RAMINIT_IGNORE_XMP_MAX_DIMMS(自 coreboot 4.7 起):忽略 XMP 对每通道最大 DIMM 数的限制,允许每通道插两根 DIMM 即使 XMP 不允许;NATIVE_RAMINIT_IGNORE_XMP_REQUESTED_VOLTAGE:允许使用请求 1.65V 的 XMP 配置,而不是回退到非 XMP 设置(源码 249-258 行验证了该分支)。
注意:
NATIVE_RAMINIT_IGNORE_XMP_REQUESTED_VOLTAGE在仓库中同样存在,因为原生 raminit 目前只支持 1.5V 操作。Kconfig 帮助文本明确指出这些是"超频选项,请小心处理"(src/northbridge/intel/sandybridge/Kconfig)。
4.2 软熔丝(Soft fuses)
板卡制造商会在芯片中编程"软"熔丝,指示其支持的最大 DRAM 频率。但这类熔丝并不构成硬件限制,因此被称为"软"熔丝——可以被忽略:
- Sandy Bridge 读取
CAPID0_A的 DMFC 位(低 3 位); - Ivy Bridge 读取
CAPID0_B的 DMFC 位((reg32 >> 4) & 0x7)。
源码get_mem_min_tck()(src/northbridge/intel/sandybridge/raminit_native.c)完整实现了这一逻辑:根据 CPU 基址修订(BASE_REV_SNB)选择寄存器,并按位段映射到TCK_533MHZ~TCK_1333MHZ。Ivy Bridge 的映射表明显更长,与特性矩阵中 Ivy Bridge 支持更多频率一致。
coreboot 默认遵守该上限,除非开启CONFIG_NATIVE_RAMINIT_IGNORE_MAX_MEM_FUSES(自 coreboot 4.7 起支持)。想要让内存跑在 DIMM 的"标称"频率上的超频用户需要启用它。忽略熔丝可能导致系统不稳定!
4.3 硬熔丝(Hard fuses)
"硬"熔丝由 Intel 编程,限制给定 CPU/板卡/芯片组可用的最大频率。当前没有寄存器可在设置频率前读取该限制——内存 PLL 无法锁定即表示所选倍频不可用,此时 coreboot 会逐级尝试下一个更小的倍频,直到 PLL 锁定。
4.4 Devicetree 覆盖
devicetree 寄存器max_mem_clock_mhz用于覆盖板卡制造商的"软"熔丝设置,可强制一个最小工作频率。它在芯片配置结构体中定义(src/northbridge/intel/sandybridge/chip.h),例如 666 表示 DDR3-1333、800 表示 DDR3-1600。get_mem_min_tck()中cfg->max_mem_clock_mhz非零时优先返回对应的 tCK。
4.5 参考时钟与倍频
Sandy Bridge 支持 133 MHz 参考时钟(REFCK),Ivy Bridge 额外支持 100 MHz。参考时钟与 DRAM 倍频按以下公式决定 DRAM 频率:
REFCK * MULT = 1 / DCK注意:Ivy Bridge 的 100 MHz REFCK 自 coreboot 4.6 起支持。源码在
find_cas_tck()中通过CAPID0_B的PLL_REF100_CFG位((reg32 >> 21) & 0x7)探测 100 MHz 参考时钟支持,并在normalize_tclk()中处理不支持的频率回落(src/northbridge/intel/sandybridge/raminit_native.c)。
Sandy Bridge 支持频率表(SCK × MULT × 133 MHz REFCK):
| SCK [MHz] | DDR [MHz] | 倍频 MULT | 参考时钟 REFCK |
|---|---|---|---|
| 400 | DDR3-800 | 3 | 133 MHz |
| 533 | DDR3-1066 | 4 | 133 MHz |
| 666 | DDR3-1333 | 5 | 133 MHz |
| 800 | DDR3-1600 | 6 | 133 MHz |
| 933 | DDR3-1866 | 7 | 133 MHz |
| 1066 | DDR3-2133 | 8 | 133 MHz |
Ivy Bridge 支持频率表(额外支持 100 MHz REFCK 档位,自 coreboot 4.6 起):
| SCK [MHz] | DDR [MHz] | 倍频 MULT | 参考时钟 REFCK |
|---|---|---|---|
| 400 | DDR3-800 | 3 | 133 MHz |
| 533 | DDR3-1066 | 4 | 133 MHz |
| 666 | DDR3-1333 | 5 | 133 MHz |
| 800 | DDR3-1600 | 6 | 133 MHz |
| 933 | DDR3-1866 | 7 | 133 MHz |
| 1066 | DDR3-2133 | 8 | 133 MHz |
| 700 | DDR3-1400 | 7 | 100 MHz |
| 800 | DDR3-1600 | 8 | 100 MHz |
| 900 | DDR3-1800 | 9 | 100 MHz |
| 1000 | DDR3-2000 | 10 | 100 MHz |
| 1100 | DDR3-2200 | 11 | 100 MHz |
| 1200 | DDR3-2400 | 12 | 100 MHz |
4.6 倍频选择算法
nri_freq.md给出了 coreboot 选择最大工作频率的伪代码:
if devicetree's max_mem_clock_mhz > 0: freq_max := max_mem_clock_mhz else: freq_max := soft_fuse_max_mhz for i in SPDs: freq_max := MIN(freq_max, ddr_spd_max_mhz[i])可见:当插入不同最大频率的 DIMM 时,取最慢 DIMM 的频率,以避免对其超频。选定频率后得到 PLL 倍频;若 PLL 锁定(见"硬熔丝"一节)则该频率用于所有 DIMM,此后直到断电都无法再更改倍频;若 PLL 不锁定,则逐级使用更小的倍频直到找到可用的。
五、读取训练(Read Training)算法
nri_read.md深入解释了读取训练序列:其目的是补偿 DQS 与 SCK 之间的 skew(偏移),并找到最小可用的往返延迟(roundtrip delay)。
5.1 背景:Fly-By 拓扑
每块板卡的布线拓扑都不同,且可搭配任意的 DDR3 内存模块组合,这会在内存 lane 之间引入不同 skew。DDR3 引入的 "Fly-By" 布线拓扑构成了 DQS-SCK skew 的最大来源。内存代码需要实测 skew 并激活延迟门(delay gates)来"补偿"skew。
读取训练时,DRAM 与控制器进入特殊模式:每次读指令后,DRAM 输出预定义模式,控制器在给定延迟后采样 DQS。由于模式已知,每条 lane 的实际延迟即可被测量。读取训练编程的值只影响 DRAM 到内存控制器方向的数据传输!
5.2 硬件延迟能力
硬件包含两类延迟逻辑块:
- 可将某 lane/rank 的 DQ/DQS 延迟一个或多个时钟周期的块(即 IO delay);
- 可按每个 lane 以 1/64 DCK 为粒度延迟信号的块(即 IO phase)。
所有延迟值都通过写 MCHBAR 中的寄存器由软件控制。
IO phase:可在[0-512) * 1/64 DCK范围内调节。将其递增 64 等价于 IO delay 递增 1。
IO delay:将 DQ/DQS 信号延迟一个或多个时钟周期。
往返时间(Roundtrip time):内存控制器发出读命令后等待数据返回的时间。由于时钟域交叉、多个延迟实例与相位插值器,信号往返内存控制器的默认时间为 55 DCKs。真实往返时间必须实测:发出读命令后,计数器递减到零才激活输入缓冲。
5.3 训练算法步骤
算法需要同时确定三个参数:roundtrip time、IO delay、IO phase。
同步到数据相位(Synchronize to data phase):第一次测量对相位
[0-64) * 1/64 DCK采样所有 DQS 值,搜索低数据符号(low data symbol)的中点,把 timA 调整到该相位,使后续测量与低数据符号对齐。代码假设初始 roundtrip time 使测量落在交替模式的数据相位中。定位前导(Finding the preamble):与交替模式(010101...)的数据相位不同,前导由两个高数据周期组成。代码在保持 timA 不动的情况下递减 IO delay/RTT 并采样 DQS:读到 "low" 说明还在数据相位,读到 "high" 即找到前导。roundtrip time 与 IO delay 持续调整直到所有 lane 对齐。下图展示了 roundtrip time 为 49 DCKs、IO delay(蓝点处)为 6 DCKs 时 lane 0-3 的 timA 分布。
注意:采样数据已按 timA 平移,前导此时与相位对齐。
- 精细调整(Fine adjustment):由于 timA 仍指向数据符号中点,需加上偏移 32,使其指向前导的下降沿。为减小抖动引入的误差,相位从
timA - 25扫描到timA + 25,每个点采样 DQS 100 次,找出每个上升沿(实为前导下降沿)的中点作为最终 IO phase。结果如图所示:lane 0-2 会被调整 -10 相位,而 lane 3 本身已经正确。
nri_read.md还附了三张不同 roundtrip 值(55、54、53 DCKs)下的 timA 采样图,直观展示了信号中的抖动——每次采样发生在不同的循环迭代中,且结果寄存器每个 lane 只有一个位:
在源码侧,训练序列的硬件执行依赖 IOSAV(I/O Subsequence and Validation)机制:raminit_iosav.c中iosav_write_sequence()将 MRS、PRE、ACT、RD、WR、ZQCS 等命令子序列编程进 IOSAV 寄存器组并触发执行(src/northbridge/intel/sandybridge/raminit_iosav.c),训练结果则通过文档描述的 lane training result 寄存器读回。
六、MCHBAR 寄存器(非官方文档)
nri_registers.md是社区逆向出来的 MCHBAR 寄存器空间非官方文档(文档自己声明:不完整且可能有错,请谨慎对待)。MCHBAR 通过 PCI(0:0:0) 设备的寄存器 0x48 启用。
6.1 寄存器编址规律
文档按"通道 0 × lane 0-7"组织,每个 lane 有三类寄存器,呈现清晰的偏移规律:
- Lane training result 寄存器(64 位,如
MCHBAR + 0x4、0x204、0x404...,间隔 0x200):位 0-63,每一位对应 64 个 IO delay 设置之一的训练结果; - Read delay settings 寄存器(32 位,Rank 0-3 各一,如
MCHBAR + 0x10/0x14/0x18/0x1c):包含 IO phase、DQS 上升沿相位、IO delay、DQS 下降沿相位; - Write delay settings 寄存器(24 位,Rank 0-3 各一,如
MCHBAR + 0x20/0x24/0x28/0x2c):包含 DQ IO phase、DQS IO phase、DQS IO delay、DQ IO delay。
以MCHBAR + 0x10(Channel 0、lane 0、Rank 0 的读延迟设置寄存器)为例:
| 位段 | 描述 |
|---|---|
| 0:5 | IO phase shift,单位 1/64 DCK |
| 6:11 | DQS phase shift on rising edge,单位 1/64 DCK |
| 16:18 | IO delay,单位 DCK |
| 20:25 | DQS phase shift on falling edge,单位 1/64 DCK |
写延迟寄存器(如MCHBAR + 0x20)布局如下:
| 位段 | 描述 |
|---|---|
| 0:5 | DQ IO phase shift,单位 1/64 DCK |
| 8:13 | DQS IO phase shift,单位 1/64 DCK |
| 15:17 | DQS IO phase shift,单位 DCK |
| 20 | DQ IO phase shift,单位 DCK |
6.2 特殊寄存器摘要
除逐 lane 的延迟寄存器外,文档还记录了以下关键全局寄存器(均在 Channel 0 语境下):
MCHBAR + 0x1810COMP1 Register:ODT(位 9-11)、CLK drive up(位 21-23)、CTRL drive up(位 27-29);MCHBAR + 0x320cCommand crossover enable Register:CLK phase low(位 0-5)、CLK phase high(位 12)、Enable hardware(位 14)、Enable on slot 1/2(位 17/27);MCHBAR + 0x4000TC_DBP:tRCD、tRP、CAS、CWL、tRAS 各 4 位;MCHBAR + 0x4004TC_RAP:tRRD、tRTP、CKE、WTR、tFAW、tWR,以及 Command 3-state options(位 29)与 CMD stretch(位 30-31,00b=1N、10b=2N、11b=3N);MCHBAR + 0x400cOTHP ODT control:tXPDLL、tXP、ODT stretch 等;MCHBAR + 0x4024Roundtrip time Register:RTT Rank 0/1 DIMM 0/1 各 8 位;MCHBAR + 0x4028SC_IO_LATENCY:IO latency 与 roundtrip - I/O compensation;MCHBAR + 0x4200~0x423cRAM training queue:地址、命令 IO(!RAS/!CAS/!WE)、cooldown(命令后等待的时钟周期数),0x4284为执行队列的启动寄存器;MCHBAR + 0x4298/0x4e98TC Refresh parameters:tREFI(位 0-15)、tRFC(位 16-24)、tREFIx9(位 25-32,应编程为8.9 * tREFI / 1024);MCHBAR + 0x42a4SRFTP:tXSDLL、tXS_offset、tZQOPER、tMOD;MCHBAR + 0x4cb0PM Power-down config:PDWN_idle_counter(位 0-7,最小应大于等于最差往返时间加突发长度)、PDWN_mode(位 8-10:0x0=No power down、0x1=APD、0x2=PPD、0x3=APD+PPD、0x6=PPD-DLLoff、0x7=APD+PPD+DLLoff);MCHBAR + 0x4e94TC Refresh parameters:OREF_RI、Refresh_HP_WM、Refresh_panic_WM;MCHBAR + 0x5000Global channel size control:CH_A(位 0-1)、CH_B(位 2-3)、CH_C(位 4-5)定义最大/中等/最小通道;MCHBAR + 0x5004Address Decode Register:DIMMA/DIMMB 容量(256 MB 倍数)、DAS 槽位映射、rank 数、DRAM 宽度(x8/x16)、Rank interleave enable、Enhanced interleave enable、High order Rank interleave 与 ECC 使能(位 24-25:00b=无 ECC、01b=IO 上 ECC、11b=IO 与 ECC 逻辑均开启);MCHBAR + 0x5030Global DDR3 control:DDR reset(位 1)、DCLK enable(位 2)、IO reset(位 5);MCHBAR + 0x5034Version Register:MRC version;MCHBAR + 0x5060PM Self refresh config:Idle_timer 与 SR_Enable;MCHBAR + 0x5e00MC_BIOS_REQ:选定的倍频(位 0-7,100 MHz 时 [7,12]、133 MHz 时 [3,19])、位 8 指示 100 MHz 参考时钟(Ivy Bridge 独有)、位 31 为 PLL busy;MCHBAR + 0x5e04MC_BIOS_DATA:当前活动倍频;MCHBAR + 0x5f08RCOMP control:Force RCOMP(位 8)。
这些寄存器与上文算法一一对应:比如读取训练算法最终就是把 IO phase、IO delay、roundtrip time 分别写入Read delay settings与Roundtrip time寄存器,训练队列寄存器则承载 IOSAV 命令序列的地址与冷却周期。
七、SMBIOS 上报与 dmidecode 验证
内存初始化完成后,coreboot 通过 SMBIOS type 17 上报内存配置(自 coreboot 4.4 起支持)。在 GNU/Linux 下运行dmidecode -t 17即可查看:
Handle 0x0045, DMI type 17, 34 bytes Memory Device Array Handle: 0x0042 Error Information Handle: Not Provided Total Width: 64 bits Data Width: 64 bits Size: 8192 MB Form Factor: DIMM Set: None Locator: ChannelB-DIMM0 Bank Locator: BANK 2 Type: DDR3 Type Detail: Synchronous Speed: 933 MHz Manufacturer: 0420 Serial Number: 00000000 Asset Tag: 9876543210 Part Number: F3-1866C9-8GSR Rank: 2 Configured Clock Speed: 933 MHz重要解读:dmidecode 打印的内存频率是当前活动频率,既不是双倍数据率,也不是 SPD 中编码的最大频率。例中 DDR3-1866 的"Speed"显示为 933 MHz(即实际工作频率 SCK,非标称 1866 MT/s 的双倍速率)。
对应源码实现位于raminit.c中的report_memory_config(),并最终汇入setup_sdram_meminfo()(src/northbridge/intel/sandybridge/raminit.c)。
八、MRC Cache:训练结果复用与 S3 支持
命名澄清:MRC cache这个名字可能造成误导——在 Native RAM init 场景下并没有 MRC(Memory Reference Code),只是历史原因沿用了这个名称。
原理:MRC cache 是 Flash 中 coreboot 可写的部分。启动结束时 coreboot 把内存训练结果写入 Flash 以备后续使用,因为内存训练非常耗时。存储训练结果有两个收益:
- 正常启动时更快(跳过重新训练);
- 支持 S3 恢复——S3 恢复时 RAM 内容还在但训练结果无法存在 RAM 里(因为必须先配置好内存控制器才能访问 RAM)。
失效机制:内存配置改变时必须使 MRC cache 失效。检测方法是对每根 DIMM 计算 CRC16 并存入 MRC cache,下次启动比对。
源码链路完整印证了文档(自 coreboot 4.4 起):
- 保存:
save_timings()调用mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, ctrl, sizeof(*ctrl))(src/northbridge/intel/sandybridge/raminit.c),在非 fast boot 的启动末尾执行; - 加载:
mrc_cache_current_mmap_leak()尝试读取缓存(src/northbridge/intel/sandybridge/raminit.c); - 校验:缓存读取后先比对 CPUID(防止换过 CPU),再通过
verify_crc16_spds_ddr3()校验 SPD CRC16 是否与当前 DIMM 一致(src/northbridge/intel/sandybridge/raminit.c); - S3 兜底:S3 恢复时若无可用缓存,直接
system_reset()重新冷启动(src/northbridge/intel/sandybridge/raminit.c)。
raminit_mrc.c(mrc.bin 路线)同样通过save_mrc_data()/prepare_mrc_cache()使用同一套缓存基础设施(src/northbridge/intel/sandybridge/raminit_mrc.c)。
九、错误处理与调试
9.1 降级策略
目前唯一支持的错误处理方式是:禁用失败的通道并重启内存训练序列(自 coreboot 4.5 起)。因为内存通道彼此独立运行,这种降级很可能成功。若没有任何 DIMM 能被初始化,coreboot 会调用die()停机——屏幕保持黑屏直到断电。部分平台提供额外的反馈指示。
init_dram_ddr3()末尾的实现是:首次try_init_dram_ddr3()失败后,printram("Disable failing channel."),通过disable_channel(&ctrl, GET_ERR_CHANNEL(err))屏蔽失败通道再次尝试;若仍失败则die("raminit failed")(src/northbridge/intel/sandybridge/raminit.c)。
诊断技巧:如果发现dmidecode -t 17只报告了实际内存容量的一半,很可能是发生了致命的初始化失败。项目的基本立场是:一块能工作但物理内存更少的板子,远比一块根本无法启动的板子要好。
9.2 调试与日志
- 尝试对调内存模块,或换不同品牌的内存;
- 若无效,可查阅"Debugging"章节或在 ticket.coreboot.org 上报工单,附上用 EHCI debug 抓取到的完整 RAM init 日志;
- 启用 Kconfig 选项
DEBUG_RAM_SETUP可获得详尽的内存训练日志(该选项由NORTHBRIDGE_INTEL_SANDYBRIDGE自动 select,即HAVE_DEBUG_RAM_SETUP,src/northbridge/intel/sandybridge/Kconfig)。
调试时建议使用外部调试器(串口或 EHCI debug 棒)——内存初始化失败时板子可能完全无法启动,CBMEM 也就不可用。
9.3 Lenovo ThinkPad 专属死亡指示
Lenovo ThinkPad 有额外特性来指示"RAM init 失败且 coreboot 已死亡"(die()由此得名)。通过 Kconfig 选项(自 coreboot 4.7 起):
H8_BEEP_ON_DEATH:蜂鸣提示;H8_FLASH_LEDS_ON_DEATH:闪烁 LED 提示。
对应实现位于 EC 驱动中(src/ec/lenovo/h8/Kconfig 与 src/ec/lenovo/h8/panic.c),panic.c中分别处理 LED 闪烁与蜂鸣逻辑。
十、ME Cleaner:裁剪 Intel ME 固件
me_cleaner.md介绍如何在构建流程中"清理"Flash 中的 ME 分区。清理会尽量多地移除 ME 固件分区中的代码;在这种状态下ME 会报错并停止运行。
重要警告:使用"清理过的"ME 分区可能引发问题,使用前务必仔细评估!
10.1 已观察到的副作用
使用 cleaned ME 后的已知问题包括:
- LPC 总线不稳定:
- SuperIO 功能异常;
- TPM 功能异常;
- 高总线活动时系统随机关机。
报 Bug 前请务必用未修改的 IFD 和 ME 段测试,再向 coreboot 项目报告问题。
10.2 缩减 Intel ME 固件体积教程
默认情况下,清理后的 ME 固件仍会占据与原分区相同的空间。可以修改固件分区布局来回收空间给 coreboot 使用:缩减后的 Intel ME 固件让ifd、gbe、me三个区域合计占用不到 128 KiB,剩余空间全部留给bios区域。
第 1 步:获取完整 ROM
需要一份包含完整 Intel ME 固件的完整可用 ROM。
第 2 步:运行 me_cleaner
对一个完整 ROM(下称fulldump.rom)运行 me_cleaner。完整 ROM 应包含:IFD、完整可用的 Intel ME、GbE(可选)、BIOS(任意固件)。
./util/me_cleaner/me_cleaner.py -D patched_desciptor.bin -M stripped_me.bin fulldump.rom -t -r -S生成的产物:
- 打补丁的 IFD:
patched_desciptor.bin - 裁剪后的 Intel ME:
stripped_me.bin
打补丁的 IFD 设置了AltMeDisable位,并修改了 Flash 布局。me_cleaner 脚本在仓库 util/me_cleaner/me_cleaner.py 中,其命令行参数与-D(提取描述符)、-M(提取 ME 镜像)、-S(软禁用)、-r(重定位 FTPR 分区)、-t(截断 ME 分区空余部分)一一对应(util/me_cleaner/me_cleaner.py)。
注意:coreboot 允许在构建过程中选择
CONFIG_ME_CLEANER,但它不会重做 Flash 布局,只会从 ME 中移除文件并设置 AltMeDisable 位。
第 3 步:构建 coreboot
- 把上一步生成的两个文件纳入 coreboot 构建系统;
- 增大 CBFS 容量:
- 8 MiB ROM:
0x7E0000 - 12 MiB ROM:
0xBE0000 - 16 MiB ROM:
0xFE0000
- 8 MiB ROM:
- 因为已经手动跑过 me_cleaner,不要在 Kconfig 中再次启用 me_cleaner。
第 4 步:刷写 ROM
由于修改了布局,必须用外部编程器把完整 ROM刷入 Flash(刷写教程见 Documentation/tutorial/flashing_firmware/index.md)。确保 ROM 包含所有分区:IFD、EC(可能未用)、GbE(可能未用)、ME、BIOS。
十一、结语
coreboot 在 Sandy/Ivy Bridge 平台上的技术积累是一份难得的"开源固件逆向内存控制器"范本:从CAPID0_A/B熔丝读取、SPD/XMP 解析、REFCK * MULT频率公式、timA/IO delay 读取训练算法,到MCHBAR + 0x4一类的寄存器位段描述,全部沉淀在 Documentation/northbridge/intel/sandybridge 下的文档中,并与 src/northbridge/intel/sandybridge 的源码实现一一呼应。对于希望理解内存训练原理、参与 coreboot 开发或尝试 ME 裁剪的读者,这一组文档连同raminit.c、raminit_native.c、raminit_iosav.c、nri_registers.md是最直接的起点。
- 固件
- 嵌入式
- 操作系统
- 驱动开发
【免费下载链接】coreboot
Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.
相关推荐
coreboot 移植实战:Acer TravelMate P633 系列(Sandy Bridge 笔记本)构建、刷写与状态全解析
coreboot 移植实战:Acer TravelMate P633 系列(Sandy Bridge 笔记本)构建、刷写与状态全解析 本指南以 coreboot
固件嵌入式操作系统驱动开发coreboot 实战:ASUS P8Z77-M(Sandy Bridge + Panther Point)主板移植与刷写指南
coreboot 实战:ASUS P8Z77 M(Sandy Bridge + Panther Point)主板移植与刷写指南 本文以 coreboot 官方文
固件嵌入式操作系统驱动开发终极指南:如何使用me_cleaner安全清理Intel ME固件
终极指南:如何使用me_cleaner安全清理Intel ME固件 Intel ME固件安全清理技术是保护设备安全的重要环节,而me_cleaner作为一款强大
网络安全嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考