mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-18 02:44:37 +00:00
Merge patch series "env: mmc: fix use of two separate partitions with proper type GUID"
Rasmus Villemoes <rasmus.villemoes@prevas.dk> says: I always define a disk layout with two separate partitions for the two copies of the U-Boot environment and, being the one who introduced the type GUID for such partitions, of course also set those partitions' type GUID appropriately. This has worked just fine, but, it turns out, only because I've never had CONFIG_PARTITION_TYPE_GUID enabled on any of my boards; I've always just set the offsets of the two partitions via the config variables CONFIG_ENV_OFFSET(,_REDUND). I didn't even know that env/mmc.c had learnt to look for the env partition based on the type GUID, or that that would overrule the ENV_OFFSET config variables, until I experienced weird random corruption while doing bringup for an stm32 board, where PARTITION_TYPE_GUID is automatically set because it is select'ed by CMD_STM32PROG. These patches try to fix the code to fit my scheme, while not changing anything for existing setups that use the two-copies-one-partition scheme, other than complaining loudly if the system is misconfigured and avoiding such random corruption of neighbouring partitions.
This commit is contained in:
commit
667a671cca
1 changed files with 77 additions and 18 deletions
95
env/mmc.c
vendored
95
env/mmc.c
vendored
|
@ -53,11 +53,74 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
|
||||
static int mmc_env_partition_by_name(struct blk_desc *desc, const char *str,
|
||||
struct disk_partition *info)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 1;; i++) {
|
||||
ret = part_get_info(desc, i, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!strncmp((const char *)info->name, str, sizeof(info->name)))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for one or two partitions with the U-Boot environment GUID.
|
||||
*
|
||||
* If *copy is 0, return the first such partition.
|
||||
*
|
||||
* If *copy is 1 on entry and two partitions are found, return the
|
||||
* second partition and set *copy = 0.
|
||||
*
|
||||
* If *copy is 1 on entry and only one partition is found, return that
|
||||
* partition, leaving *copy unmodified.
|
||||
*/
|
||||
static int mmc_env_partition_by_guid(struct blk_desc *desc, struct disk_partition *info,
|
||||
int *copy)
|
||||
{
|
||||
const efi_guid_t env_guid = PARTITION_U_BOOT_ENVIRONMENT;
|
||||
efi_guid_t type_guid;
|
||||
int i, ret, found = 0;
|
||||
struct disk_partition dp;
|
||||
|
||||
for (i = 1;; i++) {
|
||||
ret = part_get_info(desc, i, &dp);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
uuid_str_to_bin(disk_partition_type_guid(&dp), type_guid.b, UUID_STR_FORMAT_GUID);
|
||||
if (!memcmp(&env_guid, &type_guid, sizeof(efi_guid_t))) {
|
||||
memcpy(info, &dp, sizeof(dp));
|
||||
/* If *copy is 0, we are only looking for the first partition. */
|
||||
if (*copy == 0)
|
||||
return 0;
|
||||
/* This was the second such partition. */
|
||||
if (found) {
|
||||
*copy = 0;
|
||||
return 0;
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The loop ended after finding at most one matching partition. */
|
||||
if (found)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val)
|
||||
{
|
||||
struct disk_partition info;
|
||||
struct blk_desc *desc;
|
||||
int len, i, ret;
|
||||
lbaint_t len;
|
||||
int ret;
|
||||
char dev_str[4];
|
||||
|
||||
snprintf(dev_str, sizeof(dev_str), "%d", mmc_get_env_dev());
|
||||
|
@ -65,28 +128,24 @@ static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val)
|
|||
if (ret < 0)
|
||||
return (ret);
|
||||
|
||||
for (i = 1;;i++) {
|
||||
ret = part_get_info(desc, i, &info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (str && !strncmp((const char *)info.name, str, sizeof(info.name)))
|
||||
break;
|
||||
#ifdef CONFIG_PARTITION_TYPE_GUID
|
||||
if (!str) {
|
||||
const efi_guid_t env_guid = PARTITION_U_BOOT_ENVIRONMENT;
|
||||
efi_guid_t type_guid;
|
||||
|
||||
uuid_str_to_bin(info.type_guid, type_guid.b, UUID_STR_FORMAT_GUID);
|
||||
if (!memcmp(&env_guid, &type_guid, sizeof(efi_guid_t)))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (str) {
|
||||
ret = mmc_env_partition_by_name(desc, str, &info);
|
||||
} else if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID) && !str) {
|
||||
ret = mmc_env_partition_by_guid(desc, &info, ©);
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue