QEMU打包过程解析

OpenUBMC QEMU打包完整技术文档

文档版本v2.0
文档日期2026年5月
适用范围:OpenUBMC开发与维护人员


目录


一、QEMU打包完整流程

1.1 打包脚本与入口

核心脚本build/works/packet/work_build_qemu_rootfs.py

打包入口TaskClass.run()qemu_rootfs_deploy()


1.2 打包流程七步骤

步骤1:源文件准备

源rootfs路径

rtos_with_driver/rootfs(真机rootfs)

内容包含

目录 内容说明
/bin, /sbin, /usr/bin 系统命令
/lib, /lib64 系统库
/etc 配置文件(rc.sysinit, systemd服务)
/opt/bmc/apps BMC应用程序
/boot 内核镜像

步骤2:复制到临时打包目录

# 691-698行
src_rootfs_path = "rtos_with_driver/rootfs"
qemu_rootfs_path = "temp_path/qemu/qemu_rootfs"

操作:cp -a src_rootfs_path → qemu_rootfs_path

目的:创建临时打包目录,避免破坏源rootfs


步骤3:QEMU定制化处理(核心)

处理类QemuCi.qemu_action()(374-416行)

处理对象qemu_rootfs_path目录

关键操作

  • :white_check_mark: 虚拟化驱动注入
  • :white_check_mark: 启动脚本修改
  • :white_check_mark: 硬件密钥禁用
  • :white_check_mark: Mock数据注入
  • :white_check_mark: 服务降级处理
  • :white_check_mark: 健康检查禁用
  • :white_check_mark: 初始化脚本裁剪

步骤4:清理虚拟化临时文件

# 424-461行
QemuCi.rm_ve_libs()

删除目录

目录 说明
virtio/ 虚拟化临时文件
lua_code/ Lua临时文件
scripts/ 脚本临时文件
qemu/ QEMU临时文件
qemu_luas/ QEMU Lua临时文件
sr/ SR临时文件

目的:清理打包过程中产生的临时文件,避免污染最终镜像


步骤5:编译数据脚本

# 707-708行
chdir("qemu_rootfs_path/data/script")
make  # 编译/data/script目录下的脚本

目的:确保数据脚本可执行


步骤6:CPIO打包压缩

# 712-729行
chdir("qemu_rootfs_path")
find . | cpio -H newc --quiet -o > qemu.cpio
gzip -k qemu.cpio → qemu.cpio.gz

打包格式newc格式(标准CPIO格式)

压缩方式gzip压缩


步骤7:组装最终发布包

# 733-738行
产物组成:
1. qemu.cpio.gz(根文件系统镜像)
2. zImage_openUBMC(内核镜像,从uImage提取)
3. hi1711_9p8c.dtb(设备树文件,从qemu_mockup复制)

打包:
tar -czf board_qemu_default.data.gz(包含上述3个文件)

最终路径output/packet/board_qemu_default.data.gz


1.3 打包流程图

┌────────────────────────────────────────────┐
│ 源rootfs: rtos_with_driver/rootfs         │
│ (真机rootfs,包含完整系统文件)            │
└────────────────────────────────────────────┘
                    ↓ 复制
┌────────────────────────────────────────────┐
│ 临时目录: temp_path/qemu/qemu_rootfs      │
│ (临时打包目录,所有定制化操作在此执行)    │
└────────────────────────────────────────────┘
                    ↓ QEMU定制化处理(核心步骤)
┌────────────────────────────────────────────┐
│ QemuCi.qemu_action()                      │
│ ├─ 虚拟化驱动注入                          │
│ ├─ 启动脚本修改                            │
│ ├─ 硬件密钥禁用                            │
│ ├─ Mock数据注入                            │
│ ├─ 服务降级处理                            │
│ ├─ 健康检查禁用                            │
│ └─ 初始化脚本裁剪                          │
└────────────────────────────────────────────┘
                    ↓ 清理临时文件
┌────────────────────────────────────────────┐
│ QemuCi.rm_ve_libs()                       │
│ 删除:virtio, lua_code, scripts, qemu等   │
└────────────────────────────────────────────┘
                    ↓ 编译脚本
┌────────────────────────────────────────────┐
│ make data/script                          │
└────────────────────────────────────────────┘
                    ↓ CPIO打包
┌────────────────────────────────────────────┐
│ find . | cpio -H newc -o > qemu.cpio      │
└────────────────────────────────────────────┘
                    ↓ GZIP压缩
