gpt: read entries table at the same time as the header

I personally think this reads easier. Also has the side effect of
directly comparing the primary and backup tables instead of presuming
they are equal if the crc32 matches.
This commit is contained in:
Michael Marineau 2016-09-21 15:29:55 -07:00
parent f24685b22e
commit 5342b880f4

View file

@ -32,6 +32,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t grub_gpt_magic[] = GRUB_GPT_HEADER_MAGIC;
static grub_err_t
grub_gpt_read_entries (grub_disk_t disk, grub_gpt_t gpt,
struct grub_gpt_header *header,
void **ret_entries,
grub_size_t *ret_entries_size);
char *
grub_gpt_guid_to_str (grub_gpt_guid_t *guid)
@ -401,12 +406,21 @@ grub_gpt_read_primary (grub_disk_t disk, grub_gpt_t gpt)
return grub_errno;
gpt->status |= GRUB_GPT_PRIMARY_HEADER_VALID;
if (grub_gpt_read_entries (disk, gpt, &gpt->primary,
&gpt->entries, &gpt->entries_size))
return grub_errno;
gpt->status |= GRUB_GPT_PRIMARY_ENTRIES_VALID;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_gpt_read_backup (grub_disk_t disk, grub_gpt_t gpt)
{
void *entries = NULL;
grub_size_t entries_size;
grub_uint64_t sector;
grub_disk_addr_t addr;
@ -434,12 +448,35 @@ grub_gpt_read_backup (grub_disk_t disk, grub_gpt_t gpt)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid backup GPT LBA");
gpt->status |= GRUB_GPT_BACKUP_HEADER_VALID;
if (grub_gpt_read_entries (disk, gpt, &gpt->backup,
&entries, &entries_size))
return grub_errno;
if (gpt->status & GRUB_GPT_PRIMARY_ENTRIES_VALID)
{
if (entries_size != gpt->entries_size ||
grub_memcmp (entries, gpt->entries, entries_size) != 0)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "backup GPT out of sync");
grub_free (entries);
}
else
{
gpt->entries = entries;
gpt->entries_size = entries_size;
}
gpt->status |= GRUB_GPT_BACKUP_ENTRIES_VALID;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_gpt_read_entries (grub_disk_t disk, grub_gpt_t gpt,
struct grub_gpt_header *header)
struct grub_gpt_header *header,
void **ret_entries,
grub_size_t *ret_entries_size)
{
void *entries = NULL;
grub_uint32_t count, size, crc;
@ -481,9 +518,8 @@ grub_gpt_read_entries (grub_disk_t disk, grub_gpt_t gpt,
goto fail;
}
grub_free (gpt->entries);
gpt->entries = entries;
gpt->entries_size = entries_size;
*ret_entries = entries;
*ret_entries_size = entries_size;
return GRUB_ERR_NONE;
fail:
@ -522,30 +558,7 @@ grub_gpt_read (grub_disk_t disk)
grub_gpt_read_backup (disk, gpt);
/* If either succeeded clear any possible error from the other. */
if (gpt->status & GRUB_GPT_PRIMARY_HEADER_VALID ||
gpt->status & GRUB_GPT_BACKUP_HEADER_VALID)
grub_errno = GRUB_ERR_NONE;
else
goto fail;
/* Similarly, favor the value or error from the primary table. */
if (gpt->status & GRUB_GPT_BACKUP_HEADER_VALID &&
!grub_gpt_read_entries (disk, gpt, &gpt->backup))
{
grub_dprintf ("gpt", "read valid backup GPT from %s\n", disk->name);
gpt->status |= GRUB_GPT_BACKUP_ENTRIES_VALID;
}
grub_errno = GRUB_ERR_NONE;
if (gpt->status & GRUB_GPT_PRIMARY_HEADER_VALID &&
!grub_gpt_read_entries (disk, gpt, &gpt->primary))
{
grub_dprintf ("gpt", "read valid primary GPT from %s\n", disk->name);
gpt->status |= GRUB_GPT_PRIMARY_ENTRIES_VALID;
}
if (gpt->status & GRUB_GPT_PRIMARY_ENTRIES_VALID ||
gpt->status & GRUB_GPT_BACKUP_ENTRIES_VALID)
if (grub_gpt_primary_valid (gpt) || grub_gpt_backup_valid (gpt))
grub_errno = GRUB_ERR_NONE;
else
goto fail;