OpenBMC 修改 flash 大小
romulus 机器默认的 32M flash 实在是太小,几乎就没有多少剩余空间,这对于在 Qemu 环境下进行 BMC 程序的开发调试很不方便,因此有必要把这个大小稍微调整一下。

如果没有特殊说明,下面的内容以 OpenBMC v2.14+ 版本为例进行介绍。

flash size

ERROR: obmc-phosphor-image-1.0-r0 do_generate_static: Image '/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/romulus-openbmc-linux-gnueabi/obmc-phosphor-image/1.0/deploy-obmc-phosphor-image-image-complete/obmc-phosphor-image-romulus.squashfs-xz' is 811008 bytes too large!
❯ vi build/romulus/conf/local.conf
FLASH_SIZE = "65536"

单位为 KB,该参数 romulus 机器为 32K,evb-ast2600 机器为 64K

注意 qemu -M 指定的机器类型会有要求的 flash 大小,因此即使这里修改了也只是构建能通过,在 qemu 运行阶段仍然会报错:

❯ qemu-system-arm -m 256 -M romulus-bmc -nographic -drive file=obmc-phosphor-image-romulus-20231217061705.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostname=qemu
qemu-system-arm: device requires 33554432 bytes, block backend provides 67108864 bytes

raspberrypi4-64: u-boot.bin is too large
https://github.com/openbmc/openbmc/issues/3812

qemu flash

// hw/arm/aspeed.c
aspeed_machine_class_init
aspeed_machine_romulus_class_init

aspeed_machine_init
  aspeed_board_init_flashes
    aspeed_board_init_flashes(&bmc->soc.fmc,
                              bmc->fmc_model ? bmc->fmc_model : amc->fmc_model,
                              amc->num_cs, 0);
    aspeed_board_init_flashes(&bmc->soc.spi[0],
                              bmc->spi_model ? bmc->spi_model : amc->spi_model,
                              1, amc->num_cs);

static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
{
    MachineClass *mc = MACHINE_CLASS(oc);
    AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);

    mc->desc       = "OpenPOWER Romulus BMC (ARM1176)";
    amc->soc_name  = "ast2500-a1";
    amc->hw_strap1 = ROMULUS_BMC_HW_STRAP1;
    amc->fmc_model = "n25q256a";
    amc->spi_model = "mx66l1g45g";
    amc->num_cs    = 2;
    amc->i2c_init  = romulus_bmc_i2c_init;
    mc->default_ram_size       = 512 * MiB;
    mc->default_cpus = mc->min_cpus = mc->max_cpus =
        aspeed_soc_num_cpus(amc->soc_name);
};

初始化 bmc->soc.fmc 时报 flash 大小不匹配的错误,因为 n25q256a 的大小只有 32MB (64 « 10 * 512):

// hw/block/m25p80.c

{ INFO("mx66u51235f", 0xc2253a,      0,  64 << 10, 1024, ER_4K | ER_32K) },
{ INFO("n25q256a",    0x20ba19,      0,  64 << 10, 512,
       ER_4K | HAS_SR_BP3_BIT6 | HAS_SR_TB),
  .sfdp_read = m25p80_sfdp_n25q256a },

虽然可以通过 fmc-model 选项进行规避,但是内核加载时报错:

❯ qemu-system-arm -m 256 -M romulus-bmc,fmc-model=mx66u51235f -nographic -drive file=obmc-phosphor-image-romulus-20231220014609.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostname=qemu

U-Boot 2019.04 (Jul 24 2023 - 12:31:15 +0000)

SOC : AST2500-A1 
RST : Power On 
2nd Boot : Enable
LPC Mode : SIO:Enable : SuperIO-2e
Eth : MAC0: RMII/NCSI, , MAC1: RMII/NCSI, 
Model: Romulus BMC
DRAM:  192 MiB (capacity:256 MiB, VGA:64 MiB, ECC:off)
MMC:   
Loading Environment from SPI Flash... SF: Detected mx66u51235f with page size 256 Bytes, erase size 4 KiB, total 64 MiB

