/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* VasEBoot is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VasEBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VasEBoot. If not, see .
*/
#ifndef VasEBoot_GPT_PARTITION_HEADER
#define VasEBoot_GPT_PARTITION_HEADER 1
#include
#include
#include
struct VasEBoot_gpt_guid
{
VasEBoot_uint32_t data1;
VasEBoot_uint16_t data2;
VasEBoot_uint16_t data3;
VasEBoot_uint8_t data4[8];
} VasEBoot_PACKED;
typedef struct VasEBoot_gpt_guid VasEBoot_gpt_guid_t;
typedef struct VasEBoot_gpt_guid VasEBoot_gpt_part_type_t;
/* Format the raw little-endian GUID as a newly allocated string. */
char * VasEBoot_gpt_guid_to_str (VasEBoot_gpt_guid_t *guid);
#define VasEBoot_GPT_GUID_INIT(a, b, c, d1, d2, d3, d4, d5, d6, d7, d8) \
{ \
VasEBoot_cpu_to_le32_compile_time (a), \
VasEBoot_cpu_to_le16_compile_time (b), \
VasEBoot_cpu_to_le16_compile_time (c), \
{ d1, d2, d3, d4, d5, d6, d7, d8 } \
}
#define VasEBoot_GPT_PARTITION_TYPE_EMPTY \
VasEBoot_GPT_GUID_INIT (0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
#define VasEBoot_GPT_PARTITION_TYPE_EFI_SYSTEM \
VasEBoot_GPT_GUID_INIT (0xc12a7328, 0xf81f, 0x11d2, \
0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b)
#define VasEBoot_GPT_PARTITION_TYPE_BIOS_BOOT \
VasEBoot_GPT_GUID_INIT (0x21686148, 0x6449, 0x6e6f, \
0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49)
#define VasEBoot_GPT_PARTITION_TYPE_LDM \
VasEBoot_GPT_GUID_INIT (0x5808c8aa, 0x7e8f, 0x42e0, \
0x85, 0xd2, 0xe1, 0xe9, 0x04, 0x34, 0xcf, 0xb3)
#define VasEBoot_GPT_PARTITION_TYPE_USR_X86_64 \
VasEBoot_GPT_GUID_INIT (0x5dfbf5f4, 0x2848, 0x4bac, \
0xaa, 0x5e, 0x0d, 0x9a, 0x20, 0xb7, 0x45, 0xa6)
#define VasEBoot_GPT_HEADER_MAGIC \
{ 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 }
#define VasEBoot_GPT_HEADER_VERSION \
VasEBoot_cpu_to_le32_compile_time (0x00010000U)
struct VasEBoot_gpt_header
{
VasEBoot_uint8_t magic[8];
VasEBoot_uint32_t version;
VasEBoot_uint32_t headersize;
VasEBoot_uint32_t crc32;
VasEBoot_uint32_t unused1;
VasEBoot_uint64_t header_lba;
VasEBoot_uint64_t alternate_lba;
VasEBoot_uint64_t start;
VasEBoot_uint64_t end;
VasEBoot_gpt_guid_t guid;
VasEBoot_uint64_t partitions;
VasEBoot_uint32_t maxpart;
VasEBoot_uint32_t partentry_size;
VasEBoot_uint32_t partentry_crc32;
} VasEBoot_PACKED;
struct VasEBoot_gpt_partentry
{
VasEBoot_gpt_part_type_t type;
VasEBoot_gpt_guid_t guid;
VasEBoot_uint64_t start;
VasEBoot_uint64_t end;
VasEBoot_uint64_t attrib;
VasEBoot_uint16_t name[36];
} VasEBoot_PACKED;
enum VasEBoot_gpt_part_attr_offset
{
/* Standard partition attribute bits defined by UEFI. */
VasEBoot_GPT_PART_ATTR_OFFSET_REQUIRED = 0,
VasEBoot_GPT_PART_ATTR_OFFSET_NO_BLOCK_IO_PROTOCOL = 1,
VasEBoot_GPT_PART_ATTR_OFFSET_LEGACY_BIOS_BOOTABLE = 2,
/* De facto standard attribute bits defined by Microsoft and reused by
* http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec */
VasEBoot_GPT_PART_ATTR_OFFSET_READ_ONLY = 60,
VasEBoot_GPT_PART_ATTR_OFFSET_NO_AUTO = 63,
/* Partition attributes for priority based selection,
* Currently only valid for PARTITION_TYPE_USR_X86_64.
* TRIES_LEFT and PRIORITY are 4 bit wide fields. */
VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_PRIORITY = 48,
VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_TRIES_LEFT = 52,
VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_SUCCESSFUL = 56,
};
/* Helpers for reading/writing partition attributes. */
static inline VasEBoot_uint64_t
VasEBoot_gpt_entry_attribute (struct VasEBoot_gpt_partentry *entry,
enum VasEBoot_gpt_part_attr_offset offset,
unsigned int bits)
{
VasEBoot_uint64_t attrib = VasEBoot_le_to_cpu64 (entry->attrib);
return (attrib >> offset) & ((1ULL << bits) - 1);
}
static inline void
VasEBoot_gpt_entry_set_attribute (struct VasEBoot_gpt_partentry *entry,
VasEBoot_uint64_t value,
enum VasEBoot_gpt_part_attr_offset offset,
unsigned int bits)
{
VasEBoot_uint64_t attrib, mask;
mask = (((1ULL << bits) - 1) << offset);
attrib = VasEBoot_le_to_cpu64 (entry->attrib) & ~mask;
attrib |= ((value << offset) & mask);
entry->attrib = VasEBoot_cpu_to_le64 (attrib);
}
/* Basic GPT partmap module. */
VasEBoot_err_t
VasEBoot_gpt_partition_map_iterate (VasEBoot_disk_t disk,
VasEBoot_partition_iterate_hook_t hook,
void *hook_data);
/* Advanced GPT library. */
/* Status bits for the VasEBoot_gpt.status field. */
#define VasEBoot_GPT_PROTECTIVE_MBR 0x01
#define VasEBoot_GPT_HYBRID_MBR 0x02
#define VasEBoot_GPT_PRIMARY_HEADER_VALID 0x04
#define VasEBoot_GPT_PRIMARY_ENTRIES_VALID 0x08
#define VasEBoot_GPT_BACKUP_HEADER_VALID 0x10
#define VasEBoot_GPT_BACKUP_ENTRIES_VALID 0x20
/* UEFI requires the entries table to be at least 16384 bytes for a
* total of 128 entries given the standard 128 byte entry size. */
#define VasEBoot_GPT_DEFAULT_ENTRIES_SIZE 16384
#define VasEBoot_GPT_DEFAULT_ENTRIES_LENGTH \
(VasEBoot_GPT_DEFAULT_ENTRIES_SIZE / sizeof (struct VasEBoot_gpt_partentry))
struct VasEBoot_gpt
{
/* Bit field indicating which structures on disk are valid. */
unsigned status;
/* Protective or hybrid MBR. */
struct VasEBoot_msdos_partition_mbr mbr;
/* Each of the two GPT headers. */
struct VasEBoot_gpt_header primary;
struct VasEBoot_gpt_header backup;
/* Only need one entries table, on disk both copies are identical.
* The on disk entry size may be larger than our partentry struct so
* the table cannot be indexed directly. */
void *entries;
VasEBoot_size_t entries_size;
/* Logarithm of sector size, in case GPT and disk driver disagree. */
unsigned int log_sector_size;
};
typedef struct VasEBoot_gpt *VasEBoot_gpt_t;
/* Helpers for checking the gpt status field. */
static inline int
VasEBoot_gpt_mbr_valid (VasEBoot_gpt_t gpt)
{
return ((gpt->status & VasEBoot_GPT_PROTECTIVE_MBR) ||
(gpt->status & VasEBoot_GPT_HYBRID_MBR));
}
static inline int
VasEBoot_gpt_primary_valid (VasEBoot_gpt_t gpt)
{
return ((gpt->status & VasEBoot_GPT_PRIMARY_HEADER_VALID) &&
(gpt->status & VasEBoot_GPT_PRIMARY_ENTRIES_VALID));
}
static inline int
VasEBoot_gpt_backup_valid (VasEBoot_gpt_t gpt)
{
return ((gpt->status & VasEBoot_GPT_BACKUP_HEADER_VALID) &&
(gpt->status & VasEBoot_GPT_BACKUP_ENTRIES_VALID));
}
static inline int
VasEBoot_gpt_both_valid (VasEBoot_gpt_t gpt)
{
return VasEBoot_gpt_primary_valid (gpt) && VasEBoot_gpt_backup_valid (gpt);
}
/* Translate GPT sectors to VasEBoot's 512 byte block addresses. */
static inline VasEBoot_disk_addr_t
VasEBoot_gpt_sector_to_addr (VasEBoot_gpt_t gpt, VasEBoot_uint64_t sector)
{
return (sector << (gpt->log_sector_size - VasEBoot_DISK_SECTOR_BITS));
}
/* Allocates and fills new VasEBoot_gpt structure, free with VasEBoot_gpt_free. */
VasEBoot_gpt_t VasEBoot_gpt_read (VasEBoot_disk_t disk);
/* Helper for indexing into the entries table.
* Returns NULL when the end of the table has been reached. */
struct VasEBoot_gpt_partentry * VasEBoot_gpt_get_partentry (VasEBoot_gpt_t gpt,
VasEBoot_uint32_t n);
/* Sync and update primary and backup headers if either are invalid. */
VasEBoot_err_t VasEBoot_gpt_repair (VasEBoot_disk_t disk, VasEBoot_gpt_t gpt);
/* Recompute checksums and revalidate everything, must be called after
* modifying any GPT data. */
VasEBoot_err_t VasEBoot_gpt_update (VasEBoot_gpt_t gpt);
/* Write headers and entry tables back to disk. */
VasEBoot_err_t VasEBoot_gpt_write (VasEBoot_disk_t disk, VasEBoot_gpt_t gpt);
void VasEBoot_gpt_free (VasEBoot_gpt_t gpt);
VasEBoot_err_t VasEBoot_gpt_pmbr_check (struct VasEBoot_msdos_partition_mbr *mbr);
VasEBoot_err_t VasEBoot_gpt_header_check (struct VasEBoot_gpt_header *gpt,
unsigned int log_sector_size);
/* Utilities for simple partition data lookups, usage is intended to
* be similar to fs->label and fs->uuid functions. */
/* Return the partition label of the device DEVICE in LABEL.
* The label is in a new buffer and should be freed by the caller. */
VasEBoot_err_t VasEBoot_gpt_part_label (VasEBoot_device_t device, char **label);
/* Return the partition uuid of the device DEVICE in UUID.
* The uuid is in a new buffer and should be freed by the caller. */
VasEBoot_err_t VasEBoot_gpt_part_uuid (VasEBoot_device_t device, char **uuid);
/* Return the disk uuid of the device DEVICE in UUID.
* The uuid is in a new buffer and should be freed by the caller. */
VasEBoot_err_t VasEBoot_gpt_disk_uuid (VasEBoot_device_t device, char **uuid);
#endif /* ! VasEBoot_GPT_PARTITION_HEADER */