* [PATCH 1/6] partitions: gpt: pass epd context pointer to find_valid_gpt()
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:28 ` Ahmad Fatoum
2025-12-03 15:19 ` [PATCH 2/6] partitions: gpt: only write actual ptes size to device Sascha Hauer
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
Pass the epd context pointer to find_valid_gpt() which we'll use in a
followup patch. This makes other arguments unnecessary, so they are
dropped. While at it change the return value of find_valid_gpt() to
standard 0 for success and negative error code otherwise.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/efi.c | 58 ++++++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 88d8a2d739c4e545952684f5647d105d9f38b028..da9c2d89c1c68ae1acebc1f8eaea8da48243f0d6 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -381,11 +381,10 @@ compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
/**
* find_valid_gpt() - Search disk for valid GPT headers and PTEs
- * @state
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
- * Description: Returns 1 if valid, 0 on error.
- * If valid, returns pointers to newly allocated GPT header and PTEs.
+ * @buf buffer containing the first lba
+ * @epd the efi partition descriptor context pointer
+ * Description: Returns 0 for success, negative error code otherwise.
+ * If valid, epd is filled with pointers to newly allocated GPT header and PTEs.
* Validity depends on PMBR being valid (or being overridden by the
* 'gpt' kernel command line option) and finding either the Primary
* GPT header and PTEs valid, or the Alternate GPT header and PTEs
@@ -394,17 +393,14 @@ compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
* This protects against devices which misreport their size, and forces
* the user to decide to use the Alternate GPT.
*/
-static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
- gpt_entry **ptes)
+static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
{
+ struct block_device *blk = epd->pd.blk;
int good_pgpt = 0, good_agpt = 0;
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
u64 lastlba;
- if (!ptes)
- return 0;
-
lastlba = last_lba(blk);
if (force_gpt) {
/* This will be added to the EFI Spec. per Intel after v1.02. */
@@ -430,21 +426,20 @@ static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
/* The good cases */
if (good_pgpt) {
- *gpt = pgpt;
- *ptes = pptes;
+ epd->gpt = pgpt;
+ epd->ptes = pptes;
free(agpt);
free(aptes);
if (!good_agpt)
dev_warn(blk->dev, "Alternate GPT is invalid, using primary GPT.\n");
- return 1;
- }
- else if (good_agpt) {
- *gpt = agpt;
- *ptes = aptes;
+ return 0;
+ } else {
+ epd->gpt = agpt;
+ epd->ptes = aptes;
free(pgpt);
free(pptes);
dev_warn(blk->dev, "Primary GPT is invalid, using alternate GPT.\n");
- return 1;
+ return 0;
}
fail:
@@ -452,9 +447,8 @@ static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
free(agpt);
free(pptes);
free(aptes);
- *gpt = NULL;
- *ptes = NULL;
- return 0;
+
+ return -EINVAL;
}
static void part_set_efi_name(gpt_entry *pte, char *dest)
@@ -516,9 +510,17 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
struct efi_partition *epart;
struct partition *pentry;
struct efi_partition_desc *epd;
+ int ret;
- if (!find_valid_gpt(buf, blk, &gpt, &ptes) || !gpt || !ptes)
- return NULL;
+ epd = xzalloc(sizeof(*epd));
+ partition_desc_init(&epd->pd, blk);
+
+ ret = find_valid_gpt(epd, buf);
+ if (ret)
+ goto err;
+
+ gpt = epd->gpt;
+ ptes = epd->ptes;
blk->cdev.flags |= DEVFS_IS_GPT_PARTITIONED;
@@ -530,12 +532,6 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
nb_part = MAX_PARTITION;
}
- epd = xzalloc(sizeof(*epd));
- partition_desc_init(&epd->pd, blk);
-
- epd->gpt = gpt;
- epd->ptes = ptes;
-
snprintf(blk->cdev.diskuuid, sizeof(blk->cdev.diskuuid), "%pUl", &gpt->disk_guid);
add_gpt_diskuuid_param(epd, blk);
@@ -560,6 +556,10 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
}
return &epd->pd;
+err:
+ free(epd);
+
+ return NULL;
}
static void efi_partition_free(struct partition_desc *pd)
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1/6] partitions: gpt: pass epd context pointer to find_valid_gpt()
2025-12-03 15:19 ` [PATCH 1/6] partitions: gpt: pass epd context pointer to find_valid_gpt() Sascha Hauer
@ 2025-12-15 12:28 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:28 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> Pass the epd context pointer to find_valid_gpt() which we'll use in a
> followup patch. This makes other arguments unnecessary, so they are
> dropped. While at it change the return value of find_valid_gpt() to
> standard 0 for success and negative error code otherwise.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/partitions/efi.c | 58 ++++++++++++++++++++++++-------------------------
> 1 file changed, 29 insertions(+), 29 deletions(-)
>
> diff --git a/common/partitions/efi.c b/common/partitions/efi.c
> index 88d8a2d739c4e545952684f5647d105d9f38b028..da9c2d89c1c68ae1acebc1f8eaea8da48243f0d6 100644
> --- a/common/partitions/efi.c
> +++ b/common/partitions/efi.c
> @@ -381,11 +381,10 @@ compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
>
> /**
> * find_valid_gpt() - Search disk for valid GPT headers and PTEs
> - * @state
> - * @gpt is a GPT header ptr, filled on return.
> - * @ptes is a PTEs ptr, filled on return.
> - * Description: Returns 1 if valid, 0 on error.
> - * If valid, returns pointers to newly allocated GPT header and PTEs.
> + * @buf buffer containing the first lba
> + * @epd the efi partition descriptor context pointer
> + * Description: Returns 0 for success, negative error code otherwise.
> + * If valid, epd is filled with pointers to newly allocated GPT header and PTEs.
> * Validity depends on PMBR being valid (or being overridden by the
> * 'gpt' kernel command line option) and finding either the Primary
> * GPT header and PTEs valid, or the Alternate GPT header and PTEs
> @@ -394,17 +393,14 @@ compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
> * This protects against devices which misreport their size, and forces
> * the user to decide to use the Alternate GPT.
> */
> -static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
> - gpt_entry **ptes)
> +static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
> {
> + struct block_device *blk = epd->pd.blk;
> int good_pgpt = 0, good_agpt = 0;
> gpt_header *pgpt = NULL, *agpt = NULL;
> gpt_entry *pptes = NULL, *aptes = NULL;
> u64 lastlba;
>
> - if (!ptes)
> - return 0;
> -
> lastlba = last_lba(blk);
> if (force_gpt) {
> /* This will be added to the EFI Spec. per Intel after v1.02. */
> @@ -430,21 +426,20 @@ static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
>
> /* The good cases */
> if (good_pgpt) {
> - *gpt = pgpt;
> - *ptes = pptes;
> + epd->gpt = pgpt;
> + epd->ptes = pptes;
> free(agpt);
> free(aptes);
> if (!good_agpt)
> dev_warn(blk->dev, "Alternate GPT is invalid, using primary GPT.\n");
> - return 1;
> - }
> - else if (good_agpt) {
> - *gpt = agpt;
> - *ptes = aptes;
> + return 0;
> + } else {
> + epd->gpt = agpt;
> + epd->ptes = aptes;
> free(pgpt);
> free(pptes);
> dev_warn(blk->dev, "Primary GPT is invalid, using alternate GPT.\n");
> - return 1;
> + return 0;
> }
>
> fail:
> @@ -452,9 +447,8 @@ static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt,
> free(agpt);
> free(pptes);
> free(aptes);
> - *gpt = NULL;
> - *ptes = NULL;
> - return 0;
> +
> + return -EINVAL;
> }
>
> static void part_set_efi_name(gpt_entry *pte, char *dest)
> @@ -516,9 +510,17 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
> struct efi_partition *epart;
> struct partition *pentry;
> struct efi_partition_desc *epd;
> + int ret;
>
> - if (!find_valid_gpt(buf, blk, &gpt, &ptes) || !gpt || !ptes)
> - return NULL;
> + epd = xzalloc(sizeof(*epd));
> + partition_desc_init(&epd->pd, blk);
> +
> + ret = find_valid_gpt(epd, buf);
> + if (ret)
> + goto err;
> +
> + gpt = epd->gpt;
> + ptes = epd->ptes;
>
> blk->cdev.flags |= DEVFS_IS_GPT_PARTITIONED;
>
> @@ -530,12 +532,6 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
> nb_part = MAX_PARTITION;
> }
>
> - epd = xzalloc(sizeof(*epd));
> - partition_desc_init(&epd->pd, blk);
> -
> - epd->gpt = gpt;
> - epd->ptes = ptes;
> -
> snprintf(blk->cdev.diskuuid, sizeof(blk->cdev.diskuuid), "%pUl", &gpt->disk_guid);
> add_gpt_diskuuid_param(epd, blk);
>
> @@ -560,6 +556,10 @@ static struct partition_desc *efi_partition(void *buf, struct block_device *blk)
> }
>
> return &epd->pd;
> +err:
> + free(epd);
> +
> + return NULL;
> }
>
> static void efi_partition_free(struct partition_desc *pd)
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2/6] partitions: gpt: only write actual ptes size to device
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
2025-12-03 15:19 ` [PATCH 1/6] partitions: gpt: pass epd context pointer to find_valid_gpt() Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:29 ` Ahmad Fatoum
2025-12-03 15:19 ` [PATCH 3/6] partitions: gpt: factor out a function to write primary/alternate GPT Sascha Hauer
` (4 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
For the alternate GPT we hardcode to write 32 blocks for the partition
entries. When writing partitions we only accept partition tables with
128 entries which translates to 32 blocks anyway, so no functional
change, but for correctness use the variable we also use for writing
the primary GPT's partition entries.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/efi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index da9c2d89c1c68ae1acebc1f8eaea8da48243f0d6..76c5393dddb04e2966d3a4b4478d5085f008d935 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -801,7 +801,7 @@ static __maybe_unused int efi_partition_write(struct partition_desc *pd)
if (ret)
goto err_block_write;
- ret = block_write(blk, epd->ptes, last_lba(blk) - 32, 32);
+ ret = block_write(blk, epd->ptes, last_lba(blk) - 32, size);
if (ret)
goto err_block_write;
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 2/6] partitions: gpt: only write actual ptes size to device
2025-12-03 15:19 ` [PATCH 2/6] partitions: gpt: only write actual ptes size to device Sascha Hauer
@ 2025-12-15 12:29 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:29 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> For the alternate GPT we hardcode to write 32 blocks for the partition
> entries. When writing partitions we only accept partition tables with
> 128 entries which translates to 32 blocks anyway, so no functional
> change, but for correctness use the variable we also use for writing
> the primary GPT's partition entries.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/partitions/efi.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/common/partitions/efi.c b/common/partitions/efi.c
> index da9c2d89c1c68ae1acebc1f8eaea8da48243f0d6..76c5393dddb04e2966d3a4b4478d5085f008d935 100644
> --- a/common/partitions/efi.c
> +++ b/common/partitions/efi.c
> @@ -801,7 +801,7 @@ static __maybe_unused int efi_partition_write(struct partition_desc *pd)
>
> if (ret)
> goto err_block_write;
> - ret = block_write(blk, epd->ptes, last_lba(blk) - 32, 32);
> + ret = block_write(blk, epd->ptes, last_lba(blk) - 32, size);
> if (ret)
> goto err_block_write;
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 3/6] partitions: gpt: factor out a function to write primary/alternate GPT
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
2025-12-03 15:19 ` [PATCH 1/6] partitions: gpt: pass epd context pointer to find_valid_gpt() Sascha Hauer
2025-12-03 15:19 ` [PATCH 2/6] partitions: gpt: only write actual ptes size to device Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:34 ` Ahmad Fatoum
2025-12-03 15:19 ` [PATCH 4/6] partitions: gpt: write inactive GPT first Sascha Hauer
` (3 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
In preparation for writing the inactive GPT first factor out a function
which either writes the primary or alternate GPT based on a boolean
argument.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/efi.c | 92 ++++++++++++++++++++++++++++---------------------
1 file changed, 53 insertions(+), 39 deletions(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 76c5393dddb04e2966d3a4b4478d5085f008d935..8da62acf36646b62ff2fac25673adbc48650d299 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -740,75 +740,89 @@ static int efi_protective_mbr(struct block_device *blk)
return ret;
}
-static __maybe_unused int efi_partition_write(struct partition_desc *pd)
+static int __efi_partition_write(struct efi_partition_desc *epd, bool primary)
{
- struct block_device *blk = pd->blk;
- struct efi_partition_desc *epd = container_of(pd, struct efi_partition_desc, pd);
- gpt_header *gpt = epd->gpt, *altgpt;
+ struct block_device *blk = epd->pd.blk;
+ gpt_header *gpt;
+ unsigned int count, size;
+ uint64_t my_lba, partition_entry_lba;
int ret;
- uint32_t count;
- uint64_t from, size;
- if (le32_to_cpu(gpt->num_partition_entries) != 128) {
- /*
- * This is not yet properly implemented. At least writing of the
- * alternative GPT is not correctly implemented for this case as
- * we can't assume that the partition entries are written at
- * last_lba() - 32, we would have to calculate that from the number
- * of partition entries.
- */
- pr_err("num_partition_entries is != 128. This is not yet supported for writing\n");
- return -EINVAL;
- }
+ gpt = xmemdup(epd->gpt, SECTOR_SIZE);
count = le32_to_cpu(gpt->num_partition_entries) *
le32_to_cpu(gpt->sizeof_partition_entry);
- gpt->my_lba = cpu_to_le64(1);
- gpt->alternate_lba = cpu_to_le64(last_lba(blk));
+ size = count / GPT_BLOCK_SIZE;
+
+ if (primary) {
+ my_lba = 1;
+ partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
+ gpt->alternate_lba = cpu_to_le64(last_lba(blk));
+ } else {
+ my_lba = last_lba(blk);
+ partition_entry_lba = last_lba(blk) - 32;
+ gpt->alternate_lba = cpu_to_le64(1);
+ }
+
+ gpt->my_lba = cpu_to_le64(my_lba);
+ gpt->partition_entry_lba = cpu_to_le64(partition_entry_lba);
gpt->partition_entry_array_crc32 = cpu_to_le32(efi_crc32(
(const unsigned char *)epd->ptes, count));
gpt->header_crc32 = 0;
gpt->header_crc32 = cpu_to_le32(efi_crc32((const unsigned char *)gpt,
le32_to_cpu(gpt->header_size)));
- ret = efi_protective_mbr(blk);
+ ret = block_write(blk, gpt, my_lba, 1);
if (ret)
- return ret;
+ goto err_block_write;
- ret = block_write(blk, gpt, 1, 1);
+ ret = block_write(blk, epd->ptes, partition_entry_lba, size);
if (ret)
goto err_block_write;
- from = le64_to_cpu(gpt->partition_entry_lba);
- size = count / GPT_BLOCK_SIZE;
+err_block_write:
+ free(gpt);
- ret = block_write(blk, epd->ptes, from, size);
- if (ret)
- goto err_block_write;
+ return ret;
+}
- altgpt = xmemdup(gpt, SECTOR_SIZE);
+static __maybe_unused int efi_partition_write(struct partition_desc *pd)
+{
+ struct block_device *blk = pd->blk;
+ struct efi_partition_desc *epd = container_of(pd, struct efi_partition_desc, pd);
+ gpt_header *gpt = epd->gpt;
+ int ret;
- altgpt->alternate_lba = cpu_to_le64(1);
- altgpt->my_lba = cpu_to_le64(last_lba(blk));
- altgpt->partition_entry_lba = cpu_to_le64(last_lba(blk) - 32);
- altgpt->header_crc32 = 0;
- altgpt->header_crc32 = cpu_to_le32(efi_crc32((const unsigned char *)altgpt,
- le32_to_cpu(altgpt->header_size)));
- ret = block_write(blk, altgpt, last_lba(blk), 1);
+ if (le32_to_cpu(gpt->num_partition_entries) != 128) {
+ /*
+ * This is not yet properly implemented. At least writing of the
+ * alternative GPT is not correctly implemented for this case as
+ * we can't assume that the partition entries are written at
+ * last_lba() - 32, we would have to calculate that from the number
+ * of partition entries.
+ */
+ pr_err("num_partition_entries is != 128. This is not yet supported for writing\n");
+ return -EINVAL;
+ }
- free(altgpt);
+ ret = efi_protective_mbr(blk);
+ if (ret)
+ return ret;
+ ret = __efi_partition_write(epd, true);
if (ret)
goto err_block_write;
- ret = block_write(blk, epd->ptes, last_lba(blk) - 32, size);
+
+ ret = __efi_partition_write(epd, false);
if (ret)
goto err_block_write;
- return 0;
+ ret = 0;
err_block_write:
- pr_err("Cannot write to block device: %pe\n", ERR_PTR(ret));
+ if (ret)
+ pr_err("Cannot write to block device: %pe\n", ERR_PTR(ret));
return ret;
}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 3/6] partitions: gpt: factor out a function to write primary/alternate GPT
2025-12-03 15:19 ` [PATCH 3/6] partitions: gpt: factor out a function to write primary/alternate GPT Sascha Hauer
@ 2025-12-15 12:34 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:34 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> In preparation for writing the inactive GPT first factor out a function
> which either writes the primary or alternate GPT based on a boolean
> argument.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/partitions/efi.c | 92 ++++++++++++++++++++++++++++---------------------
> 1 file changed, 53 insertions(+), 39 deletions(-)
>
> diff --git a/common/partitions/efi.c b/common/partitions/efi.c
> index 76c5393dddb04e2966d3a4b4478d5085f008d935..8da62acf36646b62ff2fac25673adbc48650d299 100644
> --- a/common/partitions/efi.c
> +++ b/common/partitions/efi.c
> @@ -740,75 +740,89 @@ static int efi_protective_mbr(struct block_device *blk)
> return ret;
> }
>
> -static __maybe_unused int efi_partition_write(struct partition_desc *pd)
> +static int __efi_partition_write(struct efi_partition_desc *epd, bool primary)
> {
> - struct block_device *blk = pd->blk;
> - struct efi_partition_desc *epd = container_of(pd, struct efi_partition_desc, pd);
> - gpt_header *gpt = epd->gpt, *altgpt;
> + struct block_device *blk = epd->pd.blk;
> + gpt_header *gpt;
> + unsigned int count, size;
> + uint64_t my_lba, partition_entry_lba;
> int ret;
> - uint32_t count;
> - uint64_t from, size;
>
> - if (le32_to_cpu(gpt->num_partition_entries) != 128) {
> - /*
> - * This is not yet properly implemented. At least writing of the
> - * alternative GPT is not correctly implemented for this case as
> - * we can't assume that the partition entries are written at
> - * last_lba() - 32, we would have to calculate that from the number
> - * of partition entries.
> - */
> - pr_err("num_partition_entries is != 128. This is not yet supported for writing\n");
> - return -EINVAL;
> - }
> + gpt = xmemdup(epd->gpt, SECTOR_SIZE);
>
> count = le32_to_cpu(gpt->num_partition_entries) *
> le32_to_cpu(gpt->sizeof_partition_entry);
>
> - gpt->my_lba = cpu_to_le64(1);
> - gpt->alternate_lba = cpu_to_le64(last_lba(blk));
> + size = count / GPT_BLOCK_SIZE;
> +
> + if (primary) {
> + my_lba = 1;
> + partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
> + gpt->alternate_lba = cpu_to_le64(last_lba(blk));
> + } else {
> + my_lba = last_lba(blk);
> + partition_entry_lba = last_lba(blk) - 32;
> + gpt->alternate_lba = cpu_to_le64(1);
> + }
> +
> + gpt->my_lba = cpu_to_le64(my_lba);
> + gpt->partition_entry_lba = cpu_to_le64(partition_entry_lba);
> gpt->partition_entry_array_crc32 = cpu_to_le32(efi_crc32(
> (const unsigned char *)epd->ptes, count));
> gpt->header_crc32 = 0;
> gpt->header_crc32 = cpu_to_le32(efi_crc32((const unsigned char *)gpt,
> le32_to_cpu(gpt->header_size)));
>
> - ret = efi_protective_mbr(blk);
> + ret = block_write(blk, gpt, my_lba, 1);
> if (ret)
> - return ret;
> + goto err_block_write;
>
> - ret = block_write(blk, gpt, 1, 1);
> + ret = block_write(blk, epd->ptes, partition_entry_lba, size);
> if (ret)
> goto err_block_write;
>
> - from = le64_to_cpu(gpt->partition_entry_lba);
> - size = count / GPT_BLOCK_SIZE;
> +err_block_write:
> + free(gpt);
>
> - ret = block_write(blk, epd->ptes, from, size);
> - if (ret)
> - goto err_block_write;
> + return ret;
> +}
>
> - altgpt = xmemdup(gpt, SECTOR_SIZE);
> +static __maybe_unused int efi_partition_write(struct partition_desc *pd)
> +{
> + struct block_device *blk = pd->blk;
> + struct efi_partition_desc *epd = container_of(pd, struct efi_partition_desc, pd);
> + gpt_header *gpt = epd->gpt;
> + int ret;
>
> - altgpt->alternate_lba = cpu_to_le64(1);
> - altgpt->my_lba = cpu_to_le64(last_lba(blk));
> - altgpt->partition_entry_lba = cpu_to_le64(last_lba(blk) - 32);
> - altgpt->header_crc32 = 0;
> - altgpt->header_crc32 = cpu_to_le32(efi_crc32((const unsigned char *)altgpt,
> - le32_to_cpu(altgpt->header_size)));
> - ret = block_write(blk, altgpt, last_lba(blk), 1);
> + if (le32_to_cpu(gpt->num_partition_entries) != 128) {
> + /*
> + * This is not yet properly implemented. At least writing of the
> + * alternative GPT is not correctly implemented for this case as
> + * we can't assume that the partition entries are written at
> + * last_lba() - 32, we would have to calculate that from the number
> + * of partition entries.
> + */
> + pr_err("num_partition_entries is != 128. This is not yet supported for writing\n");
> + return -EINVAL;
> + }
>
> - free(altgpt);
> + ret = efi_protective_mbr(blk);
> + if (ret)
> + return ret;
>
> + ret = __efi_partition_write(epd, true);
> if (ret)
> goto err_block_write;
> - ret = block_write(blk, epd->ptes, last_lba(blk) - 32, size);
> +
> + ret = __efi_partition_write(epd, false);
> if (ret)
> goto err_block_write;
>
> - return 0;
> + ret = 0;
>
> err_block_write:
> - pr_err("Cannot write to block device: %pe\n", ERR_PTR(ret));
> + if (ret)
> + pr_err("Cannot write to block device: %pe\n", ERR_PTR(ret));
>
> return ret;
> }
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 4/6] partitions: gpt: write inactive GPT first
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
` (2 preceding siblings ...)
2025-12-03 15:19 ` [PATCH 3/6] partitions: gpt: factor out a function to write primary/alternate GPT Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:38 ` Ahmad Fatoum
2025-12-03 15:19 ` [PATCH 5/6] partitions: gpt: fix GPT restauration from alternate GPT Sascha Hauer
` (2 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
There are two GPT partition tables on a device, the primary at the
beginning of a device and the alternate at the end of the device.
For the sake of being more robust against power failures let's write the
inactive GPT first and the currently active one afterwards. This always
leaves us a usable GPT on the device when updating the partition table.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/efi.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 8da62acf36646b62ff2fac25673adbc48650d299..1766f0123353d502065673d02e983e6cdd51b9af 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -27,6 +27,8 @@ struct efi_partition_desc {
gpt_header *gpt;
gpt_entry *ptes;
struct param_d *param_guid;
+ bool good_pgpt;
+ bool good_agpt;
};
struct efi_partition {
@@ -424,6 +426,9 @@ static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_COMPARE))
compare_gpts(blk->dev, pgpt, agpt, lastlba);
+ epd->good_pgpt = good_pgpt;
+ epd->good_agpt = good_agpt;
+
/* The good cases */
if (good_pgpt) {
epd->gpt = pgpt;
@@ -810,11 +815,11 @@ static __maybe_unused int efi_partition_write(struct partition_desc *pd)
if (ret)
return ret;
- ret = __efi_partition_write(epd, true);
+ ret = __efi_partition_write(epd, !epd->good_pgpt);
if (ret)
goto err_block_write;
- ret = __efi_partition_write(epd, false);
+ ret = __efi_partition_write(epd, epd->good_pgpt);
if (ret)
goto err_block_write;
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 4/6] partitions: gpt: write inactive GPT first
2025-12-03 15:19 ` [PATCH 4/6] partitions: gpt: write inactive GPT first Sascha Hauer
@ 2025-12-15 12:38 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:38 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Hi,
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> There are two GPT partition tables on a device, the primary at the
> beginning of a device and the alternate at the end of the device.
>
> For the sake of being more robust against power failures let's write the
> inactive GPT first and the currently active one afterwards. This always
> leaves us a usable GPT on the device when updating the partition table.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/partitions/efi.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/common/partitions/efi.c b/common/partitions/efi.c
> index 8da62acf36646b62ff2fac25673adbc48650d299..1766f0123353d502065673d02e983e6cdd51b9af 100644
> --- a/common/partitions/efi.c
> +++ b/common/partitions/efi.c
> @@ -27,6 +27,8 @@ struct efi_partition_desc {
> gpt_header *gpt;
> gpt_entry *ptes;
> struct param_d *param_guid;
> + bool good_pgpt;
> + bool good_agpt;
> };
>
> struct efi_partition {
> @@ -424,6 +426,9 @@ static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
> if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_COMPARE))
> compare_gpts(blk->dev, pgpt, agpt, lastlba);
>
> + epd->good_pgpt = good_pgpt;
> + epd->good_agpt = good_agpt;
> +
> /* The good cases */
> if (good_pgpt) {
> epd->gpt = pgpt;
> @@ -810,11 +815,11 @@ static __maybe_unused int efi_partition_write(struct partition_desc *pd)
> if (ret)
> return ret;
>
> - ret = __efi_partition_write(epd, true);
> + ret = __efi_partition_write(epd, !epd->good_pgpt);
> if (ret)
> goto err_block_write;
>
> - ret = __efi_partition_write(epd, false);
> + ret = __efi_partition_write(epd, epd->good_pgpt);
> if (ret)
> goto err_block_write;
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 5/6] partitions: gpt: fix GPT restauration from alternate GPT
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
` (3 preceding siblings ...)
2025-12-03 15:19 ` [PATCH 4/6] partitions: gpt: write inactive GPT first Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:41 ` Ahmad Fatoum
2025-12-03 15:19 ` [PATCH 6/6] partitions: gpt: refresh partition tables when necessary Sascha Hauer
2025-12-15 14:09 ` [PATCH 0/6] partitions: GPT: " Sascha Hauer
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
We read GPT headers from the device and store it in epd->gpt. When
writing a partition table we assume that epd->gpt is read from
the primary GPT header: We only adjust the partition_entry_lba for
the alternate header. This assumption is wrong, in case the primary
GPT header is corrupted epd->gpt could also come from the alternate
GPT header. When this happens we have to set partition_entry_lba
correctly for the primary GPT header as well.
Unfortunately this is not trivial. While we could just use LBA2 for
the partition entries, this might overwrite a bootloader stored there (see
[1]). Instead the following logic is applied:
When the primary GPT header was good when reading it, keep the partition
table entries where they are. If not, take the first usable LBA and
substract the size we need for the partition entries.
[1] https://lore.barebox.org/20250602-createnv-v1-2-c3239ff875d5@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/efi.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 1766f0123353d502065673d02e983e6cdd51b9af..0fd60c9fd0442c3c571c685a5b0b41b8f33db7bd 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -762,7 +762,36 @@ static int __efi_partition_write(struct efi_partition_desc *epd, bool primary)
if (primary) {
my_lba = 1;
- partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
+
+ if (epd->good_pgpt) {
+ /*
+ * The primary GPT was good, we can just leave the partition
+ * entries where they are.
+ */
+ partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
+ } else {
+ /*
+ * The primary GPT was bad. When this is not a new partition
+ * table, but instead read from the disk, the header is from the
+ * alternate GPT, meaning the partition_entry_lba also points
+ * to the alternate partitions. We have to find a place for the
+ * primary partition entries in this case. We could store them
+ * right after the GPT header, but this might destroy a bootloader
+ * stored there. Instead, substract the size we need from the
+ * first usable LBA.
+ */
+ uint64_t first_usable_lba;
+
+ first_usable_lba = le64_to_cpu(gpt->first_usable_lba);
+
+ if (first_usable_lba < 32 + 1 + 1) {
+ pr_err("First usable LBA is %llu which doesn't leave "
+ "enough space for partition entries\n",
+ first_usable_lba);
+ return -EINVAL;
+ }
+ partition_entry_lba = first_usable_lba - 32;
+ }
gpt->alternate_lba = cpu_to_le64(last_lba(blk));
} else {
my_lba = last_lba(blk);
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 5/6] partitions: gpt: fix GPT restauration from alternate GPT
2025-12-03 15:19 ` [PATCH 5/6] partitions: gpt: fix GPT restauration from alternate GPT Sascha Hauer
@ 2025-12-15 12:41 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> We read GPT headers from the device and store it in epd->gpt. When
> writing a partition table we assume that epd->gpt is read from
> the primary GPT header: We only adjust the partition_entry_lba for
> the alternate header. This assumption is wrong, in case the primary
> GPT header is corrupted epd->gpt could also come from the alternate
> GPT header. When this happens we have to set partition_entry_lba
> correctly for the primary GPT header as well.
>
> Unfortunately this is not trivial. While we could just use LBA2 for
> the partition entries, this might overwrite a bootloader stored there (see
> [1]). Instead the following logic is applied:
>
> When the primary GPT header was good when reading it, keep the partition
> table entries where they are. If not, take the first usable LBA and
> substract the size we need for the partition entries.
>
> [1] https://lore.barebox.org/20250602-createnv-v1-2-c3239ff875d5@pengutronix.de
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/partitions/efi.c | 31 ++++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/common/partitions/efi.c b/common/partitions/efi.c
> index 1766f0123353d502065673d02e983e6cdd51b9af..0fd60c9fd0442c3c571c685a5b0b41b8f33db7bd 100644
> --- a/common/partitions/efi.c
> +++ b/common/partitions/efi.c
> @@ -762,7 +762,36 @@ static int __efi_partition_write(struct efi_partition_desc *epd, bool primary)
>
> if (primary) {
> my_lba = 1;
> - partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
> +
> + if (epd->good_pgpt) {
> + /*
> + * The primary GPT was good, we can just leave the partition
> + * entries where they are.
> + */
> + partition_entry_lba = le64_to_cpu(gpt->partition_entry_lba);
> + } else {
> + /*
> + * The primary GPT was bad. When this is not a new partition
> + * table, but instead read from the disk, the header is from the
> + * alternate GPT, meaning the partition_entry_lba also points
> + * to the alternate partitions. We have to find a place for the
> + * primary partition entries in this case. We could store them
> + * right after the GPT header, but this might destroy a bootloader
> + * stored there. Instead, substract the size we need from the
> + * first usable LBA.
> + */
> + uint64_t first_usable_lba;
> +
> + first_usable_lba = le64_to_cpu(gpt->first_usable_lba);
> +
> + if (first_usable_lba < 32 + 1 + 1) {
> + pr_err("First usable LBA is %llu which doesn't leave "
> + "enough space for partition entries\n",
> + first_usable_lba);
> + return -EINVAL;
> + }
> + partition_entry_lba = first_usable_lba - 32;
> + }
> gpt->alternate_lba = cpu_to_le64(last_lba(blk));
> } else {
> my_lba = last_lba(blk);
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 6/6] partitions: gpt: refresh partition tables when necessary
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
` (4 preceding siblings ...)
2025-12-03 15:19 ` [PATCH 5/6] partitions: gpt: fix GPT restauration from alternate GPT Sascha Hauer
@ 2025-12-03 15:19 ` Sascha Hauer
2025-12-15 12:47 ` Ahmad Fatoum
2025-12-15 14:09 ` [PATCH 0/6] partitions: GPT: " Sascha Hauer
6 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-03 15:19 UTC (permalink / raw)
To: BAREBOX
The GPT alternative header must be at the end of the device. When disk
images are written to a device this often is not the case which results
in warnings:
WARNING: mmc0: GPT:Primary header thinks Alt. header is not at the end of the disk.
WARNING: mmc0: GPT:6561831 != 62160895
WARNING: mmc0: GPT:Alternate GPT header not at the end of the disk.
WARNING: mmc0: GPT:6561831 != 62160895
WARNING: mmc0: GPT: Use parted to correct GPT errors.
This patch adds support for automatically rewriting the partition table
when this happens. This behaviour is optional and needs to be enabled at
compile time with CONFIG_PARTITION_DISK_EFI_REFRESH. Also this is
runtime configurable with global.system.gpt_refresh
Link: https://lore.barebox.org/20251128111929.2463263-1-s.hauer@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/partitions/Kconfig | 14 ++++++
common/partitions/efi.c | 109 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 120 insertions(+), 3 deletions(-)
diff --git a/common/partitions/Kconfig b/common/partitions/Kconfig
index 3bbcceedc191be783fa0a5ca0031c9fb24a85b1b..1007dbbe19d26f9b8008a41e227fc0ee93acf5cc 100644
--- a/common/partitions/Kconfig
+++ b/common/partitions/Kconfig
@@ -24,6 +24,20 @@ config PARTITION_DISK_EFI
help
Add support to handle partitions in GUID Partition Table style.
+config PARTITION_DISK_EFI_REFRESH
+ depends on PARTITION_DISK_EFI && PARTITION_MANIPULATION
+ bool "refresh GPT partition on demand"
+ help
+ The GPT alternative header must be at the end of the device. When disk
+ images are written to a device this often is not the case which results
+ in warnings:
+
+ GPT:Primary header thinks Alt. header is not at the end of the disk.
+
+ Enable this option and set global.system.gpt_refresh to true to refresh
+ GPT partition tables when necessary. Only erroneous partition tables will
+ be rewritten, once fixed up partition tables will not be touched.
+
config PARTITION_DISK_EFI_GPT_NO_FORCE
depends on PARTITION_DISK_EFI
default y
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 0fd60c9fd0442c3c571c685a5b0b41b8f33db7bd..e4293e0e9ccae128ee8d0d8b08ab82a463d8a10b 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -15,8 +15,11 @@
#include <common.h>
#include <disks.h>
#include <init.h>
+#include <magicvar.h>
+#include <globalvar.h>
#include <asm/unaligned.h>
#include <crc.h>
+#include <fcntl.h>
#include <linux/ctype.h>
#include <efi/partition.h>
@@ -38,6 +41,93 @@ struct efi_partition {
static const int force_gpt = IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_NO_FORCE);
+struct gpt_refresh {
+ struct block_device *blk;
+ struct list_head list;
+};
+
+static LIST_HEAD(gpt_refreshes);
+
+static unsigned int global_gpt_refresh;
+
+static int gpt_refresh_one(struct block_device *blk)
+{
+ struct partition_desc *pdesc;
+ int ret;
+
+ if (!global_gpt_refresh)
+ return 0;
+
+ ret = cdev_open(&blk->cdev, O_RDWR);
+ if (ret)
+ return ret;
+
+ pdesc = partition_table_read(blk);
+ if (!pdesc) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = partition_table_write(pdesc);
+ if (ret)
+ goto out;
+
+ ret = 0;
+
+ partition_table_free(pdesc);
+out:
+ cdev_close(&blk->cdev);
+
+ if (ret)
+ dev_err(blk->dev, "Refreshing partition table failed: %pe\n",
+ ERR_PTR(ret));
+
+ return ret;
+}
+
+static bool gpt_refresh_done;
+
+static int do_gpt_refreshes(void)
+{
+ struct gpt_refresh *r, *tmp;
+
+ if (!IS_ENABLED(CONFIG_PARTITION_DISK_EFI_REFRESH))
+ return 0;
+
+ if (!global_gpt_refresh)
+ return 0;
+
+ list_for_each_entry_safe(r, tmp, &gpt_refreshes, list) {
+ gpt_refresh_one(r->blk);
+ list_del(&r->list);
+ free(r);
+ }
+
+ gpt_refresh_done = true;
+
+ return 0;
+}
+postenvironment_initcall(do_gpt_refreshes);
+
+static void add_gpt_refresh(struct block_device *blk)
+{
+ struct gpt_refresh *r;
+
+ if (!IS_ENABLED(CONFIG_PARTITION_DISK_EFI_REFRESH))
+ return;
+
+ if (gpt_refresh_done) {
+ gpt_refresh_one(blk);
+ return;
+ }
+
+ r = xzalloc(sizeof(*r));
+
+ r->blk = blk;
+
+ list_add_tail(&r->list, &gpt_refreshes);
+}
+
/**
* compute_partitions_entries_size() - return the size of all partitions
* @gpt: GPT header
@@ -290,9 +380,11 @@ is_pte_valid(const gpt_entry *pte, const u64 lastlba)
*
*/
static void
-compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
+compare_gpts(struct block_device *blk, gpt_header *pgpt, gpt_header *agpt,
u64 lastlba)
{
+ struct device *dev = blk->dev;
+
int error_found = 0;
if (!pgpt || !agpt)
return;
@@ -376,8 +468,11 @@ compare_gpts(struct device *dev, gpt_header *pgpt, gpt_header *agpt,
error_found++;
}
- if (error_found)
+ if (error_found) {
+ add_gpt_refresh(blk);
dev_warn(dev, "GPT: Use parted to correct GPT errors.\n");
+ }
+
return;
}
@@ -424,7 +519,7 @@ static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
goto fail;
if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_COMPARE))
- compare_gpts(blk->dev, pgpt, agpt, lastlba);
+ compare_gpts(blk, pgpt, agpt, lastlba);
epd->good_pgpt = good_pgpt;
epd->good_agpt = good_agpt;
@@ -874,8 +969,16 @@ static struct partition_parser efi_partition_parser = {
.name = "gpt",
};
+#ifdef CONFIG_PARTITION_DISK_EFI_REFRESH
+BAREBOX_MAGICVAR(global.system.gpt_refresh, "When true, refresh GPT partitions when necessary");
+#endif
+
static int efi_partition_init(void)
{
+ if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_REFRESH))
+ globalvar_add_simple_bool("system.gpt_refresh",
+ &global_gpt_refresh);
+
return partition_parser_register(&efi_partition_parser);
}
postconsole_initcall(efi_partition_init);
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 6/6] partitions: gpt: refresh partition tables when necessary
2025-12-03 15:19 ` [PATCH 6/6] partitions: gpt: refresh partition tables when necessary Sascha Hauer
@ 2025-12-15 12:47 ` Ahmad Fatoum
2025-12-15 14:13 ` Sascha Hauer
0 siblings, 1 reply; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 12:47 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Hi,
On 12/3/25 4:19 PM, Sascha Hauer wrote:
> The GPT alternative header must be at the end of the device. When disk
> images are written to a device this often is not the case which results
> in warnings:
>
> WARNING: mmc0: GPT:Primary header thinks Alt. header is not at the end of the disk.
> WARNING: mmc0: GPT:6561831 != 62160895
> WARNING: mmc0: GPT:Alternate GPT header not at the end of the disk.
> WARNING: mmc0: GPT:6561831 != 62160895
> WARNING: mmc0: GPT: Use parted to correct GPT errors.
>
> This patch adds support for automatically rewriting the partition table
> when this happens. This behaviour is optional and needs to be enabled at
> compile time with CONFIG_PARTITION_DISK_EFI_REFRESH. Also this is
> runtime configurable with global.system.gpt_refresh
>
> Link: https://lore.barebox.org/20251128111929.2463263-1-s.hauer@pengutronix.de
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
With below point addressed:
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> - if (error_found)
> + if (error_found) {
> + add_gpt_refresh(blk);
> dev_warn(dev, "GPT: Use parted to correct GPT errors.\n");
With CONFIG_PARTITION_DISK_EFI_REFRESH enabled, I would suggest changing
this to a dev_info(dev, "GPT: barebox will autocorrect.\n") or something.
> + }
> +
> return;
> }
>
> @@ -424,7 +519,7 @@ static int find_valid_gpt(struct efi_partition_desc *epd, void *buf)
> goto fail;
>
> if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_COMPARE))
> - compare_gpts(blk->dev, pgpt, agpt, lastlba);
> + compare_gpts(blk, pgpt, agpt, lastlba);
>
> epd->good_pgpt = good_pgpt;
> epd->good_agpt = good_agpt;
> @@ -874,8 +969,16 @@ static struct partition_parser efi_partition_parser = {
> .name = "gpt",
> };
>
> +#ifdef CONFIG_PARTITION_DISK_EFI_REFRESH
> +BAREBOX_MAGICVAR(global.system.gpt_refresh, "When true, refresh GPT partitions when necessary");
> +#endif
> +
> static int efi_partition_init(void)
> {
> + if (IS_ENABLED(CONFIG_PARTITION_DISK_EFI_REFRESH))
> + globalvar_add_simple_bool("system.gpt_refresh",
> + &global_gpt_refresh);
> +
> return partition_parser_register(&efi_partition_parser);
> }
> postconsole_initcall(efi_partition_init);
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 6/6] partitions: gpt: refresh partition tables when necessary
2025-12-15 12:47 ` Ahmad Fatoum
@ 2025-12-15 14:13 ` Sascha Hauer
2025-12-15 14:15 ` Ahmad Fatoum
0 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2025-12-15 14:13 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: BAREBOX
On Mon, Dec 15, 2025 at 01:47:09PM +0100, Ahmad Fatoum wrote:
> Hi,
>
> On 12/3/25 4:19 PM, Sascha Hauer wrote:
> > The GPT alternative header must be at the end of the device. When disk
> > images are written to a device this often is not the case which results
> > in warnings:
> >
> > WARNING: mmc0: GPT:Primary header thinks Alt. header is not at the end of the disk.
> > WARNING: mmc0: GPT:6561831 != 62160895
> > WARNING: mmc0: GPT:Alternate GPT header not at the end of the disk.
> > WARNING: mmc0: GPT:6561831 != 62160895
> > WARNING: mmc0: GPT: Use parted to correct GPT errors.
> >
> > This patch adds support for automatically rewriting the partition table
> > when this happens. This behaviour is optional and needs to be enabled at
> > compile time with CONFIG_PARTITION_DISK_EFI_REFRESH. Also this is
> > runtime configurable with global.system.gpt_refresh
> >
> > Link: https://lore.barebox.org/20251128111929.2463263-1-s.hauer@pengutronix.de
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>
> With below point addressed:
>
> Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>
>
> > - if (error_found)
> > + if (error_found) {
> > + add_gpt_refresh(blk);
> > dev_warn(dev, "GPT: Use parted to correct GPT errors.\n");
>
> With CONFIG_PARTITION_DISK_EFI_REFRESH enabled, I would suggest changing
> this to a dev_info(dev, "GPT: barebox will autocorrect.\n") or something.
We can know that this feature is compiled in, but we don't know yet if it
is actually enabled, so the best we can write is something like:
dev_info(dev, "GPT: will repair later when global.system.gpt_refresh is true\n");
I added this while applying.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 6/6] partitions: gpt: refresh partition tables when necessary
2025-12-15 14:13 ` Sascha Hauer
@ 2025-12-15 14:15 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2025-12-15 14:15 UTC (permalink / raw)
To: Sascha Hauer; +Cc: BAREBOX
On 12/15/25 3:13 PM, Sascha Hauer wrote:
> On Mon, Dec 15, 2025 at 01:47:09PM +0100, Ahmad Fatoum wrote:
>> Hi,
>>
>> On 12/3/25 4:19 PM, Sascha Hauer wrote:
>>> The GPT alternative header must be at the end of the device. When disk
>>> images are written to a device this often is not the case which results
>>> in warnings:
>>>
>>> WARNING: mmc0: GPT:Primary header thinks Alt. header is not at the end of the disk.
>>> WARNING: mmc0: GPT:6561831 != 62160895
>>> WARNING: mmc0: GPT:Alternate GPT header not at the end of the disk.
>>> WARNING: mmc0: GPT:6561831 != 62160895
>>> WARNING: mmc0: GPT: Use parted to correct GPT errors.
>>>
>>> This patch adds support for automatically rewriting the partition table
>>> when this happens. This behaviour is optional and needs to be enabled at
>>> compile time with CONFIG_PARTITION_DISK_EFI_REFRESH. Also this is
>>> runtime configurable with global.system.gpt_refresh
>>>
>>> Link: https://lore.barebox.org/20251128111929.2463263-1-s.hauer@pengutronix.de
>>> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>>
>> With below point addressed:
>>
>> Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>>
>>
>>> - if (error_found)
>>> + if (error_found) {
>>> + add_gpt_refresh(blk);
>>> dev_warn(dev, "GPT: Use parted to correct GPT errors.\n");
>>
>> With CONFIG_PARTITION_DISK_EFI_REFRESH enabled, I would suggest changing
>> this to a dev_info(dev, "GPT: barebox will autocorrect.\n") or something.
>
> We can know that this feature is compiled in, but we don't know yet if it
> is actually enabled, so the best we can write is something like:
>
> dev_info(dev, "GPT: will repair later when global.system.gpt_refresh is true\n");
Maybe: "GPT: will repair later if global.system.gpt_refresh=1" ?
>
> I added this while applying.
>
> Sascha
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/6] partitions: GPT: refresh partition tables when necessary
2025-12-03 15:19 [PATCH 0/6] partitions: GPT: refresh partition tables when necessary Sascha Hauer
` (5 preceding siblings ...)
2025-12-03 15:19 ` [PATCH 6/6] partitions: gpt: refresh partition tables when necessary Sascha Hauer
@ 2025-12-15 14:09 ` Sascha Hauer
6 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2025-12-15 14:09 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer
On Wed, 03 Dec 2025 16:19:04 +0100, Sascha Hauer wrote:
> This is a continuation of the patch previously sent separately:
>
> https://lore.kernel.org/all/20251128111929.2463263-1-s.hauer@pengutronix.de/
>
> Ahmad's comment to this was that we should write the inactive GPT first
> to make sure there's always a valid GPT on the device. This series
> implements just that. I stumbled upon a bug when we restore the primary
> GPT from the alternate GPT, this is fixed in this series.
>
> [...]
Applied, thanks!
[1/6] partitions: gpt: pass epd context pointer to find_valid_gpt()
https://git.pengutronix.de/cgit/barebox/commit/?id=21f0f27d4ee8 (link may not be stable)
[2/6] partitions: gpt: only write actual ptes size to device
https://git.pengutronix.de/cgit/barebox/commit/?id=a8ce79acad3f (link may not be stable)
[3/6] partitions: gpt: factor out a function to write primary/alternate GPT
https://git.pengutronix.de/cgit/barebox/commit/?id=39d9c24162e0 (link may not be stable)
[4/6] partitions: gpt: write inactive GPT first
https://git.pengutronix.de/cgit/barebox/commit/?id=825fa5c84455 (link may not be stable)
[5/6] partitions: gpt: fix GPT restauration from alternate GPT
https://git.pengutronix.de/cgit/barebox/commit/?id=58ddade72049 (link may not be stable)
[6/6] partitions: gpt: refresh partition tables when necessary
https://git.pengutronix.de/cgit/barebox/commit/?id=131ef8e9ef99 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 16+ messages in thread