固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载本文基于 coreboot 仓库文档 Customizing Module Behavior讲解 coreboot 中更具体的模块如何定制更基础模块行为的核心机制以__weak弱符号为载体的静态依赖注入。读完本文你能理解 coreboot 从 commonlib 到 mainboard 的分层定制模型、弱符号被链接器替换的底层原理、构建系统如何确保同一符号只链接一份实现以及如何用git grep -w __weak系统地找出所有定制点并判断何时应该改用函数指针等更安全的模式。一、coreboot 模块的分层与定制方向coreboot 的模块按从基础到具体可分为若干层次该列表并不完整commonlib被众多模块共享的库代码与辅助代码平台代码Platform code支撑某一计算平台的代码例如arch/x86包含 bootblock、romstage、ramstage或arch/arm64drivers、CPU、SoC、North-/Southbridge 代码支撑某一具体 CPU 平台的代码如 Intel Alder Lakemainboard主板专用的初始化代码、配置数据与钩子hooksMainboard variants主板变体可选一块主板可以有多个仅在细节上不同的变体。软件开发中一个常见的模式是让更具体的模块能够定制更基础的模块的行为或者说钩住它们。许多开发者熟悉的做法是运行时动态注册函数指针依赖注入。而 coreboot 展现的是该模式的静态变体不在运行时注册函数指针而是借助链接器linker在构建期静态地实现可定制性。二、定制点以弱符号提供的默认实现各类模块通过定制点customization points来开放定制能力它们是带有默认实现或空操作no-op实现的函数被声明为__weak弱符号。更具体的实现可以按需要覆盖它们。文档同时提醒在某些特定场景之外用弱函数取代函数指针有缺点因此不被鼓励详见第五节。以 src/lib/bootblock.c 为例它提供了四个弱符号默认实现__weak void bootblock_mainboard_early_init(void) { /* no-op */ } __weak void bootblock_soc_early_init(void) { /* do nothing */ } __weak void bootblock_soc_init(void) { /* do nothing */ } __weak void bootblock_mainboard_init(void) { /* do nothing */ }各主板实现可以自由地重新定义这些符号完成自己需要的早期初始化例如早期 GPIO 初始化。这些弱符号的声明位于 src/include/bootblock_common.h头文件注释明确说明了调用顺序/* * These are defined as weak no-ops that can be overridden by mainboard/SoC. * The early variants are called prior to console initialization. Also, the * SoC functions are called prior to the mainboard functions. */ void bootblock_mainboard_early_init(void); void bootblock_mainboard_init(void); void bootblock_soc_early_init(void); void bootblock_soc_init(void);2.1 默认实现与调用时机在 src/lib/bootblock.c 的bootblock_main_with_timestamp()中可以看到调用链先采集TS_BOOTBLOCK_START时间戳然后依次调用bootblock_soc_early_init()、bootblock_mainboard_early_init()early 变体在控制台初始化之前调用SoC 先于主板随后在CONFIG(BOOTBLOCK_CONSOLE)使能时才做console_init()再调用bootblock_soc_init()与bootblock_mainboard_init()最后run_romstage()进入下一阶段。这正是基础代码调用定制点、具体代码提供实现的静态注入点如果主板没有提供自己的实现链接器就使用lib/bootblock.c中的空操作。2.2 真实的主板覆盖示例仓库中mainboard/目录下有大量文件实现了bootblock_mainboard_early_init()通常命名为early_init.c或bootblock.c这只是惯例。例如 src/mainboard/asrock/spc741d8/bootblock.c 覆盖了该符号用于通过 PCR 寄存器PCR_DMI_LPCIOD/PCR_DMI_LPCIOE在 PCH 上打开 LPC I/O 解码窗口通过 PCI 配置空间LPC_IO_DECODE、LPC_IO_ENABLES、LPC_ESPI_CS1_ROUTING使能 com10x3f8、com20x2f8和 SuperIO 端口进入 Nuvoton NCT6791D 的 PnP 配置态禁用其 UART1避免与 AST2600 的串行口冲突使能 AST2600 SuperIO 的 UART1 作为调试串口。这些都是必须极早完成、但控制台尚未可用的初始化正符合 weak no-op 钩子的使用定位。2.3 链接器行为覆盖而非报错弱符号的关键语义由链接器保证只要存在非 weak 的同名定义链接器总是优先取非 weak 版本并丢弃 weak 版本而不是抛出 duplicate definition重复定义错误只有当其他定义都不存在时链接器才采用__weak实现而不是抛出 undefined symbol未定义符号错误。因此基础代码可以放心地调用定制点无论主板是否提供实现链接都能成功运行时行为自然取决于哪份实现被链接进来。三、Kconfig 与 Makefile 的角色弱符号机制只解决链接时如何选择实现而选择哪份实现参与编译则由构建系统完成详见 build system 文档。git grep可以发现mainboard/目录下众多文件都实现了bootblock_mainboard_early_init(void)但对于任何一个给定的构建配置只有其中一份源文件会被编译并链接进最终固件。具体机制体现在各主板的Makefile.mk中。例如 src/mainboard/asrock/spc741d8/Makefile.mkbootblock-y bootblock.c romstage-y romstage.c ramstage-y ramstage.c而 src/mainboard/supermicro/x9scl/Makefile.mk 则是bootblock-y early_init.c romstage-y early_init.ccoreboot 的构建流程会根据 Kconfig 中选择的MAINBOARD只拉取对应mainboard/厂商/型号/Makefile.mk声明的源文件于是同一符号的多份候选实现中只有被选中的那份进入编译从根源上避免了重复定义。此外文档给出一条重要的可读性建议当某段代码只在特定 Kconfig 选项使能时才被包含时调用它的语句本身也应当用该 Kconfig 选项条件化以提高可读性。bootblock.c中的调用本身就遵循了这一惯例if (CONFIG(BOOTBLOCK_CONSOLE)) { console_init(); exception_init(); }四、如何识别所有定制点文档坦承目前没有一份穷尽式的定制点清单。但有一个简单的发现方法git grep -w __weak这会列出所有.c文件中的默认weak定义再到.h文件中查找对应声明往往能发现更多说明文档。以仓库实际为准src/lib/下就有大量这样的定制点例如src/lib/smbios_defaults.c约 27 个 weak 函数构成 SMBIOS 表的默认值如 smbios_mainboard_product_name() 默认返回CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME而smbios_mainboard_bios_version()默认返回NULL。主板只需覆盖自己关心的一项其余字段自动沿用默认值——这是文档中SMBIOS table overrides这一典型用法的直接体现其他如src/lib/coreboot_table.c、src/lib/gpio.c、src/lib/cbfs.c、src/lib/timestamp.c等文件中也各自定义了多个 weak 定制点覆盖 coreboot table 字段、GPIO 默认行为、console/时间戳等场景。实践建议是遇到某个行为想定制时先git grep -w __weak 符号名或通读所在模块的 weak 定义确认是否存在现成定制点若.h文件中有文档注释如bootblock_common.h那样可优先以它为准理解调用顺序与语义。五、适用场景与不适用场景弱符号带来的定制非常轻量——不需要 RAM 已经可用就能挂上钩子这对 bootblock 这类最早期阶段尤其重要。但文档也明确指出了它的缺点可发现性差bad discoverability没有中央清单定制点只能靠 grep 发现错误覆盖难以察觉当错误的 override 被误包含进构建或本该被覆盖却用了默认实现时行为会出人意料而且不会产生任何构建错误来提示问题这类问题极难调试。文档给出的经验法则是范围有限或用途明确的用法是可以接受的典型场景包括mainboard variants主板变体同一主板不同细节变体之间做小范围差异化SMBIOS 表覆盖如上文smbios_defaults.c的用法公共代码中的钩子供 mainboard 或 SoC 覆盖的 hooks如bootblock_mainboard_early_init这类 bootblock 钩子。在这些场景之外通常应改用其他模式例如函数指针。与 weak 符号静默地以意外方式失败不同函数指针模式在使用错误时会产生清晰的构建错误错误定位成本显著更低。选择哪种模式时可以按错误代价来权衡早期启动钩子选 weak 符号换取 RAM-free 可用性其余场合优先让链接器/编译器帮你把错误显式化。小结与延伸阅读机制本质__weak默认实现 主板/SoC 的具体覆盖 链接器择优 Makefile/Kconfig 控制哪份源码参与编译关键文件src/lib/bootblock.c默认 no-op 与调用链、src/include/bootblock_common.h声明与顺序注释、src/lib/smbios_defaults.cSMBIOS 覆盖示例识别方法git grep -w __weak设计取舍早期钩子与变体差异用 weak 符号其他场景优先函数指针等能产生构建错误的模式深入阅读构建系统文档、Kconfig 文档、架构文档。赞分享固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载相关推荐grok-build 0.2.110 更新解析Extensions 删除确认、会话创建失败兜底与自动压缩登录重试机制grok build 0.2.110 更新解析Extensions 删除确认、会话创建失败兜底与自动压缩登录重试机制 导读 本文基于 grok buildS人工智能大模型AI Agent代码智能体CLI工具调用MCP ClientsGrumpy中的弱引用机制Go实现的Python weakref模块Grumpy中的弱引用机制Go实现的Python weakref模块 1. 弱引用Weak Reference基础 弱引用Weak Reference编译器语言运行时开发工具KernelSU实战指南从内核级Root到模块管理的深度解析与避坑技巧KernelSU实战指南从内核级Root到模块管理的深度解析与避坑技巧 KernelSU作为基于内核的Android root解决方案以其独特的系统级权限管操作系统驱动开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考