📄 dosfsfmtlib.c
字号:
/* dosFsFmtLib.c - MS-DOS media-compatible file system formatting library */ /* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01s,18oct99,jkf avoiding div by zero if nHeads*blksPerTrack = 0, SPR#2950801r,27oct99,jkf Documentation correction for compatibility section.01q,03oct99,jkf setup a pseudo LCHS translation to mimic MSDOS more. This helps VxLd on large disks formatted by us.01p,03oct99,jkf removed random signature, breaks vxsys booting. Correction from vxsys investigation, removed random signature, configure hidden sectors to sec per track, change nClust calculation to match Microsoft.01o,03oct99,jkf added sysId check to dosFsFmtReadBootBlock, changed reserved sectors setting to one in dosFsVolFormat. Disabled the ret instructions being written in dosFsFmtNonFsBootInit.01n,15sep99,jkf changes for new CBIO API.01m,31jul99,jkf FAT12/FAT16 calculation per NT, SPR#28274. improved media byte support, SPR#27282. added support FSTYPE (0x36) in boot sector, SPR#28273.01l,16jun99,jkf correctly set FS ID for FAT32, SPR#28275.01k,12jul99,jkf T2 merge, tidiness & spelling. (allows Windows to mount our FAT32)01j,30nov98,lrn changed JMP instruction to be Win98 compatible (SPR#23442)01i,07sep98,lrn fixed formatting of 4 MB disks to be FAT1601h,30jul98,wlf partial doc cleanup01g,14jul98,lrn replaced perror() with printErr01f,12jul98,lrn fixed: option may force format to FAT1601e,22jun98,lrn vol desc name change01d,03jun98,lrn Libinit, integ, increased max root dirs for small disks01c,03jun98,lrn polished main function and interactive params control, doc01b,14may98,lrn added VxLong names 01a,12may98,lrn initial version*//*DESCRIPTIONThis module is a scaleable companion module for dosFsLib, and is intended to facilitate high level formatting of disk volumes.There are two ways to high level format a volume:.IP "(1)"Directly calling dosFsVolFormat() routine allows to have completecontrol over the format used, parameters and allows to supply a hookroutine which for instance could interactively prompt the user tomodify disk parameters..IP "(2)"Calling ioctl command FIODISKINIT will invoke the formatting routinevia dosFsLib. This uses the default volume format and parameters.AVAILABILITYThis routine is an optional part of the MS-DOS file system,and may be included in a target system if it is required tobe able to format new volumes.In order to include this option, the following function needsto be invoked during system initialization:.CSvoid dosFsFmtLibInit( void );.CESee reference page dosFsVolFormat() for complete description ofsupported formats, options and arguments.SEE ALSOdosFsLib*//* includes */#include "vxWorks.h"#include "string.h"#include "stdio.h"#include "stdlib.h"#include "ctype.h"#include "errnoLib.h"#include "memLib.h"#include "tickLib.h"#include "dosFsLib.h"#include "private/dosFsLibP.h"/* defines *//* defines - FAT Boot Sector values */#define DOS_BOOT_SEC_NUM 0 /* sector number of boot sector */#define DOS_MIN_CLUST 2 /* lowest cluster number used *//* most of these are old defaults which are now calculated */#define DEFAULT_MAX_ROOT_ENTS 112 /* default max # of root dir entries */#define DEFAULT_SEC_PER_CLUST 2 /* default sectors per cluster */#define DEFAULT_MEDIA_BYTE 0xF8 /* default media byte value */#define DEFAULT_NFATS 2 /* default number FAT copies */#define DEFAULT_NRESERVED 1 /* default # of reserved sec's (min=1)*/#define DOS_FAT_12BIT_MAX 4085 /* max clusters, 12 bit FAT entries *//* * FIXME - these are not really -2, but -11, but it is ok because * we then should take into account the FAT sectors overhead when * calculating cluster size. */#define DOS_FAT_16BIT_MAX (0x10000-2) /* max clusters, 16 bit FAT */#define DOS_FAT_32BIT_MAX (0x200000-2) /* max clusters, 32-bit FAT entries */#define DOS32_INFO_SEC 1 /* FAT32 info sector location */#define DOS32_BACKUP_BOOT 6 /* FAT32 backup boot block location *//********************************************************************************* dosFsFmtShow - print volume parameters to stdout**/LOCAL void dosFsFmtShow( DOS_VOL_CONFIG * pConf ) { printf("Volume Parameters: FAT type: FAT%d, sectors per cluster %d\n", pConf->fatType, pConf->secPerClust); printf(" %d FAT copies, %ld clusters, %ld sectors per FAT\n", pConf->nFats, pConf->nClust, pConf->secPerFat ); printf(" Sectors reserved %d, hidden %ld, FAT sectors %ld\n", pConf->nResrvd, pConf->nHidden, pConf->secPerFat* pConf->nFats); printf(" Root dir entries %d, sysId %-8s, serial number %lx\n", pConf->maxRootEnts, pConf->sysId, pConf->volSerial ); printf(" Label:\"%-11s\" ...\n", pConf->volLabel ); }/********************************************************************************* dosFsFmtAutoParams - automatically calculate FAT formatting params** This function attempts to imitate MSFT formulae for setting* disk parameters for maximum compatibility.* For fully automatic configuration, the configuration structure* should be all zeroed out.* If any of the modifiable fields are non-zero, this function will* calculate the rest of the parameters, honoring the values filled* in prior to the call.** Note however that MSFT compatibility can not be always maintained* unless fully automatic configuration is performed.**/LOCAL STATUS dosFsFmtAutoParams ( DOS_VOL_CONFIG * pConf, /* config params structure */ ULONG nBlks, /* # of secs on volume */ int bytesPerBlk, /* sector size */ int opt /* VxLongs */ ) { ULONG nClust, maxClust, minClust ; int rootSecs, fatBytes ; int dirEntrySize = 0x20 ; if( opt & DOS_OPT_VXLONGNAMES ) dirEntrySize = 0x40 ; if( (bytesPerBlk < dirEntrySize ) || (bytesPerBlk < 64 && nBlks > 0xfffe) ) { errno = EINVAL; return ERROR; } if( bytesPerBlk < 512 ) { /* tiny RAMdisks */ if(pConf->secPerClust == 0 ) pConf->secPerClust = 1 ; if(pConf->mediaByte == 0 ) pConf->mediaByte = 0xfd; /* TODO, what to use for RAMDISK? */ if(pConf->nFats == 0 ) pConf->nFats = 1; rootSecs = (DEFAULT_MAX_ROOT_ENTS * dirEntrySize / bytesPerBlk); minClust = 1 ; } else if (nBlks <= 720) /* i.e. 360KB 5.25" */ { /* temporary value, later scaled up as needed */ if(pConf->secPerClust == 0) pConf->secPerClust = 1 ; if(pConf->mediaByte == 0) pConf->mediaByte = 0xfd; /* per NT Resource Kit */ if(pConf->fatType == _AUTO) pConf->fatType = _FAT12; /* floppies use FAT12 */ pConf->maxRootEnts = 112; /* always 112 for 360KB */ rootSecs = (112 * dirEntrySize / bytesPerBlk); minClust = 2; } else if (nBlks <= 1440 ) /* i.e. 720KB 3.5" */ { /* temporary value, later scaled up as needed */ if( pConf->secPerClust == 0) pConf->secPerClust = 1 ; if( pConf->mediaByte == 0) pConf->mediaByte = 0xf9; /* per NT Resource Kit */ if(pConf->fatType == _AUTO) pConf->fatType = _FAT12; /* floppies use FAT12 */ pConf->maxRootEnts = 112; /* always 112 for 720KB */ rootSecs = (112 * dirEntrySize / bytesPerBlk); minClust = 2; } else if (nBlks <= 2400 ) /* i.e. 1.2Mb 5.25" */ { /* temporary value, later scaled up as needed */ if(pConf->secPerClust == 0) pConf->secPerClust = 1 ; if(pConf->mediaByte == 0) pConf->mediaByte = 0xf9;/* per NT Resource Kit */ if(pConf->fatType == _AUTO) pConf->fatType = _FAT12; /* floppies use FAT12 */ pConf->maxRootEnts = 224; /* always 224 for 1.2 MB floppies */ rootSecs = (224 * dirEntrySize / bytesPerBlk); minClust = 2; } else if( nBlks <= 2880 ) /* i.e. 1.44MB 5.25" floppy */ { /* temporary value, later scaled up as needed */ if(pConf->secPerClust == 0) pConf->secPerClust = 1 ; if(pConf->mediaByte == 0) pConf->mediaByte = 0xf0;/* Per NT Resource Kit */ pConf->maxRootEnts = 224; /* always 224 for 1.44MB floppies */ rootSecs = (224 * dirEntrySize / bytesPerBlk); minClust = 2; } else if( nBlks <= 5000 ) /* probally a hard disk or PCMCIA, etc.*/ { /* temporary value, later scaled up as needed */ if(pConf->secPerClust == 0) pConf->secPerClust = 1; if(pConf->mediaByte == 0) pConf->mediaByte = DEFAULT_MEDIA_BYTE ; pConf->maxRootEnts = 224; rootSecs = (224 * dirEntrySize / bytesPerBlk); minClust = 1 ; } else { /* temporary value, later scaled up as needed */ if(pConf->secPerClust == 0) pConf->secPerClust = 2; if(pConf->mediaByte == 0) pConf->mediaByte = DEFAULT_MEDIA_BYTE; pConf->maxRootEnts = 512; rootSecs = (512 * dirEntrySize / bytesPerBlk); minClust = 2; } /* fixup root directory entries */ if( pConf->maxRootEnts != 0 ) rootSecs = pConf->maxRootEnts * dirEntrySize / bytesPerBlk ; pConf->maxRootEnts = rootSecs * bytesPerBlk / dirEntrySize ; if( pConf->nFats == 0 ) pConf->nFats = DEFAULT_NFATS; pConf->nFats = min( pConf->nFats, 16 ); /* temporary value, may be way too large */ nClust = nBlks / pConf->secPerClust ; /* define FAT type first, many other params depend on it */ if( pConf->fatType == _AUTO ) { /* * Here we decide which FAT format to use. * FAT12 < 32680 sectors is per NT Workstation Resource Kit. * This will help reduce fragmentation on smaller disks (PCMCIA) * FAT 16 should be less than 2GB volume. */ if((nClust <= DOS_FAT_12BIT_MAX) || (nBlks < 32680)) pConf->fatType = _FAT12 ; /* <16MB volume, FAT12 */ else if ( nBlks < 0x400000 ) pConf->fatType = _FAT16 ; /* 16MB+ <2GB, FAT16 */ else pConf->fatType = _FAT32 ; /* 2GB+ volume, FAT32 */ } switch(pConf->fatType) { case _FAT32: if( pConf->nResrvd == 0) pConf->nResrvd = 32; maxClust = DOS_FAT_32BIT_MAX; minClust = 8; break; default: case _FAT16: if( pConf->nResrvd == 0) pConf->nResrvd = 1; maxClust = DOS_FAT_16BIT_MAX; minClust = 2; break; case _FAT12: if( pConf->nResrvd == 0) pConf->nResrvd = 1; maxClust = DOS_FAT_12BIT_MAX; minClust = 1; break; } /* now, we know the FAT type, so we can really calculate secs per clust */ while( (nClust > maxClust ) || ((ULONG)pConf->secPerClust < minClust) ) { pConf->secPerClust <<= 1 ; /* multiply secs/clust by 2 */ nClust = nBlks / pConf->secPerClust ; /* recalc */ } /* max secs/clust is limited to 254 */ pConf->secPerClust = min( pConf->secPerClust, 254 ); nClust = nBlks / pConf->secPerClust ; /* recalc */ switch( pConf->fatType ) { case _FAT32: fatBytes = nClust * 4; rootSecs = 0 ; /* root dir is a normal cluster */ if(pConf->sysId==NULL) pConf->sysId = "VX5DOS32"; break; default: case _FAT16: fatBytes = nClust * 2; if(pConf->sysId==NULL) pConf->sysId = "VXDOS16"; break; case _FAT12: fatBytes = nClust * 3 / 2; if(pConf->sysId==NULL) pConf->sysId = "VXDOS12"; break; } /* setup a special id for longnames */ if( opt & DOS_OPT_VXLONGNAMES ) { pConf->sysId = "VXEXT1.1"; } /* calculate sectors per fat */ pConf->secPerFat = (fatBytes + bytesPerBlk - 1) / bytesPerBlk ; /* figure out root dir size */ pConf->maxRootEnts = rootSecs * bytesPerBlk / dirEntrySize ; /* one last time, recalculate cluster nClust, knowing reserved */ nClust = (nBlks - pConf->nResrvd - rootSecs - pConf->nHidden - (pConf->secPerFat * pConf->nFats ) ) / pConf->secPerClust; pConf->nClust = nClust; /* see if it all sums up */ if(pConf->nHidden + pConf->nResrvd + rootSecs + (pConf->secPerFat * pConf->nFats ) + (pConf->nClust * pConf->secPerClust) > nBlks ) goto error; if( (pConf->secPerClust <= 255 ) ) return OK ;error: errno = EINVAL ; return ERROR; }/********************************************************************************* dosFsFmtReadBootBlock - read existing boot block on the disk** Read the existing boot block on the disk, to salvage some fields* that should be preserved, if the volume is already formatted.** RETURNS: results confidence level: 100 is the highest confidence, * a lower value means more probability for bogus values, or ERROR if * could not read block.*/LOCAL int dosFsFmtReadBootBlock ( CBIO_DEV_ID cbio_dev, DOS_VOL_CONFIG * pConf ) { int Confidence = 100 ; STATUS stat ; u_char bootBlockBuffer [ 512 ] ; u_char * pBoot ; u_char c1 ; u_long i, work ; int bytesPerBlk; u_char tmpType [ DOS_BOOT_FSTYPE_LEN + 1] = { 0 }; CBIO_PARAMS cbioParams; /* Get CBIO device parameters */ if (ERROR == cbioParamsGet (cbio_dev, &cbioParams)) { return (ERROR); } bytesPerBlk = cbioParams.cbio_bytesPerBlk ; if( bytesPerBlk > (int) sizeof(bootBlockBuffer) ) pBoot = malloc(bytesPerBlk); else pBoot = bootBlockBuffer ; bzero( (char *) pBoot, bytesPerBlk ); /* read the boot block */ stat = cbioBlkRW( cbio_dev, DOS_BOOT_SEC_NUM, 1, (addr_t)pBoot, CBIO_READ, NULL ); if( stat == ERROR ) return ERROR ; /* inspect the boot block fields, and decrease confidence value * each time a field seems bogus, by something relative to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -