# general_hardware

# 功能简介

**general_hardware**组件用于管理天池板卡以及板卡中的固件，具体管理的功能有：

* 天池组件的管理：符合天池规范的板卡，包括ExpBoard、CpuBoard、NPUBoard等
* 固件管理：板卡上的各种逻辑单元以及CSR升级，逻辑单元包括MCU、VRD、CPLD、FPGA、Retimer、安全模块
* DPU卡管理：DPU卡作为智能网卡，单独一个种类进行管理
* GPU、NPU管理：用于管理GPU、NPU对象
* 装备接口：提供装备接口用于生产中关于板卡情况的测试

# 关键特性

## 天池板卡管理

该特性主要是天池板卡各种属性的显示以及BMC与板卡逻辑之间的交互，src目录下天池组件管理主要代码位置及实现功能如下：

```text
├─lualib                                       
│  └─unit_manager
│     ├─class
│     │   └─unit
│     │      ├─bcu
│     │      │  ├─bcu.lua               # 继承unit类
│     │      │  └─cpu_board.lua         # CPU板，对bcu类的继承
│     │      ...
│     │ 
│     │ 
│     └─unit_manager.lua                # 对象的增加、删除
│
```

1. 天池板卡对象都有者共同基类unit，初始化的时候从硬件处去更新PCB版本号、MCU版本、CPLD版本、Slot槽位，同时启动任务去更新MCU/CPLD的心跳检测状态，以及一键收集时获取板卡的DFX信息
2. 继承unit类的各种子类具体板卡，对基类的方法进行覆写或新增方法（如BMC启动后需要给基础板上报，用于更新电源灯状态）

## 固件管理

### 固件升级管理

当前升级流程由平台的firmware\_mgmt进行统一管理，包括web、cli、redfish、IPMI接口的升级包传输、解压和各个升级阶段的信号广播，具体见固件升级。general\_hardware负责具体的升级流程，固件当前包括mcu、vrd、cpld、sr、fpga、retimer。

#### CSR升级

src目录下SR升级主要代码位置及实现功能如下：

```text
├─lualib                                       
│  └─sr_upg_service
│     ├─class
│     │   ├─sr_upgrade_with_protect_chip.lua  # 继承sr_upgrade，使用smbus进行eeprom的开关写保护
│     │   └─sr_upgrade.lua                    # 基于升级对象提供基础能力
│     └─sr_upg_service.lua                    # SR升级主任务
│
```

- 对应了sr文件中的SRUpgrade对象，其中UID对应V2的BoardID，根据UID进行升级的匹配；StorageChip负责具体数据的写入；WriteProtect负责写保护的开关

```
"SRUpgrade_1": {
			"UID": "00000001020302031825",
			"Type": "BCU",
			"Version": "1.39",
			"StorageChip": "#/Eeprom_BCU",
			"SoftwareId": "HWSR-BC83AMDA",
			"WriteProtect": "#/Accessor_BCUWP.Value"
		},
```

- SR升级时会遍历环境上的SR升级对象，每个升级对象都会根据UID到升级文件目录下寻找是否有对应的升级文件（UID.sr文件），如果有则启动升级，将升级文件写到对应eeprom中，升级流程图如下：
  ![image](../image/general_hardware/1_SR升级流程.png)

* 具体升级流程：①为了防止eeprom里的数据被篡改，eeprom配置有写保护，升级前需要关闭写保护 ②获取头文件信息，写入头文件③根据头文件信息，在特定偏移写入sr具体数据④关闭写保护

#### MCU升级

src目录下MCU管理主要代码位置及实现功能如下：

```text
├─lualib                                       
│  └─mcu
│     ├─upgrade
│     │   ├─mcu_upg_exe.lua             # 升级最上层接口，管理总体升级流程，包括并行升级、mutihost升级
│     │   ├─mcu_upg_service.lua         # 主升级任务
│     │   ├─vaild.lua                   # vrd生效流程
│     │   ├─smbus_interface.lua         # 基于SMBUS协议实现升级接口
│     │   └─smc_interface.lua           # 基于SMC协议实现升级接口
│     ├─mcu_object.lua                  # 实现MCU固件对象的基本类型
│     ├─smbus_mcu_object.lua            # 基于smbus协议通信的MCU固件对象
│     ├─smc_mcu_object.lua              # 基于smc协议通信的MCU固件对象
│     ├─mcu_service.lua                 # 管理MCU固件对象
│
```

- MCU类图：

![MCU类图](../image/general_hardware/2_MCU类图.jpg)

