通过自定义Eeprom格式进行厂商板卡加载

答案内容由AI生成,仅供参考:

关于通过自定义EEPROM格式进行厂商板卡加载的配置机制分析

根据当前系统架构和已知信息,针对通过自定义Eeprom格式进行厂商板卡加载的问题,现就现有机制、技术限制及可行方案进行全面梳理与回答。


:puzzle_piece: 问题背景概述

某厂商采用自定义的EEPROM数据格式,在特定域中存储板卡编码(Board ID),以用于识别和加载对应的SR(System Resource)文件。具体格式如下:

Eeprom Header 结构(关键偏移)

域内偏移 段含义
0 规范码(Signature)
12 规范版本(Spec Version)
13 Elabel Offset
15 System Offset
17 PDR Offset
19 CDR Offset

CDR 域结构(Component Description Record)

域内偏移 段含义
0 CDR版本
1 Vendor(厂商标识)
17 Component ID(组件ID)
33 子域数量
34 子域类型
35 子域偏移

实际案例中:

  • CDR_Offset = 0x104(从Header中读取)
  • 实际Component ID起始偏移:(0x104 * 8) + 17 = 0x831
  • 0x831开始读取8字节数据,作为Board ID字符串

:warning: 当前现状与挑战

:white_check_mark: 现状1:Accessor/Scanner 不支持动态Offset

"Accessor_BoardUID1": {
    "Chip": "#Eeprom_SEU",
    "Offset": "<= Accessor_CDR_Offset.Value |> expr(($1 * 8) + 17)",
    "Size": 2,
    "Type": 0
}

:pushpin: 问题
尽管可通过表达式语法(expr(($1 * 8) + 17))实现动态偏移计算,但 Accessor 和 Scanner 的 Offset 在对象创建时即固化,不会实时刷新或重新计算。

:magnifying_glass_tilted_left: 来自社区官方答复:

“offset当前不支持变更,不会实时读取资源树的值,并且Accessor的值需要访问才会触发硬件读取,同步Accessor的操作实际是没有意义的”

:right_arrow: 结论:动态偏移配置在初始化后失效,无法用于运行时更新。


:cross_mark: 现状2:无法直接将多字节整数转为字符串

  • Accessor读取结果为无符号整数(uint),即使块读8字节(Size=8),返回值仍以数值形式存在。
  • 虽然CSR语法支持string.format等表达式处理,但当尝试将Accessor.Value通过<=/A1.Value; <=/A2.Value; ... |> string.format(...)等方式拼接为字符串时,资源树不支持多值绑定与序列化表达式拼接

:pushpin: 官方说明:

“当前csr的语法配置使用string类型去同步其他类型时会进行强转,理论上U8类型会强转为字符串类型再赋值”
但实际中,这种“理论上的强转”仅适用于单个U8字段绑定到字符串属性,不支持8个独立Accessor逐个读取后拼接成字符串。

:right_arrow: 结论:无法通过标准Accessor + 表达式机制构建出8字节字符串ID。


:warning: 现状3:多级Accessor + 手动拼接存在时序风险

现有方案尝试通过配置多个单字节Accessor(如Accessor_KunLun_BoardUID1~8),然后在Connector.Id中使用链式引用:

"Id": "<=Accessor_KunLun_BoardUID1.Value<=Accessor_KunLun_BoardUID2.Value..."

:pushpin: 问题

  1. 读取非原子操作:每个Accessor需单独触发硬件读取(Status=4未读取 → Status=0已读取)
  2. 加载时序依赖Presence检测先于Id计算完成,导致框架可能因Id为空而跳过加载
  3. 无自动重试机制:Connector不会等待所有Accessor数据就绪后再加载下级SR

:right_arrow: 结果概率性加载失败,存在稳定性风险。


:white_check_mark: 可行解决方案分析

:white_check_mark: 方案一:使用 Chip.BlockIo 接口 + 自定义驱动或脚本(推荐)

目前最可靠的方式是绕过Accessor/Scanner机制,使用底层接口直接读取EEPROM。

:white_check_mark: 使用 busctl 手动调用BlockIo读取(适用于调试与引导阶段)

busctl --user call bmc.kepler.hwproxy \
  /bmc/kepler/Chip/Eeprom/Eeprom_SEU \
  bmc.kepler.Chip.BlockIo Read a{ss}uu 0 0x831 8
  • 0x831:计算后的Component ID起始偏移
  • 8:读取8字节
  • 返回原始字节数组,可由上层服务解析为字符串

:white_check_mark: 在自发现或加载服务中集成此逻辑(生产级方案)

