linuxer
linuxer
发布于 2026-05-24 / 2 阅读
0
0

HP Chromebox G3 自编译 Coreboot UEFI 记录

HP Chromebox G3 自编译 Coreboot UEFI 记录

这篇是一次 HP Chromebox G3(Noibat)自编译 coreboot UEFI 固件的完整记录,重点不只是“编译成功”,而是把桌面机上不该出现的电池、充电策略、声卡兼容 ID、UEFI Payload 容量等坑都一起处理掉。

背景

HP Chromebox G3(Google 代号 Noibat)是一台基于 Intel Comet Lake-U 平台的小型台式机。MrChromebox 维护的 coreboot 分支提供了 UEFI 固件支持,但原版固件有几个桌面机不需要的问题:

  • ChromeEC 会暴露 BAT0 电池 ACPI 设备,导致 Windows 显示电池图标并启用笔记本电源策略
  • DPTF 包含充电性能控制(Charger Performance Control),台式机无电池,这些配置无意义
  • Realtek RT5682 声卡的 ACPI HID 是 10EC5682,macOS 需要兼容 ID RTL5682 才能驱动
  • GitHub Actions 因账号 billing 限制无法运行,ARM64 编译 crossgcc-i386 会失败,必须在 x86 主机上编译

一张图看完整流程

Noibat Coreboot UEFI 自编译流程 目标:桌面机体验 + Win/macOS 友好 + 可重复构建 1 准备环境x86_64 Ubuntu安装 iasl/gnat 等依赖 2 拉源码builder 自动 cloneMrChromebox-2603 3 预缓存包crossgcc tarballsbinutils 用 sourceware 4 验 hashSHA1 对照避免中途失败 5 应用补丁BAT0 用 _STA=0DPTF 去充电控制RTL5682 / FV 9MB 6 Kconfig复制 noibat-mac 配置make olddefconfig 7 编译工具链crossgcc-i386 + iasl首次 15~25 分钟 8 编译 ROMbuild-uefi.sh noibat-mac 9 输出 16MB coreboot.rom刷写前必须编程器备份原厂 ROM

目标