┌────────────────────────────────────────────┐
│ gzip qemu.cpio → qemu.cpio.gz             │
└────────────────────────────────────────────┘
                    ↓ 提取内核镜像
┌────────────────────────────────────────────┐
│ dd if=uImage of=zImage bs=1 skip=64       │
│ (跳过64字节uImage头)                     │
└────────────────────────────────────────────┘
                    ↓ 组装发布包
┌────────────────────────────────────────────┐
│ 最终产物:                                 │
│ ├─ qemu.cpio.gz(根文件系统)               │
│ ├─ zImage_openUBMC(内核镜像)             │
│ ├─ hi1711_9p8c.dtb(设备树)               │
│ └─ board_qemu_default.data.gz(发布包)    │
└────────────────────────────────────────────┘

二、真机与QEMU的核心差异

2.1 差异总览对比表

维度 真机 QEMU虚拟化环境 差异说明
硬件访问 直接访问物理寄存器(I2C/GPIO/SPI) 通过virtio读取宿主机文件(9p文件系统) 核心差异:物理硬件 vs 虚拟化文件
数据来源 真实传感器/EEPROM硬件数据 Mock数据文件(JSON/二进制) 核心差异:真实数据 vs 模拟数据
驱动类型 I2C/GPIO/SPI/UART物理驱动 Virtio虚拟化驱动(virtio_pci/9pnet) 核心差异:物理驱动 vs 虚拟驱动
数据挂载 物理分区挂载(mtdblock/mmcblk) 9p虚拟文件系统挂载(hostshare/pramshare) 核心差异:物理分区 vs 虚拟挂载
启动流程 完整硬件检查和初始化 跳过硬件检查,裁剪初始化脚本 核心差异:完整流程 vs 裁剪流程
服务安全 secbox用户 + 沙箱隔离 + 最小权限 root用户 + 无沙箱 + 扩展权限 核心差异:安全隔离 vs 开放环境
健康检查 MACA重启机制 + 健康监控 + 离线阈值 全部禁用(避免反复重启) 核心差异:严格监控 vs 放宽限制
密钥验证 硬件根密钥验证(EFUSE芯片) 软件模拟(禁用硬件验证) 核心差异:硬件验证 vs 软件模拟
调试方式 串口/JTAG硬件调试 telnet + 虚拟串口(远程调试) 核心差异:硬件调试 vs 软件调试
网络配置 真实物理网络接口(eth0物理MAC) 虚拟网络接口(eth0: 10.0.2.15虚拟MAC) 核心差异:物理网络 vs 虚拟网络

2.2 启动流程差异详解

真机启动流程

Bootloader(U-Boot)
    ↓ 加载uImage + rootfs
内核启动
    ↓ 加载物理驱动
    ├─ i2c_drv.ko(I2C总线驱动)
    ├─ gpio_drv.ko(GPIO驱动)
    ├─ uart_drv.ko(UART驱动)
    ├─ spi_drv.ko(SPI驱动)
    ├─ watchdog_drv.ko(硬件看门狗)
    └─ mctp_drv.ko(MCTP协议驱动)
    ↓
rc.sysinit初始化
    ├─ 硬件检查(cooling.sh散热检查)
    ├─ 分区挂载(mount /dev/mmcblk0p1 /data)
    ├─ 设备树解析(读取真实硬件信息)
    ├─ RTOS快照加载(rtos_snapshot.ko)
    └─ 物理设备初始化(读取硬件寄存器)
    ↓
systemd服务启动
    ├─ 以secbox用户运行(安全隔离)
    ├─ 通过secbox沙箱启动(ExecStart=secbox -f ...)
    ├─ 最小权限集(CAP_DAC_OVERRIDE, CAP_NET_BIND_SERVICE)
    ├─ MACA异常重启机制(健康检查失败 → 重启)
    └─ 硬件根密钥验证(HARDWARE_ROOTKEY_ENABLE=true)
    ↓
rc.start脚本执行
    ├─ S11EventInit.sh(读取真实Event传感器)
    ├─ S11FrudataInit.sh(读取真实FRU EEPROM)
    ├─ S11SensorInit.sh(读取真实Sensor数据)
    ├─ S12BiosInit.sh(初始化真实BIOS硬件)
    ├─ S12PCIeInit.sh(扫描真实PCIe设备)
    └─ S12StorageInit.sh(初始化真实存储设备)
    ↓
应用程序运行
    ├─ 健康检查机制(启动失败 → MACA重启)
    ├─ 真实硬件访问(i2c_read → 物理寄存器)
    ├─ Watchdog监控(硬件看门狗触发)
    └─ 物理传感器数据上报

