first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple 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 Inc.
|
||||
#
|
||||
|
||||
LIBPARTITION_DIR := $(GET_LOCAL_DIR)
|
||||
LIBPARTITION_BUILD := $(call TOLIBDIR,$(LIBPARTITION_DIR)/LIBPARTITION.a)
|
||||
COMMONLIBS += LIBPARTITION
|
||||
|
||||
# Only process the remainder of the makefile if we are building libraries
|
||||
#
|
||||
ifeq ($(MAKEPHASE),libraries)
|
||||
|
||||
LIBPARTITION_OBJS := \
|
||||
$(LIBPARTITION_DIR)/gpt.o \
|
||||
$(LIBPARTITION_DIR)/lwvm.o \
|
||||
$(LIBPARTITION_DIR)/mbr.o \
|
||||
$(LIBPARTITION_DIR)/partition.o
|
||||
|
||||
LIBPARTITION_OBJS := $(call TOLIBOBJDIR,$(LIBPARTITION_OBJS))
|
||||
|
||||
ALL_DEPS += $(LIBPARTITION_OBJS:%o=%d)
|
||||
|
||||
$(LIBPARTITION_BUILD): $(LIBPARTITION_OBJS)
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 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/partition.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/cksum.h>
|
||||
|
||||
/*
|
||||
* Cutdown types from LwVMFormat.h
|
||||
*/
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define kLwVMMaxChunks 1024
|
||||
#define kLwVMMaxPartitions 8
|
||||
#define kLwVMPartitionAttributeEffaceable (1ULL<<48)
|
||||
|
||||
#define LwVM_CME_TO_PARTITION(_CME) (((_CME) >> 12) & 0xf)
|
||||
#define LwVM_CME_TO_INDEX(_CME) ((_CME) & 0x3ff)
|
||||
|
||||
typedef unsigned char uuid_t[16];
|
||||
typedef uint16_t LwVMChunkMapEntry;
|
||||
typedef uint16_t LwVMChunkIndex;
|
||||
|
||||
static const uuid_t LwVMMediaUUIDv1 = {
|
||||
0xB1, 0x89, 0xA5, 0x19, 0x4F, 0x59, 0x4B, 0x1D,
|
||||
0xAD, 0x44, 0x1E, 0x12, 0x7A, 0xAF, 0x45, 0x39
|
||||
};
|
||||
|
||||
static const uuid_t LwVMMediaUUIDv2 = {
|
||||
0x6A, 0x90, 0x88, 0xCF, 0x8A, 0xFD, 0x63, 0x0A,
|
||||
0xE3, 0x51, 0xE2, 0x48, 0x87, 0xE0, 0xB9, 0x8B
|
||||
};
|
||||
|
||||
static const uint16_t UpgradePartitionName[] = {
|
||||
'U', 'p', 'd', 'a', 't', 'e', '\0',
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uuid_t miLwVMUUID;
|
||||
uuid_t miThisUUID;
|
||||
uint64_t miBaseMediaSize;
|
||||
uint32_t miPartitionCount;
|
||||
uint32_t miCRC; // not present in v1
|
||||
} LwVMMediaInfo;
|
||||
|
||||
typedef struct {
|
||||
uuid_t peType;
|
||||
uuid_t peUUID;
|
||||
uint64_t peStart;
|
||||
uint64_t peEnd;
|
||||
uint64_t peAttributes;
|
||||
uint16_t peName[36];
|
||||
} LwVMPartitionEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LwVMMediaInfo mhInfo;
|
||||
uint8_t _pad1[512 - sizeof(LwVMMediaInfo)];
|
||||
LwVMPartitionEntry mhPartitionTable[kLwVMMaxPartitions];
|
||||
uint8_t _pad2[1536 -
|
||||
(sizeof(LwVMPartitionEntry) *
|
||||
kLwVMMaxPartitions)];
|
||||
LwVMChunkMapEntry mhChunkMap[kLwVMMaxChunks];
|
||||
} LwVMMediaHeader;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/*
|
||||
* LwVM blockdev
|
||||
*/
|
||||
struct lwvm_partition {
|
||||
struct blockdev thisdev;
|
||||
struct blockdev *parent;
|
||||
uint32_t chunk_size; /* chunk size in blocks */
|
||||
uint32_t chunk_shift; /* log2(chunk_size) */
|
||||
uint32_t chunk_count;
|
||||
uint16_t chunk_map[kLwVMMaxChunks]; /* XXX could dynamically allocate */
|
||||
};
|
||||
|
||||
static void lwvm_scan_partition(struct blockdev *bdev, LwVMMediaHeader *header, int partition);
|
||||
static int lwvm_read_block(struct blockdev *dev, void *ptr, block_addr block, uint32_t count);
|
||||
|
||||
int
|
||||
lwvm_scan(struct blockdev *dev)
|
||||
{
|
||||
LwVMMediaHeader *header;
|
||||
uint32_t i;
|
||||
int ret;
|
||||
uint32_t crc;
|
||||
int tried;
|
||||
uint32_t chunk_shift, chunk_size;
|
||||
|
||||
ret = -1;
|
||||
header = NULL;
|
||||
header = memalign(sizeof(*header), dev->alignment);
|
||||
memset(header, 0, sizeof(*header));
|
||||
|
||||
/* do required geometry calculations */
|
||||
chunk_shift = 32 - clz((uint32_t)((dev->total_len - 1) / kLwVMMaxChunks));
|
||||
chunk_size = 1 << chunk_shift;
|
||||
|
||||
/* read the media header */
|
||||
for (tried = 0; tried < 2; tried++) {
|
||||
/*
|
||||
* Read either the main header from 0, or the backup header from the last block of the
|
||||
* first chunk.
|
||||
*/
|
||||
if (blockdev_read(dev,
|
||||
header,
|
||||
(tried ? (((off_t)chunk_size << dev->block_shift) - dev->block_size) : 0),
|
||||
sizeof(*header))
|
||||
!= sizeof(*header))
|
||||
continue;
|
||||
|
||||
/* check to see whether it's LwVM */
|
||||
if (memcmp(header->mhInfo.miLwVMUUID, LwVMMediaUUIDv2, 16) == 0) {
|
||||
crc = header->mhInfo.miCRC;
|
||||
header->mhInfo.miCRC = 0;
|
||||
if (crc != crc32((void *)header, sizeof(*header))) {
|
||||
/* v2 but corrupt */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (header->mhInfo.miPartitionCount > kLwVMMaxPartitions)
|
||||
continue;
|
||||
|
||||
goto valid;
|
||||
}
|
||||
if (memcmp(header->mhInfo.miLwVMUUID, LwVMMediaUUIDv1, 16) == 0) {
|
||||
if (header->mhInfo.miPartitionCount > kLwVMMaxPartitions)
|
||||
continue;
|
||||
|
||||
goto valid;
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
|
||||
valid:
|
||||
/* create partitions */
|
||||
for (i = 0; i < header->mhInfo.miPartitionCount; i++)
|
||||
lwvm_scan_partition(dev, header, i);
|
||||
|
||||
ret = header->mhInfo.miPartitionCount;
|
||||
out:
|
||||
if (NULL != header)
|
||||
free(header);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
lwvm_scan_partition(struct blockdev *dev, LwVMMediaHeader *header, int partition)
|
||||
{
|
||||
struct lwvm_partition *part;
|
||||
LwVMChunkMapEntry cme;
|
||||
LwVMChunkIndex ci;
|
||||
int i;
|
||||
char dev_name[32];
|
||||
block_addr total_blocks;
|
||||
uint64_t partition_blockcount;
|
||||
|
||||
if (header->mhPartitionTable[partition].peAttributes & kLwVMPartitionAttributeEffaceable) {
|
||||
#if DEBUG_BUILD
|
||||
printf("enumerating effaceable LwVM partition\n");
|
||||
#else
|
||||
/* ignore effaceable partitions, as we can't get their keys */
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
part = calloc(sizeof(*part), 1);
|
||||
|
||||
part->parent = dev;
|
||||
|
||||
/* do required geometry calculations */
|
||||
total_blocks = dev->total_len >> dev->block_shift;
|
||||
part->chunk_shift = 32 - clz((uint32_t)((total_blocks - 1) / kLwVMMaxChunks));
|
||||
part->chunk_size = 1 << part->chunk_shift;
|
||||
|
||||
/* scan chunk map in header for chunks belonging to this partition */
|
||||
for (i = 1; i < kLwVMMaxChunks; i++) {
|
||||
|
||||
cme = header->mhChunkMap[i];
|
||||
|
||||
/* if it matches this partition */
|
||||
if (LwVM_CME_TO_PARTITION(cme) == partition) {
|
||||
/* register it in the map */
|
||||
ci = LwVM_CME_TO_INDEX(cme);
|
||||
part->chunk_map[ci] = i;
|
||||
if (ci >= part->chunk_count)
|
||||
part->chunk_count = ci + 1;
|
||||
}
|
||||
}
|
||||
|
||||
partition_blockcount = header->mhPartitionTable[partition].peEnd - header->mhPartitionTable[partition].peStart;
|
||||
|
||||
/* construct the device */
|
||||
snprintf(dev_name, sizeof(dev_name), "%s%c", dev->name, 'a' + partition);
|
||||
construct_blockdev(&part->thisdev, dev_name, partition_blockcount, dev->block_size);
|
||||
part->thisdev.read_block_hook = &lwvm_read_block;
|
||||
blockdev_set_buffer_alignment(&part->thisdev, dev->alignment);
|
||||
|
||||
/* Check if this is the upgrade partition */
|
||||
if (memcmp(UpgradePartitionName, header->mhPartitionTable[partition].peName, sizeof(UpgradePartitionName)) == 0) {
|
||||
part->thisdev.flags |= BLOCKDEV_FLAG_UPGRADE_PARTITION;
|
||||
}
|
||||
|
||||
/* register the device */
|
||||
register_blockdev(&part->thisdev);
|
||||
}
|
||||
|
||||
static int
|
||||
lwvm_read_block(struct blockdev *dev, void *ptr, block_addr block, uint32_t count)
|
||||
{
|
||||
struct lwvm_partition *part;
|
||||
LwVMChunkIndex ci;
|
||||
uint8_t *buf;
|
||||
off_t offset;
|
||||
size_t read_size;
|
||||
block_addr chunk_start;
|
||||
size_t resid;
|
||||
int ret;
|
||||
|
||||
part = (struct lwvm_partition *)dev;
|
||||
buf = (uint8_t *)ptr;
|
||||
resid = count;
|
||||
|
||||
/* iterate reading from chunk(s) until we are done */
|
||||
while (resid > 0) {
|
||||
|
||||
/*
|
||||
* Compute the chunk index into the partition, and the
|
||||
* block offset into the chunk.
|
||||
*/
|
||||
ci = block >> part->chunk_shift;
|
||||
offset = block & (part->chunk_size - 1);
|
||||
|
||||
/* are we off the end of the partition? */
|
||||
if (ci >= part->chunk_count)
|
||||
break;
|
||||
|
||||
/* find the starting block for the indexed chunk */
|
||||
chunk_start = (block_addr)part->chunk_map[ci] << part->chunk_shift;;
|
||||
|
||||
/* read no more than one chunk */
|
||||
ASSERT(offset >= 0);
|
||||
read_size = __min(resid, part->chunk_size - (size_t)offset);
|
||||
|
||||
/* do the read */
|
||||
ret = blockdev_read_block(part->parent, buf, chunk_start + offset, read_size);
|
||||
if (ret <= 0)
|
||||
return(ret);
|
||||
|
||||
/* update for data read */
|
||||
resid -= ret;
|
||||
block += ret;
|
||||
buf += ret << dev->block_shift;
|
||||
}
|
||||
return(count - resid);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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/partition.h>
|
||||
#include <lib/blockdev.h>
|
||||
|
||||
#include "partition_private.h"
|
||||
|
||||
int
|
||||
mbr_scan(struct mbr_partition *part, struct blockdev *dev, struct partition_entry *entry_list)
|
||||
{
|
||||
uint32_t i;
|
||||
int scanned_entries = 0;
|
||||
|
||||
for (i=0; i < MBR_PARTITIONS; i++) {
|
||||
dprintf(DEBUG_SPEW, "MBR part %d: id 0x%x, startlba %d, sizelba %d\n", i, part[i].sysid, part[i].startlba, part[i].size);
|
||||
|
||||
/* needs to be spiffed up a bit, but detect based on id */
|
||||
if (part[i].sysid != 0) {
|
||||
off_t offset;
|
||||
off_t len;
|
||||
|
||||
offset = (off_t)part[i].startlba << dev->block_shift;
|
||||
len = (off_t)part[i].size << dev->block_shift;
|
||||
|
||||
entry_list[scanned_entries].id = part[i].sysid;
|
||||
entry_list[scanned_entries].valid = true;
|
||||
entry_list[scanned_entries].offset = offset;
|
||||
entry_list[scanned_entries].len = len;
|
||||
dprintf(DEBUG_SPEW, "MBR part %d: id 0x%x, off 0x%llx, size 0x%llx, blocksize %d\n", scanned_entries, part[i].sysid,
|
||||
entry_list[scanned_entries].offset, entry_list[scanned_entries].len, dev->block_size);
|
||||
scanned_entries++;
|
||||
}
|
||||
}
|
||||
|
||||
return scanned_entries;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2007, 2009-2011, 2014 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple 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 Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <compiler.h>
|
||||
#include <lib/mib.h>
|
||||
#include <lib/partition.h>
|
||||
#include <lib/blockdev.h>
|
||||
|
||||
#include "partition_private.h"
|
||||
|
||||
static bool
|
||||
partition_overlap_check(struct partition_entry *part, int num_entries)
|
||||
{
|
||||
int i, j;
|
||||
bool overlap;
|
||||
|
||||
overlap = false;
|
||||
for (i=0; i < num_entries; i++) {
|
||||
off_t ioff = part[i].offset;
|
||||
off_t iend = part[i].offset + part[i].len;
|
||||
for (j=0; j < num_entries; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
off_t joff = part[j].offset;
|
||||
off_t jend = part[j].offset + part[j].len;
|
||||
|
||||
/* is j's starting offset within i's range */
|
||||
if ((joff >= ioff) && (joff < iend))
|
||||
overlap = true;
|
||||
|
||||
/* is j's end within i's range */
|
||||
if ((jend <= iend) && (jend > ioff))
|
||||
overlap = true;
|
||||
|
||||
/* does j completely cover i */
|
||||
if ((joff <= ioff) && (jend >= iend))
|
||||
overlap = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap)
|
||||
dprintf(DEBUG_INFO, "partition_scan: some partitions overlap, probably garbage partition data\n");
|
||||
return overlap;
|
||||
}
|
||||
|
||||
static bool
|
||||
partition_extents_check(struct partition_entry *part, int num_entries, struct blockdev *dev)
|
||||
{
|
||||
int i;
|
||||
bool toobig;
|
||||
|
||||
toobig = false;
|
||||
for (i=0; i < num_entries; i++) {
|
||||
if (part[i].offset + part[i].len > dev->total_len) {
|
||||
dprintf(DEBUG_INFO, "partition %i overshoots size of device\n", i);
|
||||
toobig = true;
|
||||
}
|
||||
}
|
||||
|
||||
return toobig;
|
||||
}
|
||||
|
||||
static int
|
||||
partition_scan(struct blockdev *dev, struct partition_entry *entry_list, size_t num_entries)
|
||||
{
|
||||
int scanned_entries;
|
||||
int err;
|
||||
struct mbr_partition *part;
|
||||
int mbr_bytes;
|
||||
|
||||
scanned_entries = 0;
|
||||
part = NULL;
|
||||
mbr_bytes = MBR_PARTITIONS * sizeof(struct mbr_partition);
|
||||
|
||||
/* read what we expect to be an MBR from the beginning of the blockdev */
|
||||
part = memalign(mbr_bytes, mib_get_size(kMIBPlatformCacheLineSize));
|
||||
|
||||
/* read *just* the partition table */
|
||||
err = blockdev_read(dev, part, MBR_ADDRESS, mbr_bytes);
|
||||
if (err != mbr_bytes) {
|
||||
dprintf(DEBUG_INFO, "mbr: read error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* scan it as an mbr */
|
||||
scanned_entries = mbr_scan(part, dev, entry_list);
|
||||
|
||||
/* does it look like it might be GPT? */
|
||||
if ((scanned_entries == 1) && (entry_list[0].id == 0xee))
|
||||
scanned_entries = gpt_scan(dev, entry_list);
|
||||
|
||||
/* do an overlap check to make sure this is a sort of reasonable layout */
|
||||
if (partition_overlap_check(entry_list, scanned_entries)) {
|
||||
scanned_entries = 0;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (NULL != part)
|
||||
free(part);
|
||||
return scanned_entries;
|
||||
}
|
||||
|
||||
int partition_scan_and_publish_subdevices(const char *dev_name)
|
||||
{
|
||||
struct partition_entry entries[MAX_PARTITIONS];
|
||||
int found;
|
||||
int i;
|
||||
struct blockdev *dev;
|
||||
|
||||
dev = lookup_blockdev(dev_name);
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
/* scan for LwVM partitions */
|
||||
found = lwvm_scan(dev);
|
||||
if (found > 0)
|
||||
return found;
|
||||
|
||||
/* scan for regular partitions */
|
||||
found = partition_scan(dev, entries, MAX_PARTITIONS);
|
||||
for (i=0; i < found; i++) {
|
||||
/* publish subdevices */
|
||||
struct blockdev *subdev;
|
||||
char subdev_name[32];
|
||||
|
||||
snprintf(subdev_name, 32, "%s%c", dev_name, 'a' + i);
|
||||
|
||||
// make sure it doesn't already exist
|
||||
if (lookup_blockdev(subdev_name))
|
||||
continue;
|
||||
|
||||
subdev = create_subdev_blockdev(subdev_name, dev, entries[i].offset, entries[i].len, dev->block_size);
|
||||
if (subdev)
|
||||
register_blockdev(subdev);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2011 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.
|
||||
*/
|
||||
|
||||
#define MAX_PARTITIONS 8
|
||||
|
||||
struct partition_entry {
|
||||
bool valid;
|
||||
uint32_t id;
|
||||
off_t offset;
|
||||
uint64_t len;
|
||||
};
|
||||
|
||||
extern int gpt_scan(struct blockdev *dev, struct partition_entry *entry_list);
|
||||
|
||||
#define MBR_PARTITIONS 4
|
||||
#define MBR_ADDRESS 0x1be
|
||||
|
||||
struct mbr_partition {
|
||||
uint8_t bootid;
|
||||
uint8_t starthead;
|
||||
uint8_t startsect;
|
||||
uint8_t startcyl;
|
||||
uint8_t sysid;
|
||||
uint8_t endhead;
|
||||
uint8_t endsect;
|
||||
uint8_t endcyl;
|
||||
uint32_t startlba;
|
||||
uint32_t size;
|
||||
} __packed;
|
||||
|
||||
extern int mbr_scan(struct mbr_partition *part, struct blockdev *dev, struct partition_entry *entry_list);
|
||||
|
||||
extern int lwvm_scan(struct blockdev *dev);
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright (C) 20010, 2013-2014 Apple Inc. All rights reserved.
|
||||
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple 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 Inc.
|
||||
#
|
||||
|
||||
MODULES += lib/cksum
|
||||
LIBRARY_MODULES += lib/partition
|
||||
OPTIONS += WITH_PARTITION=1
|
||||
|
||||
Reference in new issue
Block a user