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