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:
parent
f24685b22e
commit
5342b880f4
1 changed files with 41 additions and 28 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue