📄 dosfsfmtlib.c
字号:
else pBoot = bootBlockBuffer ; if (NULL == pBoot) { return (ERROR); } bzero( (char *)pBoot, bytesPerBlk ); /* clear out the entire FAT, all copies of it ! */ for(i = 0; i < (pConf->secPerFat * pConf->nFats); i++ ) { if(cbioBlkRW( cbioDev, i + DOS_BOOT_SEC_NUM + pConf->nResrvd, 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) { goto _done_; } } /* clear out the entire Root directory */ /* size of Root Dir in sectors */ if( pConf->fatType == _FAT32 ) { work = pConf->secPerClust ; } else /* FAT16/FAT12 */ { /* SPR#34704 This must round up */ work = (((pConf->maxRootEnts * dirEntrySize) + (bytesPerBlk - 1)) / bytesPerBlk); } /* this is where the Root dir starts */ rootStartSec = DOS_BOOT_SEC_NUM + pConf->nResrvd + (pConf->secPerFat * pConf->nFats); /* clear it really now */ for( i = 0; i < work; i++ ) if( cbioBlkRW( cbioDev, i+rootStartSec, 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; /* * now that we are done with zero's, we initialize the FAT's head * with the required beginning for the FAT type, this appears: * * FAT12: f8 ff ff xx xx xx xx xx xx xx xx xx xx xx * FAT16: f8 ff ff ff xx xx xx xx xx xx xx xx xx xx * FAT32: f8 ff ff ff ff ff ff ff ff ff ff 0f xx xx * f8 is the media byte. * * Noticed that Win95 OSR2 FAT32 uses: * f8 ff ff 0f ff ff ff 0f ff ff ff 0f xx xx * Probally due to simplified formatting code, does not * affect anything in MS ScanDisk or Norton Disk Doctor, * so we just leave it as is here, just noted. */ if( pConf->fatType == _FAT32 ) /* how many bytes to init */ { work = 11 ; /* 0, 1, and 2 entry for root dir */ pBoot[ 11 ] = 0x0f; /* root dir EOF msb */ } else if( pConf->fatType == _FAT16 ) work = 4 ; else /* FAT12 */ work = 3 ; pBoot[ 0 ] = pConf->mediaByte ; /* 0th byte always media */ for(i=1; i < work ; i++ ) pBoot[i] = 0xff ; /* 1th to i-th bytes 0xff */ for(i = DOS_BOOT_SEC_NUM + pConf->nResrvd ; i < DOS_BOOT_SEC_NUM + pConf->nResrvd + pConf->secPerFat * pConf->nFats; i += pConf->secPerFat ) if( cbioBlkRW( cbioDev, i , 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; /* create file system info sector for FAT32 */ if( pConf->fatType == _FAT32 ) { /* FS info sector */ bzero( (char *)pBoot, bytesPerBlk ); /* FSI_LeadSig (magic signature) */ pBoot[ 0 ] = 'R'; /* 0x52 */ pBoot[ 1 ] = 'R'; /* 0x52 */ pBoot[ 2 ] = 'a'; /* 0x61 */ pBoot[ 3 ] = 'A'; /* 0x41 */ /* FSI_StructSig */ pBoot[ 484 ] = 'r'; /* 0x72 */ pBoot[ 485 ] = 'r'; /* 0x72 */ pBoot[ 486 ] = 'A'; /* 0x41 */ pBoot[ 487 ] = 'a'; /* 0x61 */ /* * Many FAT documents mistakenly say that the 0x55AA signature word * "occupies the last two bytes of the boot sector". That is only * true when the bytes-per-sector value is 512 bytes. Microsoft * defines the signature at offsets 510 and 511 (zero-based) * regardless of the sector size. It is okay, however to have the * signature also at the end of the sector. We do both to be safe. */ pBoot[ bytesPerBlk - 1 ] = 0xaa; /* tail signature */ pBoot[ bytesPerBlk - 2 ] = 0x55; if (bytesPerBlk > 512) { pBoot[510] = 0x55; pBoot[511] = 0xaa; /* tail signature */ } /* * The FAT32 `free count of clusters' field will be set 0xffffffff * This indicates to MSDOS to not consider the field valid. * Note dosFsLib does not update this field currently. * A possible setting is shown below in comments. */ pBoot[ 488 ] = 0xff; /* & (pConf->nClust - 1); */ pBoot[ 489 ] = 0xff; /* & ( (pConf->nClust - 1) >> 8); */ pBoot[ 490 ] = 0xff; /* & ( (pConf->nClust - 1) >> 16); */ pBoot[ 491 ] = 0xff; /* & ( (pConf->nClust - 1) >> 24); */ /* * The FAT32 `next free cluster' field will be 0xffffffff * This indicates to MSDOS to not consider the field valid. * Note dosFsLib does not update this field currently. */ pBoot[ 492 ] = 0xff; pBoot[ 493 ] = 0xff; pBoot[ 494 ] = 0xff; pBoot[ 495 ] = 0xff; /* now write this info sector to disk */ if( cbioBlkRW( cbioDev, DOS32_INFO_SEC , 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; } /* create a boot sector image, and write it last */ /* first, prepare the non-fs boot block data */ if(TRUE == preserve) { if( cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM , 1, (addr_t)pBoot, CBIO_READ, NULL ) == ERROR ) goto _done_; } else { bzero( (char *)pBoot, bytesPerBlk ); dosFsFmtNonFsBootInit( pBoot, bytesPerBlk ); } /* now write the fields which are relevant to our params */ /* byte fields copied directly */ pBoot [DOS_BOOT_SEC_PER_CLUST] = pConf->secPerClust ; pBoot [DOS_BOOT_NFATS] = pConf->nFats ; pBoot [DOS_BOOT_MEDIA_BYTE] = pConf->mediaByte ; bcopy( pConf->sysId, (char *)pBoot+DOS_BOOT_SYS_ID, DOS_SYS_ID_LEN ); /* 16-bit values */ if( FALSE == preserve ) { /* * Small Hack with Big Comment. Mimic MSDOS n based translation. * This is just to appease MSDOS BIOS calls. * DOSFSII could care less really, but it helps MSDOS programs. * (such as our VxLd) Typical LCHS to CHS BIOS translation appears: * * +----------------+----------+------------+-------------+--------+ * |Actual Cylinders|Actual Hds|Altered Cyl |Altered Heads|Max Size| * +----------------+----------+------------+-------------+--------+ * | 1<C<=1024 | 1<H<=16 | C=C | H=H |528 MB | * +----------------+----------+------------+-------------+--------+ * | 1024<C<=2048 | 1<H<=16 | C=C/2 | H=H*2 | 1GB | * +----------------+----------+------------+-------------+--------+ * | 2048<C<=4096 | 1<H<=16 | C=C/4 | H=H*4 | 2.1GB | * +----------------+----------+------------+-------------+--------+ * | 4096<C<=8192 | 1<H<=16 | C=C/8 | H=H*8 | 4.2GB | * +----------------+----------+------------+-------------+--------+ * | 8192<C<=16384 | 1<H<=16 | C=C/16 | H=H*16 | 8.4GB | * +----------------+----------+------------+-------------+--------+ * | 16384<C<=32768 | 1<H<=8 | C=C/32 | H=H*32 | 8.4GB | * +----------------+----------+------------+-------------+--------+ * | 32768<C<=65536 | 1<H<=4 | C=C/64 | H=H*64 | 8.4GB | * +----------------+----------+------------+-------------+--------+ * * The MSDOS "logical CHS" (LCHS) format combined with the * Physical IDE/ATA CHS interface (PCHS) gives MSDOS the * following addressing limitation: * * +------------+----------+----------------+ * | BIOS INT13 | IDE/ATA | Combined Limit | * +-----------------+------------+----------+----------------+ * |Max Sectors/Track| 63 | 255 | 63 | * +-----------------+------------+----------+----------------+ * |Max Heads | 256 | 16 | 16 | * +-----------------+------------+----------+----------------+ * |Max Cylinders | 1024 | 65536 | 1024 | * +-----------------+------------+----------+----------------+ * |Capacity | 8.4GB | 136.9GB | 528 MB | * +-----------------+------------+----------+----------------+ * * 1024 x 16 x 63 X 512 bytes/sector = 528.48 MB limit. * * Cylinder bits : 10 = 1024 * Head bits : 4 = 16 * Sector bits : 6 (-1) = 63 * (by convention, CHS sector numbering begins at * #1, not #0; LBA begins at zero, which is CHS#1) * To overcome the limitation. PC BIOS/OS vendors perform * what is often referred to as geometric or "drive" CHS * translation to address more than 528MB, and to "address" * cylinders above 1024. So we just attempt to mimic here. */ if (((block_t)(cbioParams.nHeads) * (block_t)(cbioParams.blocksPerTrack)) != (block_t) 0) { work = (block_t)(((block_t)(cbioParams.blockOffset) + (block_t)(cbioParams.nBlocks)) / ((block_t)(cbioParams.nHeads) * (block_t)(cbioParams.blocksPerTrack))); while ( (work > (block_t) 1023) && (((block_t)(cbioParams.nHeads) << (block_t) 2) < (block_t) 256) ) { cbioParams.nHeads <<= (block_t) 2; work >>= (block_t) 2; } } /* values coming from driver, better not trust them if preserving */ if( pConf->secPerTrack == 0 ) pConf->secPerTrack = cbioParams.blocksPerTrack ; if( pConf->nHeads == 0 ) pConf->nHeads = cbioParams.nHeads ; VX_TO_DISK_16( pConf->secPerTrack, pBoot + DOS_BOOT_SEC_PER_TRACK); VX_TO_DISK_16( pConf->nHeads, pBoot + DOS_BOOT_NHEADS); } VX_TO_DISK_16( pConf->nResrvd, pBoot + DOS_BOOT_NRESRVD_SECS ); VX_TO_DISK_16( pConf->maxRootEnts, pBoot + DOS_BOOT_MAX_ROOT_ENTS ); VX_TO_DISK_16( bytesPerBlk, pBoot + DOS_BOOT_BYTES_PER_SEC); /* total sector count */ if( (cbioParams.nBlocks & ~0xffff ) == 0 ) { VX_TO_DISK_16( cbioParams.nBlocks, pBoot + DOS_BOOT_NSECTORS); } else { if( bytesPerBlk < 64 ) /* can not do with 32 byte sectors */ goto _done_; VX_TO_DISK_16( 0, pBoot + DOS_BOOT_NSECTORS); VX_TO_DISK_32( cbioParams.nBlocks, pBoot + DOS_BOOT_LONG_NSECTORS); } if( pConf->nResrvd >= 32 ) backupBootSec = 6 ; else if( pConf->nResrvd >= 2 ) backupBootSec = pConf->nResrvd -1 ; if( pConf->fatType == _FAT32 ) { pBoot [DOS32_BOOT_SIGNATURE] = DOS_EXT_BOOT_SIG; VX_TO_DISK_16( 0, pBoot + DOS_BOOT_SEC_PER_FAT ); VX_TO_DISK_32( pConf->secPerFat, pBoot + DOS32_BOOT_SEC_PER_FAT ); VX_TO_DISK_16( 0, pBoot + DOS32_BOOT_EXT_FLAGS ); VX_TO_DISK_16( 0 /* XXX-? */, pBoot + DOS32_BOOT_FS_VERSION ); VX_TO_DISK_32( 2 /* MUST */, pBoot + DOS32_BOOT_ROOT_START_CLUST); VX_TO_DISK_16( 1 /* MUST */, pBoot + DOS32_BOOT_FS_INFO_SEC ); VX_TO_DISK_16( backupBootSec, pBoot + DOS32_BOOT_BOOT_BKUP ); VX_TO_DISK_32( pConf->volSerial, pBoot + DOS32_BOOT_VOL_ID); bcopy( pConf->volLabel, (char *) pBoot + DOS32_BOOT_VOL_LABEL, DOS_VOL_LABEL_LEN ); bcopy( DOS_BOOT_SYSID_FAT32, (char *)pBoot + DOS32_BOOT_FS_TYPE, DOS_SYS_ID_LEN ); /* "FAT32 " */ if(FALSE == preserve) { pBoot [ DOS32_BOOT_BIOS_DRV_NUM ] = 0x80; /* assume hard */ } } else /* FAT 16 or FAT 12 */ { /* from offset 0x24 in FAT12/16 have other meaning in FAT32 */ /* indicate extended boot sector fields in use */ pBoot [DOS_BOOT_SIG_REC] = DOS_EXT_BOOT_SIG; VX_TO_DISK_32( pConf->nHidden, pBoot + DOS_BOOT_NHIDDEN_SECS); VX_TO_DISK_32( pConf->volSerial, pBoot + DOS_BOOT_VOL_ID); VX_TO_DISK_16( pConf->secPerFat, pBoot + DOS_BOOT_SEC_PER_FAT ); bcopy( pConf->volLabel, (char *) pBoot + DOS_BOOT_VOL_LABEL, DOS_VOL_LABEL_LEN ); /* Add file system type to offset 0x36, later DOS versions do this */ /* FAT12 */ if (pConf->fatType == _FAT12) { bcopy (DOS_BOOT_FSTYPE_FAT12, (char *) pBoot + DOS_BOOT_FSTYPE_ID, DOS_BOOT_FSTYPE_LEN); } /* FAT16 */ if (pConf->fatType == _FAT16) { bcopy (DOS_BOOT_FSTYPE_FAT16, (char *) pBoot + DOS_BOOT_FSTYPE_ID, DOS_BOOT_FSTYPE_LEN); } if(FALSE == preserve) { /* * jkf - Below is a hack. When writing this value out, * we really should be writing 0xN for floppies where * N=0 for drive 0, 1 for drive 1, and 2 for drive 2, etc. * For hard disks we should be writing out 0x8N. */ pBoot [ DOS_BOOT_DRIVE_NUM ] = (pConf->fatType == _FAT12) ? 0x00: 0x80 ; /* floppy or hard */ } } /* write the backup boot block */ if( backupBootSec != NONE ) if( cbioBlkRW( cbioDev, backupBootSec , 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; /* now write the real boot block */ if( cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM , 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; /* Done */ stat = OK ;_done_: if( pBoot != bootBlockBuffer ) KHEAP_FREE(pBoot); return( stat ); }/******************************************************************************** * dosFsVolFormat - format an MS-DOS compatible volume** This utility routine performs the initialization of file system data* structures on a disk. It supports FAT12 for small disks, FAT16 for* medium size and FAT32 for large volumes.* The <device> argument may be either a device name known to the I/O* system, or a dosFsLib Volume descriptor or a CBIO device handle.** The <opt> argument is a bit-wise or'ed combination of options controlling the* operation of this routine as follows:** .IP DOS_OPT_DEFAULT * If the current volume boot block is reasonably intact, use existing* parameters, else calculate parameters based only on disk size, possibly* reusing only the volume label and serial number.* * .IP DOS_OPT_PRESERVE* Attempt to preserve the current volume parameters even if they seem to* be somewhat unreliable.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -