Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion board/xmedia/xm72050200/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,13 @@ void clear_update_flag(int update_flag)

int misc_init_r(void)
{
/* Before openipc_helper(): a FIT on the split NOR layout carries
* hashes, and firmware_scan() drops this for it. */
env_set("verify", "n");
openipc_helper();
#ifdef CONFIG_RANDOM_ETHADDR
random_init_r();
#endif
env_set("verify", "n");

#ifdef CFG_MMU_HANDLEOK
dcache_stop();
Expand Down
4 changes: 3 additions & 1 deletion board/xmedia/xm72050300/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,13 @@ void clear_update_flag(int update_flag)

int misc_init_r(void)
{
/* Before openipc_helper(): a FIT on the split NOR layout carries
* hashes, and firmware_scan() drops this for it. */
env_set("verify", "n");
openipc_helper();
#ifdef CONFIG_RANDOM_ETHADDR
random_init_r();
#endif
env_set("verify", "n");

#ifdef CFG_MMU_HANDLEOK
dcache_stop();
Expand Down
10 changes: 10 additions & 0 deletions common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1060,3 +1060,13 @@ config PRODUCT_SOCMODEL
Optional board/binning model exposed as 'socmodel=' in the default
environment (e.g. hi3516cv610 DDR binnings).

config OPENIPC_NOR_FIT_SPLIT
bool "OpenIPC: boot the split NOR layout (FIT + squashfs in one partition)"
depends on FIT
help
A FIT found at the NOR kernel offset is taken for the split layout:
the FIT and the squashfs back to back in one "firmware" partition,
which a kernel with mtdsplit divides at boot. Linux is passed that
one partition. Only for boards whose kernel carries mtdsplit; a FIT
kernel without it (hi3516cv610) keeps its fixed slots.

113 changes: 111 additions & 2 deletions common/openipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#define SQSH_MAGIC_BE 0x73717368
#define SQSH_MAGIC_LE 0x68737173

static int check_squashfs(void *buf) {
static int __maybe_unused check_squashfs(void *buf) {
uint32_t magic = get_unaligned_be32(buf);
if (magic == SQSH_MAGIC_BE || magic == SQSH_MAGIC_LE)
return 1;
Expand Down Expand Up @@ -76,7 +76,7 @@ static int ubi_marker_present(void) {
}
#endif

static int check_kernel(void *buf) {
static int __maybe_unused check_kernel(void *buf) {
struct image_header *hdr = (struct image_header *)buf;
if (image_check_magic(hdr)) {
return 1;
Expand Down Expand Up @@ -495,6 +495,43 @@ int firmware_recovery(void) {
}
#endif

#if !defined(CONFIG_FMC_SPI_NAND) && defined(CONFIG_OPENIPC_NOR_FIT_SPLIT)
/*
* The kernel learns the NOR layout from bootargs. A saved environment carries
* its own bootargs with "root=/dev/mtdblock3" spelled out, which is right for
* fixed slots but names the FIT under the split layout, where the partitions
* are u-boot, env, firmware, then the kernel's split of firmware into kernel
* (3), rootfs (4) and rootfs_data (5). Rewrite that one token for the layout
* found, in RAM only, and add openipc_nor_fit=1: the word sysupgrade reads from
* /proc/cmdline to know this bootloader boots the split layout.
*/
static void nor_bootargs_adjust(int fit)
{
const char *cur = env_get("bootargs");
const char *want = fit ? "root=/dev/mtdblock4" : "root=/dev/mtdblock3";
const char *other = fit ? "root=/dev/mtdblock3" : "root=/dev/mtdblock4";
char buf[1024];
const char *p;

if (!cur || strlen(cur) + 32 >= sizeof(buf))
return;
p = strstr(cur, other);
if (p) {
size_t head = p - cur;

memcpy(buf, cur, head);
strcpy(buf + head, want);
strcat(buf, p + strlen(other));
} else {
strcpy(buf, cur);
}
if (!strstr(buf, "openipc_nor_fit=1"))
strcat(buf, " openipc_nor_fit=1");
if (strcmp(buf, cur))
env_set("bootargs", buf);
}
#endif

int firmware_scan(void) {
#ifdef CONFIG_FMC_SPI_NAND
u8 buf[64];
Expand Down Expand Up @@ -568,7 +605,79 @@ int firmware_scan(void) {
rootfs_size = 0xa00000;
#endif

/*
* A FIT at the kernel offset is the split layout: FIT and squashfs back to
* back in one "firmware" partition that the kernel divides at boot
* (mtdsplit). Linux gets that one partition, the read is the FIT's own
* size, and nothing is clamped to a slot.
*/
#ifdef CONFIG_OPENIPC_NOR_FIT_SPLIT
if (kernel_off && rootfs_off) {
u8 hdr[64];

if (!spi_flash_read(flash, kernel_off, sizeof(hdr), hdr) &&
fdt_magic(hdr) == FDT_MAGIC && fdt_check_header(hdr) == 0) {
char str[32], mtds[128], mtdparts[160];
const char *mtdids = env_get("mtdids");
ulong fit_size = ALIGN(fdt_totalsize(hdr), 0x10000);
ulong kern_slot, root_slot;

/*
* kernsize is what loadkernel reads, and also what uk erases; rootaddr
* and rootsize are where ur writes. Those commands install a uImage
* and a squashfs, i.e. fixed slots, so they get the fixed slots: the
* kernel slot whole (the split squashfs starts inside it, and a head
* left there would be found by the next scan before the new rootfs),
* the rootfs slot after it. The FIT is read whole either way.
*/
if (fit_size <= 0x200000) {
kern_slot = 0x200000;
root_slot = 0x500000;
} else if (fit_size <= 0x300000 && flash->size > 0x800000) {
kern_slot = 0x300000;
root_slot = 0xa00000;
} else {
/* No fixed-slot layout holds this kernel. */
kern_slot = fit_size;
root_slot = flash->size - kernel_off - fit_size;
}
spi_flash_free(flash);
sprintf(str, "0x%08lx", kernel_off);
env_set("kernaddr", str);
sprintf(str, "0x%lx", kern_slot);
env_set("kernsize", str);
sprintf(str, "0x%08lx", kernel_off + kern_slot);
env_set("rootaddr", str);
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
sprintf(str, "0x%lx", root_slot);
env_set("rootsize", str);
#ifdef SFC
if (!mtdids || !*mtdids)
mtdids = SFC;
#endif
sprintf(mtds, "%dk(u-boot),%dk(env),-(firmware)",
CONFIG_ENV_OFFSET / 1024, CONFIG_ENV_SIZE / 1024);
env_set("mtds", mtds);
sprintf(mtdparts, "%s:%s", mtdids ? mtdids : "", mtds);
env_set("mtdparts", mtdparts);
/* The DTB stays in the kernel's lowmem (mem=${osmem}); a saved
* environment from a uImage-only bootloader has no bootm_size. */
if (!env_get("bootm_size"))
env_set("bootm_size", "0x2000000");
/* The FIT carries crc32 and sha1 for the kernel and the DTB; a
* verify=n saved by an older bootloader must not skip them. RAM
* only, like the rest of the scan. */
env_set("verify", NULL);
nor_bootargs_adjust(1);
env_set("bootfail", NULL);
return 0;
}
}
#endif

spi_flash_free(flash);
#ifdef CONFIG_OPENIPC_NOR_FIT_SPLIT
nor_bootargs_adjust(0);
#endif

if (kernel_off) {
char str[32];
Expand Down
4 changes: 4 additions & 0 deletions openipc/xm72050200_config
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ CONFIG_SYS_LOAD_ADDR=0x42000000
CONFIG_MMC=y
CONFIG_CMD_MMC=y
CONFIG_MMC_SDHCI=y
# Split NOR layout: a hashed FIT kernel (board nor-fit.its in OpenIPC/firmware)
CONFIG_FIT=y
CONFIG_SHA1=y
CONFIG_OPENIPC_NOR_FIT_SPLIT=y
Comment on lines +6 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Standard builds omit split firmware support 🐞 Bug ≡ Correctness

The new options are added to xm72050200_config and xm72050300_config, but build_xmedia()
selects ${soc}_config for the advertised GK7205V200 and GK7205V300 targets. For those targets it
looks for gk7205v200_config and gk7205v300_config, neither of which exists, so this build path
never consumes the new flags or produces the intended split-capable images.
Agent Prompt
## Issue description
The GK7205 build dispatch does not select the configuration fragments that enable split NOR firmware support.
## Fix Focus Areas
- openipc/xm72050200_config[5-8]
- openipc/xm72050300_config[11-14]
- build.sh[245-255]
## Recommended Fix
Map the GK7205V200 and GK7205V300 build targets to their corresponding xm configuration fragments, and verify that both generated NOR configurations retain the new options.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

4 changes: 4 additions & 0 deletions openipc/xm72050300_config
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ CONFIG_SYS_LOAD_ADDR=0x42000000
CONFIG_MMC=y
CONFIG_CMD_MMC=y
CONFIG_MMC_SDHCI=y
# Split NOR layout: a hashed FIT kernel (board nor-fit.its in OpenIPC/firmware)
CONFIG_FIT=y
CONFIG_SHA1=y
CONFIG_OPENIPC_NOR_FIT_SPLIT=y
Loading