1 /* 2 * Copyright (C) 2020 Adrien Destugues <pulkomandy@pulkomandy.tk> 3 * 4 * Distributed under terms of the MIT license. 5 */ 6 7 8 #ifdef _BOOT_MODE 9 # include <boot/partitions.h> 10 #else 11 # include <DiskDeviceTypes.h> 12 #endif 13 14 #include <ByteOrder.h> 15 #include <ddm_modules.h> 16 #include <util/kernel_cpp.h> 17 #include <KernelExport.h> 18 #include <stdint.h> 19 #include <string.h> 20 21 22 //#define TRACE_SUN_PARTITION 23 #ifdef TRACE_SUN_PARTITION 24 # define TRACE(x) dprintf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 #define SUN_PARTITION_MODULE_NAME "partitioning_systems/sun/v1" 30 #define SUN_PARTITION_NAME "Sun volume table of contents" 31 32 33 static uint16_t kMainSignature = 0xDABE; 34 static uint32_t kVtocSignature = 0x600DDEEE; 35 static uint32_t kVtocVersion = 1; 36 static off_t kSectorSize = 512; 37 38 39 struct sun_vtoc { 40 char diskName[128]; 41 struct { 42 uint32_t version; 43 char volumeName[8]; 44 uint16_t partitionCount; 45 struct { 46 uint16_t type; 47 uint16_t flags; 48 } partitions[8]; 49 uint8_t bootinfo[12]; 50 uint8_t reserved[2]; 51 uint32_t signature; 52 uint8_t reserved2[38]; 53 uint32_t timestamp[8]; 54 } __attribute__((packed)) vtoc; 55 uint16_t write_skip; 56 uint16_t read_skip; 57 uint8_t reserved[154]; 58 uint16_t diskSpeed; 59 uint16_t cylinders; 60 uint16_t alternates; 61 uint8_t reserved2[4]; 62 uint16_t interleave; 63 uint16_t dataCylinders; 64 uint16_t alternateCylinders; 65 uint16_t heads; 66 uint16_t sectorsPerTrack; 67 uint8_t reserved3[4]; 68 struct { 69 uint32_t startCylinder; 70 uint32_t sectorCount; 71 } partitions[8]; 72 uint16_t signature; 73 uint16_t checksum; 74 } __attribute__((packed)); 75 76 77 // #pragma mark - 78 // Sun VTOC public module interface 79 80 81 static status_t 82 sun_std_ops(int32 op, ...) 83 { 84 switch (op) { 85 case B_MODULE_INIT: 86 case B_MODULE_UNINIT: 87 return B_OK; 88 } 89 90 return B_ERROR; 91 } 92 93 94 static float 95 sun_identify_partition(int fd, partition_data *partition, void **_cookie) 96 { 97 uint8 buffer[512]; 98 ssize_t bytesRead = read_pos(fd, 0, buffer, sizeof(buffer)); 99 sun_vtoc *vtoc = (sun_vtoc *)buffer; 100 if (bytesRead < (ssize_t)sizeof(buffer)) { 101 TRACE(("%s: read error: %ld\n", __FUNCTION__, bytesRead)); 102 return B_ERROR; 103 } 104 105 if (vtoc->signature == B_HOST_TO_BENDIAN_INT16(kMainSignature) 106 && vtoc->vtoc.signature == B_HOST_TO_BENDIAN_INT32(kVtocSignature) 107 && vtoc->vtoc.version == B_HOST_TO_BENDIAN_INT32(kVtocVersion)) { 108 // TODO verify the checksum 109 110 uint16_t partitionCount 111 = B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount); 112 TRACE(("Found %d partitions\n", partitionCount)); 113 114 if (partitionCount > 8) 115 return B_ERROR; 116 117 vtoc = new sun_vtoc(); 118 memcpy(vtoc, buffer, sizeof(sun_vtoc)); 119 *_cookie = (void *)vtoc; 120 121 bool hasParent = (get_parent_partition(partition->id) != NULL); 122 if (!hasParent) 123 return 0.61; // Larger than iso9660 124 else 125 return 0.3; 126 } 127 128 return B_ERROR; 129 } 130 131 132 static status_t 133 sun_scan_partition(int fd, partition_data *partition, void *cookie) 134 { 135 sun_vtoc *vtoc = (sun_vtoc *)cookie; 136 137 partition->status = B_PARTITION_VALID; 138 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 139 | B_PARTITION_READ_ONLY; 140 partition->content_size = partition->size; 141 142 off_t headCount = B_BENDIAN_TO_HOST_INT16(vtoc->heads); 143 off_t sectorsPerTrack = B_BENDIAN_TO_HOST_INT16(vtoc->sectorsPerTrack); 144 off_t cylinderSize = kSectorSize * headCount * sectorsPerTrack; 145 146 TRACE(("%" B_PRIdOFF " heads, %" B_PRIdOFF " sectors, cylindersize %" 147 B_PRIdOFF "\n", headCount, sectorsPerTrack, cylinderSize)); 148 149 for (int i = 0; i < B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount); 150 i++) { 151 uint16_t type = B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitions[i].type); 152 // Ignore unused and "whole disk" entries 153 if (type == 0 || type == 5) 154 continue; 155 156 off_t start = B_BENDIAN_TO_HOST_INT32( 157 vtoc->partitions[i].startCylinder) * cylinderSize; 158 off_t size = B_BENDIAN_TO_HOST_INT32(vtoc->partitions[i].sectorCount) 159 * kSectorSize; 160 TRACE(("Part %d type %d start %" B_PRIdOFF " size %" B_PRIdOFF "\n", i, 161 type, start, size)); 162 partition_data *child = create_child_partition(partition->id, i, 163 start, size, -1); 164 if (child == NULL) { 165 TRACE(("sun: Creating child at index %d failed\n", i)); 166 return B_ERROR; 167 } 168 child->block_size = partition->block_size; 169 } 170 171 return B_OK; 172 } 173 174 175 static void 176 sun_free_identify_partition_cookie(partition_data *partition, void *_cookie) 177 { 178 delete (sun_vtoc *)_cookie; 179 } 180 181 182 #ifndef _BOOT_MODE 183 static partition_module_info sSunPartitionModule = { 184 #else 185 partition_module_info gSunPartitionModule = { 186 #endif 187 { 188 SUN_PARTITION_MODULE_NAME, 189 0, 190 sun_std_ops 191 }, 192 "sun", // short_name 193 SUN_PARTITION_NAME, // pretty_name 194 0, // flags 195 196 // scanning 197 sun_identify_partition, // identify_partition 198 sun_scan_partition, // scan_partition 199 sun_free_identify_partition_cookie, // free_identify_partition_cookie 200 NULL, 201 // atari_free_partition_content_cookie, // free_partition_content_cookie 202 }; 203 204 #ifndef _BOOT_MODE 205 partition_module_info *modules[] = { 206 &sSunPartitionModule, 207 NULL 208 }; 209 #endif 210