[toc]
1 BIOS升级简要操作
1.1 升级包获取方式
要获取相关的BIOS hpm包,可以到华为官网按机型+bios搜索软件包。
1.2 升级接口
目前BMC升级bios主要有redfish、web和cli三个接口,接口的使用方法如下:
url:/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate
参数:
{
"ImageURI":"/tmp/biosimage.hpm"
}ipmcset -d upgrade -v /tmp/biosimage.hpm1.3 升级场景
升级包区分
| 升级包类型 | 升级包的update.cfg |
|---|---|
| 补丁包(无感升级的包) | 版本包含HPxxxx |
| 普通包 | 版本不包含HPxxxx |
BMC模式区分
| BMC模式 | 场景 |
|---|---|
| 装备模式 | 打包manufacture文件夹(装备包) |
| 非装备模式 | 未打包manufacture文件夹(装备包) |
目前支持的升级场景有
| BIOS hpm包类型 | BMC模式 | OS状态 | 升级模式 |
|---|---|---|---|
| 普通包 | 装备模式 | 上电 | 强制下电升级(全擦升级) |
| 普通包 | 装备模式 | 下电 | 直接升级(全擦升级) |
| 普通包 | 非装备模式 | 上电 | 缓存hpm包,待下电或复位生效 |
| 普通包 | 非装备模式 | 下电 | 直接升级 |
| 补丁包 | 非装备模式 | 上电 | 无感升级 |
目前BIOS的无感升级只有redfish接口支持,首先查询无感升级固件 URI:/redfish/v1/UpdateService/FirmwareInventory/Bios【其中Hotfix表示可以无感升级的固件】:
再触发无感升级,且可从日志中看到升级成功的打印,以及版本发生变化
url:/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate
参数:
{
"ImageURI":"/tmp/biosimage_patch.hpm",
"BiosActivatedScope":["IMU","IMP","SCC"] --由上一步可查询
}另外,装备模式下的升级均为全擦升级,ipmcset -t maintenance -d upgradebios -v /tmp/biosimage.hpm在非装备模式下也是全擦升级,全擦升级不会保留Bios的配置项。
2 底层原理
2.1 升级内容
升级内容围绕BIOS的核心功能展开,重点优化安全、兼容、稳定三大维度,具体如下:
- 安全漏洞修复:修补BIOS、UEFI及CPU微码中的高危漏洞,防范固件级攻击(如Rootkit、缓冲区溢出),强化安全启动(Secure Boot)策略,保障服务器启动链安全,符合服务器安全合规要求。
- 硬件兼容性优化:新增对新一代CPU、高频率内存、新型NVMe硬盘、RAID卡等硬件的识别和支持,解决新硬件无法识别、无法正常运行的问题,延长服务器硬件升级空间。
- 稳定性与Bug修复:解决BIOS层面导致的开机异常(黑屏、自检报错)、运行故障(蓝屏、掉电)、休眠唤醒异常等问题,优化电源管理和散热控制,减少服务器运行中的异常停机。
- 功能与性能优化:缩短开机自检时间、优化内存时序和CPU睿频策略,提升服务器启动速度和运行性能;新增BIOS设置项,支持虚拟化、远程部署等新增功能,适配服务器多样化应用场景。
通过解析bin包的header区域获取所需要升级的固件类型、地址和长度,其中固件类型主要分为5类,0x0为固件,0x1为数据,0x2为变量,0x3为ROM固件,0x4为HEADER,其中0x0、0x1、0x4为固定擦写,0x3永不擦除,0x2只有在全擦升级场景下擦写。
2.2 硬件通道
对于普通包升级BMC主要使用的是spi(Serial Peripheral Interface,串行外围设备接口)链路,BMC、CPU和BIOS flash之间的spi链路大致为下图,只支持BMC同时连接一块BIOS flash,一块BIOS flash同时只能与CPU或者BMC其中一个连接。在一般情况下spi链路所有权归属CPU,通过BMC升级BIOS需要将链路所有权切换至BMC侧。
对于补丁包升级BMC主要使用的是IPMB(Intelligent PlatformManagement Bus)通道,BMC通过IPMB通道将需要更新的固件传递给IMU,由IMU负责将固件写入到对应的Flash区域中。
3 功能介绍
3.1 升级流程图和时序图
3.2 升级的三个主要阶段
当前升级框架将BMC所有支持的固件升级分为三个阶段:prepare、process、finish,对于BIOS升级这三个阶段的主要任务如下:
3.3 升级任务链的组建
| Executor名称 | 场景 | Executor作用 |
|---|---|---|
| PackageCheckExecutor | 所有场景 | 校验包合法性,如:冷升级不能升级补丁包、无感升级不能升级非补丁包、装备模式不能升级补丁包 |
| BackExecutor | 所有场景 | 将升级包备份至/data/upgrade/bios.tar.gz,用于ac、bmc复位场景恢复升级 |
| Cache | 非装备模式普通包 | 判断带内上电状态,若上电缓存升级包,待下电生效,结束任务链 |
| ForcePower | 装备模式普通包 | 强制下电,升级完成后上电 |
| LockPower | 普通包 | 升级的时候需要锁住上下电,不允许上电,升级完成后解锁 |
| SpiDriver | 普通包 | 设置bios flash通道方向,加载spi驱动 |
| DecompressFile | 所有场景 | 将bios.tar.gz解压成bin包(bin包大小与flash大小一样,地址也一致) |
| ParserBin | 所有场景 | 解析bin包,主要是header以及固件个数、固件大小、固件地址 |
| ComponentFilter | 补丁包 | 无感升级根据输入的BiosActivatedScope设置升级的固件,过滤版本一致的固件,这部分固件不升级 |
| SelectChannel | 所有场景 | 通道选择,无感升级(ipmb通道)、其他(spi链路) |
| UpgradeComponent | 所有场景 | 升级固件,根据不同的通道执行写动作 |
| WaitUpgradeFinish | 补丁包 | 无感升级等待固件升级完成 |
| ActivateFirmware | 补丁包 | 无感升级根据输入的BiosActivatedScope调用imu生效相关固件 |
3.4 其他升级场景(TeeOS、CCA、krun、多flash、多host)
TeeOS、CCA均为BIOS Flash上的固件,升级方式除了不支持无感升级,其他与Bios保持一致。
krun为基础板下挂的CPLD下面的Flash固件,升级方式同样不支持无感升级,另外则是krun升级SelectChannel使用的是Hisport链路,因此支持krun和BIOS的并行升级。
对于多flash场景,目前是通过配置csr中的FlashChannel和FlashChannelIds实现,FlashChannel用于配置当前bios对象的spi链路指向哪一块flash,FlashChannelIds用于表示哪些flash归属于当前Bios对象。 对于多host场景则配置多个类似的Bios对象实现。
"Bios_1": {
"SystemId": 1,
"FlashChannel": 1,
"FlashChannelIds": [0, 1]
}在升级指定bios对象时,会根据FlashChannelIds将hpm包依次刷入对应的flash中。
4 代码流程
主要涉及到的代码文件
├── domain
│ ├── bios_firmware
│ │ ├── defs.lua -- 固件定义信息文件
│ │ └── package -- bios升级包
│ │ ├── channel
│ │ │ ├── channel_selector.lua -- 升级通道选择
│ │ │ ├── firmware_process_channel.lua
│ │ │ ├── hisport_channel.lua -- hisport链路
│ │ │ ├── ipmb_channel.lua -- ipmb链路
│ │ │ └── spi_flash_channel.lua -- spi_flash链路
│ │ ├── executors
│ │ │ └── upgrade_executor.lua -- 任务链
│ │ ├── krun_flash.lua -- krun flash
│ │ ├── package.lua -- 升级包
│ │ ├── package_builder.lua -- 升级包构建
│ │ ├── package_cfg.lua -- 升级包参数解析
│ │ ├── package_snapshot.lua -- 升级快照
│ │ ├── package_validator.lua -- 升级包和升级模式校验
│ │ ├── upgrade_config_builder.lua -- 升级任务链构造
│ │ └── upgrade_scenarios.lua -- 升级任务链参数构造
│ ├── mapping
│ │ ├── component_info.lua -- 无感升级文件基类
│ │ ├── component_manager.lua -- 无感升级文件管理器
│ │ └─── component_version.lua -- 无感升级版本文件
│ └── transport
│ ├── component_communicate.lua -- imu交互
│ ├── component_effective.lua -- 无感升级生效
│ ├── component_info_query.lua -- 查询无感升级文件
│ ├── component_process_query.lua -- 查询无感升级进度
│ ├── component_send_confirmed.lua -- 确认无感升级升结果
│ ├── component_upgrade.lua -- 无感升级
│ └── imu_communicate.lua -- imu交互
├── infrastructure
│ ├── chain.lua -- 责任链
│ ├── fructl.lua -- 上下电类
│ ├── imu.lua -- imu交互类
│ └── power_lock.lua -- 上下电锁
├── interface
│ ├── mdb
│ │ └── firmware.lua -- 升级资源树
│ └── signal.lua -- 信号类
├── pojo -- 实体类
└── service -- 服务类
├── upgrade_service.lua -- 升级服务
├── krun_service.lua -- krun升级服务
└── upgrade_state_machine.lua -- 升级状态机
4.1 注册对应的固件信息至升级框架
以Bios为例
其中ComponentID和SubComponentID 唯一指定固件类型,StageSupported代表固件是否支持缓存生效。
4.2 UpgradePrepare阶段
升级框架信号入口
在upgrade_service完成cfg文件解析
4.3 UpgradeProcess阶段
升级框架信号入口
多flash和单flash的分支判断,同时构建对应的upgrade_info
初始化升级快照
根据upgrade_info构造对应任务链以及上下文ctx,并开始执行升级。
4.4 UpgradeFinish阶段
升级框架信号入口
若为上电缓存升级则需注册生效信号,这里设置了重启生效or下电生效
升级是否保留配置
4.5 ActiveProcess阶段
下电生效阶段升级框架信号入口
生效流程与普通包下电升级一致