iBoot/lib/partition/gpt.c

154 lines
5.0 KiB
C

/*
* Copyright (C) 2010-2011, 2013-2014 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <debug.h>
#include <compiler.h>
#include <lib/mib.h>
#include <lib/partition.h>
#include <lib/blockdev.h>
#include "partition_private.h"
struct gpt_pth {
char sig[8];
#define PTH_SIGNATURE "EFI PART"
uint32_t revision;
#define PTH_REVISION 0x00010000
uint32_t hsize;
uint32_t hcrc;
uint32_t reserved;
uint64_t this_lba;
uint64_t backup_lba;
uint64_t first_lba;
uint64_t last_lba;
uint8_t uuid[16];
uint64_t ptab_lba;
uint32_t ptab_entrycount;
uint32_t ptab_entrysize;
uint32_t ptab_crc;
};
struct gpt_pte {
uint8_t ptype_uuid[16];
uint8_t unique_uuid[16];
uint64_t first_lba;
uint64_t last_lba;
uint64_t attributes;
#define PATTR_SYSTEM (1ULL<<0)
#define PATTR_READONLY (1ULL<<60)
#define PATTR_HIDDEN (1ULL<<62)
#define PATTR_NOMOUNT (1ULL<<63)
uint16_t name[36];
};
/*
* Known UUIDs. Note that these are in the inexplicable
* pre-swapped form.
*/
static uint8_t ptype_hfs[] __unused = {
0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
};
static uint8_t ptype_bdp[] __unused = {
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7
};
int
gpt_scan(struct blockdev *dev, struct partition_entry *entry_list)
{
unsigned int entry, part;
off_t cursor;
struct gpt_pth *pth;
struct gpt_pte *pte;
const char *reason;
size_t cacheLineSize = mib_get_size(kMIBPlatformCacheLineSize);
pth = NULL;
pte = NULL;
entry = 0;
reason = NULL;
/* allocate buffers */
pth = memalign(sizeof(*pth), cacheLineSize);
pte = memalign(sizeof(*pte), cacheLineSize);
/* read the partition table header from LBA 1 */
if (sizeof(*pth) != blockdev_read(dev, pth, dev->block_size, sizeof(*pth))) {
reason = "read error";
goto out;
}
if (memcmp(pth->sig, PTH_SIGNATURE, 8)) {
reason = "bad signature";
goto out;
}
if (PTH_REVISION != pth->revision) {
reason = "bad revision";
goto out;
}
if (pth->ptab_entrysize < sizeof(*pte)) {
reason = "entries too small";
goto out;
}
/* set up to scan partition table entries */
cursor = pth->ptab_lba << dev->block_shift;
part = 0;
while ((entry < MAX_PARTITIONS) && (part++ < pth->ptab_entrycount)) {
/* read an entry */
if (sizeof(*pte) != blockdev_read(dev, pte, cursor, sizeof(*pte))) {
reason = "read error";
goto out;
}
cursor += pth->ptab_entrysize;
/* skip no-mount entries */
if (pte->attributes & PATTR_NOMOUNT) {
continue;
}
/* assume not valid */
entry_list[entry].valid = false;
/* handle recognised partition types */
dprintf(DEBUG_SPEW, "gpt: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
pte->ptype_uuid[0], pte->ptype_uuid[1], pte->ptype_uuid[2], pte->ptype_uuid[3],
pte->ptype_uuid[4], pte->ptype_uuid[5], pte->ptype_uuid[6], pte->ptype_uuid[7],
pte->ptype_uuid[8], pte->ptype_uuid[9], pte->ptype_uuid[10], pte->ptype_uuid[11],
pte->ptype_uuid[12], pte->ptype_uuid[13], pte->ptype_uuid[14], pte->ptype_uuid[15]);
//#if WITH_HFS
if (!memcmp(pte->ptype_uuid, ptype_hfs, 16)) {
entry_list[entry].valid = true;
entry_list[entry].id = 0xaf; /* HFS+ */
}
//#endif
if (!entry_list[entry].valid)
continue;
/* calculate partition layout */
entry_list[entry].offset = (off_t)pte->first_lba << dev->block_shift;
entry_list[entry].len = (off_t)(pte->last_lba - pte->first_lba + 1) << dev->block_shift;
entry++;
}
out:
if (NULL != pte)
free(pte);
if (NULL != pth)
free(pth);
if (NULL != reason)
dprintf(DEBUG_INFO, "gpt: %s\n", reason);
return entry;
}