当前位置: 首页 > news >正文

UEFI 随笔 011 — NULL Lib 聚合案例 SKU View Design

声明:个人笔记,概不负责
无责声明:所谓设计,一方之言。抄出毛病,概不负责。(可以联系我,付费咨询)

引言:在 UEFI(浮光掠影 般的) 短暂生命中,需要用 native code 把主板 上,各个芯片拉到一个确定状态。但说起来容易,做起来折腾。

一、问题 与 痛点(软件需求分析):

如果一颗 IC 只是“孤板”支持,UEFI 这里 撸起袖子干就完了,控制 GPIO 拉时序的代码 放哪儿都行,长啥样都行。▶ 但是,如果这粒 IC 在支持一群板子,那(正常脑回路)就自然开始考虑 reuse 问题了,得长得像个啥样。(当然,copy-paste-modify 也是一种“很先进的”复用方式,做工程嘛,不必太计较。)

首先,有些 IC 是 combo 封装,里面有些 IP 之间上电有时序需求。比如说,通常是上层给电,等供电稳定了,下层各个 IP 才可以 被 enable 工作。▶ 软件不能瞎捅,不是给个 GPIO 清单就来个批处理,得一个个来,控制好节奏。█ ——这是刚需

第二,一块“严肃一点的”板子,通常会有一堆“软件自己施加的”Policy 来“To Enable or Not to Enable” 板子上的,硬件模块、软件功能。这些 Policy 特性,企业特别喜欢,比如发给你个笔记本,在固件层 锁掉 USB 功能。 ▶ 如果 Policy 与 模块 之间是“简单映射”,那 SW 干活非常简单,查完模块的 Pocily 就直接“捅 or 不捅”。 但是有时候, 模块之间 、Policy 之间,居然还有 纠缠的“依赖关系”;“捅 or 不捅”还分 大类,一般性的 GPIO 捅上捅下,Silicon 独有手法的捅。▶ 软件不能瞎捅,软件得先算(“得加钱”),算完相关的后,最后决定 “捅 or 不捅”。█ ——这,也是刚需

第三,即使不是 combo 封装,一堆 IC 凑一起,也会形成一个功能模块。▶ 这对软件来说,实在没啥区别。这堆凑一起的 IC 也可以被看做是一个逻辑上的 combo 单元:比如说 Audio,可以是 模拟音频、纯血数字音频 杂凑;比如说 Camera,可以是 前置、后置 的杂凑。这些杂凑,都可以用一个“假象的”componet 来控制状态,实际硬件 有 or 没有,可以(付出点代价)动态检测。毕竟 代价小收益大,对于控制 GPIOs 拉个时序,内聚的收益大。▶ 无论是 真 combo,还是软件拟合的 comob,站在 combo 位面来看、站在 motherboard 位面来看,软件都需要一种 动态检测“存在 or 不存在”的机制。█ ——这是,工程建造时发现的、脑回路里迭代出来的,工程自身需求。

注意:这些问题是“野生”就存在的,并不是因为用 UEFI 而存在,也不会因为 UEFI 不能解而不存在,也不是用 UEFI 才能解。 UEFI 只是浮光掠影的过客。

二、解题思路(软件概要设计):

基本解:
(1)两阶段控制。第一阶段,计算 Policy 施加的规则,给出控制标志;第二阶段,根据控制标志,控制上电时序。
(2)建立逻辑 combo 设备抽象。轻量级组合,毕竟 UEFI 也就“真男人 3 秒”的东西,别太复杂了。
(3)确定硬件检测机制。这是为“逻辑 combo 模块”付出的代价;也是某些“真 combo 模块”的刚需。

落地增值解:
(1)如何 组织 每个 combo 设备的代码,形成可复用模块?
(2)如何 把这些 combo 设备 聚合在一起?
(3)如何 实现 两阶段流水线 效果?

首先,排除 UEFI 的 Protocol 机制,以及基于 Protocol 的 UEFI driver model 机制。对于我们这种 轻量级函数复用,这投入有点大,亏本买卖。