## Loading kernel from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus.dtb' configuration

## Loading ramdisk from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus.dtb' configuration

## Loading fdt from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus.dtb' configuration

Starting kernel ...

[    0.773751] Run /init as init process
rofs = mtd4 squashfs   rwfs = mtd5 jffs2
mount: mounting /dev/mtdblock4 on run/initramfs/ro failed: Invalid argument
[    1.295717] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000000: 0xe10c instead
[    1.295992] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000004: 0x6d5b instead

conf-aspeed-bmc-opp-romulus.dtb 的定义见 linux 内核代码:

// arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
// arch/arm/boot/dts/openbmc-flash-layout.dtsi

Aspeed family boards
https://github.com/qemu/qemu/blob/v8.2.0/docs/system/arm/aspeed.rst

custom dtb

devtool error

❯ devtool modify linux-aspeed

Traceback (most recent call last):
  File "/home/runsisi/working/bmc/openbmc/scripts/devtool", line 349, in <module>
    ret = main()
          ^^^^^^
  File "/home/runsisi/working/bmc/openbmc/scripts/devtool", line 336, in main
    ret = args.func(args, config, basepath, workspace)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runsisi/working/bmc/openbmc/poky/scripts/lib/devtool/standard.py", line 922, in modify
    if not initial_revs["."]:
           ~~~~~~~~~~~~^^^^^
KeyError: '.'

这是 devtool 的代码 bug,简单修改如下:

diff --git a/poky/scripts/lib/devtool/standard.py b/poky/scripts/lib/devtool/standard.py
index ad6e346279..4188606809 100644
--- a/poky/scripts/lib/devtool/standard.py
+++ b/poky/scripts/lib/devtool/standard.py
@@ -919,7 +919,7 @@ def modify(args, config, basepath, workspace):
                     if line.startswith('*'):
                         (stdout, _) = bb.process.run('git rev-parse devtool-base', cwd=srctree)
                         initial_revs["."] = stdout.rstrip()
-                if not initial_revs["."]:
+                if not "." in initial_revs:
                     # Otherwise, just grab the head revision
                     (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree)
                     initial_revs["."] = stdout.rstrip()
@@ -992,7 +992,7 @@ def modify(args, config, basepath, workspace):
             if initial_revs:
                 for name, rev in initial_revs.items():
                         f.write('\n# initial_rev %s: %s\n' % (name, rev))
-                        for commit in commits[name]:
+                        for commit in commits.get(name, []):
                             f.write('# commit %s: %s\n' % (name, commit))
             if branch_patches:
                 for branch in branch_patches:

linux-aspeed dtb

❯ devtool modify linux-aspeed

增加 dtb 定义(注意修改的是 linux 内核代码):

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index fb9cc95f1b60..3919d6ea81d5 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
        aspeed-bmc-opp-nicole.dtb \
        aspeed-bmc-opp-palmetto.dtb \
        aspeed-bmc-opp-romulus.dtb \
+       aspeed-bmc-opp-romulus-64.dtb \
        aspeed-bmc-opp-swift.dtb \
        aspeed-bmc-opp-tacoma.dtb \
        aspeed-bmc-opp-vesnin.dtb \

--- arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts 2023-12-19 08:16:23.864332235 +0800
+++ arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus-64.dts      2023-12-24 12:39:55.905046503 +0800
@@ -113,7 +113,7 @@
                m25p,fast-read;
                label = "bmc";
                spi-max-frequency = <50000000>;
-#include "openbmc-flash-layout.dtsi"
+#include "openbmc-flash-layout-64.dtsi"
        };
 };

修改 flash 定义:

❯ vi build/romulus/conf/local.conf
FLASH_SIZE = "65536"