QEMU启动流程

QEMU虚拟化层启动
    ↓ 配置虚拟化参数
    ├─ 加载zImage_openUBMC(内核镜像)
    ├─ 加载qemu.cpio.gz(根文件系统)
    ├─ 加载hi1711_9p8c.dtb(设备树)
    ├─ 配置virtfs共享(hostshare, pramshare, mockshare)
    └─ 配置虚拟网络(eth0: 10.0.2.15)
    ↓
内核启动 + virtio驱动加载
    ├─ insmod_9p_vfs.sh(第179行执行)
    ├─ 加载virtio驱动(virtio_pci, virtio_net, 9pnet)
    ├─ 配置虚拟网络(ifconfig eth0 10.0.2.15)
    └─ 挂载9p文件系统
        ├─ mount hostshare → /data(宿主机数据共享)
        ├─ mount pramshare → /opt/bmc/pram(宿主机PRAM共享)
        └─ mount mockshare → /mockdata(宿主机Mock数据共享)
    ↓
rc.sysinit初始化(修改版)
    ├─ 跳过硬件检查(注释cooling.sh)
    ├─ 注释RTOS快照(rtos_snapshot.ko)
    ├─ 启动telnetd服务(调试入口)
    ├─ 创建虚拟设备标志(touch /dev/uart_connect)
    ├─ 软链接shadow文件(ln -s /data/trust/shadow)
    └─ 调整分区参数(logpart_sectors_num=0)
    ↓
systemd服务启动(修改版)
    ├─ 以root用户运行(User=root,原secbox)
    ├─ 直接bash启动(ExecStart=bash -c,跳过secbox沙箱)
    ├─ 扩展权限集(增加CAP_SYS_MODULE等10个权限)
    ├─ 禁用健康检查(IGNORE_HEALTH_CHECK_RESULT=true)
    ├─ 禁用MACA机制(mc_control.json: true → false)
    └─ 禁用硬件密钥(HARDWARE_ROOTKEY_ENABLE=false)
    ↓
rc.start脚本执行(裁剪版)
    ├─ S11EventInit.sh(删除硬件检查,保留脚本)
    ├─ S11FrudataInit.sh(删除硬件读取,保留脚本)
    ├─ S11SensorInit.sh(删除传感器读取,保留脚本)
    ├─ S12BiosInit.sh(删除BIOS检查,保留脚本)
    ├─ S12PCIeInit.sh(删除PCIe扫描,保留脚本)
    └─ S12StorageInit.sh(删除存储检查,保留脚本)
    ↓
应用程序运行
    ├─ 禁用健康检查(启动失败不重启)
    ├─ 读取mock数据(/mockdata/i2c/1/0x60_smc.json)
    ├─ 无Watchdog监控(虚拟环境)
    └─ 模拟传感器数据上报(从mockdata读取)

2.3 关键差异点详解

差异点1:硬件访问方式

真机

应用层调用:i2c_read(bus=1, addr=0x60)
    ↓
驱动层执行:ioctl(/dev/i2c-1, I2C_SLAVE, 0x60)
    ↓
硬件层读取:读取I2C总线物理寄存器
    ↓
返回真实数据:温度35.5°C(从物理传感器读取)

QEMU

应用层调用:i2c_read(bus=1, addr=0x60)
    ↓
驱动层拦截:检测到QEMU环境
    ↓
文件读取:读取/mockdata/i2c/1/0x60_smc.json
    ↓
返回mock数据:温度35.5°C(从JSON文件读取)

应用层无感知:接口相同,底层实现不同


差异点2:数据挂载机制

真机

# 物理分区挂载
mount /dev/mmcblk0p1 /data        # 物理SD卡分区
mount /dev/mtdblock7 /opt/bmc     # 物理Flash分区

特点

  • 数据持久化在物理存储介质
  • 分区大小固定(硬件限制)
  • I/O性能取决于硬件速度

QEMU

# 9p虚拟文件系统挂载
mount -t 9p hostshare /data       # 宿主机目录共享
mount -t 9p pramshare /opt/bmc/pram  # 宿主机PRAM共享
mount -t 9p mockshare /mockdata   # 宿主机Mock数据共享

特点

  • 数据持久化在宿主机目录
  • 分区大小由宿主机决定(无限制)
  • I/O性能取决于virtio传输速度
  • 实时同步(宿主机修改立即生效)

差异点3:服务安全机制

真机(严格安全隔离):