构建一个 "桌面 /Win/macOS 友好" 的 coreboot UEFI 固件变体 noibat-mac,包含以下实验性修改:

  1. 隐藏 BAT0 电池设备(_STA 返回 0)
  2. 移除 DPTF 充电性能控制
  3. 添加 RT5682 兼容 ID _CID=RTL5682
  4. 兼容 shallow clone(git describe --always

环境

  • 主机: x86_64 Ubuntu 24.04
  • CPU: 4 核
  • 磁盘: ~15GB 可用空间(编译中间产物 + crossgcc)
  • 源码: MrChromebox/coreboot branch MrChromebox-2603
  • 目标 Board: google/puff variant noibat-mac

编译过程

1. 依赖安装

sudo apt-get update
sudo apt-get install -y \
  build-essential git curl wget ca-certificates \
  gcc g++ make flex bison gnat \
  libssl-dev libncurses-dev zlib1g-dev \
  uuid-dev nasm iasl pkg-config python3 python3-pip \
  unzip xz-utils bzip2 cpio rsync file

⚠️ iasl(ACPI 编译器)必须安装,否则构建时找不到 crossgcc 编译的 iasl 会直接报错停止。

2. 克隆 Builder 仓库

git clone https://github.com/rothdren-lion/noibat-bios-builder.git
cd noibat-bios-builder

这个仓库只是一个编排脚本,不包含 coreboot 完整源码,编译时会自动拉取。

3. 拉取 Coreboot 源码

export WORKDIR="$PWD/work"
export GIT_HTTP_VERSION=HTTP/1.1
export GIT_TERMINAL_PROMPT=0
./scripts-build-noibat.sh noibat-mac

脚本会执行 git clone --branch MrChromebox-2603 --depth 1 https://github.com/MrChromebox/coreboot.git work/coreboot

⚠️ 国内环境直接访问 GitHub 可能 TLS 握手失败,使用 GIT_HTTP_VERSION=HTTP/1.1 可绕过部分 TLS 问题。

4. 预缓存 CrossGCC 依赖(关键踩坑点)

coreboot 的 crossgcc 构建系统会从 coreboot.org 下载交叉编译工具链的源码包,但 coreboot.org 经常返回 403 Forbidden。替代方案是从 GNU 官方镜像下载,但 部分包的 hash 与 coreboot 期望的不一致(如 binutils-2.45.tar.xz),会导致 hash 校验失败。

解决方案:提前从正确来源下载所有 tarball 并放入缓存目录:

TARBALL_DIR="work/coreboot/util/crossgcc/tarballs"
mkdir -p "$TARBALL_DIR"

# 这些包从 GNU mirror 下载,hash 与 coreboot 一致
curl -Lf -o "$TARBALL_DIR/gmp-6.3.0.tar.xz" \
  "https://ftpmirror.gnu.org/gmp/gmp-6.3.0.tar.xz"
curl -Lf -o "$TARBALL_DIR/mpfr-4.2.2.tar.xz" \
  "https://ftpmirror.gnu.org/mpfr/mpfr-4.2.2.tar.xz"
curl -Lf -o "$TARBALL_DIR/mpc-1.3.1.tar.gz" \
  "https://ftpmirror.gnu.org/mpc/mpc-1.3.1.tar.gz"
curl -Lf -o "$TARBALL_DIR/gcc-14.2.0.tar.xz" \
  "https://ftpmirror.gnu.org/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz"

# ⚠️ binutils 必须从 sourceware.org 下载,GNU mirror 版本 hash 不匹配!
curl -Lf -o "$TARBALL_DIR/binutils-2.45.tar.xz" \
  "https://sourceware.org/pub/binutils/releases/binutils-2.45.tar.xz"

curl -Lf -o "$TARBALL_DIR/nasm-2.16.03.tar.bz2" \
  "https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/nasm-2.16.03.tar.bz2"
curl -Lf -o "$TARBALL_DIR/acpica-unix-20250807.tar.gz" \
  "https://downloadmirror.intel.com/864114/acpica-unix-20250807.tar.gz"

验证 hash:

cd work/coreboot/util/crossgcc
for f in tarballs/*; do
  name=$(basename "$f")
  if [ -f "sum/$name.cksum" ]; then
    expected=$(sed -e 's@.*\([0-9a-f]\{40,\}\).*@\1@' < "sum/$name.cksum")
    actual=$(sha1sum "$f" | awk '{print $1}')
    if [ "$expected" = "$actual" ]; then
      echo "✓ $name"
    else
      echo "✗ $name HASH MISMATCH"
    fi
  fi
done

踩坑: 如果 binutils 从 GNU mirror 下载,hash 会是 b576a0...,但 coreboot 期望的是 09fd8a...。必须从 sourceware.org 下载才能 hash 匹配。

5. 手动应用实验性补丁

由于 shallow clone 和重复应用的问题,git apply 会失败。我们手动修改源文件:

5.1 build-uefi.sh — 兼容 shallow clone

cd work/coreboot
sed -i 's/rev=$(git describe --tags --dirty)/rev=$(git describe --tags --dirty --always)/' build-uefi.sh

shallow clone 没有 tag 信息,git describe --tags 会失败。加 --always 后回退到 commit hash。

5.2 ec.h — 定义 NOIBAT_DESKTOP_NO_BATTERY

// 文件: src/mainboard/google/puff/variants/noibat/include/variant/ec.h
// 在 #endif 之前添加:

/*
 * HP Chromebox G3 / Noibat is a desktop Chromebox, not a laptop.
 * The common ChromeEC ACPI block always exposes ACPI0003 AC adapter and
 * PNP0C0A BAT0 battery devices. Windows then shows a battery icon and may
 * select laptop-style power UX/policies even though the machine has no
 * battery. Keep the EC, AC power-source state, DPTF CPU/fan/thermal policy,
 * and PD notifications intact, but make the battery package effectively
 * disappear from the OS.
 */
#define NOIBAT_DESKTOP_NO_BATTERY

5.3 battery.asl — 条件隐藏电池设备

修改 Device (BAT0) 中已有的 _STA 方法:

// 文件: src/ec/google/chromeec/acpi/battery.asl
// 将 BAT0 中原来的 _STA 方法:
	Method (_STA, 0, Serialized)
	{
		Return (BSTA (0))
	}

// 替换为:
	Method (_STA, 0, Serialized)
	{
#ifdef NOIBAT_DESKTOP_NO_BATTERY
		Return (0)
#else
		Return (BSTA (0))
#endif
	}

踩坑: 不能用 #ifndef 包裹整个 Device (BAT0) 块!因为 ec.asl 中的 Notify(BAT0, ...) 仍然引用 BAT0,如果 BAT0 设备不存在,ASL 编译会报 Object does not exist 错误。用 _STA=0 的方式,设备存在但 OS 看不到,完美解决。

踩坑: 不能在 BAT0 内新增第二个 _STA 方法!ASL 不允许同一作用域内重复定义方法名,会报 Name already exists in scope。必须修改原有的 _STA

5.4 ec.asl — 修复 ECPD 前向引用

// 文件: src/ec/google/chromeec/acpi/ec.asl
// 将直接引用 ECPD 的 Notify 调用:
Notify (\_SB.PCI0.LPCB.EC0.CREC.ECPD, 0x80)

// 替换为 CondRefOf 安全引用:
If (CondRefOf (\_SB.PCI0.LPCB.EC0.CREC.ECPD)) {
    Notify (\_SB.PCI0.LPCB.EC0.CREC.ECPD, 0x80)
}

踩坑: ASL 不支持前向引用。ECPD 设备定义在 _Q16/_Q1C 方法之后,但 Notify 在之前就引用了它,导致 Object does not exist 编译错误。用 CondRefOf 是 coreboot 自身代码库中已有的模式。

5.5 overridetree.cb — 移除充电控制 + 添加声卡 CID

cd work/coreboot
OTREE="src/mainboard/google/puff/variants/noibat/overridetree.cb"

# 移除 Charger Performance Control 注册项(5行)
sed -i '/## Charger Performance Control/,/register "controls.charger_perf\[3\]"/d' "$OTREE"

# 在 RT5682 的 hid 行后添加 cid
sed -i 's/register "hid" = ""10EC5682""/register "hid" = ""10EC5682""\n\t\t\t\tregister "cid" = ""RTL5682""/' "$OTREE"

5.6 复制自定义 Config

cp patches/config.noibat-mac.uefi work/coreboot/configs/cml/config.noibat-mac.uefi

5.7 UefiPayloadPkg.fdf — 增大 FV 容量

FDF="work/coreboot/payloads/external/edk2/workspace/mrchromebox/UefiPayloadPkg/UefiPayloadPkg.fdf"

# RELEASE 模式下 FV 从 8MB 增大到 9MB
sed -i '/!else/,/!endif/ s/DEFINE FD_SIZE     = 0x0800000/DEFINE FD_SIZE     = 0x0900000/' "$FDF"
sed -i '/!else/,/!endif/ s/DEFINE NUM_BLOCKS  = 0x800/DEFINE NUM_BLOCKS  = 0x900/' "$FDF"

踩坑: UEFI payload 编译后约 8.6MB,超过默认的 8MB FV 限制。GenFv 报错 the required fv image size 0x83e160 exceeds the set fv image size 0x800000。增大到 9MB 解决。

6. 运行 Kconfig

cd work/coreboot
make olddefconfig KCONFIG_CONFIG="configs/cml/config.noibat-mac.uefi"

7. 编译 CrossGCC + IASL

make crossgcc-i386 iasl CPUS="$(nproc)" BUILDGCC_OPTIONS="-m"

首次编译约 15-25 分钟。crossgcc 编译 i386-elf 交叉工具链(GCC 14.2 + Ada 支持)和 IASL ACPI 编译器。

踩坑: 必须确保所有 tarball hash 正确,否则中途失败需要删除错误文件重新下载。

8. 编译 UEFI ROM

bash build-uefi.sh noibat-mac

编译过程约 3-5 分钟,包含:

  • coreboot 主板代码编译
  • ACPI 表生成(DSDT 用 iasl 编译)
  • EDK2 UEFI Payload 编译
  • FSP(Firmware Support Package)集成
  • CBFS 打包

9. 输出

ls -lh out/
# coreboot.rom  16MB  ← 完整的 UEFI 固件镜像

ROM 内容一览

cbfs.ioplus                           0x000   raw             12200 none
config                                0x817c0 raw              4846 LZMA
revision                              0x82b00 raw               785 none
build_info                            0x82e40 raw               117 none
fallback/dsdt.aml                     0x82f00 raw             12200 none  ← 我们的 ACPI 补丁
ecrw                                  0x85f00 raw            139116 none
fspm.bin                              0xa7fc0 fsp            462848 none
fsps.bin                              0x119000 fsp            190102 LZMA
vbt.bin                               0x147700 raw              1182 LZMA
fallback/postcar                      0x147c00 stage           57876 none
fallback/payload                      0x155e80 simple elf    1966159 none  ← UEFI Payload
bootblock                             0xc5ffc0 bootblock       28672 none

踩坑总结

问题 症状 解决方案
GitHub TLS 失败 git clone 卡住或报 GnuTLS 错误 GIT_HTTP_VERSION=HTTP/1.1
coreboot.org 403 crossgcc 下载失败 预缓存所有 tarball
binutils hash 不匹配 hash mismatch 校验失败 sourceware.org 下载,不用 GNU mirror
git describe 失败 shallow clone 没有 tag --always 参数
BAT0 整体隐藏 Object does not exist (BAT0) 改用 _STA=0 代替 #ifndef 包裹
_STA 重复定义 Name already exists in scope 修改原有 _STA,不新增
ECPD 前向引用 Object does not exist (ECPD) CondRefOf 包裹
FV 容量溢出 fv image size exceeds set size FDF 中 FD_SIZE 增大到 9MB
4K 屏幕显示小框 开机 Logo 只占屏幕中间一小块 EDK2 DSC 中 PcdVideo 从 1280×800 改为 0(自动检测原生分辨率)
4K BMP 塞不进 ROM 3840×2160 BMP 约 24MB > 16MB ROM BMP 做小图 400×300,4K 全屏由 GOP 黑色背景填充
iPXE git stash 冲突 Your local changes would be overwritten by checkout git stash drop + git checkout coreboot

注意事项

  • ⚠️ 此固件为实验性质,刷写前必须用 programmer 备份原厂固件
  • ⚠️ 不要盲目刷写,保留回滚方案
  • 桌面机隐藏电池设备后,Windows 不再显示电池图标,也不会启用笔记本省电策略
  • RTL5682 CID 可能帮助 macOS 识别声卡,但不保证完整驱动支持
  • 后续若需更新,只需 git fetch 更新 coreboot 源码,重新应用补丁即可

参考链接

by 数码罗记 · godsun.pro


评论