From: Rasmus Villemoes Date: Thu, 12 Sep 2024 13:41:40 +0000 (+0200) Subject: env: mmc: do not return an offset before the start of the partition X-Git-Url: http://git.dujemihanovic.xyz/img/static/git-favicon.png?a=commitdiff_plain;h=9402e3bb8c5dea255af7ad2854aed8f09a08bcf8;p=u-boot.git env: mmc: do not return an offset before the start of the partition I have an GPT layout containing two partitions with the type GUID for U-Boot environment: partition U-Boot-env-1 { offset = 0x1fc000 size = 0x2000 partition-type-uuid = "3de21764-95bd-54bd-a5c3-4abe786f38a8" } partition U-Boot-env-2 { offset = 0x1fe000 size = 0x2000 partition-type-uuid = "3de21764-95bd-54bd-a5c3-4abe786f38a8" } and have set CONFIG_ENV_OFFSET=0x1fc000, CONFIG_ENV_OFFSET_REDUND=0x1fe000 and CCONFIG_ENV_SIZE=0x2000. This usually works just fine, but on an stm32mp, I was seeing weird behaviour. It turns out that can be tracked down to that board setting CONFIG_PARTITION_TYPE_GUID, so the logic in mmc.c ends up only finding the first of the two partitions, but then in the copy=1 case ends up computing 0x1fa000 as the *val returned (that is, the end of the partition minus two times the environment size). That is of course outside the found partition and leads to random corruption of the partition preceding U-Boot-env-1. Add a sanity check that the partition found is at least as large as needed for the "one or two copies from the end of the partition" logic to at least produce something within that partition. That will also catch a bug where the partition is too small for even one copy of the environment. Signed-off-by: Rasmus Villemoes --- diff --git a/env/mmc.c b/env/mmc.c index db2d35e9bd..5d09140655 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -91,7 +91,8 @@ static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val) { struct disk_partition info; struct blk_desc *desc; - int len, ret; + lbaint_t len; + int ret; char dev_str[4]; snprintf(dev_str, sizeof(dev_str), "%d", mmc_get_env_dev()); @@ -110,6 +111,13 @@ static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val) /* round up to info.blksz */ len = DIV_ROUND_UP(CONFIG_ENV_SIZE, info.blksz); + if ((1 + copy) * len > info.size) { + printf("Partition '%s' [0x"LBAF"; 0x"LBAF"] too small for %senvironment, required size 0x"LBAF" blocks\n", + (const char*)info.name, info.start, info.size, + copy ? "two copies of " : "", (1 + copy)*len); + return -ENOSPC; + } + /* use the top of the partion for the environment */ *val = (info.start + info.size - (1 + copy) * len) * info.blksz;