[Service]
User=secbox                      # 非root用户运行
Group=secbox                     # 专用安全组
AmbientCapabilities=CAP_DAC_OVERRIDE CAP_NET_BIND_SERVICE  # 最小权限集
ExecStart=secbox -f secbox.cfg -c skynet config.cfg  # 通过secbox沙箱启动

安全机制

机制 说明
沙箱隔离 secbox容器隔离应用
用户隔离 secbox用户(UID=104)
权限限制 仅2个权限(最小原则)
进程审计 所有操作被审计记录

QEMU(开放环境):

[Service]
User=root                        # root用户运行(无隔离)
AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_SYS_MODULE ...  # 扩展权限集(10个权限)
ExecStart=bash -c 'exec -a om skynet config.cfg'  # 直接bash启动(无沙箱)

开放原因

原因 说明
虚拟化环境无需安全隔离 测试环境,不涉及生产数据
root简化权限管理 无需复杂的用户权限配置
扩展权限访问虚拟硬件 需要加载virtio驱动等操作
无审计需求 测试环境不需要审计

差异点4:健康检查机制

真机(严格监控):

{
    "maca_enable": true,              // 启用MACA机制
    "health_monitor_enable": true,    // 启用健康监控
    "restart_on_failure": true,       // 失败自动重启
    "timeout_mins": 2,                // 超时2分钟
    "max_restart_count": 5            // 最大重启5次
}

检查机制

检查类型 触发条件 执行动作
启动检查 服务启动失败 记录日志 → MACA重启
健康检查 健康异常 告警 → MACA重启
离线计数 离线次数 > 3 服务重启

QEMU(放宽限制):

{
    "maca_enable": false,             // 禁用MACA机制
    "health_monitor_enable": false,   // 禁用健康监控
    "restart_on_failure": false,      // 禁用失败重启
    "timeout_mins": 99,               // 超时99分钟(放宽)
    "max_restart_count": 99           // 最大重启99次(放宽)
}

放宽原因

原因 说明
QEMU性能可能受限 虚拟化开销可能导致响应慢
避免反复重启导致不稳定 性能限制下可能频繁触发重启
测试环境允许失败 不影响生产,允许服务失败

差异点5:启动脚本差异

真机(完整硬件初始化):

#!/bin/bash

# 硬件设备检查
BIOS_DEV="/dev/bios_spi"
if [ ! -e $BIOS_DEV ]; then
    log_error "BIOS device not exist"
    exit 1
fi

# BIOS寄存器读取
BIOS_VERSION=$(hexdump -C $BIOS_DEV | head -1)
if [ -z "$BIOS_VERSION" ]; then
    log_error "Read BIOS version failed"
    exit 1
fi

# 硬件初始化
init_bios_registers $BIOS_DEV

# 目录创建和权限设置
mkdir -p /data/backup/bios
chown -R secbox:secbox /data/backup/bios

QEMU(裁剪版):

#!/bin/bash

# 硬件检查代码已删除(第4-12行被删除)

# 保留:目录创建和权限设置
mkdir -p /data/backup/bios
mkdir -p /data/opt/bmc/conf/bios
mkdir -p /dev/shm/bios
chown -R secbox:secbox /data/backup/bios

裁剪原则

操作 是否执行 原因
保留脚本文件 :white_check_mark: 执行 维护启动依赖链
删除硬件检查 :cross_mark: 不执行 无真实硬件
删除寄存器读取 :cross_mark: 不执行 使用mock数据
保留目录创建 :white_check_mark: 执行 业务功能需要

三、QEMU打包详细机制

3.1 打包定制化处理七大步骤详解

步骤详解1:虚拟化驱动注入

处理目的:为QEMU提供虚拟化硬件访问能力

关键操作

操作1:复制virtio驱动模块

源路径 目标路径 文件列表
qemu_mockup/src/lualib/mock/kernel/ qemu_rootfs/lib/modules/qemu/ virtio.ko, virtio_pci.ko, virtio_net.ko, virtio_blk.ko, 9pnet.ko, 9pnet_virtio.ko, 9p.ko, sys_info.ko, dfx.ko

操作2:复制关键脚本

源路径 目标路径 文件列表
qemu_mockup/src/lualib/mock/script/ qemu_rootfs/opt/bmc/ insmod_9p_vfs.sh(核心), insmod_drv.sh

操作3:复制专用驱动

源路径 目标路径 文件列表
qemu_mockup/src/lualib/mock/kernel/ qemu_rootfs/lib/modules/ko/ bmc_hisport_drv.ko, mctp_drv.ko