❯ vi build/romulus/workspace/appends/linux-aspeed_git.bbappend
KERNEL_DEVICETREE = "aspeed/aspeed-bmc-opp-romulus-64.dtb"

image

构建 image:

❯ bitbake obmc-phosphor-image

❯ ls -lh build/romulus/tmp/deploy/images/romulus/obmc-phosphor-image-romulus-20231224045650.static.mtd
-rw-r--r-- 2 runsisi runsisi 64M Dec 24 13:04 build/romulus/tmp/deploy/images/romulus/obmc-phosphor-image-romulus-20231224045650.static.mtd

整个 bmc 的 image 由 obmc-phosphor-image recipe 构建,各部分的空间占用信息通过 FLASH_UBOOT_OFFSET, FLASH_KERNEL_OFFSET, FLASH_ROFS_OFFSET, FLASH_RWFS_OFFSET 以及 FLASH_SIZE 进行配置,更多实现细节可以通过 log.do_generate_static 和 run.do_generate_static 进行分析得到。

需要注意 image 的定义需要与 kernel dtb 中定义的 flash 的 layout 保持一致。

running

❯ qemu-system-arm -m 256 -M romulus-bmc,fmc-model=mx66u51235f -nographic -drive file=obmc-phosphor-image-romulus-20231224045650.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostname=qemu

U-Boot 2019.04 (Jul 24 2023 - 12:31:15 +0000)

SOC : AST2500-A1 
RST : Power On 
2nd Boot : Enable
LPC Mode : SIO:Enable : SuperIO-2e
Eth : MAC0: RMII/NCSI, , MAC1: RMII/NCSI, 
Model: Romulus BMC
DRAM:  192 MiB (capacity:256 MiB, VGA:64 MiB, ECC:off)
MMC:   
Loading Environment from SPI Flash... SF: Detected mx66u51235f with page size 256 Bytes, erase size 4 KiB, total 64 MiB

## Loading kernel from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus-64.dtb' configuration

## Loading ramdisk from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus-64.dtb' configuration

## Loading fdt from FIT Image at 20100000 ...
   Using 'conf-aspeed-bmc-opp-romulus-64.dtb' configuration

64M flash 文件系统利用率:

root@romulus:~# df -h
Filesystem                Size      Used Available Use% Mounted on
dev                      57.1M         0     57.1M   0% /dev
tmpfs                    90.1M     11.6M     78.5M  13% /run
/dev/mtdblock4           31.5M     31.5M         0 100% /run/initramfs/ro
/dev/mtdblock5           22.0M    700.0K     21.3M   3% /run/initramfs/rw
cow                      22.0M    700.0K     21.3M   3% /
tmpfs                    90.1M      4.0K     90.1M   0% /dev/shm
tmpfs                    90.1M         0     90.1M   0% /tmp
tmpfs                    90.1M         0     90.1M   0% /var/volatile

下面是 32M flash 的文件系统利用率:

root@romulus:~# df -h
Filesystem                Size      Used Available Use% Mounted on
dev                      57.1M         0     57.1M   0% /dev
tmpfs                    90.1M     11.6M     78.5M  13% /run
/dev/mtdblock4           22.1M     22.1M         0 100% /run/initramfs/ro
/dev/mtdblock5            4.0M    824.0K      3.2M  20% /run/initramfs/rw
cow                       4.0M    824.0K      3.2M  20% /
tmpfs                    90.1M      8.0K     90.1M   0% /dev/shm
tmpfs                    90.1M         0     90.1M   0% /tmp
tmpfs                    90.1M         0     90.1M   0% /var/volatile