接着,下推一层,EDK2 的 LibarayClass 机制,貌似有点占边,那么就是讲,每一个 SW component 都可以做成 LibarayClass 形式,然后提供两个函数,第一阶段 计算,第二阶段 控制。 ▶ 但是,我滴个神哪!我得取不同得名字,否则必然 link-time 冲突啊!也就是说,仅仅为了名字不同,得造一堆 LibarayClass 出来?严格地走 LibarayClass 这条路线,对于我们这种 轻量级函数复用,也是血亏。▶ 就算执着的 SW 人,写出一堆正统的、 link-time 不冲突的 LibarayClass 来,那么怎么调度它们?我要一堆莫名其妙的名字干嘛?再说 C 语言也玩不起来啊,嗯,必须得整张 函数指针表啊。▶ ▶

综合 轻量级函数复用,及函数指针表,有一个念头浮现出来,NULL Lib 聚合模式。这是一种廉价的 聚合模式。█

// Ray: 所谓 EDK2 的 LibraryClass 就是(被 EDK2 精心打扮的)平凡的 C Library 而已。
// Ray:
// Ray: 关联函数表,可以避免 link-time 冲突
// Ray: 传统的 LibraryClasse 强调,同名(不同实现),一个 PE 可执行文件,只能链接一份
// Ray: 关联函数表,可以做到,同型 (不同实现)同名访问,
// Ray: 这就给 多份实例(multi-instance)、伪动态链接(fake-dynamic-link)提供了操作空间
// Ray: 只要(同型)不同实现,使用 不同名字,它们在 link-time 就可以共存在 一个  PE 可执行文件中。

三、解题思路(软件详细设计):

3.1)流水线模型:

首先,我们需要一张 地图,拆解 软件维度 与 硬件维度。再按 两阶段 把软件操作,按时间先后牌序。
这样,最终我们得到了一个,二维表结构,流水线模型。对我们的需求来说,两阶段流水线,已经足够满足
(1)第一阶段,计算所有 Policy 的规则,算出 GPIOs 需要做的设置,Combo 的“依赖”问题在此得到解决。
(3)第二阶段,执行 GPIOs 的设置,单纯的 拉时序。

image

插播
一般性软件建模分析,软件 可能按照 HW 的思路写(表中的行),也可能按照 SW 功能的思路写(表中的列)。不管是哪种思路作为 故事主线,它们之间,大致可以分为三种情况:
(1)Case-001 纯血 软件思路(列),各种 HW 自动得到加持
(2)Case-002 纯血 硬件思路(行),啥事都我来
(3)Case-003 混血模式,打架 or 协作

image

两阶段流水线的本质,是 纯血软件思路 为 主故事线叙事。所谓自动加持,就是从 HW 的视角看去,得把功能“按软件功能的思路”拆成 一块块写,去填充(与丰满)主故事线 叙事逻辑。

3.2)硬件检测机制

(1)基于 pin 脚的检测,如果 pin 脚不存在(清单里),Cobmo 设备 对应功能区,自然就不存在。
(2)基于主板 SKU 检测,如果 主板 SKU 号不支持,即使 pin 脚存在,该功能块,也不存在。
(3)基于 PnP 的动态检测技术,比如 主板提供了个 PnP 插槽,咱检测到了,好歹给人家电上上去吧?

3.3)聚合结构设计

核心数据结构

typedef struct {COMP_ID               CompId;PFN_STAGE_POLICY      StagePolicy;     // Stage-1 [fn]  Check Policy and Stage ActionsPFN_TRIGGER_ACTION    TriggerActions;  // Stage-2 [fn]  Execute Policy Controlled Actions.// ..
} DISPATCH_ENTRY;

直接白送一个架构图吧
image

四、尾声

至此,'SKU View' Design 的设计思路,叙述完毕。这个名字的灵感来自 DSC 文件中的 SKUID 定义。
以及,电子商务普及后,烂大街的 SKU(Stock Keeping Unit) 概念。但凡网购,嘴里不喷个 SKU 出来,就不地道、专业。

Typical Tag Names Required / Optional Value Notes
SKUID_IDENTIFIER Required Formatted text This value may be passed on the command line and must match one of the defined names in the [SkuIds] section. If it is passed on the command line, the command line value takes precedence.

From https://tianocore-docs.github.io/edk2-DscSpecification/draft/2_dsc_overview/23_[defines]_section_processing.html#table-6-edk-ii-defines-section-elements

本文,指出了 UEFI 需求中,一个超轻量的 上电逻辑 native 代码复用问题。并提供了一个 设计思路 与 详细设计 草图。