步骤详解2:启动脚本修改

修改对象/etc/rc.d/rc.sysinit(584行)

关键修改位置

修改1:注释硬件检查(289行)

# 修改前:
insmod /lib/modules/${KERNEL_NAME}/rtos_snapshot.ko

# 修改后:
#insmod /lib/modules/${KERNEL_NAME}/rtos_snapshot.ko  # QEMU不支持RTOS快照

原因:QEMU无RTOS快照功能


修改2:注释散热检查(292-297行)

# 修改前:
if [ -x /opt/bmc/script/cooling.sh ]; then
    sh /opt/bmc/script/cooling.sh &
fi

# 修改后:
#if [ -x /opt/bmc/script/cooling.sh ]; then
#    sh /opt/bmc/script/cooling.sh &
#fi

原因:QEMU无真实散热系统


修改3:插入9p挂载脚本(324行,关键)

# 插入位置:在"rm -rf /var/lib"之前(第179行)
# 插入内容:
sh /opt/bmc/insmod_9p_vfs.sh

原因

  • 确保/data在访问前已挂载
  • 避免软链接失效(ln -s /data/var/lib)

修改4:添加QEMU定制命令(末尾追加)

# 新增内容:
chmod 755 /data/home/busybox_x
/data/home/busybox_x telnetd &     # 启动telnet服务(调试)
touch /dev/uart_connect             # 创建虚拟串口标志
rm /etc/shadow
ln -s /data/trust/shadow /etc/shadow  # shadow文件软链接

步骤详解3:硬件密钥禁用

修改对象:各应用配置文件

影响组件

组件 说明
iam 身份认证管理
event_policy 事件策略
firmware_mgmt 固件管理
key_mgmt 密钥管理
hica各子系统 bmc_core, security, framework, om, hardware等

修改内容

# 修改前:
HARDWARE_ROOTKEY_ENABLE = true   # 真机:启用硬件根密钥验证
KEY_STORAGE = hardware           # 真机:密钥存储在硬件EFUSE

# 修改后:
HARDWARE_ROOTKEY_ENABLE = false  # QEMU:禁用硬件根密钥验证
KEY_STORAGE = hardware           # QEMU:实际使用mock数据

禁用原因

  • :cross_mark: QEMU无硬件EFUSE芯片
  • :cross_mark: 无法进行硬件根密钥验证
  • :white_check_mark: key_mgmt服务启动会失败

步骤详解4:Mock数据注入

数据源qemu_mockup/src/lualib/mock/data/

映射配置mockdata_mapping.json

注入流程

流程1:解析映射配置

{
    "i2c": {
        "1": {
            "Data": {
                "0x60_smc.json": "BCU/00000001020302031825/0x60_smc.json",
                "0xae_eeprom.bin": "BCU/00000001020302031825/0xae_eeprom.bin"
            }
        }
    }
}

流程2:递归创建目录层级

def parse_node(node, des_dir):
    # 处理Data节点:复制数据文件
    if 'Data' in node:
        for filename, source_file in node['Data'].items():
            cp -a {source_file} {des_dir}/{filename}
    
    # 处理Address节点:递归创建地址层级
    if 'Address' in node:
        for address, address_node in node['Address'].items():
            parse_node(address_node, {des_dir}/{address})
    
    # 处理Channel节点:递归创建通道层级
    if 'Channel' in node:
        for channel, channel_node in node['Channel'].items():
            parse_node(channel_node, {des_dir}/{channel})

流程3:最终目录结构

/mockdata/
├── i2c/                    # I2C设备模拟数据
│   ├── 1/                  # I2C总线1
│   │   ├── 0x60_smc.json   # SMC设备信息(JSON)
│   │   └── 0xae_eeprom.bin # EEPROM数据(二进制)
│   ├── 7/                  # I2C总线7
│   │   └── 0xe0/           # 地址0xe0(Mux)
│   │       └── 0/          # 通道0
│   │           └── 0x42_pca9555.json
│   └── 12/                 # Hisport总线0(编号+12)
│       ├── 0xD8_atlas300ipro.json  # PCIe卡
│       └── 0x02_lsi.json           # LSI RAID卡
├── IMU/                    # IMU传感器数据
│   ├── imu_info.json
│   └── pcie_card.json
├── pciecard/               # PCIe卡数据
│   └── 0x02_0x9700_mctp.bin
└── nvme/                   # NVMe设备数据
    ├── pcie_nvme.json
    └── 0x04_0x9500_mctp.bin

