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 <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
This commit is contained in:
Weijie Gao
2026-07-08 11:35:29 +02:00
committed by Heiko Schocher
parent c719d2627a
commit 93ae75361f
2 changed files with 74 additions and 11 deletions
Vendored
+20
View File
@@ -739,6 +739,26 @@ config ENV_UBI_VOLUME_REDUND
help help
Name of the redundant volume that you want to store the environment in. 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 config ENV_UBI_VID_OFFSET
int "ubi environment VID offset" int "ubi environment VID offset"
depends on ENV_IS_IN_UBI depends on ENV_IS_IN_UBI
Vendored
+54 -11
View File
@@ -103,12 +103,30 @@ static int env_ubi_save(void)
} }
#endif /* CONFIG_ENV_REDUNDANT */ #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 #ifdef CONFIG_ENV_REDUNDANT
static int env_ubi_load(void) static int env_ubi_load(void)
{ {
ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE); ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE);
ALLOC_CACHE_ALIGN_BUFFER(char, env2_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; env_t *tmp_env1, *tmp_env2;
/* /*
@@ -132,17 +150,35 @@ static int env_ubi_load(void)
return -EIO; return -EIO;
} }
read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, tmp_env1, 0, if (IS_ENABLED(CONFIG_ENV_UBI_VOLUME_CREATE)) {
CONFIG_ENV_SIZE); create1_fail = env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME);
if (read1_fail) create2_fail = env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME_REDUND);
printf("\n** Unable to read env from %s:%s **\n", if (create1_fail && create2_fail) {
CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); env_set_default(NULL, 0);
return -ENODEV;
}
}
read2_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, if (!create1_fail) {
tmp_env2, 0, CONFIG_ENV_SIZE); read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, tmp_env1, 0,
if (read2_fail) CONFIG_ENV_SIZE);
printf("\n** Unable to read redundant env from %s:%s **\n", if (read1_fail)
CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); 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, return env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
read2_fail, H_EXTERNAL); read2_fail, H_EXTERNAL);
@@ -169,6 +205,13 @@ static int env_ubi_load(void)
return -EIO; 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)) { if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, 0, CONFIG_ENV_SIZE)) {
printf("\n** Unable to read env from %s:%s **\n", printf("\n** Unable to read env from %s:%s **\n",
CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);