同类问题,
(1)在 OS Driver 中,企图用 ACPI 来烫平这个 轻量级的需求,解决上电,或拉时序问题。
(2)在 ACPI 近乎癫狂的清单里,用 PowerResource 来解决 Combo 类 Device 的上电依赖。
(3)随着 硬件的日益精进,而 ACPI 执行的颗粒度 过于粗犷,陈旧不堪的 ACPI 最终放弃了挣扎(或 不想开放),冒出个 Microsoft 封闭的 PEP 驱动架构。

回到 UEFI 这里,官方标准对 native code 从来就没有,从这么细的颗粒度、这么轻量级的支持。这不是 UEFI 的 Protocol 机制做不到,而是用 EDK2 来实现,代价太大。当然,随着岁月的沉淀,这种需求若被反复放大,有代码积累后,或许可以做到。

'SKU View' Design 是基于 LibarayClass 就是一种 C Library 这个事实,运用 Null Lib 聚合模式,设计了个 超轻量的 便于代码复用的解决方案。它廉价的实现了一个 两阶段 流水线模型,清晰地解决了
(1)“Policy 机制” 介入到 上电时序后 的逻辑混乱;
(2) Combo 模块的 上电时序 控制。

// Ray: 关联函数表,可以做到,同型 (不同实现)同名访问,// Ray: EDK2 有一种,利用 LibraryClasse 把代码聚合在一起的方法。(这是 EDK2 独有的,与 UEFI spec 无关)
// Ray: 这是一种(本质上的) 动态聚合 的手法。我称为 NULL Lib 聚合模式

好奇的猫吐槽:为啥不复用 ACPI 代码呢?ACPI 就是个为了 满足 OS 的癖好,而凑吧的一个脚本而已。ACPI 只是 UEFI 对 OS 的单向输出,UEFI 自己从不用 这个东西。

====== 稍微有点破财的,结束线

http://www.jsqmd.com/news/556685/

相关文章:

  • ESP32 BLE MTU 协商实战:从原理到手机端配置优化
  • Java AI 面试常见问题
  • 重构智能体通信:agno MCP协议的设计哲学与实践指南
  • G-Helper终极指南:告别臃肿控制中心,华硕笔记本性能优化完全教程
  • 揭秘Mem Reduct:被忽视的内存管理技术如何解决系统卡顿难题
  • # 发散创新:基于 Rust的分布式数据库架构设计与实战演练在当前云原生和微服务架
  • RouteRAG:用特殊 Token 和强化学习构建可学习的 RAG 检索策略
  • 别再只玩文字聊天了!手把手教你用25元月付服务器,给微信AI伙伴装上‘眼睛’和‘嘴巴’
  • 三相并网逆变器FCS MPC模型预测控制技术说明与LCL matlab simulink仿真视...
  • 逆向思维玩转PS掩码图:当白色背景变成透明利器(EasyX三元光栅操作码详解)
  • JiYuTrainer技术探索指南:从原理到实践的完整路径
  • 每日算法题 19---142.环形链表Ⅱ
  • Shell脚本一键部署Kubenetes(k8s)前置环境
  • 群晖DSM解锁ROOT权限与WinSCP高效管理全攻略
  • matlab程序, 脉冲波合成与提取,滑冲效应、方向性效应,自定义脉冲模型,提取脉冲波
  • Termux:X11的10个核心功能解析:触摸手势、键盘切换与多显示器支持
  • 提示工程智能推荐系统的资源调度与成本优化(架构师经验)
  • 如何让键盘听懂你的设备语言?设备条件判断打造智能多设备键盘映射方案
  • AgiBot World数据集实战:如何用百万级轨迹训练你的机器人策略(附避坑指南)
  • Windows下TDEngine 3.0.4.0保姆级安装教程(含常见错误排查)
  • 别再死记硬背了!用SelectIO IP核搞定FPGA高速接口,从Camera到DVI的实战配置指南
  • 51:L构建容器与Kubernetes安全:蓝队的容器防御
  • docker搭建typecho
  • 提示工程架构师:掌握分布式缓存策略的秘诀
  • CogVLM模型训练终极指南:从环境配置到微调实战完整教程
  • MoveCertificate终极指南:Android 7-15系统证书管理全解析
  • 从零开始:crAPI靶场环境搭建与实战通关指南
  • 漫画脸生成器部署指南:3步完成Linux系统环境搭建
  • 四旋翼无人机轨迹跟踪:预设性能控制、滑模控制与 PID 的探索之旅
  • liteparse 支持的文档格式