dosFsFmtLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:47k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* dosFsFmtLib.c - MS-DOS media-compatible file system formatting library */ 
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02b,29apr02,jkf  SPR#76013, dosFsVolFormat shall cbioUnlock all it cbioLock's
  8. 02a,12dec01,jkf  fixing diab warnings
  9. 01z,10dec01,jkf  SPR#72039, MSDOS FAT32 fsInfo sector now using hard coded 
  10.                  offsets to properly support blkSize > 512bps.
  11.                  increase check for bytesPerBlk minimum in dosFsFmtAutoParams.
  12. 01y,15nov01,jkf  SPR#71720, avoid unaligned pointer access.
  13. 01x,09nov01,jkf  SPR#71633, dont set errno when VolFormat suceeded.
  14. 01w,20sep01,jkf  SPR#69031, common code for both AE & 5.x.
  15. 01v,08dec00,jkf  SPR#34704,FAT12/FAT16 determination, SPR#62415 sig location.
  16. 01u,15sep00,jkf  cleaning warning
  17. 01t,29feb00,jkf  T3 changes, cleanup
  18. 01s,18oct99,jkf  avoiding div by zero if nHeads*blksPerTrack = 0, SPR#29508
  19. 01r,27oct99,jkf  Documentation correction for compatibility section.
  20. 01q,03oct99,jkf  setup a pseudo LCHS translation to mimic MSDOS more.
  21.                  This helps VxLd on large disks formatted by us.
  22. 01p,03oct99,jkf  removed random signature, breaks vxsys booting.
  23.                  Correction from vxsys investigation, removed random
  24.                  signature, configure hidden sectors to sec per track,
  25.                  change nClust calculation to match Microsoft.
  26. 01o,03oct99,jkf  added sysId check to dosFsFmtReadBootBlock, 
  27.                  changed reserved sectors setting to one in 
  28.                  dosFsVolFormat. Disabled the ret instructions
  29.                  being written in dosFsFmtNonFsBootInit.
  30. 01n,15sep99,jkf  changes for new CBIO API.
  31. 01m,31jul99,jkf  FAT12/FAT16 calculation per NT, SPR#28274. 
  32.                  improved media byte support, SPR#27282. 
  33.  added support FSTYPE (0x36) in boot sector, SPR#28273.
  34. 01l,16jun99,jkf  correctly set FS ID for FAT32, SPR#28275.
  35. 01k,12jul99,jkf  T2 merge, tidiness & spelling.
  36.                  (allows Windows to mount our FAT32)
  37. 01j,30nov98,lrn  changed JMP instruction to be Win98 compatible (SPR#23442)
  38. 01i,07sep98,lrn  fixed formatting of 4 MB disks to be FAT16
  39. 01h,30jul98,wlf  partial doc cleanup
  40. 01g,14jul98,lrn  replaced perror() with printErr
  41. 01f,12jul98,lrn  fixed: option may force format to FAT16
  42. 01e,22jun98,lrn  vol desc name change
  43. 01d,03jun98,lrn  Libinit, integ, increased max root dirs for small disks
  44. 01c,03jun98,lrn  polished main function and interactive params control, doc
  45. 01b,14may98,lrn  added VxLong names 
  46. 01a,12may98,lrn  initial version
  47. */
  48. /*
  49. DESCRIPTION
  50. This module is a scaleable companion module for dosFsLib, 
  51. and is intended to facilitate high level formatting of 
  52. disk volumes.
  53. There are two ways to high level format a volume:
  54. .IP "(1)"
  55. Directly calling dosFsVolFormat() routine allows to have complete
  56. control over the format used, parameters and allows to supply a hook
  57. routine which for instance could interactively prompt the user to
  58. modify disk parameters.
  59. .IP "(2)"
  60. Calling ioctl command FIODISKINIT will invoke the formatting routine
  61. via dosFsLib. This uses the default volume format and parameters.
  62. AVAILABILITY
  63. This routine is an optional part of the MS-DOS file system,
  64. and may be included in a target system if it is required to
  65. be able to format new volumes.
  66. In order to include this option, the following function needs
  67. to be invoked during system initialization:
  68. .CS
  69. void dosFsFmtLibInit( void );
  70. .CE
  71. See reference page dosFsVolFormat() for complete description of
  72. supported formats, options and arguments.
  73. SEE ALSO
  74. dosFsLib
  75. */
  76. /* includes */
  77. #include "vxWorks.h"
  78. #include "private/dosFsVerP.h"
  79. #include "string.h"
  80. #include "stdio.h"
  81. #include "stdlib.h"
  82. #include "ctype.h"
  83. #include "errnoLib.h"
  84. #include "memLib.h"
  85. #include "tickLib.h"
  86. #include "dosFsLib.h"
  87. #include "private/dosFsLibP.h"
  88. #include "private/dosDirLibP.h"
  89. /* defines */
  90. /* defines - FAT Boot Sector values */
  91. #define DOS_BOOT_SEC_NUM        0       /* sector number of boot sector */
  92. #define DOS_MIN_CLUST           2       /* lowest cluster number used */
  93. /* most of these are old defaults which are now calculated */
  94. #define DEFAULT_ROOT_ENTS       112     /* default # of root dir entries */
  95. #define DEFAULT_MAX_ROOT_ENTS   512     /* default max # of root dir entries */
  96. #define DEFAULT_SEC_PER_CLUST   2       /* default sectors per cluster */
  97. #define DEFAULT_MEDIA_BYTE      0xF8    /* default media byte value */
  98. #define DEFAULT_NFATS           2       /* default number FAT copies */
  99. #define MAX_NFATS 16 /* maximum number FAT copies */
  100. #define DEFAULT_NRESERVED       1       /* default # of reserved sec's (min=1)*/
  101. #define DOS_FAT_12BIT_MAX       4085    /* max clusters, 12 bit FAT entries */
  102. /* 
  103.  * FIXME - these are not really -2, but -11, but it is ok because
  104.  * we then should take into account the FAT sectors overhead when
  105.  * calculating cluster size.
  106.  */
  107. #define DOS_FAT_16BIT_MAX   (0x10000-2) /* max clusters, 16 bit FAT */
  108. #define DOS_FAT_32BIT_MAX (0x200000-2)  /* max clusters, 32-bit FAT entries */
  109. #define DOS32_INFO_SEC 1 /* FAT32 info sector location */
  110. #define DOS32_BACKUP_BOOT 6 /* FAT32 backup boot block location */
  111. /*******************************************************************************
  112. *
  113. * dosFsFmtShow - print volume parameters to stdout
  114. *
  115. */
  116. LOCAL void dosFsFmtShow( DOS_VOL_CONFIG * pConf )
  117.     {
  118.     printf("Volume Parameters: FAT type: FAT%d, sectors per cluster %dn",
  119. pConf->fatType, pConf->secPerClust);
  120.     printf("  %d FAT copies, %ld clusters, %ld sectors per FATn",
  121. pConf->nFats, pConf->nClust, pConf->secPerFat );
  122.     printf("  Sectors reserved %d, hidden %ld, FAT sectors %ldn",
  123. pConf->nResrvd, pConf->nHidden, pConf->secPerFat* pConf->nFats);
  124.     printf("  Root dir entries %d, sysId %-8s, serial number %lxn",
  125. pConf->maxRootEnts, pConf->sysId, pConf->volSerial );
  126.     printf("  Label:"%-11s" ...n", pConf->volLabel );
  127.     }
  128. /*******************************************************************************
  129. *
  130. * dosFsFmtAutoParams - automatically calculate FAT formatting params
  131. *
  132. * This function attempts to imitate MSFT formulae for setting
  133. * disk parameters for maximum compatibility.
  134. * For fully automatic configuration, the configuration structure
  135. * should be all zeroed out.
  136. * If any of the modifiable fields are non-zero, this function will
  137. * calculate the rest of the parameters, honoring the values filled
  138. * in prior to the call.
  139. *
  140. * Note however that MSFT compatibility can not be always maintained
  141. * unless fully automatic configuration is performed.
  142. *
  143. */
  144. LOCAL STATUS dosFsFmtAutoParams
  145.     (
  146.     DOS_VOL_CONFIG * pConf, /* config params structure */
  147.     ULONG nBlks, /* # of secs on volume */
  148.     int bytesPerBlk, /* sector size */
  149.     int opt /* VxLongs */
  150.     )
  151.     {
  152.     ULONG nClust, maxClust, minClust ;
  153.     int rootSecs, fatBytes ;
  154.     int dirEntrySize = DOS_DIRENT_STD_LEN;
  155.     /* 
  156.      * adjust the directory entry size if using vxLongnames which
  157.      * use a unique directory entry size.
  158.      */
  159.     if( opt & DOS_OPT_VXLONGNAMES )
  160. dirEntrySize = DOS_VX_DIRENT_LEN;
  161.     /* verify bytes per block supports the file system */
  162.     if( (bytesPerBlk < (dirEntrySize *3))     || 
  163.         (bytesPerBlk < 64 && nBlks > 0xfffe) )
  164. {
  165. errno = EINVAL;
  166. return ERROR;
  167. }
  168.     
  169.     /* setup some pConf field based on disk size */
  170.     if( bytesPerBlk < 512 )
  171. {
  172. /* most likely a tiny RAMdisks */
  173. if(pConf->secPerClust == 0 )
  174.     pConf->secPerClust = 1 ;
  175. if(pConf->mediaByte == 0 )
  176.     pConf->mediaByte = 0xfd;  /* TODO, what to use for RAMDISK? */
  177. if(pConf->nFats == 0 )
  178.     pConf->nFats = 1;
  179. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  180.  bytesPerBlk);
  181. minClust = 1 ;
  182. }
  183.     else if (nBlks <= 720) /* i.e. 360KB 5.25" */
  184. {
  185. /* temporary value, later scaled up as needed */
  186. if(pConf->secPerClust == 0)
  187.     pConf->secPerClust = 1 ;
  188. if(pConf->mediaByte == 0)
  189.     pConf->mediaByte = 0xfd; /* per NT Resource Kit */
  190. if(pConf->fatType == _AUTO)
  191.     pConf->fatType = _FAT12; /* floppies use FAT12 */
  192. pConf->maxRootEnts = DEFAULT_ROOT_ENTS; /* always 112 for 360KB */
  193. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  194.  bytesPerBlk);
  195. minClust = 2;
  196. }
  197.     else if (nBlks <= 1440 ) /* i.e. 720KB 3.5" */
  198. {
  199. /* temporary value, later scaled up as needed */
  200. if( pConf->secPerClust == 0)
  201.     pConf->secPerClust = 1 ;
  202. if( pConf->mediaByte == 0)
  203.     pConf->mediaByte = 0xf9; /* per NT Resource Kit */ 
  204. if(pConf->fatType == _AUTO)
  205.     pConf->fatType = _FAT12; /* floppies use FAT12 */
  206. pConf->maxRootEnts = DEFAULT_ROOT_ENTS; /* always 112 for 720KB */
  207. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  208.  bytesPerBlk);
  209. minClust = 2;
  210. }
  211.     else if (nBlks <= 2400 ) /* i.e. 1.2Mb 5.25" */
  212. {
  213. /* temporary value, later scaled up as needed */
  214. if(pConf->secPerClust == 0)
  215.     pConf->secPerClust = 1 ;
  216. if(pConf->mediaByte == 0)
  217.    pConf->mediaByte = 0xf9;/* per NT Resource Kit */
  218. if(pConf->fatType == _AUTO)
  219.     pConf->fatType = _FAT12; /* floppies use FAT12 */
  220. pConf->maxRootEnts = DEFAULT_ROOT_ENTS;
  221. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  222.  bytesPerBlk);
  223. minClust = 2;
  224. }
  225.     else if( nBlks <= 2880 ) /* i.e. 1.44MB 3.5" floppy */
  226. {
  227. /* temporary value, later scaled up as needed */
  228. if(pConf->secPerClust == 0)
  229.     pConf->secPerClust = 1 ;
  230. if(pConf->mediaByte == 0)
  231.     pConf->mediaByte = 0xf0;/* Per NT Resource Kit */
  232. if(pConf->fatType == _AUTO)
  233.     pConf->fatType = _FAT12; /* floppies use FAT12 */
  234. pConf->maxRootEnts = DEFAULT_ROOT_ENTS; 
  235. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  236.  bytesPerBlk);
  237. minClust = 2;
  238. }
  239.     else if( nBlks <= 4000 ) /* probally a hard disk or PCMCIA, FLASH etc.*/
  240. {
  241. /* temporary value, later scaled up as needed */
  242. if(pConf->secPerClust == 0)
  243.     pConf->secPerClust = 1;
  244. if(pConf->mediaByte == 0)
  245.     pConf->mediaByte = DEFAULT_MEDIA_BYTE;
  246. if(pConf->fatType == _AUTO)
  247.     pConf->fatType = _FAT12; /* floppies use FAT12 */
  248. pConf->maxRootEnts = DEFAULT_ROOT_ENTS; 
  249. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  250.  bytesPerBlk);
  251.         minClust = 1 ;
  252. }
  253.     else
  254. {
  255. /* temporary value, later scaled up as needed */
  256. if(pConf->secPerClust == 0)
  257.     pConf->secPerClust = 2;
  258. if(pConf->mediaByte == 0)
  259.     pConf->mediaByte = DEFAULT_MEDIA_BYTE;
  260. pConf->maxRootEnts = DEFAULT_MAX_ROOT_ENTS;
  261. rootSecs = (((DEFAULT_ROOT_ENTS * dirEntrySize) + (bytesPerBlk -1)) / 
  262.  bytesPerBlk);
  263. minClust = 2;
  264. }
  265.     /* fixup root directory entries */
  266.     if( pConf->maxRootEnts != 0 )
  267. {
  268. rootSecs = (((pConf->maxRootEnts * dirEntrySize) + (bytesPerBlk -1)) / 
  269.     bytesPerBlk);
  270. }
  271.     if( pConf->nFats == 0 )
  272. pConf->nFats = DEFAULT_NFATS;
  273.     pConf->nFats = min( pConf->nFats, MAX_NFATS );
  274.     /* temporary value, may be way too large */
  275.     nClust = nBlks / pConf->secPerClust ;
  276.     /* define FAT type first, many other params depend on it */
  277.     if( pConf->fatType == _AUTO )
  278. {
  279. /* 
  280.  * Here we decide which FAT format to use.
  281.  */
  282. if(nClust < DOS_FAT_12BIT_MAX)
  283.     pConf->fatType = _FAT12 ; /* <16MB volume, FAT12 */
  284. else if ( nBlks < 0x400000 )
  285.     pConf->fatType = _FAT16 ;   /* 16MB+ <2GB, FAT16 */
  286. else
  287.     pConf->fatType = _FAT32 ; /* 2GB+ volume, FAT32 */
  288. }
  289.     switch(pConf->fatType)
  290. {
  291. case _FAT32:
  292.     if( pConf->nResrvd == 0)
  293. pConf->nResrvd = 32;
  294.     maxClust = DOS_FAT_32BIT_MAX;
  295.     minClust = 8;
  296.     break;
  297. default:
  298. case _FAT16:
  299.     if( pConf->nResrvd == 0)
  300. pConf->nResrvd = 1;
  301.     maxClust = DOS_FAT_16BIT_MAX;
  302.     minClust = 2;
  303.     break;
  304. case _FAT12:
  305.     if( pConf->nResrvd == 0)
  306. pConf->nResrvd = 1;
  307.     maxClust = DOS_FAT_12BIT_MAX;
  308.     minClust = 1;
  309.     break;
  310. }
  311.     /* now, we know the FAT type, so we can really calculate secs per clust */
  312.     while( (nClust > maxClust ) || ((ULONG)pConf->secPerClust < minClust) )
  313. {
  314. pConf->secPerClust <<= 1 ; /* multiply secs/clust by 2 */
  315. nClust = nBlks / pConf->secPerClust ; /* recalc */
  316. }
  317.     /* max secs/clust is limited to 254 */
  318.     pConf->secPerClust = min( pConf->secPerClust, 254 );
  319.     nClust = nBlks / pConf->secPerClust ; /* recalc */
  320.     switch( pConf->fatType )
  321. {
  322. case _FAT32:
  323.     fatBytes = nClust * 4;
  324.     rootSecs = 0 ; /* root dir is a normal cluster */
  325.     if(pConf->sysId==NULL) pConf->sysId = "VX5DOS32";
  326.     break;
  327. default:
  328. case _FAT16:
  329.     fatBytes = nClust * 2;
  330.     if(pConf->sysId==NULL) pConf->sysId = "VXDOS16";
  331.     break;
  332. case _FAT12:
  333.     fatBytes = nClust * 3 / 2;
  334.     if(pConf->sysId==NULL) pConf->sysId = "VXDOS12";
  335.     break;
  336. }
  337.     /* setup a special id for longnames */
  338.     if( opt & DOS_OPT_VXLONGNAMES )
  339. {
  340. pConf->sysId = "VXEXT1.1";
  341. }
  342.     /* calculate sectors per fat */
  343.     pConf->secPerFat =  (fatBytes + bytesPerBlk - 1) / bytesPerBlk ;
  344.     /* figure out root dir size */
  345.     pConf->maxRootEnts = rootSecs * bytesPerBlk / dirEntrySize ;
  346.     /* root entries are never bigger than 512 */
  347.     if ((pConf->fatType != _FAT32) && (pConf->maxRootEnts > DEFAULT_MAX_ROOT_ENTS))
  348. {
  349.         pConf->maxRootEnts = DEFAULT_MAX_ROOT_ENTS;
  350. }
  351.     /* one last time, recalculate cluster nClust, knowing reserved */
  352.     nClust = (nBlks - pConf->nResrvd - rootSecs - pConf->nHidden -
  353. (pConf->secPerFat * pConf->nFats ) ) /
  354. pConf->secPerClust;
  355.     pConf->nClust = nClust;
  356.     /* see if it all sums up */
  357.     if((pConf->nHidden + pConf->nResrvd + rootSecs +
  358. (pConf->secPerFat * pConf->nFats ) +
  359. (pConf->nClust * pConf->secPerClust))  > nBlks )
  360. goto error;
  361.     if( (pConf->secPerClust <= 255 ) )
  362. return OK ;
  363. error:
  364.     errno = EINVAL ;
  365.     return ERROR;
  366.     }
  367. /*******************************************************************************
  368. *
  369. * dosFsFmtReadBootBlock - read existing boot block on the disk
  370. *
  371. * Read the existing boot block on the disk, to salvage some fields
  372. * that should be preserved, if the volume is already formatted.
  373. *
  374. * RETURNS: results confidence level: 100 is the highest confidence, 
  375. * a lower value means more probability for bogus values, or ERROR if 
  376. * could not read block.
  377. */
  378. LOCAL int dosFsFmtReadBootBlock
  379.     (
  380.     CBIO_DEV_ID cbioDev,
  381.     DOS_VOL_CONFIG * pConf
  382.     )
  383.     {
  384.     int confidence = 100 ;
  385.     STATUS stat ;
  386.     u_char bootBlockBuffer [ 512 ] ;   /* must be at least 512 bytes */
  387.     u_char * pBoot ;
  388.     u_char c1 ;
  389.     u_long i, work ;
  390.     int bytesPerBlk;
  391.     u_char tmpType [ DOS_BOOT_FSTYPE_LEN + 1] = { 0 };
  392.     CBIO_PARAMS cbioParams;
  393.      /* Below we request the (underlying CBIO) device parameters.  */
  394.     if (ERROR == cbioParamsGet (cbioDev, &cbioParams))
  395. {
  396. return (ERROR);
  397. }
  398.     bytesPerBlk = cbioParams.bytesPerBlk ;
  399.     if (0 == bytesPerBlk)
  400. {
  401. return (ERROR);
  402. }
  403.     if( bytesPerBlk > (int) sizeof(bootBlockBuffer) )
  404. {
  405. pBoot = KHEAP_ALLOC(bytesPerBlk);
  406. }
  407.     else
  408. {
  409. pBoot = bootBlockBuffer ;
  410. }
  411.     if (NULL == pBoot)
  412. {
  413. return (ERROR);
  414. }
  415.     bzero( (char *) pBoot, bytesPerBlk);
  416.     /* read the boot block */
  417.     stat = cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM, 1,
  418.        (addr_t)pBoot, CBIO_READ, NULL );
  419.     if( stat == ERROR )
  420. return (ERROR);
  421.     /* 
  422.      * inspect the boot block fields, and decrease confidence value
  423.      * each time a field seems bogus, by something relative to
  424.      * level of criticality of an appropriate field
  425.      */
  426.     /* check for either 80x80 JMP instruction opcodes */
  427.     if( pBoot[ DOS_BOOT_JMP ]  != 0xe9 && pBoot[ DOS_BOOT_JMP ] != 0xeb )
  428. confidence -= 5;
  429.     /* 
  430.      * Many FAT documents mistakenly state that the 0x55aa signature word
  431.      * "occupies the last two bytes of the boot sector".  That is only true 
  432.      * when the bytes-per-sector value is 512 bytes.  Microsoft
  433.      * defines the signature at offsets 510 and 511 (zero-based)
  434.      * regardless of the sector size.  It is okay, however to have
  435.      * the signature at the end of the sector.  We accept either.
  436.      */
  437.     /* First, check for a signature at the end of the sector. */
  438.     if((pBoot[ bytesPerBlk - 2 ] != 0x55 ) || (pBoot[ bytesPerBlk-1] != 0xaa))
  439. {
  440.         /* Didn't find signature, check the 510 and 511 offsets. */
  441.         if ((pBoot[510] != 0x55) || (pBoot[511] != 0xaa))
  442.     {
  443.     confidence -= 5; /* no 0x55aa signature :-( */
  444.     }
  445. }
  446.     if( DISK_TO_VX_16(pBoot+DOS_BOOT_BYTES_PER_SEC) != bytesPerBlk )
  447. confidence -= 5 ;
  448.     if((pConf->secPerClust = pBoot[ DOS_BOOT_SEC_PER_CLUST ]) == 0)
  449. confidence -= 5 ;
  450.     if((pConf->mediaByte = pBoot[ DOS_BOOT_MEDIA_BYTE ]) == 0)
  451. confidence -= 2;
  452.     if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NRESRVD_SECS )) == 0 )
  453. confidence -= 5;
  454.     else
  455. pConf->nResrvd = work ;
  456.     if((pConf->nFats = pBoot[ DOS_BOOT_NFATS ]) == 0)
  457. confidence -= 5 ;
  458.     if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_MAX_ROOT_ENTS )) == 0 )
  459. confidence -= 5 ;
  460.     else
  461. pConf->maxRootEnts = work ;
  462.     if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NSECTORS )) == 0 )
  463.         {
  464.         if((work = DISK_TO_VX_32( pBoot + DOS_BOOT_LONG_NSECTORS )) == 0)
  465.     confidence -= 5;
  466.         }
  467.     /* a problem here may indicate a problem in cbio layer partitioning */
  468.     if( work > cbioParams.nBlocks )
  469. confidence -= 5;
  470.     /* setup the fat type and sectors per fat */
  471.     if((work = DISK_TO_VX_16(pBoot + DOS_BOOT_SEC_PER_FAT)) == 0 )
  472. {
  473. /* when 16 bit sectors per FAT field is zero, we presume FAT32 */
  474. if((work = DISK_TO_VX_32( pBoot + DOS32_BOOT_SEC_PER_FAT )) == 0 )
  475.     confidence -= 5 ;
  476. bcopy((char *) pBoot + DOS32_BOOT_FS_TYPE, 
  477.       (char *) tmpType, DOS_SYS_ID_LEN );
  478. if(strcmp ((char *)tmpType, DOS_BOOT_SYSID_FAT32) != 0 )
  479.     confidence -= 5 ;
  480. pConf->fatType = _FAT32;
  481. pConf->secPerFat = work; 
  482. }
  483.     else /* must be using either FAT12 or FAT16 */
  484. {
  485. /* 
  486.  * Not using FAT32, determine between FAT12 and FAT16,
  487.  * and test the cluster count against the string, if present. 
  488.  */
  489. pConf->secPerFat = work;
  490.         bcopy ( (char *) pBoot + DOS_BOOT_FSTYPE_ID,
  491.                 (char *) tmpType, DOS_BOOT_FSTYPE_LEN);
  492.         stat = dosFsVolIsFat12 (pBoot);
  493.  
  494.         if (ERROR == stat)
  495.             {
  496.     confidence -= 5;
  497.             }
  498. if (TRUE == stat) /* calc'd FAT12 */
  499.     {
  500.     /* 
  501.      * Check the FSTYPE field in the BPB to ensure the string
  502.      * value matches our calculation.  If not, the we assume
  503.      * the formatter knew what they wanted, and we honor
  504.      * the string value. We look for "FAT12   " or "FAT16   ".
  505.      */
  506.     if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT16)) == 0)
  507.         {
  508.              pConf->fatType = _FAT16;
  509.         printf("dosFsFmtLib: %s indicated by BPB FSTYPE string, "
  510.        "cluster calculation was FAT12. Returning string.n",
  511. tmpType);
  512.         }
  513.     else 
  514. {
  515.              pConf->fatType = _FAT12;
  516.      }
  517.     }
  518. else /* calc'd FAT16 */
  519.     {
  520.     /* 
  521.      * Check the FSTYPE field in the BPB to ensure the string
  522.      * value matches our calculation.  If not, the we assume
  523.      * the formatter knew what they wanted, and we honor
  524.      * the string value. We look for "FAT12   " or "FAT16   ".
  525.      */
  526.     if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT12)) == 0)
  527.         {
  528.              pConf->fatType = _FAT12;
  529.         printf("dosFsFmtLib: %s indicated by BPB FSTYPE string, "
  530.        "cluster calculation was FAT16. Returning string.n",
  531. tmpType);
  532.         }
  533.     else
  534. {
  535.              pConf->fatType = _FAT16;
  536.      }
  537.     }
  538. }
  539.     /* this is not the CHKDSK, no need to be absolutely perfect. */
  540.     if( (pConf->nHeads = DISK_TO_VX_32( pBoot + DOS_BOOT_NHEADS))== 0)
  541. confidence -=5 ;
  542.     if((pConf->secPerTrack = DISK_TO_VX_32(pBoot + DOS_BOOT_SEC_PER_TRACK))==0)
  543. confidence -=5 ;
  544.     /* get volume serial number, this is what its all about, actually */
  545.     if( pConf->fatType == _FAT32 )
  546. work = DISK_TO_VX_32( pBoot + DOS32_BOOT_VOL_ID ) ;
  547.     else
  548. work = DISK_TO_VX_32( pBoot + DOS_BOOT_VOL_ID ) ;
  549.     /* scrutinize the serial number */
  550.     if( (work & 0xffff) == ((work >> 16) & 0xffff) || (work & 0xffff0000) == 0)
  551. {
  552. /* found suspicious serial number, so we mangle it XXX WHY? */
  553. confidence -= 5 ;
  554. work |= tickGet() << 16 ;
  555. }
  556.     pConf->volSerial = work;
  557.     /* get label, should be useful too */
  558.     if( pConf->fatType == _FAT32 )
  559. i = DOS32_BOOT_VOL_LABEL;
  560.     else
  561. i = DOS_BOOT_VOL_LABEL;
  562.     bcopy( (char *)pBoot + i, pConf->volLabel, DOS_VOL_LABEL_LEN );
  563.     /* replace any illegal character with a space */
  564.     for(i = 0; i< DOS_VOL_LABEL_LEN; i++)
  565. {
  566. c1 = pConf->volLabel[i] ;
  567. if( ! isupper(c1) && ! isdigit(c1) && (c1 != '_') && (c1 != '$'))
  568.     pConf->volLabel[i] = ' ';
  569. }
  570.     /* preserve hidden sectors */
  571.     pConf->nHidden = DISK_TO_VX_32 (pBoot + DOS_BOOT_NHIDDEN_SECS);
  572.     /* Done */
  573.     if( pBoot != bootBlockBuffer )
  574. KHEAP_FREE(pBoot);
  575.     if( confidence < 0 )
  576. confidence = 0 ;
  577.     return( confidence  );
  578.     }
  579. /*******************************************************************************
  580. *
  581. * dosFsFmtNonFsBootInit - initialize non-fs fields in boot block
  582. *
  583. * Set areas such as JUMP command, boot code,  signature
  584. */
  585. LOCAL void dosFsFmtNonFsBootInit
  586.     ( 
  587.     u_char * pBoot,   /* comment for this arg */
  588.     int bytesPerBlk   /* comment for this arg */
  589.     )
  590.     {
  591.     /* 
  592.      * 0xEB is a x86, JMP rel8, Jump short, relative, 
  593.      * displacement relative to next instruction, 0x3e
  594.      * The 0x90 is a NOP instruction and it is an alias 
  595.      * mnemonic for the XCHG (E)AX, (E)AX instruction.   
  596.      */
  597.     pBoot[ 0 ] = 0xeb ; /* JUMP */
  598.     pBoot[ 1 ] = 0x3e ;  /* program offset */
  599.     pBoot[ 2 ] = 0x90 ;  /* NOP */
  600.     /* 
  601.      * Many FAT documents mistakenly say that the 0x55AA signature word
  602.      * "occupies the last two bytes of the boot sector".  That is only true 
  603.      * when the bytes-per-sector value is 512 bytes.  Microsoft
  604.      * defines the signature at offsets 510 and 511 (zero-based)
  605.      * regardless of the sector size.  It is okay, however to have
  606.      * the signature also at the end of the sector.  We write it to
  607.      * both places to be safe.
  608.      */
  609.     pBoot[ bytesPerBlk-2 ] = 0x55 ; 
  610.     pBoot[ bytesPerBlk-1 ] = 0xaa ;
  611.     if (bytesPerBlk > 512)
  612. {
  613.         pBoot[ 510 ] = 0x55 ; 
  614.         pBoot[ 511 ] = 0xaa ;
  615. }
  616.     }
  617. /*******************************************************************************
  618. * dosFsFmtVolInit - perform the actual disk formatting
  619. *
  620. * Initialize all file system control structure on the disk, optionally
  621. * preserving the boot block non-file system fields such as boot code
  622. * and partition table.
  623. *
  624. */
  625. LOCAL int dosFsFmtVolInit
  626.     (
  627.     CBIO_DEV_ID cbioDev, /* cbio handle */
  628.     DOS_VOL_CONFIG * pConf, /* volume parameters */
  629.     BOOL preserve, /* =1 - preserve boot blocks fields */
  630.     int opt /* VxLong names */
  631.     )
  632.     {
  633.     STATUS stat = ERROR ;
  634.     u_char bootBlockBuffer [512] ;    
  635.     u_char * pBoot ;
  636.     u_char dirEntrySize = DOS_DIRENT_STD_LEN;
  637.     int backupBootSec = NONE ;
  638.     u_long i, work, rootStartSec ;
  639.     int bytesPerBlk;
  640.     CBIO_PARAMS cbioParams;
  641.     /* 
  642.      * Below we request the (underlying CBIO) device parameters.  
  643.      * These parameters will be used to help calculate this dosFs volumes 
  644.      * configuration.  The information will be used to help
  645.      * determine the FAT type, the sectors per cluster, etc.
  646.      * For example, the number of sectors (aka blocks) on the device returned 
  647.      * by the cbioParamsGet call must reflect the partitions total block 
  648.      * values, which is NOT necessarily the entire disk; else the calculations 
  649.      * may be incorrect.
  650.      */
  651.     if (ERROR == cbioParamsGet (cbioDev, &cbioParams))
  652. {
  653. return (ERROR);
  654. }
  655.     bytesPerBlk = cbioParams.bytesPerBlk ;
  656.     if (0 == bytesPerBlk)
  657. {
  658. return (ERROR);
  659. }
  660.     if( opt & DOS_OPT_VXLONGNAMES )
  661. dirEntrySize = DOS_VX_DIRENT_LEN; /* Thanks Kent! */
  662.     /* 
  663.      * Need enough space for at least a sector, 
  664.      * depending on sector size we may KHEAP_ALLOC it.
  665.      */
  666.     if( bytesPerBlk > (int)sizeof(bootBlockBuffer) )
  667. pBoot = KHEAP_ALLOC(bytesPerBlk);
  668.     else
  669. pBoot = bootBlockBuffer ;
  670.     if (NULL == pBoot)
  671. {
  672. return (ERROR);
  673. }
  674.     bzero( (char *)pBoot, bytesPerBlk );
  675.     /* clear out the entire FAT, all copies of it ! */
  676.     for(i = 0; i < (pConf->secPerFat * pConf->nFats); i++ )
  677. {
  678. if(cbioBlkRW( cbioDev, i + DOS_BOOT_SEC_NUM + pConf->nResrvd, 1,
  679.              (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR )
  680.     {
  681.     goto _done_;
  682.     }
  683. }
  684.     /* clear out the entire Root directory */
  685.     /* size of Root Dir in sectors */
  686.     if( pConf->fatType == _FAT32 )
  687. {
  688. work = pConf->secPerClust ;  
  689. }
  690.     else /* FAT16/FAT12 */
  691. {
  692. /* SPR#34704 This must round up */
  693. work = (((pConf->maxRootEnts * dirEntrySize) + (bytesPerBlk - 1)) /
  694. bytesPerBlk);
  695. }
  696.     /* this is where the Root dir starts */
  697.     rootStartSec = DOS_BOOT_SEC_NUM + pConf->nResrvd +
  698. (pConf->secPerFat * pConf->nFats);
  699.     /* clear it really now */
  700.     for( i = 0; i < work; i++ )
  701. if( cbioBlkRW( cbioDev, i+rootStartSec,
  702. 1, (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR )
  703.     goto _done_;
  704.     /* 
  705.      * now that we are done with zero's, we initialize the FAT's head
  706.      * with the required beginning for the FAT type, this appears: 
  707.      *
  708.      * FAT12: f8 ff ff xx xx xx xx xx xx xx xx xx xx xx
  709.      * FAT16: f8 ff ff ff xx xx xx xx xx xx xx xx xx xx
  710.      * FAT32: f8 ff ff ff ff ff ff ff ff ff ff 0f xx xx 
  711.      * f8 is the media byte.
  712.      *  
  713.      * Noticed that Win95 OSR2 FAT32 uses:
  714.      *        f8 ff ff 0f ff ff ff 0f ff ff ff 0f xx xx 
  715.      * Probally due to simplified formatting code, does not 
  716.      * affect anything in MS ScanDisk or Norton Disk Doctor,
  717.      * so we just leave it as is here, just noted.
  718.      */
  719.     if( pConf->fatType == _FAT32 ) /* how many bytes to init */
  720. {
  721. work = 11 ; /* 0, 1, and 2 entry for root dir */
  722. pBoot[ 11 ] = 0x0f; /* root dir EOF msb */
  723. }
  724.     else if( pConf->fatType == _FAT16 )
  725. work = 4 ;
  726.     else  /* FAT12 */
  727. work = 3 ;
  728.     pBoot[ 0 ] = pConf->mediaByte ; /* 0th byte always media */
  729.     for(i=1; i < work ; i++ )
  730. pBoot[i] = 0xff ; /* 1th to i-th bytes 0xff */
  731.     for(i = DOS_BOOT_SEC_NUM + pConf->nResrvd ;
  732. i < DOS_BOOT_SEC_NUM + pConf->nResrvd 
  733.                      + pConf->secPerFat * pConf->nFats;
  734. i += pConf->secPerFat )
  735. if( cbioBlkRW( cbioDev, i , 1, (addr_t)pBoot, CBIO_WRITE, 
  736. NULL ) == ERROR )
  737.     goto _done_;
  738.     /* create file system info sector for FAT32 */
  739.     if( pConf->fatType == _FAT32 )
  740. {
  741. /* FS info sector  */
  742. bzero( (char *)pBoot, bytesPerBlk );
  743. /* FSI_LeadSig (magic signature) */
  744. pBoot[ 0 ] = 'R'; /* 0x52 */
  745. pBoot[ 1 ] = 'R'; /* 0x52 */
  746. pBoot[ 2 ] = 'a'; /* 0x61 */
  747. pBoot[ 3 ] = 'A'; /* 0x41 */
  748. /* FSI_StructSig */
  749. pBoot[ 484 ] = 'r'; /* 0x72 */
  750. pBoot[ 485 ] = 'r'; /* 0x72 */
  751. pBoot[ 486 ] = 'A'; /* 0x41 */
  752. pBoot[ 487 ] = 'a'; /* 0x61 */
  753.         /* 
  754.          * Many FAT documents mistakenly say that the 0x55AA signature word
  755.          * "occupies the last two bytes of the boot sector".  That is only 
  756.  * true when the bytes-per-sector value is 512 bytes.  Microsoft
  757.          * defines the signature at offsets 510 and 511 (zero-based)
  758.          * regardless of the sector size.  It is okay, however to have the 
  759.  * signature also at the end of the sector.  We do both to be safe.
  760.          */
  761. pBoot[ bytesPerBlk - 1 ] = 0xaa; /* tail signature */
  762. pBoot[ bytesPerBlk - 2 ] = 0x55;
  763.         if (bytesPerBlk > 512)
  764.     {
  765.     pBoot[510] = 0x55;
  766.     pBoot[511] = 0xaa; /* tail signature */
  767.     }
  768. /* 
  769.  * The FAT32 `free count of clusters' field will be set 0xffffffff 
  770.  * This indicates to MSDOS to not consider the field valid.
  771.          * Note dosFsLib does not update this field currently.
  772.          * A possible setting is shown below in comments.
  773.  */
  774.         pBoot[ 488 ] = 0xff;       /* &   (pConf->nClust - 1); */
  775.         pBoot[ 489 ] = 0xff;       /* & ( (pConf->nClust - 1) >> 8); */
  776.         pBoot[ 490 ] = 0xff;       /* & ( (pConf->nClust - 1) >> 16); */
  777.         pBoot[ 491 ] = 0xff;       /* & ( (pConf->nClust - 1) >> 24); */
  778. /* 
  779.  * The FAT32 `next free cluster' field will be 0xffffffff 
  780.  * This indicates to MSDOS to not consider the field valid.
  781.          * Note dosFsLib does not update this field currently.
  782.  */
  783.         pBoot[ 492 ] = 0xff; 
  784.         pBoot[ 493 ] = 0xff;
  785.         pBoot[ 494 ] = 0xff;
  786.         pBoot[ 495 ] = 0xff;
  787. /* now write this info sector to disk */
  788. if( cbioBlkRW( cbioDev, DOS32_INFO_SEC , 1, 
  789. (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR )
  790.     goto _done_;
  791. }
  792.     /* create a boot sector image, and write it last */
  793.     /* first, prepare the non-fs boot block data */
  794.     if(TRUE == preserve)
  795. {
  796. if( cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM , 1, 
  797. (addr_t)pBoot, CBIO_READ, NULL ) == ERROR )
  798.     goto _done_;
  799. }
  800.     else
  801. {
  802. bzero( (char *)pBoot, bytesPerBlk );
  803. dosFsFmtNonFsBootInit( pBoot, bytesPerBlk );
  804. }
  805.     /* now write the fields which are relevant to our params */
  806. /* byte fields copied directly */
  807.     pBoot [DOS_BOOT_SEC_PER_CLUST] = pConf->secPerClust ;
  808.     pBoot [DOS_BOOT_NFATS]              = pConf->nFats ;
  809.     pBoot [DOS_BOOT_MEDIA_BYTE] = pConf->mediaByte ;
  810.     bcopy( pConf->sysId,  (char *)pBoot+DOS_BOOT_SYS_ID, DOS_SYS_ID_LEN );
  811.     /* 16-bit values */
  812.     if( FALSE == preserve )
  813. {
  814. /* 
  815.          * Small Hack with Big Comment. Mimic MSDOS n based translation.
  816.          * This is just to appease MSDOS BIOS calls.
  817.          * DOSFSII could care less really, but it helps MSDOS programs.
  818.          * (such as our VxLd) Typical LCHS to CHS BIOS translation appears:
  819.          *
  820.          * +----------------+----------+------------+-------------+--------+
  821.          * |Actual Cylinders|Actual Hds|Altered Cyl |Altered Heads|Max Size|
  822.          * +----------------+----------+------------+-------------+--------+
  823.          * |  1<C<=1024     | 1<H<=16  |     C=C    |    H=H      |528 MB  |
  824.          * +----------------+----------+------------+-------------+--------+
  825.          * | 1024<C<=2048   | 1<H<=16  |     C=C/2  |    H=H*2    |  1GB   |
  826.          * +----------------+----------+------------+-------------+--------+
  827.          * | 2048<C<=4096   | 1<H<=16  |     C=C/4  |    H=H*4    | 2.1GB  |
  828.          * +----------------+----------+------------+-------------+--------+
  829.          * | 4096<C<=8192   | 1<H<=16  |     C=C/8  |    H=H*8    | 4.2GB  |
  830.          * +----------------+----------+------------+-------------+--------+
  831.          * | 8192<C<=16384  | 1<H<=16  |     C=C/16 |    H=H*16   | 8.4GB  |
  832.          * +----------------+----------+------------+-------------+--------+
  833.          * | 16384<C<=32768 | 1<H<=8   |     C=C/32 |    H=H*32   | 8.4GB  |
  834.          * +----------------+----------+------------+-------------+--------+
  835.          * | 32768<C<=65536 | 1<H<=4   |     C=C/64 |    H=H*64   | 8.4GB  |
  836.          * +----------------+----------+------------+-------------+--------+
  837.          * 
  838.          * The  MSDOS "logical CHS" (LCHS) format combined with the 
  839.          * Physical IDE/ATA CHS interface (PCHS) gives MSDOS the 
  840.          * following addressing limitation:
  841.          * 
  842.          *                   +------------+----------+----------------+   
  843.          *                   | BIOS INT13 | IDE/ATA  | Combined Limit |
  844.          * +-----------------+------------+----------+----------------+   
  845.          * |Max Sectors/Track|  63        |    255   |     63         |
  846.          * +-----------------+------------+----------+----------------+
  847.          * |Max Heads        |  256       |     16   |     16         |
  848.          * +-----------------+------------+----------+----------------+
  849.          * |Max Cylinders    |  1024      |  65536   |    1024        |
  850.          * +-----------------+------------+----------+----------------+
  851.          * |Capacity         |  8.4GB     |  136.9GB |   528 MB       |
  852.          * +-----------------+------------+----------+----------------+
  853.          * 
  854.          * 1024 x 16 x 63 X 512 bytes/sector = 528.48 MB limit.
  855.          * 
  856.          * Cylinder bits : 10 = 1024
  857.          * Head bits     :  4 = 16
  858.          * Sector bits   :  6 (-1) = 63 
  859.          * (by convention, CHS sector numbering begins at
  860.          *  #1, not #0; LBA begins at zero, which is CHS#1) 
  861.          * To overcome the limitation. PC BIOS/OS vendors perform 
  862.          * what is often referred to as geometric or "drive" CHS 
  863.          * translation to address more than 528MB, and to "address" 
  864.          * cylinders above 1024. So we just attempt to mimic here. 
  865.          */
  866. if (((block_t)(cbioParams.nHeads) *
  867.      (block_t)(cbioParams.blocksPerTrack)) != (block_t) 0) 
  868.     {
  869.             work = (block_t)(((block_t)(cbioParams.blockOffset) + 
  870.                               (block_t)(cbioParams.nBlocks)) / 
  871.                              ((block_t)(cbioParams.nHeads) * 
  872.                               (block_t)(cbioParams.blocksPerTrack)));
  873.             while ( (work > (block_t) 1023) && 
  874.                     (((block_t)(cbioParams.nHeads) << (block_t) 2) < 
  875.                      (block_t) 256) )
  876.                 {
  877.         cbioParams.nHeads <<= (block_t) 2;
  878.                 work >>= (block_t) 2;
  879.         }
  880.     }   
  881. /* values coming from driver, better not trust them if preserving */
  882. if( pConf->secPerTrack == 0 )
  883.     pConf->secPerTrack = cbioParams.blocksPerTrack ;
  884. if( pConf->nHeads == 0 )
  885.     pConf->nHeads = cbioParams.nHeads ;
  886. VX_TO_DISK_16( pConf->secPerTrack, pBoot + DOS_BOOT_SEC_PER_TRACK);
  887. VX_TO_DISK_16( pConf->nHeads, pBoot + DOS_BOOT_NHEADS);
  888. }
  889.     VX_TO_DISK_16( pConf->nResrvd, pBoot + DOS_BOOT_NRESRVD_SECS );
  890.     VX_TO_DISK_16( pConf->maxRootEnts, pBoot + DOS_BOOT_MAX_ROOT_ENTS );
  891.     VX_TO_DISK_16( bytesPerBlk, pBoot + DOS_BOOT_BYTES_PER_SEC);
  892.     /* total sector count */
  893.     if( (cbioParams.nBlocks & ~0xffff ) == 0 )
  894. {
  895. VX_TO_DISK_16( cbioParams.nBlocks, 
  896. pBoot + DOS_BOOT_NSECTORS);
  897. }
  898.     else
  899. {
  900. if( bytesPerBlk < 64 ) /* can not do with 32 byte sectors */
  901.     goto _done_;
  902. VX_TO_DISK_16( 0, pBoot + DOS_BOOT_NSECTORS);
  903. VX_TO_DISK_32( cbioParams.nBlocks, 
  904. pBoot + DOS_BOOT_LONG_NSECTORS);
  905. }
  906.     if( pConf->nResrvd >= 32 )
  907. backupBootSec = 6 ;
  908.     else if( pConf->nResrvd  >= 2 )
  909. backupBootSec = pConf->nResrvd -1 ;
  910.     if( pConf->fatType == _FAT32 )
  911. {
  912. pBoot [DOS32_BOOT_SIGNATURE]  = DOS_EXT_BOOT_SIG;
  913. VX_TO_DISK_16( 0,    pBoot + DOS_BOOT_SEC_PER_FAT );
  914. VX_TO_DISK_32( pConf->secPerFat,  pBoot + DOS32_BOOT_SEC_PER_FAT );
  915. VX_TO_DISK_16( 0,    pBoot + DOS32_BOOT_EXT_FLAGS );
  916. VX_TO_DISK_16( 0 /* XXX-? */,   pBoot + DOS32_BOOT_FS_VERSION );
  917. VX_TO_DISK_32( 2 /* MUST */,    pBoot + DOS32_BOOT_ROOT_START_CLUST);
  918. VX_TO_DISK_16( 1 /* MUST */,   pBoot + DOS32_BOOT_FS_INFO_SEC );
  919. VX_TO_DISK_16( backupBootSec,   pBoot + DOS32_BOOT_BOOT_BKUP );
  920. VX_TO_DISK_32( pConf->volSerial,  pBoot + DOS32_BOOT_VOL_ID);
  921. bcopy( pConf->volLabel,  (char *) pBoot + DOS32_BOOT_VOL_LABEL,
  922. DOS_VOL_LABEL_LEN );
  923. bcopy( DOS_BOOT_SYSID_FAT32, (char *)pBoot + DOS32_BOOT_FS_TYPE,
  924. DOS_SYS_ID_LEN ); /* "FAT32   " */
  925. if(FALSE == preserve)
  926.     {
  927.     pBoot [ DOS32_BOOT_BIOS_DRV_NUM ] = 0x80; /* assume hard */
  928.     }
  929. }
  930.     else /* FAT 16 or FAT 12 */
  931. {
  932. /* from offset 0x24 in FAT12/16 have other meaning in FAT32 */
  933.     /* indicate extended boot sector fields in use */
  934. pBoot [DOS_BOOT_SIG_REC]  = DOS_EXT_BOOT_SIG;
  935. VX_TO_DISK_32( pConf->nHidden, pBoot + DOS_BOOT_NHIDDEN_SECS);
  936. VX_TO_DISK_32( pConf->volSerial, pBoot + DOS_BOOT_VOL_ID);
  937. VX_TO_DISK_16( pConf->secPerFat, pBoot + DOS_BOOT_SEC_PER_FAT );
  938. bcopy( pConf->volLabel, (char *) pBoot + DOS_BOOT_VOL_LABEL,
  939. DOS_VOL_LABEL_LEN );
  940. /* Add file system type to offset 0x36, later DOS versions do this */
  941. /* FAT12 */
  942. if (pConf->fatType == _FAT12)
  943.     {
  944.     bcopy (DOS_BOOT_FSTYPE_FAT12, (char *) pBoot + DOS_BOOT_FSTYPE_ID,
  945.    DOS_BOOT_FSTYPE_LEN);
  946.     }
  947. /* FAT16 */
  948. if (pConf->fatType == _FAT16)
  949.     {
  950.     bcopy (DOS_BOOT_FSTYPE_FAT16, (char *) pBoot + DOS_BOOT_FSTYPE_ID, 
  951.    DOS_BOOT_FSTYPE_LEN);
  952.     }
  953. if(FALSE == preserve)
  954.     {
  955.     /* 
  956.      * jkf - Below is a hack. When writing this value out, 
  957.      * we really should  be writing 0xN for floppies where 
  958.      * N=0 for drive 0, 1 for drive 1, and 2 for drive 2, etc.  
  959.      * For hard disks we should be writing out 0x8N.
  960.      */
  961.     pBoot [ DOS_BOOT_DRIVE_NUM ] = 
  962. (pConf->fatType == _FAT12) ? 0x00: 0x80 ; /* floppy or hard */
  963.     }
  964. }
  965.     /* write the backup boot block */
  966.     if( backupBootSec != NONE )
  967. if( cbioBlkRW( cbioDev, backupBootSec , 1, (addr_t)pBoot, 
  968. CBIO_WRITE, NULL ) == ERROR )
  969.     goto _done_;
  970.     /* now write the real boot block */
  971.     if( cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM , 1, 
  972. (addr_t)pBoot, CBIO_WRITE, NULL ) == ERROR )
  973. goto _done_;
  974.     /* Done */
  975.     stat = OK ;
  976. _done_:
  977.     if( pBoot != bootBlockBuffer )
  978. KHEAP_FREE(pBoot);
  979.     return( stat  );
  980.     }
  981. /*******************************************************************************
  982. * dosFsVolFormat - format an MS-DOS compatible volume
  983. *
  984. * This utility routine performs the initialization of file system data
  985. * structures on a disk. It supports FAT12 for small disks, FAT16 for
  986. * medium size and FAT32 for large volumes.
  987. * The <device> argument may be either a device name known to the I/O
  988. * system, or a dosFsLib Volume descriptor or a CBIO device handle.
  989. *
  990. * The <opt> argument is a bit-wise or'ed combination of options controlling the
  991. * operation of this routine as follows:
  992. *
  993. * .IP DOS_OPT_DEFAULT
  994. * If the current volume boot block is reasonably intact, use existing
  995. * parameters, else calculate parameters based only on disk size, possibly
  996. * reusing only the volume label and serial number.
  997. * .IP DOS_OPT_PRESERVE
  998. * Attempt to preserve the current volume parameters even if they seem to
  999. * be somewhat unreliable.
  1000. * .IP DOS_OPT_BLANK
  1001. * Disregard the current volume parameters, and calculate new parameters
  1002. * based only on disk size.
  1003. *
  1004. * .IP DOS_OPT_QUIET
  1005. * Do not produce any diagnostic output during formatting.
  1006. *
  1007. * .IP DOS_OPT_FAT16
  1008. * Format the volume with FAT16 format even if the disk is larger then 
  1009. * 2 Gbytes, which would normally be formatted with FAT32.
  1010. *
  1011. * .IP DOS_OPT_FAT32
  1012. * Format the volume with FAT32, even if the disk is smaller then 
  1013. * 2 Gbytes, but is larger then 512 Mbytes.
  1014. *
  1015. * .IP DOS_OPT_VXLONGNAMES
  1016. * Format the volume to use Wind River proprietary case-sensitive Long
  1017. * File Names. Note that this format is incompatible with any other
  1018. * implementation of the MS-DOS file system.
  1019. *
  1020. * .LP
  1021. * The third argument, <pPromptFunc> is an optional pointer to a function
  1022. * that may interactively prompt the user to change any of the
  1023. * modifiable volume parameters before formatting:
  1024. *
  1025. * .CS
  1026. * void formatPromptFunc( DOS_VOL_CONFIG *pConfig );
  1027. * .CE
  1028. *
  1029. * The <*pConfig> structure upon entry to formatPromptFunc() will contain
  1030. * the initial volume parameters, some of which can be changed before it
  1031. * returns. <pPromptFunc> should be NULL if no interactive prompting is
  1032. * required.
  1033. *
  1034. * COMPATIBILITY
  1035. *
  1036. * Although this routine tries to format the disk to be
  1037. * compatibile with Microsoft implementations of the FAT and FAT32
  1038. * file systems, there may be differences which are not under WRS
  1039. * control.  For this reason, it is highly recommended that any
  1040. * disks which are expected to be interchanged between vxWorks and
  1041. * Windows should be formatted under Windows to provide the best
  1042. * interchangeability.  The WRS implementation is more flexible,
  1043. * and should be able to handle the differences when formatting is
  1044. * done on Windows, but Windows implementations may not be able to
  1045. * handle minor differences between their implementation and ours.
  1046. *
  1047. * AVAILABILITY
  1048. * This function is an optional part of the MS-DOS file system,
  1049. * and may be included in a target system if it is required to
  1050. * be able to format new volumes.
  1051. *
  1052. * RETURNS: OK or ERROR if was unable to format the disk.
  1053. */
  1054. STATUS dosFsVolFormat
  1055.     (
  1056.     void *  device, /* device name or volume or CBIO pointer */
  1057.     int opt, /* bit-wise or'ed options */
  1058.     FUNCPTR pPromptFunc /* interactive parameter change callback */
  1059.     )
  1060.     {
  1061.     DOS_VOL_CONFIG cfg, cfgOld;
  1062.     CBIO_DEV_ID    cbioDev = NULL;
  1063.     STATUS         stat    = ERROR;
  1064.     char *         pTail;
  1065.     BOOL           preserve;
  1066.     CBIO_PARAMS    cbioParams;
  1067.     /* 
  1068.      * Determine what type of device handle we were passed,
  1069.      * and extract the CBIO pointer.
  1070.      */
  1071.     /* NULL is presumed to be an invalid device */
  1072.     if (NULL == device)
  1073.         {
  1074.         errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1075.         return (ERROR);
  1076.         }
  1077.     /*
  1078.      * check for 'device' being a valid DOS_VOLUME_DESC_ID or a CBIO_DEV_ID
  1079.      * SPR#71720 : Ensure the pointer is aligned before attempting to access
  1080.      * any structure member from it.  Avoid exception on SH arch w/DIAB.
  1081.      * cbioDevVerify() will do an alignment check internally. The check
  1082.      * "((DOS_VOLUME_DESC_ID)device)->magic" needs _WRS_ALIGN_CHECK().
  1083.      */
  1084.     if (OK == cbioDevVerify ((CBIO_DEV_ID) device))
  1085.         {
  1086.         /* 'device' is a valid CBIO_DEV_ID */
  1087.         cbioDev = device;
  1088.         }
  1089.     else if (TRUE == _WRS_ALIGN_CHECK(device, DOS_VOLUME_DESC))
  1090.         {
  1091.         if (DOS_FS_MAGIC == ((DOS_VOLUME_DESC_ID)device)->magic)
  1092.             {
  1093.             /*
  1094.              * 'device' a valid DOS_VOLUME_DESC_ID, use its cbio ptr
  1095.              * Note that it will be cbioDevVerify()'d again below.
  1096.              */
  1097.             cbioDev = ((DOS_VOLUME_DESC_ID)device)->pCbio;
  1098.             }
  1099.         }
  1100.     if (NULL == cbioDev)
  1101.         {
  1102.         /*
  1103.          * didn't find anything valid above. Last try an iosDevFind()
  1104.          * to see if 'device' is a character string, an io device name.
  1105.          */
  1106. #ifdef _WRS_DOSFS2_VXWORKS_AE
  1107.         cbioDev = (CBIO_DEV_ID) iosDevFind((char *) device, 
  1108.                                            (const char **)&pTail );
  1109. #else
  1110.         cbioDev = (CBIO_DEV_ID) iosDevFind((char *) device, 
  1111.                                            (char **)&pTail );
  1112. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  1113.         if( (NULL == cbioDev) || (pTail == device) )
  1114.             {
  1115.             /* 'device' appears invalid, so we bail out */
  1116.             errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1117.             return (ERROR);
  1118.             }
  1119.         if (TRUE == _WRS_ALIGN_CHECK(cbioDev, DOS_VOLUME_DESC))
  1120.             {
  1121.             if( ((DOS_VOLUME_DESC_ID)cbioDev)->magic != DOS_FS_MAGIC )
  1122.                 {
  1123.                 /* 'device' appears invalid, so we bail out */
  1124.                 errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1125.                 return (ERROR);
  1126.                 }
  1127.             else
  1128.                 {
  1129.                 /* 
  1130.                  * 'cbioDev' is now a valid DOS_VOLUME_DESC_ID, use its CBIO
  1131.                  * PTR. Note that it will be cbioDevVerify()'d again below.
  1132.                  */
  1133.         cbioDev = ((DOS_VOLUME_DESC_ID)cbioDev)->pCbio;
  1134.                 }
  1135.             }
  1136.         }
  1137.     /* Again, verify that we have a valid CBIO handle */
  1138.     if( ERROR == cbioDevVerify(cbioDev))
  1139. {
  1140. return (ERROR);
  1141. }
  1142.     else
  1143. {
  1144.         /* 
  1145.          * SPR#71633: cbioDevVerify() may have set errno 
  1146.          * above, but if we made it here, then it doesn't 
  1147.          * matter to the user, so we clear any errno.
  1148.          */
  1149.         errno = 0;
  1150. }
  1151.     /* clear the DOS_VOL_CONFIG structures */
  1152.     bzero( (caddr_t) &cfg, sizeof(cfg));
  1153.     bzero( (caddr_t) &cfgOld, sizeof(cfgOld));
  1154.     /* take ownership of the device */
  1155.     if( ERROR == cbioLock (cbioDev, WAIT_FOREVER))
  1156. return ERROR;
  1157.     /* RESET the CBIO device */
  1158.     if( cbioIoctl( cbioDev, CBIO_RESET, 0) != OK )
  1159. goto _done_;
  1160.     /* Ensure we can write to this CBIO device */
  1161.     if( O_RDONLY == cbioModeGet(cbioDev))
  1162. {
  1163. errno = S_dosFsLib_READ_ONLY ;
  1164. goto _done_;
  1165. }
  1166.     /* Get the underlying CBIO device parameters */
  1167.     if (ERROR == cbioParamsGet (cbioDev, &cbioParams))
  1168. {
  1169.         stat = ERROR;
  1170. goto _done_;
  1171. }
  1172.     /* set hidden to sectors per track for hard disk */
  1173.     /*  
  1174.      * jkf The below is a hack. The boot sectors nHidden field should be 
  1175.      * set to the same value as the Relative Sector field in the MS 
  1176.      * partition table that defines the location of this volume.  This 
  1177.      * is not being handled here or in usrFdiskPartCreate.  Somehow 
  1178.      * usrFdiskPartLib.c and dpartCbio.c, should account for this someday.  
  1179.      * The value is also typically equal to the sectors per track value.  
  1180.      * Don't like the below code at all, it assumes too much.
  1181.      */
  1182.     if (36 <  cbioParams.blocksPerTrack) /* 36=2.88 floppy*/
  1183. {
  1184. if ((block_t)cbioParams.blockOffset <= 
  1185.             (block_t)cbioParams.blocksPerTrack) 
  1186.     {
  1187.             cfgOld.nHidden = cbioParams.blockOffset;
  1188.             cfg.nHidden = cbioParams.blockOffset;
  1189.     }
  1190. else
  1191.     {
  1192.             cfgOld.nHidden = cbioParams.blocksPerTrack;
  1193.             cfg.nHidden = cbioParams.blocksPerTrack;
  1194.     }
  1195. }
  1196.     else
  1197. {
  1198.         cfgOld.nHidden = 0;
  1199.         cfg.nHidden = 0;
  1200. }
  1201.     /* read the existing boot block from the disk. */
  1202.     stat = dosFsFmtReadBootBlock( cbioDev, &cfgOld );
  1203.     if((opt & DOS_OPT_QUIET) == 0)
  1204. {
  1205. printf("Retrieved old volume params with %%%d confidence:n", stat );
  1206. dosFsFmtShow(&cfgOld);
  1207. }
  1208.    switch (opt & (DOS_OPT_BLANK | DOS_OPT_PRESERVE))
  1209. {
  1210. default:
  1211.     /* preserve if well structured boot block uncovered */
  1212.     if( stat < 90 )
  1213. {
  1214. cfg.volSerial = cfgOld.volSerial ;
  1215. bcopy(cfgOld.volLabel, cfg.volLabel, sizeof(cfg.volLabel)) ;
  1216. preserve = FALSE ;
  1217. }
  1218.     else
  1219. {
  1220. cfg = cfgOld ;
  1221. preserve = TRUE ;
  1222. }
  1223.     break ;
  1224. case DOS_OPT_PRESERVE: /* preserve if not totally corrupt */
  1225.     if( stat < 70 )
  1226. {
  1227. cfg.volSerial = cfgOld.volSerial ;
  1228. bcopy(cfgOld.volLabel, cfg.volLabel, sizeof(cfg.volLabel)) ;
  1229. preserve = FALSE ;
  1230. }
  1231.     else
  1232. {
  1233. cfg = cfgOld ;
  1234. preserve = TRUE ;
  1235. }
  1236.     break ;
  1237. case DOS_OPT_BLANK: /* never preserve */
  1238.     cfg.volSerial = cfgOld.volSerial ;
  1239.     bcopy(cfg.volLabel, cfgOld.volLabel, sizeof(cfgOld.volLabel)) ;
  1240.     preserve = FALSE ;
  1241.     break ;
  1242.     
  1243. }
  1244.     /* forcing FAT32 or FAT16 */
  1245.     if( opt & DOS_OPT_FAT32 )
  1246. cfg.fatType = _FAT32 ;
  1247.     else if( opt & DOS_OPT_FAT16 )
  1248. cfg.fatType = _FAT16 ;
  1249.     /* calculate the BPB */
  1250.     stat = dosFsFmtAutoParams( &cfg,
  1251. cbioParams.nBlocks, cbioParams.bytesPerBlk, opt );
  1252.     if( pPromptFunc != NULL )
  1253. {
  1254. /* interactive prompting */
  1255. (void) (*pPromptFunc)( &cfg );
  1256. stat = dosFsFmtAutoParams( &cfg,
  1257.     cbioParams.nBlocks, cbioParams.bytesPerBlk, opt );
  1258. }
  1259.     if((opt & DOS_OPT_QUIET) == 0)
  1260. {
  1261. printf("Disk with %ld sectors of %d bytes will be formatted with:n",
  1262.     cbioParams.nBlocks, (int) cbioParams.bytesPerBlk );
  1263. dosFsFmtShow(&cfg);
  1264. }
  1265.     if(stat != OK)
  1266. {
  1267. printErr("dosFsVolFormat: bad format parameters, errno = %#xn",
  1268. errno );
  1269. goto _done_;
  1270. }
  1271.     stat = dosFsFmtVolInit( cbioDev, &cfg, preserve, opt );
  1272.     /* flush and invalidate cache immediately */
  1273.     stat |= cbioIoctl( cbioDev, CBIO_CACHE_INVAL, 0) ;
  1274.     if(stat != OK)
  1275. {
  1276. printErr("dosFsVolFormat: format failed, errno=%#xn", errno );
  1277. }
  1278.     cbioRdyChgdSet (cbioDev, TRUE); /* force re-mount */
  1279. _done_:
  1280.     cbioUnlock (cbioDev) ;
  1281.     return stat ;
  1282.     }
  1283. /*******************************************************************************
  1284. *
  1285. * dosFsFmtLibInit - initialize the MS-DOS formatting library
  1286. *
  1287. * This function is called to optionally enable the formatting
  1288. * functionality from dosFsLib.
  1289. *
  1290. * SEE ALSO: dosFsLib
  1291. *
  1292. * NOMANUAL
  1293. */
  1294. void dosFsFmtLibInit( void )
  1295.     {
  1296.     dosFsVolFormatRtn = dosFsVolFormat;
  1297.     }
  1298. #ifdef __unused__ 
  1299. /*******************************************************************************
  1300. *
  1301. * dosFsFmtTest - UNITEST CODE
  1302. *
  1303. * NOMANUAL
  1304. */
  1305. void dosFsFmtTest( int size)
  1306.     {
  1307.     DOS_VOL_CONFIG cfg;
  1308.     ULONG i, k ;
  1309.     STATUS stat ;
  1310.     if( size != 0 )
  1311. {
  1312. i = size ;
  1313. bzero((caddr_t) &cfg, sizeof(cfg));
  1314. stat = dosFsFmtAutoParams( &cfg, i, 512, 0) ;
  1315. dosFsFmtShow( &cfg );
  1316. if( stat == ERROR )
  1317.     perror("dosFsFmtAutoParams");
  1318. return;
  1319. }
  1320.     i = 100 ;
  1321.     for(k=0; k< 1000; k++ )
  1322. {
  1323. bzero((caddr_t) &cfg, sizeof(cfg));
  1324. i += rand() ;
  1325. stat = dosFsFmtAutoParams( &cfg, i, 512, 0) ;
  1326. dosFsFmtShow( &cfg );
  1327. if( stat == ERROR )
  1328.     {
  1329.     perror("dosFsFmtAutoParams");
  1330.     return;
  1331.     }
  1332. }
  1333.     }
  1334. #endif /* __unused__ */