In a typical embedded boot process, at power-on, the device runs “built-in” code to determine which type of “acceptable” flash are connected (if there is a choice at all) and “picks the right one” and starts executing code from a pre-defined location. In some cases this is simple code that then starts a “fancy” boot loader like U-Boot, or it might be U-Boot itself, or the like. U-Boot’s “job” is to be able to load the kernel to memory, set up any information it might need to run, then transfer control to the kernel. For simple devices, it might not have to do anything more than load the kernel and jump to the kernel’s entry point. On many devices, additional information is passed, such as the kernel command line, and/or information about how the board is “wired up” and how the flash is partitioned. Since the OEM typically builds a device-specific version of U-Boot, the default parameters are often compiled into the U-Boot binary.

There are cases where the defaults aren’t “right” for the task at hand. Many units are run tested and calibrated using different firmware than that on flash. A special U-Boot command or variable can be used to, for example, load a kernel and firmware over TFTP directly to RAM and ignore the on-board flash. Another time that changing the U-Boot environment may happen is with dual-firmware units. For example, a U-Boot variable called boot_part is used in some units to select between firmware A and firmware B to be able to save that decision over a power-off period or reboot.

U-boot CRC warning at boot
https://forum.openwrt.org/t/solved-u-boot-crc-warning-at-boot/35576

OpenBMC v2.8

OpenBMC v2.8 的修改类似,但与 v2.14+ 稍有差异,简单记录如下。

❯ devtool modify linux-aspeed

增加 dtb 定义(注意这是内核代码):

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d6dfdf73e66b..167249f9d482 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1299,6 +1299,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
        aspeed-bmc-opp-mihawk.dtb \
        aspeed-bmc-opp-palmetto.dtb \
        aspeed-bmc-opp-romulus.dtb \
+       aspeed-bmc-opp-romulus-128.dtb \
        aspeed-bmc-opp-swift.dtb \
        aspeed-bmc-opp-tacoma.dtb \
        aspeed-bmc-opp-vesnin.dtb \

--- arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts        2023-12-22 15:56:43.780211840 +0000
+++ arch/arm/boot/dts/aspeed-bmc-opp-romulus-128.dts    2023-12-24 06:26:19.841785693 +0000
@@ -113,7 +113,7 @@
                m25p,fast-read;
                label = "bmc";
                spi-max-frequency = <50000000>;
-#include "openbmc-flash-layout.dtsi"
+#include "openbmc-flash-layout-128.dtsi"
        };
 };

修改 flash 定义:

❯ vi build/romulus/conf/local.conf
FLASH_SIZE = "131072"

❯ vi build/romulus/workspace/appends/linux-aspeed_git.bbappend
KERNEL_DEVICETREE = "aspeed-bmc-opp-romulus-128.dtb"

构建 image:

❯ bitbake obmc-phosphor-image

❯ ls -lh build/romulus/tmp/deploy/images/romulus/obmc-phosphor-image-romulus-20231225075638.static.mtd
-rw-rw-r-- 2 runsisi runsisi 128M Dec 25 07:57 build/romulus/tmp/deploy/images/romulus/obmc-phosphor-image-romulus-20231225075638.static.mtd

需要注意的是,不是所有 qemu 支持的 flash 型号都可以随意替换,比如 uboot 2016.07 就不支持 mx66u1g45g flash 型号:

❯ qemu-system-arm -m 256 -M romulus-bmc,fmc-model=mx66u1g45g -nographic -drive file=obmc-phosphor-image-romulus.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostname=qemu

U-Boot 2016.07 (Dec 25 2023 - 02:51:59 +0000)

       Watchdog enabled
DRAM:  240 MiB
Flash: Unsupported SPI Flash!! 0x003b25c2
Can't support this SPI Flash!!

见如下代码:

// u-boot-aspeed/arch/arm/mach-aspeed/flash.c

flash_get_size
    switch (info->flash_id) {
    default:
        printf("Unsupported SPI Flash!! 0x%08lx\n", info->flash_id);
    }

将 flash 型号切换成 mx66l1g45g(128M)之后出现新的问题:

❯ qemu-system-arm -m 256 -M romulus-bmc,fmc-model=mx66l1g45g -nographic -drive file=obmc-phosphor-image-romulus-20231225025147.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostname=qemu

