+static void clear_gpt_pte_cache(void)
+{
+ if (gpt_pte_cache.desc) {
+ if (gpt_pte_cache.gpt_pte)
+ free(gpt_pte_cache.gpt_pte);
+
+ memset(&gpt_pte_cache, 0, sizeof(gpt_pte_cache));
+ }
+}
+
+static void cache_gpt_pte(struct blk_desc *desc, u64 lba,
+ gpt_entry *gpt_pte, gpt_header *pgpt_head)
+{
+ if (gpt_pte_cache.gpt_pte)
+ free(gpt_pte_cache.gpt_pte);
+
+ gpt_pte_cache.desc = desc;
+ gpt_pte_cache.lba = lba;
+ gpt_pte_cache.gpt_pte = gpt_pte;
+ if (pgpt_head)
+ memcpy(&gpt_pte_cache.gpt_head, pgpt_head, sizeof(gpt_header));
+}
+
+static gpt_entry *get_cached_gpt_pte(struct blk_desc *desc, u64 lba,
+ gpt_header *pgpt_head)
+{
+ if (gpt_pte_cache.desc && gpt_pte_cache.gpt_pte) {
+ if (gpt_pte_cache.desc == desc &&
+ gpt_pte_cache.lba == lba) {
+ memcpy(pgpt_head, &gpt_pte_cache.gpt_head, sizeof(gpt_header));
+ return gpt_pte_cache.gpt_pte;
+ }
+
+ clear_gpt_pte_cache();
+ }
+
+ return NULL;
+}
static char *print_efiname(gpt_entry *pte)
{
@@ -205,7 +251,7 @@ int get_disk_guid(struct blk_desc *desc, char *guid)
unsigned char *guid_bin;
/* This function validates AND fills in the GPT header and PTE */
- if (find_valid_gpt(desc, gpt_head, &gpt_pte) != 1)
+ if (find_valid_gpt(desc, gpt_head, &gpt_pte, false) != 1)
return -EINVAL;
guid_bin = gpt_head->disk_guid.b;
@@ -224,7 +270,7 @@ static void __maybe_unused part_print_efi(struct blk_desc
*desc)
unsigned char *uuid;
/* This function validates AND fills in the GPT header and PTE */
- if (find_valid_gpt(desc, gpt_head, &gpt_pte) != 1)
+ if (find_valid_gpt(desc, gpt_head, &gpt_pte, false) != 1)
return;
debug("%s: gpt-entry at %p\n", __func__, gpt_pte);
@@ -258,8 +304,13 @@ static void __maybe_unused part_print_efi(struct blk_desc
*desc)
return;
}
-static int __maybe_unused part_get_info_efi(struct blk_desc *desc, int part,
- struct disk_partition *info)
+static void __maybe_unused part_get_info_cache_free_efi(struct blk_desc *desc)
+{
+ clear_gpt_pte_cache();
+}
+
+static int _part_get_info_efi(struct blk_desc *desc, int part,
+ struct disk_partition *info, bool cache)
{
ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, desc->blksz);
gpt_entry *gpt_pte = NULL;
@@ -271,13 +322,14 @@ static int __maybe_unused part_get_info_efi(struct
blk_desc *desc, int part,
}
/* This function validates AND fills in the GPT header and PTE */
- if (find_valid_gpt(desc, gpt_head, &gpt_pte) != 1)
+ if (find_valid_gpt(desc, gpt_head, &gpt_pte, cache) != 1)
return -EINVAL;
if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
!is_pte_valid(&gpt_pte[part - 1])) {
log_debug("Invalid partition number %d\n", part);
- free(gpt_pte);
+ if (!cache)
+ free(gpt_pte);
return -EPERM;
}
@@ -307,11 +359,23 @@ static int __maybe_unused part_get_info_efi(struct
blk_desc *desc, int part,
log_debug("start 0x" LBAF ", size 0x" LBAF ", name %s\n", info->start,
info->size, info->name);
- /* Remember to free pte */
- free(gpt_pte);
+ if (!cache)
+ free(gpt_pte);
return 0;
}
+static int __maybe_unused part_get_info_cached_efi(struct blk_desc *desc, int
part,
+ struct disk_partition *info)
+{
+ return _part_get_info_efi(desc, part, info, true);
+}
+
+static int __maybe_unused part_get_info_efi(struct blk_desc *desc, int part,
+ struct disk_partition *info)
+{
+ return _part_get_info_efi(desc, part, info, false);
+}
+
static int part_test_efi(struct blk_desc *desc)
{
ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, desc->blksz);
@@ -689,7 +753,7 @@ int gpt_verify_headers(struct blk_desc *desc, gpt_header
*gpt_head,
*/
if (is_gpt_valid(desc,
GPT_PRIMARY_PARTITION_TABLE_LBA,
- gpt_head, gpt_pte) != 1) {
+ gpt_head, gpt_pte, false) != 1) {
log_debug("Invalid GPT\n");
return -1;
}
@@ -706,7 +770,7 @@ int gpt_verify_headers(struct blk_desc *desc, gpt_header
*gpt_head,
}
if (is_gpt_valid(desc, (desc->lba - 1),
- gpt_head, gpt_pte) != 1) {
+ gpt_head, gpt_pte, false) != 1) {
log_debug("Invalid Backup GPT\n");
return -1;
}
@@ -765,9 +829,9 @@ int gpt_repair_headers(struct blk_desc *desc)
int ret = -1;
is_gpt1_valid = is_gpt_valid(desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
- gpt_h1, &gpt_e1);
+ gpt_h1, &gpt_e1, false);
is_gpt2_valid = is_gpt_valid(desc, desc->lba - 1,
- gpt_h2, &gpt_e2);
+ gpt_h2, &gpt_e2, false);
if (is_gpt1_valid && is_gpt2_valid) {
ret = 0;
@@ -1023,12 +1087,13 @@ static int is_pmbr_valid(legacy_mbr *mbr)
* lba is the logical block address of the GPT header to test
* gpt is a GPT header ptr, filled on return.
* ptes is a PTEs ptr, filled on return.
+ * cache is a bool, true to use the cached gpt_pte from previous call