1 /* 2 * Copyright 2015, François Revol <revol@free.fr> 3 * Copyright (c) 2002 Marcus Overhagen <marcus@overhagen.de>, Haiku project 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "system_dependencies.h" 10 11 #define MKDOS 12 #include "mkdos.h" 13 14 15 #define WITH_FLOPPY_SUPPORT 16 17 18 void PrintUsage(); 19 status_t Initialize(int fatbits, const char *device, const char *label, 20 bool noprompt, bool testmode); 21 status_t parse_initialize_parameters(const char* parameterString, 22 initialize_parameters& parameters); 23 24 25 static void 26 create_volume_label_sector(void *sector, const char *label) 27 { 28 // create a volume name directory entry in the 512 byte sector 29 // XXX convert from UTF8, and check for valid characters 30 // XXX this could be changed to use long file name entrys, 31 // XXX but the dosfs would have to be updated, too 32 33 fatdirent *d = (fatdirent *)sector; 34 memset(d, 0, sizeof(*d)); 35 memset(d->Name, 0x20, 11); 36 memcpy(d->Name, label, min_c(11, strlen(label))); 37 d->Attr = 0x08; 38 } 39 40 41 status_t 42 check_volume_name(const char* name) 43 { 44 if (name == NULL) 45 return B_BAD_VALUE; 46 if (strlen(name) > 11) 47 return B_NAME_TOO_LONG; 48 if (strchr(name, '/') != NULL) 49 return B_BAD_VALUE; 50 51 return B_OK; 52 } 53 54 55 status_t 56 parse_initialize_parameters(const char* parameterString, 57 initialize_parameters& parameters) 58 { 59 parameters.flags = 0; 60 parameters.verbose = false; 61 62 void *handle = parse_driver_settings_string(parameterString); 63 if (handle == NULL) 64 return B_ERROR; 65 66 // if (get_driver_boolean_parameter(handle, "noindex", false, true)) 67 // parameters.flags |= VOLUME_NO_INDICES; 68 if (get_driver_boolean_parameter(handle, "verbose", false, true)) 69 parameters.verbose = true; 70 71 const char *string = get_driver_parameter(handle, "fat", 72 NULL, NULL); 73 uint32 fatBits = 0; 74 if (string != NULL) 75 fatBits = strtoul(string, NULL, 0); 76 77 unload_driver_settings(handle); 78 79 if (fatBits != 0 && fatBits != 12 && fatBits != 16 && fatBits != 32) { 80 dprintf("mkdos error: fat must be 12, 16, or 32 bits\n"); 81 return B_BAD_VALUE; 82 } 83 84 parameters.fatBits = fatBits; 85 86 return B_OK; 87 } 88 89 90 91 status_t 92 dosfs_initialize(int fd, partition_id partitionID, const char* name, 93 const char* parameterString, off_t partitionSize, disk_job_id job) 94 { 95 dprintf("dosfs_initialize(%d, , '%s', '%s', %" B_PRIdOFF ")\n", 96 fd, name, parameterString, partitionSize); 97 if (sizeof(bootsector1216) != 512 || sizeof(bootsector32) != 512 98 || sizeof(fsinfosector32) != 512) { 99 dprintf("dosfs: compilation error: struct alignment wrong\n"); 100 return B_BAD_VALUE; 101 } 102 103 // check name 104 status_t status = check_volume_name(name); 105 if (status != B_OK) 106 return status; 107 108 // parse parameters 109 initialize_parameters parameters; 110 status = parse_initialize_parameters(parameterString, parameters); 111 if (status != B_OK) 112 return status; 113 114 update_disk_device_job_progress(job, 0); 115 116 int fatbits = parameters.fatBits; 117 const char *label = name; 118 119 if (fatbits != 0 && fatbits != 12 && fatbits != 16 && fatbits != 32) { 120 dprintf("dosfs Error: don't know how to create a %d bit fat\n",fatbits); 121 return B_ERROR; 122 } 123 124 // initialize the volume 125 bool isRawDevice; 126 bool hasBiosGeometry; 127 bool hasDeviceGeometry; 128 bool hasPartitionInfo; 129 device_geometry biosGeometry; 130 device_geometry deviceGeometry; 131 partition_info partitionInfo; 132 133 isRawDevice = 0;//0 != strstr(device, "/raw"); 134 hasBiosGeometry = B_OK == ioctl(fd, B_GET_BIOS_GEOMETRY, &biosGeometry, 135 sizeof(biosGeometry)); 136 hasDeviceGeometry = B_OK == ioctl(fd, B_GET_GEOMETRY, &deviceGeometry, 137 sizeof(deviceGeometry)); 138 hasPartitionInfo = B_OK == ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo, 139 sizeof(partitionInfo)); 140 141 if (!isRawDevice && !hasBiosGeometry && !hasDeviceGeometry 142 && !hasPartitionInfo) { 143 isRawDevice = true; 144 } 145 146 if (hasBiosGeometry) { 147 dprintf("dosfs: bios geometry: %" B_PRIu32 " heads, " 148 "%" B_PRIu32 " cylinders, " 149 "%" B_PRIu32 " sectors/track, " 150 "%" B_PRIu32 " bytes/sector\n", 151 biosGeometry.head_count, 152 biosGeometry.cylinder_count, 153 biosGeometry.sectors_per_track, 154 biosGeometry.bytes_per_sector); 155 } 156 if (hasDeviceGeometry) { 157 dprintf("dosfs: device geometry: %" B_PRIu32 " heads, " 158 "%" B_PRIu32 " cylinders, " 159 "%" B_PRIu32 " sectors/track, " 160 "%" B_PRIu32 " bytes/sector\n", 161 deviceGeometry.head_count, 162 deviceGeometry.cylinder_count, 163 deviceGeometry.sectors_per_track, 164 deviceGeometry.bytes_per_sector); 165 } 166 if (hasPartitionInfo) { 167 dprintf("dosfs: partition info: start at %" B_PRIdOFF " bytes " 168 "(%" B_PRIdOFF " sectors), " 169 "%" B_PRIdOFF " KB, " 170 "%" B_PRIdOFF " MB, " 171 "%" B_PRIdOFF " GB\n", 172 partitionInfo.offset, 173 partitionInfo.offset / 512, 174 partitionInfo.offset / 1024, 175 partitionInfo.offset / (1024 * 1024), 176 partitionInfo.offset / (1024 * 1024 * 1024)); 177 dprintf("dosfs: partition info: size %" B_PRIdOFF " bytes, " 178 "%" B_PRIdOFF " KB, " 179 "%" B_PRIdOFF " MB, " 180 "%" B_PRIdOFF " GB\n", 181 partitionInfo.size, 182 partitionInfo.size / 1024, 183 partitionInfo.size / (1024 * 1024), 184 partitionInfo.size / (1024 * 1024 * 1024)); 185 } 186 187 if (!isRawDevice && !hasPartitionInfo) 188 dprintf("dosfs Warning: couldn't get partition information\n"); 189 190 if ((hasBiosGeometry && biosGeometry.bytes_per_sector != 512) 191 || (hasDeviceGeometry && deviceGeometry.bytes_per_sector != 512)) { 192 dprintf("dosfs Error: geometry block size not 512 bytes\n"); 193 return B_ERROR; 194 } else if (hasPartitionInfo && partitionInfo.logical_block_size != 512) { 195 dprintf("dosfs: partition logical block size is not 512, " 196 "it's %" B_PRId32 " bytes\n", 197 partitionInfo.logical_block_size); 198 } 199 200 if (hasDeviceGeometry && deviceGeometry.read_only) { 201 dprintf("dosfs Error: this is a read-only device\n"); 202 return B_ERROR; 203 } 204 if (hasDeviceGeometry && deviceGeometry.write_once) { 205 dprintf("dosfs Error: this is a write-once device\n"); 206 return B_ERROR; 207 } 208 uint64 size = 0; 209 210 if (hasPartitionInfo) { 211 size = partitionInfo.size; 212 } else if (hasDeviceGeometry) { 213 size = uint64(deviceGeometry.bytes_per_sector) 214 * deviceGeometry.sectors_per_track * deviceGeometry.cylinder_count 215 * deviceGeometry.head_count; 216 } else if (hasBiosGeometry) { 217 size = uint64(biosGeometry.bytes_per_sector) 218 * biosGeometry.sectors_per_track * biosGeometry.cylinder_count 219 * biosGeometry.head_count; 220 } else { 221 // maybe it's just a file 222 struct stat stat; 223 if (fstat(fd, &stat) < 0) { 224 dprintf("dosfs Error: couldn't get device partition or geometry " 225 "information, nor size\n"); 226 return B_ERROR; 227 } 228 size = stat.st_size; 229 } 230 231 dprintf("dosfs: size = %" B_PRIu64 " bytes " 232 "(%" B_PRIu64 " sectors), " 233 "%" B_PRIu64 " KB, " 234 "%" B_PRIu64 " MB, " 235 "%" B_PRIu64 " GB\n", 236 size, 237 size / 512, 238 size / 1024, 239 size / (1024 * 1024), 240 size / (1024 * 1024 * 1024)); 241 242 if (fatbits == 0) { 243 //auto determine fat type 244 if (isRawDevice && size <= FLOPPY_MAX_SIZE 245 && (size / FAT12_CLUSTER_MAX_SIZE) < FAT12_MAX_CLUSTER_COUNT) { 246 fatbits = 12; 247 } else if ((size / CLUSTER_MAX_SIZE) < FAT16_MAX_CLUSTER_COUNT) { 248 fatbits = 16; 249 } else if ((size / CLUSTER_MAX_SIZE) < FAT32_MAX_CLUSTER_COUNT) { 250 fatbits = 32; 251 } 252 } 253 254 if (fatbits == 0) { 255 dprintf("dosfs Error: device too large for 32 bit fat\n"); 256 return B_ERROR; 257 } 258 259 int sectorPerCluster; 260 261 sectorPerCluster = 0; 262 if (fatbits == 12) { 263 sectorPerCluster = 0; 264 if (size <= 4182016LL) 265 sectorPerCluster = 2; // XXX don't know the correct value 266 if (size <= 2091008LL) 267 sectorPerCluster = 1; // XXX don't know the correct value 268 } else if (fatbits == 16) { 269 // special BAD_CLUSTER value is 0xFFF7, 270 // but this should work anyway, since space required by 271 // two FATs will make maximum cluster count smaller. 272 // at least, this is what I think *should* happen 273 sectorPerCluster = 0; //larger than 2 GB must fail 274 if (size <= (2048 * 1024 * 1024LL)) // up to 2GB, use 32k clusters 275 sectorPerCluster = 64; 276 if (size <= (1024 * 1024 * 1024LL)) // up to 1GB, use 16k clusters 277 sectorPerCluster = 32; 278 if (size <= (512 * 1024 * 1024LL)) // up to 512MB, use 8k clusters 279 sectorPerCluster = 16; 280 if (size <= (256 * 1024 * 1024LL)) // up to 256MB, use 4k clusters 281 sectorPerCluster = 8; 282 if (size <= (128 * 1024 * 1024LL)) // up to 128MB, use 2k clusters 283 sectorPerCluster = 4; 284 if (size <= (16 * 1024 * 1024LL)) // up to 16MB, use 2k clusters 285 sectorPerCluster = 2; 286 if (size <= 4182016LL) // smaller than fat32 must fail 287 sectorPerCluster = 0; 288 } else if (fatbits == 32) { 289 sectorPerCluster = 64; // default is 32k clusters 290 if (size <= (32 * 1024 * 1024 * 1024LL)) { 291 // up to 32GB, use 16k clusters 292 sectorPerCluster = 32; 293 } 294 if (size <= (16 * 1024 * 1024 * 1024LL)) { 295 // up to 16GB, use 8k clusters 296 sectorPerCluster = 16; 297 } 298 if (size <= (8 * 1024 * 1024 * 1024LL)) { 299 // up to 8GB, use 4k clusters 300 sectorPerCluster = 8; 301 } 302 if (size <= (532480 * 512LL)) { 303 // up to 260 MB, use 0.5k clusters 304 sectorPerCluster = 1; 305 } 306 if (size <= (66600 * 512LL)) { 307 // smaller than 32.5 MB must fail 308 sectorPerCluster = 0; 309 } 310 } 311 312 if (sectorPerCluster == 0) { 313 dprintf("dosfs Error: failed to determine sector per cluster value, " 314 "partition too large for %d bit fat\n",fatbits); 315 return B_ERROR; 316 } 317 318 int reservedSectorCount = 0; // avoid compiler warning 319 int rootEntryCount = 0; // avoid compiler warning 320 int numFATs; 321 int sectorSize; 322 uint8 biosDriveId; 323 324 // get bios drive-id, or use 0x80 325 if (B_OK != ioctl(fd, B_GET_BIOS_DRIVE_ID, &biosDriveId, 326 sizeof(biosDriveId))) { 327 biosDriveId = 0x80; 328 } else { 329 dprintf("dosfs: bios drive id: 0x%02x\n", (int)biosDriveId); 330 } 331 332 // default parameters for the bootsector 333 numFATs = 2; 334 sectorSize = 512; 335 if (fatbits == 12 || fatbits == 16) 336 reservedSectorCount = 1; 337 if (fatbits == 32) 338 reservedSectorCount = 32; 339 if (fatbits == 12) 340 rootEntryCount = 128; // XXX don't know the correct value 341 if (fatbits == 16) 342 rootEntryCount = 512; 343 if (fatbits == 32) 344 rootEntryCount = 0; 345 346 // Determine FATSize 347 // calculation done as MS recommends 348 uint64 dskSize = size / sectorSize; 349 uint32 rootDirSectors = ((rootEntryCount * 32) + (sectorSize - 1)) 350 / sectorSize; 351 uint64 tmpVal1 = dskSize - (reservedSectorCount + rootDirSectors); 352 uint64 tmpVal2 = (256 * sectorPerCluster) + numFATs; 353 if (fatbits == 32) 354 tmpVal2 = tmpVal2 / 2; 355 uint32 FATSize = (tmpVal1 + (tmpVal2 - 1)) / tmpVal2; 356 // FATSize should now contain the size of *one* FAT, measured in sectors 357 // RootDirSectors should now contain the size of the fat12/16 root 358 // directory, measured in sectors 359 360 dprintf("dosfs: fatbits = %d, clustersize = %d\n", fatbits, 361 sectorPerCluster * 512); 362 dprintf("dosfs: FAT size is %" B_PRIu32 " sectors\n", FATSize); 363 dprintf("dosfs: disk label: %s\n", label); 364 365 366 367 if (status < B_OK) { 368 dprintf("dosfs: Initializing volume failed: %s\n", strerror(status)); 369 return status; 370 } 371 372 char bootsector[512]; 373 memset(bootsector,0x00,512); 374 memcpy(bootsector + BOOTJMP_START_OFFSET, bootjmp, sizeof(bootjmp)); 375 memcpy(bootsector + BOOTCODE_START_OFFSET, bootcode, sizeof(bootcode)); 376 377 if (fatbits == 32) { 378 bootsector32 *bs = (bootsector32 *)bootsector; 379 uint16 temp16; 380 uint32 temp32; 381 memcpy(bs->BS_OEMName,"Haiku ",8); 382 bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize); 383 bs->BPB_SecPerClus = sectorPerCluster; 384 bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount); 385 bs->BPB_NumFATs = numFATs; 386 bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount); 387 bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(0); 388 bs->BPB_Media = 0xF8; 389 bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(0); 390 temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63; 391 bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16); 392 temp16 = hasBiosGeometry ? biosGeometry.head_count : 255; 393 bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16); 394 temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0; 395 bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32); 396 temp32 = size / 512; 397 bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32); 398 bs->BPB_FATSz32 = B_HOST_TO_LENDIAN_INT32(FATSize); 399 bs->BPB_ExtFlags = B_HOST_TO_LENDIAN_INT16(0); 400 bs->BPB_FSVer = B_HOST_TO_LENDIAN_INT16(0); 401 bs->BPB_RootClus = B_HOST_TO_LENDIAN_INT32(FAT32_ROOT_CLUSTER); 402 bs->BPB_FSInfo = B_HOST_TO_LENDIAN_INT16(FSINFO_SECTOR_NUM); 403 bs->BPB_BkBootSec = B_HOST_TO_LENDIAN_INT16(BACKUP_SECTOR_NUM); 404 memset(bs->BPB_Reserved,0,12); 405 bs->BS_DrvNum = biosDriveId; 406 bs->BS_Reserved1 = 0x00; 407 bs->BS_BootSig = 0x29; 408 *(uint32*)bs->BS_VolID = (uint32)system_time(); 409 memset(bs->BS_VolLab, 0x20, 11); 410 memcpy(bs->BS_VolLab, label, min_c(11, strlen(label))); 411 memcpy(bs->BS_FilSysType,"FAT32 ",8); 412 bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55); 413 } else { 414 bootsector1216 *bs = (bootsector1216 *)bootsector; 415 uint16 temp16; 416 uint32 temp32; 417 uint32 sectorcount = size / 512; 418 memcpy(bs->BS_OEMName, "Haiku ", 8); 419 bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize); 420 bs->BPB_SecPerClus = sectorPerCluster; 421 bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount); 422 bs->BPB_NumFATs = numFATs; 423 bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount); 424 temp16 = (sectorcount <= 65535) ? sectorcount : 0; 425 bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(temp16); 426 bs->BPB_Media = 0xF8; 427 bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(FATSize); 428 temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63; 429 bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16); 430 temp16 = hasBiosGeometry ? biosGeometry.head_count : 255; 431 bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16); 432 temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0; 433 bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32); 434 temp32 = (sectorcount <= 65535) ? 0 : sectorcount; 435 bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32); 436 bs->BS_DrvNum = biosDriveId; 437 bs->BS_Reserved1 = 0x00; 438 bs->BS_BootSig = 0x29; 439 *(uint32*)bs->BS_VolID = (uint32)system_time(); 440 memset(bs->BS_VolLab, 0x20, 11); 441 memcpy(bs->BS_VolLab, label, min_c(11, strlen(label))); 442 memcpy(bs->BS_FilSysType,(fatbits == 12) ? "FAT12 " : "FAT16 ",8); 443 bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55); 444 } 445 446 // Disk layout: 447 // 0) reserved sectors, this includes the bootsector, fsinfosector and 448 // bootsector backup 449 // 1) FAT 450 // 2) root directory (not on fat32) 451 // 3) file & directory data 452 453 ssize_t written; 454 455 // initialize everything with zero first 456 // avoid doing 512 byte writes here, they are slow 457 dprintf("dosfs: Writing FAT\n"); 458 char * zerobuffer = (char *)malloc(65536); 459 memset(zerobuffer,0,65536); 460 int64 bytes_to_write = 512LL * (reservedSectorCount + (numFATs * FATSize) 461 + rootDirSectors); 462 int64 pos = 0; 463 while (bytes_to_write > 0) { 464 ssize_t writesize = min_c(bytes_to_write, 65536); 465 written = write_pos(fd, pos, zerobuffer, writesize); 466 if (written != writesize) { 467 dprintf("dosfs Error: write error near sector %" B_PRId64 "\n", 468 pos / 512); 469 free(zerobuffer); 470 return B_ERROR; 471 } 472 bytes_to_write -= writesize; 473 pos += writesize; 474 } 475 free(zerobuffer); 476 477 //write boot sector 478 dprintf("dosfs: Writing boot block\n"); 479 written = write_pos(fd, BOOT_SECTOR_NUM * 512, bootsector, 512); 480 if (written != 512) { 481 dprintf("dosfs Error: write error at sector %d\n", BOOT_SECTOR_NUM); 482 return B_ERROR; 483 } 484 485 if (fatbits == 32) { 486 written = write_pos(fd, BACKUP_SECTOR_NUM * 512, bootsector, 512); 487 if (written != 512) { 488 dprintf("dosfs Error: write error at sector %d\n", 489 BACKUP_SECTOR_NUM); 490 return B_ERROR; 491 } 492 } 493 494 //write first fat sector 495 dprintf("dosfs: Writing first FAT sector\n"); 496 uint8 sec[512]; 497 memset(sec,0,512); 498 if (fatbits == 12) { 499 //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 500 //FAT[1] contains EOF marker 501 sec[0] = 0xF8; 502 sec[1] = 0xFF; 503 sec[2] = 0xFF; 504 } else if (fatbits == 16) { 505 //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 506 sec[0] = 0xF8; 507 sec[1] = 0xFF; 508 //FAT[1] contains EOF marker 509 sec[2] = 0xFF; 510 sec[3] = 0xFF; 511 } else if (fatbits == 32) { 512 //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 513 sec[0] = 0xF8; 514 sec[1] = 0xFF; 515 sec[2] = 0xFF; 516 sec[3] = 0xFF; 517 //FAT[1] contains EOF marker 518 sec[4] = 0xFF; 519 sec[5] = 0xFF; 520 sec[6] = 0xFF; 521 sec[7] = 0x0F; 522 //FAT[2] contains EOF marker, used to terminate root directory 523 sec[8] = 0xFF; 524 sec[9] = 0xFF; 525 sec[10] = 0xFF; 526 sec[11] = 0x0F; 527 } 528 written = write_pos(fd, reservedSectorCount * 512, sec, 512); 529 if (written != 512) { 530 dprintf("dosfs Error: write error at sector %d\n", reservedSectorCount); 531 return B_ERROR; 532 } 533 if (numFATs > 1) { 534 written = write_pos(fd, (reservedSectorCount + FATSize) * 512,sec,512); 535 if (written != 512) { 536 dprintf("dosfs Error: write error at sector %" B_PRIu32 "\n", 537 reservedSectorCount + FATSize); 538 return B_ERROR; 539 } 540 } 541 542 //write fsinfo sector 543 if (fatbits == 32) { 544 dprintf("dosfs: Writing boot info\n"); 545 //calculate total sector count first 546 uint64 free_count = size / 512; 547 //now account for already by metadata used sectors 548 free_count -= reservedSectorCount + (numFATs * FATSize) 549 + rootDirSectors; 550 //convert from sector to clustercount 551 free_count /= sectorPerCluster; 552 //and account for 1 already used cluster of root directory 553 free_count -= 1; 554 fsinfosector32 fsinfosector; 555 memset(&fsinfosector,0x00,512); 556 fsinfosector.FSI_LeadSig = B_HOST_TO_LENDIAN_INT32(0x41615252); 557 fsinfosector.FSI_StrucSig = B_HOST_TO_LENDIAN_INT32(0x61417272); 558 fsinfosector.FSI_Free_Count 559 = B_HOST_TO_LENDIAN_INT32((uint32)free_count); 560 fsinfosector.FSI_Nxt_Free = B_HOST_TO_LENDIAN_INT32(3); 561 fsinfosector.FSI_TrailSig = B_HOST_TO_LENDIAN_INT32(0xAA550000); 562 written = write_pos(fd, FSINFO_SECTOR_NUM * 512, &fsinfosector, 512); 563 if (written != 512) { 564 dprintf("dosfs Error: write error at sector %d\n", 565 FSINFO_SECTOR_NUM); 566 return B_ERROR; 567 } 568 } 569 570 //write volume label into root directory 571 dprintf("dosfs: Writing root directory\n"); 572 if (fatbits == 12 || fatbits == 16) { 573 uint8 data[512]; 574 memset(data, 0, 512); 575 create_volume_label_sector(data, label); 576 uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize); 577 written = write_pos(fd, rootDirSector * 512, data, 512); 578 if (written != 512) { 579 dprintf("dosfs Error: write error at sector %" B_PRIu32 "\n", 580 rootDirSector); 581 return B_ERROR; 582 } 583 } else if (fatbits == 32) { 584 int size = 512 * sectorPerCluster; 585 uint8 *cluster = (uint8*)malloc(size); 586 memset(cluster, 0, size); 587 create_volume_label_sector(cluster, label); 588 uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize) 589 + rootDirSectors; 590 written = write_pos(fd, rootDirSector * 512, cluster, size); 591 free(cluster); 592 if (written != size) { 593 dprintf("dosfs Error: write error at sector %" B_PRIu32 "\n", 594 rootDirSector); 595 return B_ERROR; 596 } 597 } 598 599 ioctl(fd, B_FLUSH_DRIVE_CACHE); 600 601 602 603 // rescan partition 604 status = scan_partition(partitionID); 605 if (status != B_OK) 606 return status; 607 608 update_disk_device_job_progress(job, 1); 609 610 // print some info, if desired 611 if (parameters.verbose) { 612 // disk_super_block super = volume.SuperBlock(); 613 614 dprintf("dosfs: Disk was initialized successfully.\n"); 615 /* 616 dprintf("\tname: \"%s\"\n", super.name); 617 dprintf("\tnum blocks: %" B_PRIdOFF "\n", super.NumBlocks()); 618 dprintf("\tused blocks: %" B_PRIdOFF "\n", super.UsedBlocks()); 619 dprintf("\tblock size: %u bytes\n", (unsigned)super.BlockSize()); 620 dprintf("\tnum allocation groups: %d\n", 621 (int)super.AllocationGroups()); 622 dprintf("\tallocation group size: %ld blocks\n", 623 1L << super.AllocationGroupShift()); 624 dprintf("\tlog size: %u blocks\n", super.log_blocks.Length()); 625 */ 626 } 627 628 return B_OK; 629 } 630 631 632 status_t 633 dosfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize, 634 uint32 blockSize, disk_job_id job) 635 { 636 if (blockSize == 0) 637 return B_BAD_VALUE; 638 639 update_disk_device_job_progress(job, 0.0); 640 641 // just overwrite the superblock 642 // XXX: we might want to keep the loader part ? 643 char bootsector[512]; 644 memset(bootsector,0x00,512); 645 646 if (write_pos(fd, 512, bootsector, sizeof(bootsector)) < 0) 647 return errno; 648 649 update_disk_device_job_progress(job, 1.0); 650 651 return B_OK; 652 } 653 654 655 // #pragma mark - 656 657 658 #if 0 // For testing standalone builds 659 int 660 main(int argc, char *argv[]) 661 { 662 if (sizeof(bootsector1216) != 512 || sizeof(bootsector32) != 512 663 || sizeof(fsinfosector32) != 512) { 664 dprintf("compilation error: struct alignment wrong\n"); 665 return 1; 666 } 667 668 const char *device = NULL; 669 const char *label = NULL; 670 bool noprompt = false; 671 bool test = false; 672 int fat = 0; 673 674 while (1) { 675 int c; 676 int option_index = 0; 677 static struct option long_options[] = 678 { 679 {"noprompt", no_argument, 0, 'n'}, 680 {"test", no_argument, 0, 't'}, 681 {"fat", required_argument, 0, 'f'}, 682 {0, 0, 0, 0} 683 }; 684 685 c = getopt_long (argc, argv, "ntf:", long_options, &option_index); 686 if (c == -1) 687 break; 688 689 switch (c) { 690 case 'n': 691 noprompt = true; 692 break; 693 694 case 't': 695 test = true; 696 break; 697 698 case 'f': 699 fat = strtol(optarg, NULL, 10); 700 if (fat == 0) 701 fat = -1; 702 break; 703 704 default: 705 printf("\n"); 706 PrintUsage(); 707 return 1; 708 } 709 } 710 711 if (optind < argc) 712 device = argv[optind]; 713 if ((optind + 1) < argc) 714 label = argv[optind + 1]; 715 716 if (fat != 0 && fat != 12 && fat != 16 && fat != 32) { 717 printf("mkdos error: fat must be 12, 16, or 32 bits\n"); 718 PrintUsage(); 719 return 1; 720 } 721 722 if (device == NULL) { 723 printf("mkdos error: you must specify a device or partition or image\n"); 724 printf(" such as /dev/disk/ide/ata/1/master/0/0_0\n"); 725 PrintUsage(); 726 return 1; 727 } 728 729 if (label == NULL) { 730 label = "no name"; 731 } 732 733 if (noprompt) 734 printf("will not prompt for confirmation\n"); 735 736 if (test) 737 printf("test mode enabled (no writes will occur)\n"); 738 739 status_t s; 740 s = Initialize(fat, device, label, noprompt, test); 741 742 if (s != 0) { 743 printf("Initializing failed!\n"); 744 } 745 746 return (s == B_OK) ? 0 : 1; 747 } 748 #endif 749