U-Boot 2016.07 (Dec 25 2023 - 02:51:59 +0000)

       Watchdog enabled
DRAM:  240 MiB
Flash: 128 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   aspeednic#0
Error: aspeednic#0 address not set.

Hit any key to stop autoboot:  0 
Wrong Image Format for bootm command
ERROR: can't get kernel image!

从 20100000 地址进行 boot 即可:

ast# printenv
baudrate=115200
bootargs=console=ttyS4,115200n8 root=/dev/ram rw
bootcmd=bootm 20080000
bootdelay=2
ethact=aspeednic#0
spi_dma=yes
stderr=serial
stdin=serial
stdout=serial
verify=yes

Environment size: 204/65531 bytes

ast# imls
FIT Image at 20100000:
   FIT description: U-Boot fitImage for Phosphor OpenBMC (Phosphor OpenBMC Project Reference Distro)/5.4.39+git999/romulus

ast# bootm 20100000
## Loading kernel from FIT Image at 20100000 ...

这是因为内核地址从 32M flash 的 80000 变到了 128M 的 100000:

// linux-aspeed/arch/arm/boot/dts/openbmc-flash-layout.dtsi

partitions {
kernel@80000 {
		reg = <0x80000 0x440000>;
		label = "kernel";
	};
};

// linux-aspeed/arch/arm/boot/dts/openbmc-flash-layout-128.dtsi

partitions {
	kernel@100000 {
		reg = <0x100000 0x900000>; // 9MB
		label = "kernel";
	};
};

可以在上电时保存环境变量:

ast# env set -f bootcmd bootm 20100000

ast# env save

ast# printenv bootcmd
bootcmd=bootm 20100000

也可以直接修改 u-boot 源码:

diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h
index a0243083bd..14ba1f2d6a 100644
--- a/include/configs/ast-common.h
+++ b/include/configs/ast-common.h
@@ -111,7 +111,7 @@
 #define CONFIG_ENV_SIZE                        0x10000 /* Total Size of Environment Sector */
 #define CONFIG_ENV_SIZE_REDUND         0x10000
 
-#define CONFIG_BOOTCOMMAND             "bootm 20080000"
+#define CONFIG_BOOTCOMMAND             "bootm 20100000"
 #define CONFIG_ENV_OVERWRITE
 
 #define ASPEED_ENV_SETTINGS \

新版本 u-boot(OpenBMC v2.14+)可以通过修改配置文件实现对 CONFIG_BOOTCOMMAND 的修改:

❯ vi workspace/appends/u-boot-aspeed-sdk_2019.04.bbappend

// 参考 meta-aspeed/recipes-bsp/u-boot/u-boot-common-aspeed-sdk_2019.04.inc 的
// 修改方式会更合理(注意会合并配置,如有冲突建议直接用 u-boot-common-aspeed-sdk_2019.04.inc 的配置方式)
SRC_URI += "file://u-boot_flash_64M.cfg"

wrong Image Format for bootm command ERROR: can’t get kernel image!
https://github.com/openbmc/openbmc/issues/3876

128M flash 文件系统利用率:

root@romulus:~# df -h
Filesystem                Size      Used Available Use% Mounted on
dev                      81.5M         0     81.5M   0% /dev
tmpfs                   114.5M     11.7M    102.8M  10% /run
/dev/mtdblock4           21.3M     21.3M         0 100% /run/initramfs/ro
/dev/mtdblock5           32.0M    956.0K     31.1M   3% /run/initramfs/rw
cow                      32.0M    956.0K     31.1M   3% /
tmpfs                   114.5M      8.0K    114.5M   0% /dev/shm
tmpfs                   114.5M         0    114.5M   0% /sys/fs/cgroup
tmpfs                   114.5M         0    114.5M   0% /tmp
tmpfs                   114.5M      8.0K    114.5M   0% /var/volatile

最后修改于 2024-01-03