1/* 2** Copyright 2003-2004, Axel D��rfler, axeld@pinc-software.de. All rights reserved. 3** Distributed under the terms of the MIT License. 4*/ 5 6 7#include "apple.h" 8 9#include <ddm_modules.h> 10#include <disk_device_types.h> 11#include <KernelExport.h> 12#ifdef _BOOT_MODE 13# include <boot/partitions.h> 14#else 15# include <DiskDeviceTypes.h> 16#endif 17#include <util/kernel_cpp.h> 18 19#include <unistd.h> 20#include <string.h> 21 22 23#define TRACE_APPLE 0 24#if TRACE_APPLE 25# define TRACE(x) dprintf x 26#else 27# define TRACE(x) ; 28#endif 29 30#define APPLE_PARTITION_MODULE_NAME "partitioning_systems/apple/v1" 31 32static const char *kApplePartitionTypes[] = { 33 "partition_map", // the partition map itself 34 "Driver", // contains a device driver 35 "Driver43", // the SCSI 4.3 manager 36 "MFS", // Macintosh File System 37 "HFS", // Hierarchical File System (HFS/HFS+) 38 "Unix_SVR2", // UFS 39 "PRODOS", 40 "Free", // unused partition 41 "Scratch", // empty partition 42 "Driver_ATA", // the device driver for an ATA device 43 "Driver_ATAPI", // the device driver for an ATAPI device 44 "Driver43_CD", // an SCSI CD-ROM driver suitable for booting 45 "FWDriver", // a FireWire driver for the device 46 "Void", // dummy partition map entry (used to align entries for CD-ROM) 47 "Patches", 48 NULL 49}; 50#if 0 51static const char *kOtherPartitionTypes[] = { 52 "Be_BFS", // Be's BFS (not specified endian) 53}; 54#endif 55 56static status_t 57get_next_partition(int fd, apple_driver_descriptor &descriptor, uint32 &cookie, 58 apple_partition_map &partition) 59{ 60 uint32 block = cookie; 61 62 // find first partition map if this is the first call, 63 // or else, just load the next block 64 do { 65 ssize_t bytesRead = read_pos(fd, (off_t)block * descriptor.BlockSize(), 66 (void *)&partition, sizeof(apple_partition_map)); 67 if (bytesRead < (ssize_t)sizeof(apple_partition_map)) 68 return B_ERROR; 69 70 block++; 71 } while (cookie == 0 && block < 64 && !partition.HasValidSignature()); 72 73 if (!partition.HasValidSignature()) { 74 if (cookie) 75 return B_ENTRY_NOT_FOUND; 76 77 // we searched for the first partition map entry and failed 78 return B_ERROR; 79 } 80 81 // the first partition map entry must be of type Apple_partition_map 82 if (!cookie && (strncmp(partition.type, "Apple_", 6) 83 || strcmp(partition.type + 6, kApplePartitionTypes[0]))) 84 return B_ERROR; 85 86 // ToDo: warn about unknown types? 87 88 cookie = block; 89 return B_OK; 90} 91 92 93// #pragma mark - 94// Apple public module interface 95 96 97static status_t 98apple_std_ops(int32 op, ...) 99{ 100 switch (op) { 101 case B_MODULE_INIT: 102 case B_MODULE_UNINIT: 103 return B_OK; 104 } 105 106 return B_ERROR; 107} 108 109 110static float 111apple_identify_partition(int fd, partition_data *partition, void **_cookie) 112{ 113 struct apple_driver_descriptor *descriptor; 114 uint8 buffer[512]; 115 116 if (read_pos(fd, 0, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) 117 return B_ERROR; 118 119 descriptor = (apple_driver_descriptor *)buffer; 120 121 TRACE(("apple: read first chunk (signature = %x)\n", descriptor->signature)); 122 123 if (!descriptor->HasValidSignature()) 124 return B_ERROR; 125 126 TRACE(("apple: valid partition descriptor!\n")); 127 128 // ToDo: Should probably call get_next_partition() once to know if there 129 // are any partitions on this disk 130 131 // copy the relevant part of the first block 132 descriptor = new apple_driver_descriptor(); 133 memcpy(descriptor, buffer, sizeof(apple_driver_descriptor)); 134 135 *_cookie = (void *)descriptor; 136 137 // ToDo: reevaluate the priority with ISO-9660 and others in mind 138 // (for CD-ROM only, as far as I can tell) 139 return 0.5f; 140} 141 142 143static status_t 144apple_scan_partition(int fd, partition_data *partition, void *_cookie) 145{ 146 TRACE(("apple_scan_partition(cookie = %p)\n", _cookie)); 147 148 apple_driver_descriptor &descriptor = *(apple_driver_descriptor *)_cookie; 149 150 partition->status = B_PARTITION_VALID; 151 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 152 | B_PARTITION_READ_ONLY; 153 partition->content_size = descriptor.BlockSize() * descriptor.BlockCount(); 154 155 // scan all children 156 157 apple_partition_map partitionMap; 158 uint32 index = 0, cookie = 0; 159 status_t status; 160 161 while ((status = get_next_partition(fd, descriptor, cookie, partitionMap)) == B_OK) { 162 TRACE(("apple: found partition: name = \"%s\", type = \"%s\"\n", 163 partitionMap.name, partitionMap.type)); 164 165 if (partitionMap.Start(descriptor) + partitionMap.Size(descriptor) > (uint64)partition->size) { 166 TRACE(("apple: child partition exceeds existing space (%lld bytes)\n", 167 partitionMap.Size(descriptor))); 168 continue; 169 } 170 171 partition_data *child = create_child_partition(partition->id, index++, 172 partition->offset + partitionMap.Start(descriptor), 173 partitionMap.Size(descriptor), -1); 174 if (child == NULL) { 175 TRACE(("apple: Creating child at index %ld failed\n", index - 1)); 176 return B_ERROR; 177 } 178 179 child->block_size = partition->block_size; 180 } 181 182 if (status == B_ENTRY_NOT_FOUND) 183 return B_OK; 184 185 return status; 186} 187 188 189static void 190apple_free_identify_partition_cookie(partition_data *partition, void *_cookie) 191{ 192 delete (apple_driver_descriptor *)_cookie; 193} 194 195 196#ifndef _BOOT_MODE 197static partition_module_info sApplePartitionModule = { 198#else 199partition_module_info gApplePartitionModule = { 200#endif 201 { 202 APPLE_PARTITION_MODULE_NAME, 203 0, 204 apple_std_ops 205 }, 206 "apple", // short_name 207 APPLE_PARTITION_NAME, // pretty_name 208 0, // flags 209 210 // scanning 211 apple_identify_partition, // identify_partition 212 apple_scan_partition, // scan_partition 213 apple_free_identify_partition_cookie, // free_identify_partition_cookie 214 NULL, 215}; 216 217#ifndef _BOOT_MODE 218partition_module_info *modules[] = { 219 &sApplePartitionModule, 220 NULL 221}; 222#endif 223