📄 dosfsfmtlib.c
字号:
* level of criticality of an appropriate field */ /* JMP instruction */ if( pBoot[ DOS_BOOT_JMP ] != 0xe9 && pBoot[ DOS_BOOT_JMP ] != 0xeb ) Confidence -= 5 ; /* end of boot sector must have a signature */ if((pBoot[ bytesPerBlk - 2 ] != 0x55 ) || (pBoot[ bytesPerBlk-1] != 0xaa)) Confidence -= 20 ; if( DISK_TO_VX_16(pBoot+DOS_BOOT_BYTES_PER_SEC) != bytesPerBlk ) Confidence -= 10 ; if((pConf->secPerClust = pBoot[ DOS_BOOT_SEC_PER_CLUST ]) == 0) Confidence -= 10 ; if((pConf->mediaByte = pBoot[ DOS_BOOT_MEDIA_BYTE ]) == 0) Confidence -= 2 ; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NRESRVD_SECS )) == 0 ) Confidence -= 10 ; else pConf->nResrvd = work ; if((pConf->nFats = pBoot[ DOS_BOOT_NFATS ]) == 0) Confidence -= 10 ; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_MAX_ROOT_ENTS )) == 0 ) Confidence -= 10 ; else pConf->maxRootEnts = work ; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NSECTORS )) == 0 ) { if((work = DISK_TO_VX_32( pBoot + DOS_BOOT_LONG_NSECTORS )) == 0) Confidence -= 10 ; } if( work > cbioParams.cbio_nBlocks ) Confidence -= 10 ; else if( work != cbioParams.cbio_nBlocks ) Confidence -= 2 ; /* Check FAT12/FAT16 type ID fields */ bcopy ( (char *) pBoot + DOS_BOOT_FSTYPE_ID, (char *) tmpType, DOS_BOOT_FSTYPE_LEN); if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT16)) == 0) { pConf->fatType = _FAT16; pConf->secPerFat = DISK_TO_VX_16(pBoot + DOS_BOOT_SEC_PER_FAT); } else if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT12)) == 0) { pConf->fatType = _FAT12; pConf->secPerFat = DISK_TO_VX_16(pBoot + DOS_BOOT_SEC_PER_FAT); } else if((work = DISK_TO_VX_16(pBoot + DOS_BOOT_SEC_PER_FAT)) == 0 ) { if((work = DISK_TO_VX_32( pBoot + DOS32_BOOT_SEC_PER_FAT )) == 0 ) Confidence -= 5 ; bcopy((char *) pBoot + DOS32_BOOT_FS_TYPE, (char *) tmpType, DOS_SYS_ID_LEN ); if(strcmp ((char *)tmpType, DOS_BOOT_SYSID_FAT32) != 0 ) Confidence -= 5 ; pConf->fatType = _FAT32; pConf->secPerFat = work; } else { pConf->secPerFat = work ; if((work * bytesPerBlk / 2) <= DOS_FAT_12BIT_MAX ) pConf->fatType = _FAT12 ; else pConf->fatType = _FAT16 ; } /* * now, this is not the CHKDSK, we can skank mellow here, * ie, no need to be absolutely perfect. */ if( (pConf->nHeads = DISK_TO_VX_32( pBoot + DOS_BOOT_NHEADS))== 0) Confidence -=5 ; if((pConf->secPerTrack = DISK_TO_VX_32(pBoot + DOS_BOOT_SEC_PER_TRACK))==0) Confidence -=5 ; /* get volume serial number, this is what its all about, actually */ if( pConf->fatType == _FAT32 ) work = DISK_TO_VX_32( pBoot + DOS32_BOOT_VOL_ID ) ; else work = DISK_TO_VX_32( pBoot + DOS_BOOT_VOL_ID ) ; /* scrutinize the serial number */ if( (work & 0xffff) == ((work >> 16) & 0xffff) || (work & 0xffff0000) == 0) { /* found suspicious serial number, so we mangle it */ Confidence -= 5 ; work |= tickGet() << 16 ; } pConf->volSerial = work; /* get label, should be useful too */ if( pConf->fatType == _FAT32 ) i = DOS32_BOOT_VOL_LABEL; else i = DOS_BOOT_VOL_LABEL; bcopy( (char *)pBoot + i, pConf->volLabel, DOS_VOL_LABEL_LEN ); /* replace any illegal character with a space */ for(i = 0; i< DOS_VOL_LABEL_LEN; i++) { c1 = pConf->volLabel[i] ; if( ! isupper(c1) && ! isdigit(c1) && (c1 != '_') && (c1 != '$')) pConf->volLabel[i] = ' '; } /* Done */ if( pBoot != bootBlockBuffer ) free( pBoot ); if( Confidence < 0 ) Confidence = 0 ; return( Confidence ); }/********************************************************************************* dosFsFmtNonFsBootInit - initialize non-fs fields in boot block** Set areas such as JUMP command, boot code, signature* */LOCAL void dosFsFmtNonFsBootInit( u_char * pBoot, int bytesPerBlk) { /* * 0xEB is a x86, JMP rel8, Jump short, relative, * displacement relative to next instruction, 0x3e * The 0x90 is a NOP instruction and it is an alias * mnemonic for the XCHG (E)AX, (E)AX instruction. */ pBoot[ 0 ] = 0xeb ; /* JUMP */ pBoot[ 1 ] = 0x3e ; /* program offset */ pBoot[ 2 ] = 0x90 ; /* NOP */#if FALSE pBoot[ 0x3c ] = 0xc3 ; /* RET */ pBoot[ 0x3e ] = 0xc3 ; /* RET */ pBoot[ 0x3f ] = 0xc3 ; /* RET */#endif /* tail - 16bit word 0x55aa, little endian, standard sig. */ pBoot[ bytesPerBlk-2 ] = 0x55 ; pBoot[ bytesPerBlk-1 ] = 0xaa ; }/******************************************************************************** * dosFsFmtVolInit - perform the actual disk formatting** Initialize all file system control structure on the disk, optionally* preserving the boot block non-file system fields such as boot code* and partition table.**/LOCAL int dosFsFmtVolInit ( CBIO_DEV_ID cbio_dev, /* cache disk driver id */ DOS_VOL_CONFIG * pConf, /* volume parameters */ BOOL preserve, /* =1 - preserve boot blocks fields */ int opt /* VxLong names */ ) { STATUS stat = ERROR ; u_char bootBlockBuffer [512] ; u_char * pBoot ; u_char dirEntrySize = 0x20 ; /* maybe changed to VxLongs */ int backupBootSec = NONE ; u_long i, work, rootStartSec ; int bytesPerBlk; CBIO_PARAMS cbioParams; /* Get CBIO device parameters */ if (ERROR == cbioParamsGet (cbio_dev, &cbioParams)) { return (ERROR); } bytesPerBlk = cbioParams.cbio_bytesPerBlk ; if( opt & DOS_OPT_VXLONGNAMES ) dirEntrySize = 0x40 ; /* Thanks Kent! */ /* * Need enough space for at least a sector, * depending on sector size we may malloc it. */ if( bytesPerBlk > (int)sizeof(bootBlockBuffer) ) pBoot = malloc(bytesPerBlk); else pBoot = bootBlockBuffer ; bzero( (char *)pBoot, bytesPerBlk ); /* clear out the entire FAT, all copies of it ! */ for(i = 0; i < (pConf->secPerFat * pConf->nFats); i++ ) { if(cbioBlkRW( cbio_dev, 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 { work = (pConf->maxRootEnts * dirEntrySize) / 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( cbio_dev, 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( cbio_dev, i , 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR ) goto _done_; /* create file system info sector for FAT32 */ if( pConf->fatType == _FAT32 ) { bzero( (char *)pBoot, bytesPerBlk ); pBoot[ 0 ] = 'R'; /* info sector */ pBoot[ 1 ] = 'R'; /* magic signature */ pBoot[ 2 ] = 'a'; pBoot[ 3 ] = 'A'; pBoot[ bytesPerBlk - 28] = 'r'; pBoot[ bytesPerBlk - 27] = 'r'; pBoot[ bytesPerBlk - 26] = 'A'; pBoot[ bytesPerBlk - 25] = 'a'; pBoot[ bytesPerBlk - 1 ] = 0xaa; /* tail signature */ pBoot[ bytesPerBlk - 2 ] = 0x55; pBoot[ bytesPerBlk - 24] = 0xff; /* free cluster count */ pBoot[ bytesPerBlk - 23] = 0xff; /* unknown yet */ pBoot[ bytesPerBlk - 22] = 0xff; /* FIXME - MSFT/chkdsk */ pBoot[ bytesPerBlk - 21] = 0xff; /* wont like this */ /* next free cluster will be left as 0 */ /* now write this info sector to disk */ if( cbioBlkRW( cbio_dev, 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( preserve ) { if( cbioBlkRW( cbio_dev, 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( ! 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.cbio_nHeads) * (block_t)(cbioParams.cbio_blksPerTrack)) != (block_t) 0) { work = (block_t)(((block_t)(cbioParams.cbio_offset) + (block_t)(cbioParams.cbio_nBlocks)) / ((block_t)(cbioParams.cbio_nHeads) * (block_t)(cbioParams.cbio_blksPerTrack))); while ( (work > (block_t) 1023) && (((block_t)(cbioParams.cbio_nHeads) << (block_t) 2) < (block_t) 256) ) { cbioParams.cbio_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.cbio_blksPerTrack ; if( pConf->nHeads == 0 ) pConf->nHeads = cbioParams.cbio_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -