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