由硬件自发现服务(hwdiscovery)在探测到设备在位后,主动调用BlockIo.Read读取指定偏移的8字节数据,并解析为字符串,用于后续SR文件名匹配。

:link: 支持文档:《硬件代理总线读写接口使用方法》
:white_check_mark: 支持I2C器件的Block读写操作

:white_check_mark: 优点

  • 不依赖Accessor机制,避免表达式和类型转换问题
  • 可实现原子性读取
  • 可精确控制加载流程时序

:cross_mark: 缺点

  • 需修改或扩展自发现逻辑代码
  • 不完全通过纯CSR配置实现(需程序干预)

:white_check_mark: 方案二:扩展 Connector.Id 加载机制(建议未来优化方向)

当前Connector.Id仅支持静态字符串或简单表达式绑定,建议未来支持如下能力:

功能建议 描述
支持BlockIo表达式 允许在Id字段中嵌入`<= BlockIo(“/Eeprom_SEU”, 0x831, 8)
支持多阶段加载 Presence检测 → 等待Id获取完成 → 再加载SR,提供重试与超时机制
引入“PreLoad” Hook 在加载SR前,允许运行一段预加载脚本完成ID提取

:white_check_mark: 方案三:固化偏移 + 工具预处理(临时规避方案)

若CDR_Offset在所有板卡中固定(如恒为0x104),可预计算所有可能的ID偏移,并为每种板卡单独定义SR文件

例如:

  • 所有KunLun板卡均使用 CDR_Offset=0x104ID offset=0x831
  • 在CSR中直接写死:
    "Accessor_BoardUID": {
      "Chip": "#Eeprom_SEU",
      "Offset": 2103,  // 0x831 = 2103
      "Size": 8,
      "Type": 1  // 块读
    }
    
  • 并配合工具,在烧录EEPROM前确保ID位于指定位置

:pushpin: 适用场景:板卡型号较少、格式统一的项目


:light_bulb: 是否有计划扩展 Connector.Type 或加载机制?

根据目前文档与设计趋势分析:

:white_check_mark: 当前已有加载模式分类(基于IdentifyMode):

IdentifyMode 说明
1 BoardId可读:从Eeprom读取,支持ID识别
2 BoardId不可读:使用Bom+AuxId加载内置SR
3 天池标准组件:通过Eeprom header自动识别

来源:《CSR配置字典之Connector类》

:crystal_ball: 未来可扩展性展望:

  • 系统已支持“非标电子标签”StorageType=PowerOthers
  • 支持动态表达式语法(如exprstring.*
  • 支持refInterface实现自定义接口加载

:right_arrow: 建议:可向社区提议扩展一种新的IdentifyMode=4,表示自定义格式组件,其ID读取规则由外部脚本或配置定义。


:pushpin: 总结与建议

项目 当前状态 建议
动态Offset支持 :cross_mark: 不支持 避免依赖表达式计算Offset
多字节转字符串 :cross_mark: 无法实现 禁用拼接字符串方案
多级Accessor加载 :warning: 概率性失败 仅可用于调试,不可用于生产
可靠ID读取方式 :white_check_mark: 支持BlockIo读取 使用bmc.kepler.Chip.BlockIo接口
加载稳定性保障 :cross_mark: 缺乏等待机制 建议在自发现层增强逻辑
长期可维护性 :warning: 配置复杂 推动社区支持IdentifyMode=4或ID预加载钩子

:white_check_mark: 最佳实践建议(当前可行路径)

  1. 在系统加载初期,通过BlockIo主动读取EEPROM

    • 读取Header中CDR Offset(偏移0x13)
    • 计算Component ID偏移:(CDR_Offset × 8) + 17
    • 读取8字节数据 → 转换为ASCII字符串
  2. 将获取的ID作为SR文件名的一部分进行加载

    • 如:14140130_KUNLUN_Server.sr
  3. 在BOM或Connector中声明该设备为“自定义格式组件”

    • 使用Type="CustomPCIe" 或预留字段标记
  4. 推动openUBMC社区支持更灵活的ID加载机制

    • 提出RFC:支持IdentifyMode=4
    • 增加PreLoadScriptIdProvider机制

结论
目前CSR配置没有完全无风险的纯声明式机制来完成该需求。
推荐方案是结合BlockIo底层接口与自发现服务扩展,实现稳定、可靠的自定义板卡加载机制,同时向社区反馈增加对复杂ID提取场景的支持。

相关链接:

  1. 如何配置读取Eeprom指定偏移的字符串
  2. 自研板卡如何实现自发现
  3. FruData类StorageType属性描述中的枚举值范围、含义以及如何使用需要明确
  4. Eeprom头定义
  5. 板卡适配指南 | 文档中心 | openUBMC