步骤详解5:服务降级处理

修改对象:systemd业务服务

影响服务alarm, energy, hardware, interface, om, ras

关键修改

修改1:运行用户降级

# 修改前:
User=secbox

# 修改后:
User=root

原因:QEMU无需安全隔离


修改2:启动命令简化

# 修改前:
ExecStart=secbox -f /opt/bmc/apps/om/secbox.cfg -c /opt/bmc/skynet/skynet config.cfg

# 修改后:
ExecStart=bash -c 'exec -a om /opt/bmc/skynet/skynet config.cfg'

原因:跳过secbox沙箱,直接启动


修改3:权限集扩展

# 修改前:
AmbientCapabilities=CAP_DAC_OVERRIDE CAP_NET_BIND_SERVICE

# 修改后:
AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_SYS_MODULE CAP_DAC_OVERRIDE CAP_SYS_CHROOT CAP_NET_BIND_SERVICE CAP_MKNOD CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_RAWIO CAP_CHOWN

原因:QEMU需要扩展权限访问虚拟硬件


步骤详解6:健康检查禁用

修改对象1:framework配置

# framework/config.cfg新增:
IGNORE_STARTUP_CHECK_RESULT=true     # 忽略启动检查
IGNORE_HEALTH_CHECK_RESULT=true      # 忽略健康检查
CONTINUOUS_OFFLINE_TIMES=999          # 离线阈值放宽

修改对象2:mc_control配置

# 修改前:
{
    "maca_enable": true,
    "timeout_mins": 2,
    "time_window_mins": 10
}

# 修改后:
{
    "maca_enable": false,             // 禁用MACA
    "timeout_mins": 99,               // 超时放宽
    "time_window_mins": 99            // 时间窗口放宽
}

禁用原因

原因 说明
QEMU性能可能受限 虚拟化开销可能导致响应慢
避免反复重启导致不稳定 性能限制下可能频繁触发重启
测试环境允许失败 不影响生产,允许服务失败

步骤详解7:初始化脚本裁剪

裁剪对象:S11/S12/S16系列脚本

裁剪原则

操作 是否执行 原因
保留脚本文件和S编号 :white_check_mark: 执行 维护启动依赖链
保留目录创建和权限设置 :white_check_mark: 执行 业务功能需要
删除硬件检查代码 :cross_mark: 不执行 无真实硬件
删除硬件寄存器读取 :cross_mark: 不执行 使用mock数据
删除硬件设备初始化 :cross_mark: 不执行 虚拟化设备

裁剪示例

# S12BiosInit.sh裁剪前后对比

修改前(真机):
#!/bin/bash

# 硬件检查(第4-12行)
BIOS_DEV="/dev/bios_spi"
if [ ! -e $BIOS_DEV ]; then
    log_error "BIOS device not exist"
    exit 1
fi
BIOS_VERSION=$(hexdump -C $BIOS_DEV | head -1)

# 目录创建(第13-50行)
mkdir -p /data/backup/bios
chown -R secbox:secbox /data/backup/bios

修改后(QEMU):
#!/bin/bash

# 硬件检查已删除(第4-12行被删除)

# 目录创建(保留)
mkdir -p /data/backup/bios
mkdir -p /data/opt/bmc/conf/bios
chown -R secbox:secbox /data/backup/bios

3.2 打包产物详解

产物1:qemu.cpio.gz(根文件系统镜像)

内容结构

/
├── bin/                      # 系统命令
├── sbin/
│   ├── init → systemd        # PID=1进程
│   └── getty → busybox       # 串口登录
├── etc/
│   ├── rc.local → rc.sysinit # 初始化入口
│   ├── rc.d/
│   │   ├── rc.sysinit        # 主初始化脚本(修改版)
│   │   └── rc.start/         # 业务初始化脚本(裁剪版)
│   │       ├── S11EventInit.sh
│   │       ├── S12BiosInit.sh
│   │       └── S16FileTransferInit.sh
│   └── systemd/system/       # BMC业务服务(降级版)
│       ├── alarm.service
│       ├── om.service
│       └── interface.service
├── lib/modules/
│   ├── qemu/                 # Virtio驱动
│   │   ├── virtio.ko
│   │   ├── 9pnet.ko
│   │   └── 9p.ko
│   └─ ko/                    # 专用驱动
│       ├── bmc_hisport_drv.ko
│       └── mctp_drv.ko
├── opt/bmc/
│   ├── apps/                 # BMC应用(降级版)
│   │   ├── hica/
│   │   └── iam/
│   ├── insmod_9p_vfs.sh      # 9p挂载脚本(关键)
│   └─ conf/
│       └── mc_control.json   # MACA配置(禁用版)
└── mockdata/                 # Mock数据(注入版)
    ├── i2c/
    ├── IMU/
    └── pciecard/