升级主任务流程：
1、确认升级状态，空闲或升级失败状态表示可升级
2、初始化升级通道
3、发送升级文件
4、启动升级
5、查询升级状态1，确认是否完成
6、发送结束升级命令
7、更新版本号

- MCU升级流程图
  ![image](../image/general_hardware/3_MCU升级流程图.png)

#### VRD升级

当前VRD的升级均为天池组件下的SMC协议升级，VRD的升级方式是通过传包给MCU，MCU再去进行具体的升级，特点如下：

1. VRD升级流程与协议smc命令字与MCU升级保持一致，VRD的升级流程是复用的MCU升级代码，只是将传MCU升级数据改为传VRD升级数据
2. 因为VRD作为二级电源，是用于控制电压的逻辑单元，在OS上电时正在工作无法进行升级，上电升级为缓存VRD升级文件，给firmware_mgmt组件注册生效信号，OS下电后firmware组件通知可以生效后才取出缓存的VRD升级文件，进行生效流程：

```lua
-- VRD生效流程接口
fw_mgmt:SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal(function (...)
    self:on_active_process(...)
end)
```

#### CPLD和FPGA升级

src目录下天池组件管理主要代码位置及实现功能如下：

```text
├─lualib                                       
│  └─unit_manager
│     ├─class
│     │   └─logic_fw
│     │      ├─fpga
│     │      │  ├─fpga_package.lua         # 对fpga升级包的处理
│     │      │  ├─fpga_process.lua         # 对fpga升级主流程的处理
│     │      │  ├─fpga_self_test.lua       # 对fpga自检的处理（用来检测fpga在位状态）  
│     │      │  ├─fpga_signal.lua          # 对fpga升级信号交互流程的处理（详见固件管理流程） 
│     │      │  └─fpga_upgrade.lua         # 对启动阶段fpga自加载的处理
│     │      ├─upgrade
│     │      │  ├─drivers_api.lua         # 对cpld版本信息的处理
│     │      │  ├─fw_cfgs.lua             # 对升级包cfgs文件的处理，升级初始化阶段使用
│     │      │  ├─fw_upgrade.lua          # 对cpld升级各阶段流程的处理  
│     │      │  ├─iic_process.lua         # 对cpld升级主流程的处理（iic链路） 
│     │      │  ├─process.lua             # 对cpld升级主流程的处理（jtag链路）
│     │      │  └─fpga_upgrade.lua        # 对cpld升级信号交互的处理
│     │      ...
│     │ 
│     │ 
│     └─unit_manager.lua                # 对象的增加、删除
│
```

### 固件基本管理

#### VRD管理

主要用于VRD相关的电源、电压、温度的获取，用于告警和传感器的显示。通过IPMI从IMU获取这些信息，具体src如下：

```text
├─lualib                 
│  └─vrd
│     ├─vrd_manager.lua                  # vrd管理对象的增加、删除
│     ├─vrd_mgmt_obj.lua                 # 更新vrd_mgmt的信息
│     └─vrd_object.lua                   # 从imu获取vrd的信息
│
```

#### Retimer管理
##### M88RT51632信息管理主要代码
```text
├─lualib
...
│  ├─protocol                               # 实现和封装器件访问相关的协议，对外提供读写接口
│  │  └─smbus_5902.lua                      # 实现5902L器件访问的SMBUS协议，包括读写接口及芯片Idle状态等待，
...                                         # 根据《SD5902 Chip Solution V100R001C00 IIC_SMBUS软件接口文档说明书.docx》实现
│  └─retimer
│     ├─agent                               # 实现5902L器件访问的代理能力，封装属性读取及解析，提供定时任务刷新Retimer对象属性
│     │   ├─init.lua
│     │   └─retimer_agent_5902l.lua         # Retimer对象管理，收到Retimer后关联器件访问代理，启动定时任务
│     └─upgrade                             # Retimer升级功能实现
│         │─retimer_upg_5902l.lua           # 5902L Retimer升级
│         └─retimer_upg_service.lua         # Retimer升级公共服务入口
│
...
└─ser
```

- BMC启动后等待硬件自发现执行组件发现后，获取Retimer相关对象，启动Retimer属性刷新定时任务；
- 等待SmBios对象的SmBiosStatus状态，当状态为3时（表示写完成），执行属性更新，包括DieId、FirmwareVersion、Temperature；当状态不为3（一般为4，表示未开始）；
- 通过SMBUS协议访问Retimer器件，获取指定数据。获取数据，需要通过一次写和一次读操作完成，每次操作都需要读取并等待芯片Idle状态；
- 读取数据后，通过解析和格式化，回写Retimer对象属性。

