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 32 static 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 51 static const char *kOtherPartitionTypes[] = { 52 "Be_BFS", // Be's BFS (not specified endian) 53 }; 54 #endif 55 56 static status_t 57 get_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 97 static status_t 98 apple_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 110 static float 111 apple_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 143 static status_t 144 apple_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 189 static void 190 apple_free_identify_partition_cookie(partition_data *partition, void *_cookie) 191 { 192 delete (apple_driver_descriptor *)_cookie; 193 } 194 195 196 #ifndef _BOOT_MODE 197 static partition_module_info sApplePartitionModule = { 198 #else 199 partition_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 218 partition_module_info *modules[] = { 219 &sApplePartitionModule, 220 NULL 221 }; 222 #endif 223