产物2:zImage_openUBMC(内核镜像)

来源:从uImage提取(跳过64字节uImage头)

提取命令

dd if=uImage of=zImage_openUBMC bs=1 skip=64

用途:QEMU启动时加载的内核镜像


产物3:hi1711_9p8c.dtb(设备树文件)

来源qemu_mockup/src/lualib/mock/data/dtb/

用途:QEMU启动时加载的设备树,描述虚拟硬件拓扑


产物4:board_qemu_default.data.gz(发布包)

组成:打包上述3个产物

打包命令

tar -czf board_qemu_default.data.gz \
    qemu.cpio.gz \
    zImage_openUBMC \
    hi1711_9p8c.dtb

3.3 关键文件来源详解

文件来源1:qemu_mockup conan包

仓库位置/root/workspace/qemu_mockup

关键内容

qemu_mockup/src/lualib/mock/
├── script/
│   ├── insmod_9p_vfs.sh      # 9p挂载脚本(核心)
│   └── insmod_drv.sh         # 驱动加载脚本
├── kernel/
│   ├── virtio.ko             # Virtio驱动
│   ├── 9pnet.ko              # 9p网络协议
│   └── sys_info.ko           # 系统信息虚拟化
├── data/
│   ├── mockdata/             # Mock数据
│   │   ├── i2c/
│   │   ├── IMU/
│   │   └── pciecard/
│   ├── dtb/
│   │   └── hi1711_9p8c.dtb   # 设备树文件
│   └ lua/                    # Lua脚本
│       ├── gpio.lua
│       └── jtag.lua
└── drivers/                  # 虚拟化驱动

文件来源2:真机rootfs

来源路径rtos_with_driver/rootfs

关键内容

rootfs/
├── bin/                      # 系统命令
├── sbin/init → systemd       # Init进程
├── etc/
│   ├── rc.d/rc.sysinit       # 初始化脚本(原始版)
│   ├── systemd/system/       # BMC服务(原始版)
│   └── rc.d/rc.start/        # 初始化脚本(原始版)
├── lib/modules/ko/           # 物理驱动(原始版)
├── opt/bmc/apps/             # BMC应用(原始版)
└─ boot/uImage                # 内核镜像(原始版)

文件来源映射关系

