first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+153
View File
@@ -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;
}
+31
View File
@@ -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
+270
View File
@@ -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);
}
+47
View File
@@ -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;
}
+148
View File
@@ -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;
}
+41
View File
@@ -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);
+15
View File
@@ -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