From 93ae75361f12fb621c425dd2509f321b6b26c4b6 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 20 May 2026 16:27:41 +0800 Subject: [PATCH] env: ubi: add support to create environment volume if it does not exist When U-Boot is booting from a fresh device, the environment volume may not exist in the factory UBI image. This is a common case where factory UBI image contains only volumes with valid data. With the current design, even if the volume is created manually, the environment will still be unusable (e.g., saveenv) before a reboot. This patch adds support to automatically create missing volumes before loading environment. This will make environment available at first boot. There are two options: CONFIG_ENV_UBI_VOLUME_CREATE: whether to enable volume creation CONFIG_ENV_UBI_VOLUME_STATIC: create static volume (default is dynamic) Reviewed-by: Simon Glass Signed-off-by: Weijie Gao --- env/Kconfig | 20 +++++++++++++++++ env/ubi.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/env/Kconfig b/env/Kconfig index 3c9aaeb1f16..bbd657682d7 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -739,6 +739,26 @@ config ENV_UBI_VOLUME_REDUND help Name of the redundant volume that you want to store the environment in. +config ENV_UBI_VOLUME_CREATE + bool "Create UBI volume if it does not exist" + depends on ENV_IS_IN_UBI + help + This option is useful if U-Boot will be booted from a fresh device + where the environment volume has not been created. + This is a common case where factory UBI image contains only volumes + with valid data. + By enabling this option, any missing environment volumes will be + created before loading. + If ENV_UBI_VOLUME_REDUND is also enabled, both volumes will be + created. + +config ENV_UBI_VOLUME_STATIC + bool "Create static UBI volume" + depends on ENV_UBI_VOLUME_CREATE + help + By default environment volume will be dynamic. + Enable this option to create static volume. + config ENV_UBI_VID_OFFSET int "ubi environment VID offset" depends on ENV_IS_IN_UBI diff --git a/env/ubi.c b/env/ubi.c index 46970ba754f..810faaf7744 100644 --- a/env/ubi.c +++ b/env/ubi.c @@ -103,12 +103,30 @@ static int env_ubi_save(void) } #endif /* CONFIG_ENV_REDUNDANT */ +static int env_ubi_volume_create(const char *volume) +{ + bool dynamic = !IS_ENABLED(CONFIG_ENV_UBI_VOLUME_STATIC); + struct ubi_volume *vol; + int ret; + + vol = ubi_find_volume(volume); + if (vol) + return 0; + + ret = ubi_create_vol(volume, CONFIG_ENV_SIZE, dynamic, UBI_VOL_NUM_AUTO, + false); + if (ret) + printf("Failed to create environment volume '%s'\n", volume); + + return ret; +} + #ifdef CONFIG_ENV_REDUNDANT static int env_ubi_load(void) { ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE); ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE); - int read1_fail, read2_fail; + int read1_fail, read2_fail, create1_fail = 0, create2_fail = 0; env_t *tmp_env1, *tmp_env2; /* @@ -132,17 +150,35 @@ static int env_ubi_load(void) return -EIO; } - read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, tmp_env1, 0, - CONFIG_ENV_SIZE); - if (read1_fail) - printf("\n** Unable to read env from %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); + if (IS_ENABLED(CONFIG_ENV_UBI_VOLUME_CREATE)) { + create1_fail = env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME); + create2_fail = env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME_REDUND); + if (create1_fail && create2_fail) { + env_set_default(NULL, 0); + return -ENODEV; + } + } - read2_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, - tmp_env2, 0, CONFIG_ENV_SIZE); - if (read2_fail) - printf("\n** Unable to read redundant env from %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); + if (!create1_fail) { + read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, tmp_env1, 0, + CONFIG_ENV_SIZE); + if (read1_fail) + printf("\n** Unable to read env from %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); + } else { + read1_fail = create1_fail; + } + + if (!create2_fail) { + read2_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, + tmp_env2, 0, CONFIG_ENV_SIZE); + if (read2_fail) + printf("\n** Unable to read redundant env from %s:%s **\n", + CONFIG_ENV_UBI_PART, + CONFIG_ENV_UBI_VOLUME_REDUND); + } else { + read2_fail = create2_fail; + } return env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2, read2_fail, H_EXTERNAL); @@ -169,6 +205,13 @@ static int env_ubi_load(void) return -EIO; } + if (IS_ENABLED(CONFIG_ENV_UBI_VOLUME_CREATE)) { + if (env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME)) { + env_set_default(NULL, 0); + return -ENODEV; + } + } + if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to read env from %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);