##### M88RT51632信息管理主要代码
src目录下M88RT51632读取信息管理主要代码位置及实现功能如下：
```text
├─lualib
...
│  ├─protocol                               
│  │  └─smbus_M88RT51632.lua                    # 实现M88RT51632器件访问的SMBUS协议，包括读取温度、版本信息等接口
...                                         
│  └─retimer
│     ├─agent                               
│     │   ├─init.lua
|     |   ├─retimer_agent_M88RT51632_utils.lua  # retimer agent对象的utils配置文件，封装了温度与版本信息基于smbus的读取与解析实现
│     │   └─retimer_agent_M88RT51632.lua        # retimer agent对象，关联chip器件访问，提供定时任务刷新Retimer对象属性
│     │
│     └─retimer_M88RT51632.lua                  # retimer对象，用于管理retimer的所有功能定时任务
...
└─service
```

#### 安全模块管理

src目录下dpu卡管理主要代码位置及实现功能如下：

```text
├─lualib
...
│  ├─security_module
│  │  ├─security_object.lua                 # 提供安全模块对象属性的获取和设置接口
│  │  └─security_service.lua                # 对象的增加、删除，用于接收上报的信息，并向外提供IPMI接口
```

流程图如下：
![image](../image/general_hardware/4_安全模块管理流程图.png)

- 启动阶段，硬件自发现将包含安全模块对象的数据以ObjectGroup分组上树；general_hardware向ipmi_core注册IPMI命令Report Trusted Module Info，等待BIOS上报安全模块信息
- general_hardware从硬件自发现获取组件对象信息，对安全模块对象数据恢复持久化属性，无持久化数据时使用默认值，并上资源树
- general_hardware收到ipmi_core传递的Trusted Module info信息，更新到安全模块对象属性，同步资源树
- general_hardware上树安全模块对象后，对外提供安全模块对象查询能力

## DPU卡管理

src目录GPU信息管理主要代码位置及实现功能如下：

```text
├─lualib                 
│  └─dpu_service
│     ├─dpu_enums.lua                  # 存放dpu相关的常量
│     ├─dpu_ipmi.lua                   # dpu相关IPMI的接口
│     ├─dpu_object.lua                 # 管理dpu卡的对象
│     ├─dpu_service.lua                # dpu卡对象的管理
│     ├─dpu_upgrade_object.lua         # dpu卡相关mcu、cpld、vrd的升级
│     └─utils.lua.lua                  # dpu卡相关的通用函数
│
```

general_hardware管理的是DPU卡在板卡属性上的功能，网卡属性的功能由network_adapter负责。包括的功能主要有：dpu基本属性的更新，mcu、cpld、vrd等逻辑单元的管理，获取MRC日、MCU日志、UEFI日志，串口切换、串口录音，告警上报

- CPLD升级流程图：
  ![image](../image/general_hardware/5_CPLD升级流程图.png)

## GPU管理

src目录GPU信息管理主要代码位置及实现功能如下：

```text
├─lualib                 
│  └─gpu_service
│     ├─fructl_handler.lua                  # 上下电相关接口
│     ├─gpu_ipmi.lua                        # gpu相关IPMI的接口
│     ├─gpu_object.lua                      # 管理gpu的对象
│     └─gpu_service.lua                     # gpu整体的管理
│  └─hardware_config
│     └─Tesla_T4.lua                        # smbus_postbox协议
│
```

当前GPU管理仅支持smbus_postbox协议（主要是Tesla_T4卡），通过smbus_postbox协议从硬件获取信息，通过IPMI命令从IMU获取相关信息

![image](../image/general_hardware/6_SMBPBI协议实现的基本流程.png)
SMBPBI协议实现的基本流程如上图。某些命令字（opcode）可能需要先写入数据寄存器，再写入命令寄存器。执行结果可能既需要从数据寄存器取出，又要从另外一个数据寄存器取出。

## 装备接口管理

```text
├─lualib                 
│  └─manufacture
│     ├─eye_diagram.lua                             # 眼图测试
│     ├─general_hardware_manufacture_app.lua        # 装备测试总服务
│     ├─hw_channel_test.lua                         # 硬件链路测试
│     ├─vrd_upgrade_sim.lua                         # 模拟vrd升级接口
│     └─jtag_test.lua                               # jtag链路测试
│
```

在sr对象中会配置对应的dft测试对象，对象分发后存储在app中，当前支持以下几种：

