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 "atari.h" 8 9 #include <ByteOrder.h> 10 #include <KernelExport.h> 11 #include <ddm_modules.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 #include <ctype.h> 22 23 #define SECTSZ 512 24 25 //#define TRACE_ATARI_PARTITION 26 #ifdef TRACE_ATARI_PARTITION 27 # define TRACE(x) dprintf x 28 #else 29 # define TRACE(x) ; 30 #endif 31 32 33 #define ATARI_PARTITION_MODULE_NAME "partitioning_systems/atari/v1" 34 #define ATARI_PARTITION_NAME "Atari Partition Map" 35 36 37 #if 0 38 template<typename Type> bool 39 validate_check_sum(Type *type) 40 { 41 if (type->SummedLongs() != sizeof(*type) / sizeof(uint32)) 42 return false; 43 44 // check checksum 45 uint32 *longs = (uint32 *)type; 46 uint32 sum = 0; 47 for (uint32 i = 0; i < type->SummedLongs(); i++) 48 sum += B_BENDIAN_TO_HOST_INT32(longs[i]); 49 50 #ifdef TRACE_ATARI_PARTITION 51 if (sum != 0) 52 TRACE(("search_rdb: check sum is incorrect!\n")); 53 #endif 54 55 return sum == 0; 56 } 57 #endif 58 59 60 // #pragma mark - 61 // Atari Root Block public module interface 62 63 64 static status_t 65 atari_std_ops(int32 op, ...) 66 { 67 switch (op) { 68 case B_MODULE_INIT: 69 case B_MODULE_UNINIT: 70 return B_OK; 71 } 72 73 return B_ERROR; 74 } 75 76 77 static float 78 atari_identify_partition(int fd, partition_data *partition, void **_cookie) 79 { 80 uint8 buffer[512]; 81 atari_root_block *arb = (atari_root_block *)buffer; 82 float weight = 0.5; 83 int i; 84 ssize_t bytesRead = read_pos(fd, 0, buffer, sizeof(buffer)); 85 if (bytesRead < (ssize_t)sizeof(buffer)) { 86 TRACE(("%s: read error: %ld\n", __FUNCTION__, bytesRead)); 87 return B_ERROR; 88 } 89 if (partition->offset) 90 return B_ERROR; 91 92 if (arb->Checksum() == 0x55aa) 93 weight -= 0.1; /* possible but likely a PC sector */ 94 if (arb->_reserved_1[0] != 0x00) 95 weight -= 10; 96 /* hope so */ 97 if (arb->MaxPartitionSize() < 10) 98 weight -= 20; 99 100 if ((arb->BadSectorsStart()+arb->BadSectorsCount())*(off_t)SECTSZ > partition->size) 101 return B_ERROR; 102 103 /* check each partition */ 104 for (i = 0; i < 4; i++) { 105 struct atari_partition_entry *p = &arb->partitions[i]; 106 if (p->Flags() & ATARI_PART_EXISTS) { 107 /* check for unknown flags */ 108 if (p->Flags() & ~ (ATARI_PART_EXISTS|ATARI_PART_BOOTABLE)) 109 weight -= 10.0; 110 /* id should be readable */ 111 if (!isalnum(p->id[0])) 112 weight -= 1.0; 113 if (!isalnum(p->id[1])) 114 weight -= 1.0; 115 if (!isalnum(p->id[2])) 116 weight -= 1.0; 117 /* make sure partition doesn't overlap bad sector list */ 118 if ((arb->BadSectorsStart() < p->Start()) && 119 ((arb->BadSectorsStart() + arb->BadSectorsCount()) > p->Start())) 120 weight -= 10; 121 if ((p->Start()+p->Size())*(off_t)SECTSZ > partition->size) 122 return B_ERROR; 123 /* should check partitions don't overlap each other... */ 124 } else { 125 /* empty partition entry, then it must be all null */ 126 if (p->Flags() || p->id[0] || p->id[1] || p->id[2] || 127 p->Start() || p->Size()) 128 weight -= 10.0; 129 else 130 weight += 0.1; 131 } 132 } 133 /* not exactly sure */ 134 if (arb->Checksum() != ATARI_BOOTABLE_MAGIC) 135 weight -= 0.1; 136 137 if (weight > 1.0) 138 weight = 1.0; 139 140 if (weight > 0.0) { 141 // copy the root block to a new piece of memory 142 arb = new atari_root_block(); 143 memcpy(arb, buffer, sizeof(atari_root_block)); 144 145 *_cookie = (void *)arb; 146 return weight; 147 } 148 149 return B_ERROR; 150 } 151 152 153 static status_t 154 atari_scan_partition(int fd, partition_data *partition, void *_cookie) 155 { 156 TRACE(("atari_scan_partition(cookie = %p)\n", _cookie)); 157 158 atari_root_block &arb = *(atari_root_block *)_cookie; 159 160 partition->status = B_PARTITION_VALID; 161 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 162 | B_PARTITION_READ_ONLY; 163 partition->content_size = partition->size; 164 165 // scan all children 166 167 uint32 index = 0; 168 status_t status = B_ENTRY_NOT_FOUND; 169 170 for (index = 0; index < 4; index++) { 171 struct atari_partition_entry *p = &arb.partitions[index]; 172 if (!(p->Flags() & ATARI_PART_EXISTS)) 173 continue; 174 TRACE(("atari: file system: %.3s\n", p->id)); 175 if ((p->Start() + p->Size())*(uint64)SECTSZ > (uint64)partition->size) { 176 TRACE(("atari: child partition exceeds existing space (%Ld bytes)\n", p->Size()*SECTSZ)); 177 continue; 178 } 179 if (!isalnum(p->id[0])) 180 continue; 181 if (!isalnum(p->id[1])) 182 continue; 183 if (!isalnum(p->id[2])) 184 continue; 185 186 partition_data *child = create_child_partition(partition->id, index, 187 partition->offset + p->Start() * (uint64)SECTSZ, 188 p->Size() * (uint64)SECTSZ, -1); 189 if (child == NULL) { 190 TRACE(("atari: Creating child at index %ld failed\n", index - 1)); 191 return B_ERROR; 192 } 193 #warning M68K: use a lookup table ? 194 char type[] = "??? Partition"; 195 memcpy(type, p->id, 3); 196 child->type = strdup(type); 197 child->block_size = SECTSZ; 198 status = B_OK; 199 } 200 201 if (status == B_ENTRY_NOT_FOUND) 202 return B_OK; 203 204 return status; 205 } 206 207 208 static void 209 atari_free_identify_partition_cookie(partition_data *partition, void *_cookie) 210 { 211 delete (atari_root_block *)_cookie; 212 } 213 214 215 #ifndef _BOOT_MODE 216 static partition_module_info sAtariPartitionModule = { 217 #else 218 partition_module_info gAtariPartitionModule = { 219 #endif 220 { 221 ATARI_PARTITION_MODULE_NAME, 222 0, 223 atari_std_ops 224 }, 225 "atari", // short_name 226 ATARI_PARTITION_NAME, // pretty_name 227 0, // flags 228 229 // scanning 230 atari_identify_partition, // identify_partition 231 atari_scan_partition, // scan_partition 232 atari_free_identify_partition_cookie, // free_identify_partition_cookie 233 NULL, 234 // atari_free_partition_cookie, // free_partition_cookie 235 // atari_free_partition_content_cookie, // free_partition_content_cookie 236 }; 237 238 #ifndef _BOOT_MODE 239 partition_module_info *modules[] = { 240 &sAtariPartitionModule, 241 NULL 242 }; 243 #endif 244