文件类型 源路径 目标路径 说明
virtio驱动 qemu_mockup/kernel/*.ko lib/modules/qemu/*.ko 虚拟化驱动
9p脚本 qemu_mockup/script/insmod_9p_vfs.sh opt/bmc/insmod_9p_vfs.sh 9p挂载脚本
Mock数据 qemu_mockup/data/mockdata/* mockdata/* 模拟硬件数据
设备树 qemu_mockup/data/dtb/*.dtb dtb文件 虚拟硬件拓扑
Lua脚本 qemu_mockup/data/lua/*.lua opt/bmc/apps/hwproxy/lualib/*.lua 硬件代理脚本
真机rootfs rtos_with_driver/rootfs/* qemu_rootfs/*(修改版) 基础系统文件

四、打包关键约束与依赖关系

4.1 打包依赖关系

依赖配置build/product/BMC/openUBMC/manifest.yml

qemu:
  dependencies:
    - conan: qemu_drivers      # QEMU驱动包
    - conan: qemu_mockup       # qemu_mockup包(核心依赖)
    - conan: fructrl
      options:
        qemu: true             # fructrl启用QEMU选项
    - conan: general_hardware
      options:
        qemu: true             # general_hardware启用QEMU选项

依赖说明

依赖包 说明
qemu_mockup 提供virtio驱动、Mock数据、设备树、启动脚本
qemu_drivers 提供QEMU专用驱动
组件qemu选项 各组件启用QEMU适配选项

4.2 打包关键约束

约束1:9p挂载时机约束

约束内容insmod_9p_vfs.sh必须在第179行执行(在rm -rf /var/lib之前)

约束原因

# 错误顺序:
mkdir -p /data/var/lib          # 创建物理/data目录
ln -s /data/var/lib /var/lib    # 软链接到物理/data
sh insmod_9p_vfs.sh             # 9p挂载覆盖/data(软链接失效)

# 正确顺序:
mkdir -p /data/var/lib          # 创建目录
sh insmod_9p_vfs.sh             # 9p挂载(覆盖/data)
rm -rf /var/lib                 # 清理/var/lib
ln -s /data/var/lib /var/lib    # 软链接到9p挂载的/data(正确)

约束2:服务启动延迟约束

约束内容:所有systemd服务必须有ExecStartPre延迟(uptime > 100秒)

约束原因

# 错误场景:
ExecStartPre=sleep 5            # 仅延迟5秒
uptime=30秒                     # rc.sysinit未完成
→ 服务启动 → /data未挂载 → 服务崩溃

# 正确场景:
ExecStartPre="uptime=...; if [ $uptime -lt 100 ]; then sleep 20"
uptime=100秒                    # rc.sysinit已完成
→ 服务启动 → /data已挂载 → 服务正常运行

约束3:脚本裁剪保留约束

约束内容:S11/S12/S16脚本必须保留文件和编号,删除硬件检查

约束原因

# 错误场景:
删除S11EventInit.sh             # 完全删除脚本
→ S12BiosInit.sh依赖S11数据 → 初始化失败

# 正确场景:
保留S11EventInit.sh             # 保留脚本文件
删除硬件检查代码                # 删除硬件相关代码
→ S12BiosInit.sh仍按顺序执行 → 初始化成功

4.3 打包流程关键时序

源rootfs复制(第1步)
    ↓ 立即执行
QEMU定制化处理(第3步)
    ├─ 虚拟化驱动注入(即时)
    ├─ 启动脚本修改(sed修改)
    ├─ Mock数据注入(文件复制)
    └─ 服务降级处理(sed修改)
    ↓ 定制化完成
清理临时文件(第4步)
    ↓ 清理完成
编译脚本(第5步)
    ↓ 编译完成
CPIO打包(第6步)
    ↓ 打包完成
压缩和组装(第7步)
    ↓ 最终产物生成

五、总结要点

5.1 打包核心要点

要点 说明
基础来源 真机rootfs + qemu_mockup包
核心定制 虚拟化驱动 + 9p挂载 + Mock数据
关键修改 启动脚本位置 + 服务降级 + 脚本裁剪
最终产物 cpio.gz + zImage + dtb

5.2 真机差异核心要点

要点 说明
硬件访问 物理寄存器 vs mock文件
驱动类型 物理驱动 vs virtio虚拟化
数据挂载 物理分区 vs 9p虚拟文件系统
服务安全 secbox沙箱 vs root无沙箱
健康检查 MACA严格监控 vs 全部禁用
启动流程 完整硬件初始化 vs 裁剪版初始化

5.3 打包机制核心要点

要点 说明
定制化流程 7步定制化处理(虚拟化驱动→脚本修改→Mock注入→服务降级→健康禁用→脚本裁剪)
关键约束 9p挂载位置(第179行)、服务延迟(uptime>100)、脚本保留(维护依赖)
依赖关系 qemu_mockup包提供关键文件、真机rootfs提供基础系统
最终产物 三文件打包(cpio.gz+zImage+dtb)

附录:相关文件路径

A.1 核心脚本路径

文件 路径 说明
打包脚本 build/works/packet/work_build_qemu_rootfs.py 主打包逻辑
Mock映射配置 build/works/packet/qemu_shells/mockdata_mapping.json Mock数据映射关系
启动脚本 build/works/packet/qemu_shells/config.json QEMU配置
Schema配置 build/works/packet/qemu_shells/schema.json Schema定义

A.2 数据文件路径

文件类型 源路径 说明
Mock数据源 qemu_mockup/src/lualib/mock/data/mockdata/ Mock数据仓库
Virtio驱动源 qemu_mockup/src/lualib/mock/kernel/ Virtio驱动仓库
启动脚本源 qemu_mockup/src/lualib/mock/script/ 启动脚本仓库
设备树源 qemu_mockup/src/lualib/mock/data/dtb/ 设备树文件

A.3 打包产物路径

产物 路径 说明
CPIO镜像 output/packet/inner/qemu.cpio.gz 根文件系统镜像
内核镜像 output/packet/inner/zImage_openUBMC 内核镜像
设备树 output/packet/inner/hi1711_9p8c.dtb 设备树文件
发布包 output/packet/board_qemu_default.data.gz 最终发布包

文档结束


维护说明

  • 本文档描述了QEMU打包的完整流程和机制
  • 如有修改打包逻辑,请同步更新此文档
  • 相关问题请联系OpenUBMC维护团队
1 个赞