```
local DFT_SWITCH<const> = {
    ['DftMemoryVolt'] = 1,
    ['Dft12V0Vlot'] = 1,
    ['Dft5V0Vlot'] = 1,
    ['Dft3V3Vlot'] = 1,
    ['DftCardPresence'] = 1,
    ['DftButtonCell'] = 1,
    ['DftFlash'] = 1,
    ['DftJTAG'] = 1,
    ['DftCpld'] = 1,
    ['DftIOTest'] = 1,
    ['DftHwChannel'] = 1
}
```

由装备在带内发送IPMI命令触发具体的DFT测试，包括`Start`、`Stop`和`Result`命令（IPMI命令声明在manufacture组件，general_hardware为具体实现），接口在general_hardware_manufacture_app如下：

```
-- jtag测试的IPMI接口函数注册
function manufacture_app:register_cpld_test()
    self.app:ImplDftCpldManufactureStart(function (obj, ...)
        return self:DftCpldStart(obj)
    end)
    self.app:ImplDftCpldManufactureStop(function (obj, ...)
        return self:DftCpldStop(obj)
    end)
    self.app:ImplDftCpldManufactureGetResult(function (obj, ...)
        local private_obj = self:get_private_prop(obj)
        return self:DftCpldGetResult(obj, private_obj)
    end)
end
```

# 对外接口

### 资源树接口
```
DPUCardSetDpuNmi                    # 设置SDI卡的NMI中断 
DPUCardReset                        # DPU卡重启
DPUCardSetPowerState                # 设置DPU卡系统上下电状态
NpuBoardsSetNpuPowerCap             # 设置模组功耗封顶
NpuBoardReset                       # NPU卡重启
DPUCardSetBootOption                # 设置DPU卡SD100启动项
```
### IPMI接口
```
    ├─/bmc/kepler/IpmiCmds
    │ ├─/bmc/kepler/IpmiCmds/06
    │ │ ├─/bmc/kepler/IpmiCmds/06/58
    │ │ │ └─/bmc/kepler/IpmiCmds/06/58/SetSystemInfoParameters    # 设置系统信息
    │ │ └─/bmc/kepler/IpmiCmds/06/59
    │ │   └─/bmc/kepler/IpmiCmds/06/59/GetSystemInfoParameters    # 查询系统信息
    │ └─/bmc/kepler/IpmiCmds/30
    │   ├─/bmc/kepler/IpmiCmds/30/90
    │   │ ├─/bmc/kepler/IpmiCmds/30/90/GetCpldDeviceidInfo        # 获取cpld厂家id
    │   │ ├─/bmc/kepler/IpmiCmds/30/90/GetEyeDiagram              # 眼图测试
    │   │ └─/bmc/kepler/IpmiCmds/30/90/SetCpldChannel             # 设置cpld通道
    │   ├─/bmc/kepler/IpmiCmds/30/92
    │   │ ├─/bmc/kepler/IpmiCmds/30/92/GetSecurityModuleInfo      # BIOS 上报可信模块信息
    │   │ └─/bmc/kepler/IpmiCmds/30/92/ReportTrustedModuleInfo    # 获取可信模块信息
    │   └─/bmc/kepler/IpmiCmds/30/93
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetAllDpuEPInitStatus      # 获取dpu ep状态
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetCpuModulePower          # multihost各节点功耗
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuBiosLogLevel         # 获取dpu卡Bios日志等级
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuBootOption           # 设置DPU卡SD100启动项
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuPxeOption            # 获取dpu pxe选项
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuResetLinkage         # 获取dpu复位联动策略
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuSolSwitch            # 获取DPU卡内部串口
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuStorageIP            # 查询SD100 FusionStorage Agent的IP地址和VLAN
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetDpuSystemStatus         # 查询SD100系统启动状态
    │     ├─/bmc/kepler/IpmiCmds/30/93/GetGpuChipInfo             # 使用rootBDF获取GPU芯片类型信息
    │     ├─/bmc/kepler/IpmiCmds/30/93/RestSDI                    # 重启SDI卡
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDeviceAction            # Set Device Action
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuBiosLogLevel         # 设置dpu卡Bios日志等级
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuBootOption           # 设置DPU卡SD100启动项
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuIp                   # 查询SD100 设置VLAN 上IP 地址的状态
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuNMI                  # 设置SDI卡的NMI中断
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuPowerState           # 设置DPU卡系统上下电状态
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuPxeOption            # 设置dpupxe选项
    │     ├─/bmc/kepler/IpmiCmds/30/93/SetDpuResetLinkage         # 设置dpu复位联动策略
    │     └─/bmc/kepler/IpmiCmds/30/93/SetDpuSolSwitch            # DPU卡内部串口切换
```
# 配置介绍

general_hardware不涉及配置项
 