** Copyright 2003-2004, Axel DΓΆrfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the MIT License.
*/
#include "apple.h"
#include <ddm_modules.h>
#include <disk_device_types.h>
#include <KernelExport.h>
#ifdef _BOOT_MODE
# include <boot/partitions.h>
#else
# include <DiskDeviceTypes.h>
#endif
#include <util/kernel_cpp.h>
#include <unistd.h>
#include <string.h>
#define TRACE_APPLE 0
#if TRACE_APPLE
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
#define APPLE_PARTITION_MODULE_NAME "partitioning_systems/apple/v1"
static const char *kApplePartitionTypes[] = {
"partition_map",
"Driver",
"Driver43",
"MFS",
"HFS",
"Unix_SVR2",
"PRODOS",
"Free",
"Scratch",
"Driver_ATA",
"Driver_ATAPI",
"Driver43_CD",
"FWDriver",
"Void",
"Patches",
NULL
};
#if 0
static const char *kOtherPartitionTypes[] = {
"Be_BFS",
};
#endif
static status_t
get_next_partition(int fd, apple_driver_descriptor &descriptor, uint32 &cookie,
apple_partition_map &partition)
{
uint32 block = cookie;
do {
ssize_t bytesRead = read_pos(fd, (off_t)block * descriptor.BlockSize(),
(void *)&partition, sizeof(apple_partition_map));
if (bytesRead < (ssize_t)sizeof(apple_partition_map))
return B_ERROR;
block++;
} while (cookie == 0 && block < 64 && !partition.HasValidSignature());
if (!partition.HasValidSignature()) {
if (cookie)
return B_ENTRY_NOT_FOUND;
return B_ERROR;
}
if (!cookie && (strncmp(partition.type, "Apple_", 6)
|| strcmp(partition.type + 6, kApplePartitionTypes[0])))
return B_ERROR;
cookie = block;
return B_OK;
}
static status_t
apple_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
}
return B_ERROR;
}
static float
apple_identify_partition(int fd, partition_data *partition, void **_cookie)
{
struct apple_driver_descriptor *descriptor;
uint8 buffer[512];
if (read_pos(fd, 0, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
return B_ERROR;
descriptor = (apple_driver_descriptor *)buffer;
TRACE(("apple: read first chunk (signature = %x)\n", descriptor->signature));
if (!descriptor->HasValidSignature())
return B_ERROR;
TRACE(("apple: valid partition descriptor!\n"));
descriptor = new apple_driver_descriptor();
memcpy(descriptor, buffer, sizeof(apple_driver_descriptor));
*_cookie = (void *)descriptor;
return 0.5f;
}
static status_t
apple_scan_partition(int fd, partition_data *partition, void *_cookie)
{
TRACE(("apple_scan_partition(cookie = %p)\n", _cookie));
apple_driver_descriptor &descriptor = *(apple_driver_descriptor *)_cookie;
partition->status = B_PARTITION_VALID;
partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
| B_PARTITION_READ_ONLY;
partition->content_size = descriptor.BlockSize() * descriptor.BlockCount();
apple_partition_map partitionMap;
uint32 index = 0, cookie = 0;
status_t status;
while ((status = get_next_partition(fd, descriptor, cookie, partitionMap)) == B_OK) {
TRACE(("apple: found partition: name = \"%s\", type = \"%s\"\n",
partitionMap.name, partitionMap.type));
if (partitionMap.Start(descriptor) + partitionMap.Size(descriptor) > (uint64)partition->size) {
TRACE(("apple: child partition exceeds existing space (%lld bytes)\n",
partitionMap.Size(descriptor)));
continue;
}
partition_data *child = create_child_partition(partition->id, index++,
partition->offset + partitionMap.Start(descriptor),
partitionMap.Size(descriptor), -1);
if (child == NULL) {
TRACE(("apple: Creating child at index %ld failed\n", index - 1));
return B_ERROR;
}
child->block_size = partition->block_size;
}
if (status == B_ENTRY_NOT_FOUND)
return B_OK;
return status;
}
static void
apple_free_identify_partition_cookie(partition_data *partition, void *_cookie)
{
delete (apple_driver_descriptor *)_cookie;
}
#ifndef _BOOT_MODE
static partition_module_info sApplePartitionModule = {
#else
partition_module_info gApplePartitionModule = {
#endif
{
APPLE_PARTITION_MODULE_NAME,
0,
apple_std_ops
},
"apple",
APPLE_PARTITION_NAME,
0,
apple_identify_partition,
apple_scan_partition,
apple_free_identify_partition_cookie,
NULL,
};
#ifndef _BOOT_MODE
partition_module_info *modules[] = {
&sApplePartitionModule,
NULL
};
#endif