usrFdiskPartLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:48k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* usrFdiskPartLib.c - FDISK-style partition handler */
  2. /* Copyright 1997-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02p,10dec01,jkf  fixed typo in 02n checkin that broke 4 partition systems.
  8. 02o,09nov01,jkf  SPR#71633, dont set errno when DevCreate is called w/BLK_DEV
  9. 02n,04oct01,rip  SPR#66973, computation overflows with large capacity disks
  10.                  SPR#30850, CBIO_RESET may be needed on device's first reading
  11. 02m,20sep01,jkf  SPR#69031, common code for both AE & 5.x.
  12. 02l,03mar01,jkf  SPR#62415, use sector size from BLK_DEV.
  13. 02k,26dec99,jkf  T3 KHEAP_ALLOC, fixed usrFdiskPartCreate to work w/BLK_DEV
  14. 02j,31aug99,jkf  changes for new CBIO API.
  15. 02i,31jul99,jkf  changed usrFdiskPartCreate. SPR#28285
  16. 02h,31jul99,jkf  reentrancy overhaul. SPR#28278
  17. 02g,31jul99,jkf  fixed blind resetting cbio in show routine. SPR#28279
  18. 02f,31jul99,jkf  fixed bugs introduced in 02a adaptation: 
  19.                  useFdiskPartParse offset calculation fixed, SPR#28280
  20. 02e,31jul99,jkf  T2 merge, tidiness & spelling.
  21. 02d,07dec98,lrn  partition table creation routine (SPR#21977), terse Show
  22. 02c,15sep98,lrn  enabled SHOW by default, assume non-partitioned disk 
  23.  if all partitions are nil
  24. 02b,02jul98,lrn  DosFs 2.0 pre-release
  25. 02a,21jun98,lrn  adopted from rev 01c by jkf.
  26. 01a,01sep97,jkf  adapted from dosPartLibAta.c.
  27. */
  28. /*
  29. DESCRIPTION:
  30. This module is provided is source code to accommodate various
  31. customizations of partition table handling, resulting from
  32. variations in the partition table format in a particular 
  33. configuration.
  34. It is intended for use with dpartCbio partition manager.
  35. This code supports both mounting MSDOS file systems and
  36. displaying partition tables written by MSDOS FDISK.exe or
  37. by any other MSDOS FDISK.exe compatible partitioning software.  
  38. The first partition table is contained within a hard drives
  39. Master Boot Record (MBR) sector, which is defined as sector
  40. one, cylinder zero, head zero or logical block address zero.
  41. The mounting and displaying routines within this code will 
  42. first parse the MBR partition tables entries (defined below)
  43. and also recursively parse any "extended" partition tables,
  44. which may reside within another sector further into the hard 
  45. disk.   MSDOS file systems within extended partitions are known
  46. to those familiar with the MSDOS FDISK.exe utility as "Logical 
  47. drives within the extended partition".
  48. Here is a picture showing the layout of a single disk containing
  49. multiple MSDOS file systems:
  50. .CS
  51.   +---------------------------------------------------------+
  52.   |<---------------------The entire disk------------------->|
  53.   |M                                                        |
  54.   |B<---C:--->                                              |
  55.   |R           /---- First extended partition--------------|
  56.   |           E<---D:---><-Rest of the ext part------------>|
  57.   |P          x                                             |
  58.   |A          t          E<---E:--->E<Rest of the ext part->|
  59.   |R                     x          x                       |
  60.   |T                     t          t<---------F:---------->|
  61.   +---------------------------------------------------------+
  62.   (Ext == extended partition sector)
  63.   C: is a primary partiion
  64.   D:, E:, and F: are logical drives within the extended partition.
  65. .CE
  66. A MS-DOS partition table resides within one sector on a hard
  67. disk.  There is always one in the first sector of a hard disk
  68. partitioned with FDISK.exe.  There first partition table may
  69. contain references to "extended" partition tables residing on
  70. other sectors if there are multiple partitions.  The first 
  71. sector of the disk is the starting point.  Partition tables
  72. are of the format:
  73. .CS
  74. Offset from     
  75. the beginning 
  76. of the sector          Description
  77. -------------          -------------------------
  78.    0x1be               Partition 1 table entry  (16 bytes)
  79.    0x1ce               Partition 2 table entry  (16 bytes)
  80.    0x1de               Partition 3 table entry  (16 bytes)
  81.    0x1ee               Partition 4 table entry  (16 bytes)
  82.    0x1fe               Signature  (0x55aa, 2 bytes)
  83. .CE
  84. Individual MSDOS partition table entries are of the format:
  85. .CS
  86. Offset   Size      Description
  87. ------   ----      ------------------------------
  88.  0x0     8 bits    boot type
  89.  0x1     8 bits    beginning sector head value
  90.  0x2     8 bits    beginning sector (2 high bits of cylinder#)
  91.  0x3     8 bits    beginning cylinder# (low order bits of cylinder#)
  92.  0x4     8 bits    system indicator
  93.  0x5     8 bits    ending sector head value
  94.  0x6     8 bits    ending sector (2 high bits of cylinder#)
  95.  0x7     8 bits    ending cylinder# (low order bits of cylinder#)
  96.  0x8    32 bits    number of sectors preceding the partition
  97.  0xc    32 bits    number of sectors in the partition
  98. .CE
  99. The Cylinder, Head and Sector values herein are not used,
  100. instead the 32-bit partition offset and size (also known as LBA
  101. addresses) are used exclusively to determine partition geometry.
  102. If a non-partitioned disk is detected, in which case the 0'th block
  103. is a DosFs boot block rather then an MBR, the entire disk will be
  104. configured as partition 0, so that disks formatted with VxWorks and
  105. disks formatted on MS-DOS or Windows can be accepted interchangeably.
  106. The usrFdiskPartCreate() will create a partition table with up to four
  107. partitions, which can be later used with usrFdiskPartRead() and
  108. dpartCbio to manage a partitioned disk on VxWorks.
  109. However, it can not be guaranteed that this partition table can be used
  110. on another system due to several BIOS specific paramaters in the boot
  111. area.  If interchangeability via removable disks is a requirement, 
  112. partition tables should be created and volumes should be formatted 
  113. on the other system with which the data is to be interchanged/
  114. CAUTION
  115. The partition decode function is recursive, up to the maximum
  116. number of partitions expected, which is no more then 24.
  117. Sufficient stack space needs to be provided via taskSpawn() to 
  118. accommodate the recursion level.
  119. SEE ALSO: dpartCbio
  120. */
  121. /* includes */
  122. #include "vxWorks.h"
  123. #include "private/dosFsVerP.h"
  124. #include "stdio.h"
  125. #include "stdlib.h"
  126. #include "string.h"
  127. #include "tickLib.h"
  128. #include "dosFsLib.h"
  129. #include "usrFdiskPartLib.h"
  130. #include "private/dosFsLibP.h" /* for byte swapping macros */
  131. #include "dpartCbio.h"
  132. #include "cbioLib.h"
  133. /* defines */
  134. /* may be undefine the following to conserve memory space */
  135. #define INCLUDE_PART_SHOW /* include the show function by default */
  136. /* declarations */
  137. /* locals */
  138. LOCAL STATUS useFdiskPartParse
  139.     (
  140.     CBIO_DEV_ID dev,         /* device from which to read blocks */
  141.     CBIO_PARAMS * pCbioParams,
  142.     PART_TABLE_ENTRY *pPartTab, /* table where to fill results */
  143.     int nPart,                /* # of entries in <pPartTable> */
  144.     ULONG startBlock, /* where to expect part table */
  145.     ULONG extStartBlock /* Offset to extended partition */
  146.     );
  147. #ifdef INCLUDE_PART_SHOW
  148. STATUS usrFdiskPartShow
  149.     (
  150.     CBIO_DEV_ID cbioDev,     /* device CBIO handle */
  151.     block_t extPartOffset,    /* user should pass zero */
  152.     block_t currentOffset,    /* user should pass zero */
  153.     int extPartLevel          /* user should pass zero */
  154.     );
  155. LOCAL const struct partType /* Some partition type values & names. */
  156.     {                       /* Only MSDOS are used in this code.   */
  157.     const UINT8 partTypeNum;      
  158.     const char *partTypeName;    
  159.     } partNames[] = 
  160.         {
  161.         {0x00, "Empty (NULL) Partition"},
  162.         {0x01, "MSDOS Partition 12-bit FAT"},   
  163.         {0x02, "XENIX / (slash) Partition"},        
  164.         {0x03, "XENIX /usr Partition"}, 
  165.         {0x04, "MSDOS 16-bit FAT <32M Partition"},  
  166.         {0x05, "MSDOS Extended Partition"}, 
  167.         {0x06, "MSDOS 16-bit FAT >=32M Partition"},
  168.         {0x07, "HPFS / NTFS Partition"},
  169.         {0x08, "AIX boot or SplitDrive Partition"},
  170.         {0x09, "AIX data or Coherent Partition"},
  171.         {0x0a, "OS/2 Boot Manager Partition"},
  172.         {0x0b, "Win95 FAT32 Partition"},
  173.         {0x0c, "Win95 FAT32 (LBA) Partition"},
  174.         {0x0e, "Win95 FAT16 (LBA) Partition"},
  175.         {0x0f, "Win95 Extended (LBA) Partition"},
  176.         {0x10, "OPUS Partition"},
  177.         {0x11, "Hidden DOS FAT12 Partition"},
  178.         {0x12, "Compaq diagnostics Partition"},
  179.         {0x14, "Hidden DOS FAT16 Partition"},
  180.         {0x16, "Hidden DOS FAT16 (big) Partition"},
  181.         {0x17, "Hidden HPFS/NTFS Partition"},
  182.         {0x18, "AST Windows swapfile Partition"},
  183.         {0x24, "NEC DOS Partition"},
  184.         {0x3c, "PartitionMagic recovery Partition"},
  185.         {0x40, "Venix 80286 Partition"},
  186.         {0x41, "Linux/MINIX (shared with DRDOS) Partition"},
  187.         {0x42, "SFS or Linux swap part (shared with DRDOS)"},
  188.         {0x43, "Linux native (shared with DRDOS) Partition"},
  189.         {0x50, "DM (disk manager) Partition"},
  190.         {0x51, "DM6 Aux1 (or Novell) Partition"},
  191.         {0x52, "CP/M or Microport SysV/AT Partition"},
  192.         {0x53, "DM6 Aux3 Partition"},
  193.         {0x54, "DM6 Partition"},
  194.         {0x55, "EZ-Drive (disk manager) Partition"},
  195.         {0x56, "Golden Bow (disk manager) Partition"},
  196.         {0x5c, "Priam Edisk (disk manager) Partition"},
  197.         {0x61, "SpeedStor Partition"},
  198.         {0x63, "GNU HURD or Mach or Sys V/386 (ISC UNIX)"},
  199.         {0x64, "Novell Netware 286 Partition"},
  200.         {0x65, "Novell Netware 386 Partition"},
  201.         {0x70, "DiskSecure Multi-Boot Partition"},
  202.         {0x75, "PC/IX Partition"},
  203.         {0x77, "QNX4.x Partition"},
  204.         {0x78, "QNX4.x 2nd part Partition"},
  205.         {0x79, "QNX4.x 3rd part Partition"},
  206.         {0x80, "MINIX until 1.4a Partition"},
  207.         {0x81, "MINIX / old Linux Partition"},
  208.         {0x82, "Linux swap Partition"},
  209.         {0x83, "Linux native Partition"},
  210.         {0x84, "OS/2 hidden C: drive Partition"},
  211.         {0x85, "Linux extended Partition"},
  212.         {0x86, "NTFS volume set Partition"},
  213.         {0x87, "NTFS volume set Partition"},
  214.         {0x93, "Amoeba Partition"},
  215.         {0x94, "Amoeba BBT Partition"}, 
  216.         {0xa0, "IBM Thinkpad hibernation Partition"},
  217.         {0xa5, "BSD/386 Partition"},
  218.         {0xa7, "NeXTSTEP 486 Partition"},
  219.         {0xb7, "BSDI fs Partition"},
  220.         {0xb8, "BSDI swap Partition"},
  221.         {0xc1, "DRDOS/sec (FAT-12) Partition"},
  222.         {0xc4, "DRDOS/sec (FAT-16, < 32M) Partition"},
  223.         {0xc6, "DRDOS/sec (FAT-16, >= 32M) Partition"},
  224.         {0xc7, "Syrinx Partition"},
  225.         {0xdb, "CP/M-Concurrent CP/M-Concurrent DOS-CTOS"},
  226.         {0xe1, "DOS access-SpeedStor 12-bit FAT ext."},
  227.         {0xe3, "DOS R/O or SpeedStor Partition"},
  228.         {0xe4, "SpeedStor 16-bit FAT Ext Part. < 1024 cyl."},
  229.         {0xf1, "SpeedStor Partition"},
  230.         {0xf2, "DOS 3.3+ secondary Partition"},
  231.         {0xf4, "SpeedStor large partition Partition"},
  232.         {0xfe, "SpeedStor >1024 cyl. or LANstep Partition"},
  233.         {0xff, "Xenix Bad Block Table Partition"},
  234.      };
  235. #endif /* INCLUDE_PART_SHOW */
  236. /*****************************************************************************
  237. *
  238. * useFdiskPartParse - parse partitions on given disk
  239. *
  240. * This routine is not intended to be user callable.
  241. * This routine parses all existing partition tables on a disk.
  242. * It adds partition node data entries to a table which it has been 
  243. * passed  for any partition which contains a
  244. * file system mountable by dosFsLib().  The size (in sectors)
  245. * of the partition and the absolute offset (in sectors) from the
  246. * start of the drive are also stored, since that is what VxWorks
  247. * CBIO device create routines need to overlay partitions. 
  248. * The partition table must appear to be valid when checked with
  249. * 0x55aa signature.   The partition table in the Master Boot Record
  250. * will be parsed first.  If there are any extended partitions found,
  251. * a (recursive) call to itself is made to parse the extended
  252. * partition(s) in the new sector(s).  Recursive functions may use a lot
  253. * of stack space. Developer should beware of stack overflow.
  254. *
  255. * RETURNS: ERROR or a (positive) number of partitions decoded and filled.
  256. *
  257. */
  258. LOCAL STATUS useFdiskPartParse
  259.     (
  260.     CBIO_DEV_ID dev,         /* device from which to read blocks */
  261.     CBIO_PARAMS * pCbioParams,  /* ptr to CBIO device parameters */
  262.     PART_TABLE_ENTRY *pPartTab, /* table where to fill results */
  263.     int nPart,                /* # of entries in <pPartTable> */
  264.     ULONG startBlock, /* where to expect part table, use zero */
  265.     ULONG extStartBlock /* Offset to extended partition, use zero */
  266.     )
  267.     {
  268.     u_char * secBuf; /* sector data we work on */
  269.     int i;                      /* used for loop through parts  */
  270.     int partOffset; /* offset of part tab entry in block */
  271.     int tableIndex = 0; /* where in table to write partition geo */
  272.     u_char partBootType, partSysType ;
  273.     STATUS stat;
  274.     /* allocate a local secBuf for the read sectors MBR/Part data */
  275.     if  ((secBuf = KHEAP_ALLOC(pCbioParams->bytesPerBlk)) == NULL)
  276.         {
  277.         printErr ("usrFdiskPartParse: Error allocating sector buffer.n");
  278.         return (ERROR);
  279.         }
  280.     bzero( (char *)secBuf, pCbioParams->bytesPerBlk);
  281.     /* Get current sector containing part table into buffer */
  282.     stat = cbioBlkRW( dev, startBlock, 1, (addr_t)secBuf,
  283. CBIO_READ, NULL );
  284.    /* 
  285.     * SPR#30850.  Certain devices when accessed for the first time report 
  286.     * Error erroneously.  Once the first read fails, the device might then
  287.     * work as expected after receiving a RESET.  This fix checks for
  288.     * that condition by forcing a RESET and then retrying the read.
  289.     * If it passes after the RESET, then it continues as requested.  If
  290.     * it fails again, however, then it assumes that the Error condition will
  291.     * continue in perpetuity and returns the error code as before.
  292.     */
  293.     if( stat == ERROR ) 
  294.         {
  295.         if(cbioIoctl(dev, CBIO_RESET, 0) == ERROR)
  296.             {
  297.             printErr ("usrFdiskPartParse: error issuing "
  298.                       "CBIO_RESET cmd to device %x, errno %xn",
  299.                       dev, errno);
  300.             printErr ("usrFdiskPartParse: device is not readyn");
  301.             KHEAP_FREE(secBuf);
  302.             return (ERROR);
  303.             }
  304.         }
  305.         /* The reset terminated correctly.  Now try the access again. */
  306.         stat = cbioBlkRW( dev, startBlock, 1, (addr_t)secBuf,
  307. CBIO_READ, NULL );
  308.         /* If still returning error, then assume not going to work. */
  309.         if( stat == ERROR )
  310.             {
  311.             printErr ("usrFdiskPartParse: error reading "
  312.                       "block %ld, errno %xn",
  313.                       startBlock, errno);
  314.             KHEAP_FREE(secBuf);
  315.             return (ERROR);
  316.             }
  317.     /* Check the validity of partition data with 0x55aa signature */
  318.     if ((secBuf[pCbioParams->bytesPerBlk - 2] != PART_SIG_MSB) || 
  319.         (secBuf[pCbioParams->bytesPerBlk - 1] != PART_SIG_LSB))
  320. {
  321. if ((secBuf[PART_SIG_ADRS]     != PART_SIG_MSB) || 
  322.             (secBuf[PART_SIG_ADRS + 1] != PART_SIG_LSB))
  323.             {
  324.     if( startBlock == 0)
  325.         {
  326.         printErr ("usrFdiskPartLib warning: " 
  327.       "disk partition table is not initializedn");
  328.         printErr ("usrFdiskPartLib warning: "
  329.      "use usrFdiskPartCreate( %#x, 1) to initialize the "
  330.      "disk as a single partitionn", dev );
  331.         pPartTab [ 0 ].nBlocks = pCbioParams->nBlocks;
  332.         pPartTab [ 0 ].offset = 0;
  333.         pPartTab [ 0 ].flags = 0xeeee ;
  334.         KHEAP_FREE (secBuf);
  335.         return(1);
  336.         }
  337.             printErr ("usrFdiskPartLib error: " 
  338.                   "Sector %d contains an invalid "
  339.                   "MSDOS partition signature 0x55aa.n", startBlock);
  340.     KHEAP_FREE (secBuf);
  341.             return (ERROR);
  342.             }
  343. }
  344.     /*
  345.      * Loop through all parts add mountable parts to table, will call
  346.      * itself recursively to parse extended partitions & logical
  347.      * drives in extended parts.  Recursive functions may use a lot
  348.      * of stack space. Developer should beware of stack overflow.
  349.      */
  350.     for (i=0 ; i<4 ; i++)
  351.         {
  352. /* partition offset relative to DOS_BOOT_PART_TBL */
  353. partOffset = DOS_BOOT_PART_TBL + i * 16 ;
  354.         /* if it is a bootable & non-extended partition, add first */
  355. partBootType = secBuf[ partOffset + BOOT_TYPE_OFFSET] ;
  356. partSysType  = secBuf[ partOffset + SYSTYPE_OFFSET] ;
  357. /* XXX - for MS-DOS consistency, Bootable partitions should be first */
  358.         /* continue to next loop iteration if an empty partition */
  359.         if (partSysType == 0)
  360.             {
  361.             continue;
  362.             }
  363. /* XXX - make this more logical, if not extended and if valid FS */
  364.         if (((partSysType != PART_TYPE_DOSEXT)      &&
  365.              (partSysType != PART_TYPE_WIN95_EXT))  &&      
  366.             ((partSysType == PART_TYPE_DOS4)     ||
  367.              (partSysType == PART_TYPE_WIN95_D4) ||
  368.              (partSysType == PART_TYPE_DOS3)     ||
  369.              (partSysType == PART_TYPE_DOS32)    ||
  370.              (partSysType == PART_TYPE_DOS32X)   ||
  371.              (partSysType == PART_TYPE_DOS12)))
  372.             {
  373.             /* Fill the node with the current partition tables data */ 
  374.     pPartTab [ tableIndex ].nBlocks =
  375. DISK_TO_VX_32( &secBuf[ partOffset + NSECTORS_TOTAL]) ;
  376.     /* offset in part table is relative to table location */
  377.     pPartTab [ tableIndex ].offset =
  378. startBlock +
  379. DISK_TO_VX_32( &secBuf[ partOffset + NSECTORS_OFFSET]) ;
  380.     /* type of partition */
  381.     pPartTab [ tableIndex ].flags =
  382. partSysType | (partBootType << 8 ) ;
  383.     tableIndex ++ ; /* next partition in next entry */
  384.             }
  385.         else if ((partSysType == PART_TYPE_DOSEXT) ||
  386.                  (partSysType == PART_TYPE_WIN95_EXT))
  387.             {
  388.     /* found an extended partition, call ourselves to parse.
  389.      * For primary partitions, the Relative Sectors 
  390.      * field represents the offset from the beginning 
  391.      * of the disk to the beginning of the partition, 
  392.      * counting by sectors. The Number of Sectors field 
  393.      * represents the total number of sectors in the partition. 
  394.      * Extended partition have the System ID byte in the 
  395.      * Partition Table entry is set to 5.  Within the extended 
  396.      * partition, you can create any number of logical drives. 
  397.      * The primary partition points to an extended which can have
  398.      * multiple "logical drives".
  399.      * When you have an extended partition on the hard disk, 
  400.      * the entry for that partition in the Partition Table 
  401.      * (at the end of the Master Boot Record) points to the 
  402.      * first disk sector in the extended partition.  
  403.      * The first sector of each logical drive in an extended 
  404.      * partition also has a Partition Table, with four entries 
  405.      * (just like the others).  The first entry is for the 
  406.      * current logical drive.  The second entry contains 
  407.      * information about the next logical drive in the 
  408.      * extended partition. Entries three and four are all 
  409.      * zeroes.  This format repeats for every logical drive. 
  410.      * The last logical drive has only its own partition entry 
  411.      * listed. The entries for partitions 2-4 are all zeroes.  
  412.      * The Partition Table entry is the only information 
  413.      * on the first side of the first cylinder of each 
  414.      * logical drive in the extended partition. The entry 
  415.      * for partition 1 in each Partition Table contains the 
  416.      * starting address for data on the current logical drive. 
  417.      * And the entry for partition 2 is the address of the 
  418.      * sector that contains the Partition Table for the next 
  419.      * logical drive. 
  420.      * 
  421.      * The use of the Relative Sector and Total Sectors 
  422.      * fields for logical drives in an extended partition 
  423.      * is different than for primary partitions. 
  424.      * 
  425.      * For the partition 1 entry of each logical drive, the 
  426.      * Relative Sectors field is the sector from the beginning 
  427.      * of the logical drive that contains the Partition Boot 
  428.      * Sector. The Total Sectors field is the number of sectors 
  429.      * from the Partition Boot Sector to the end of the logical 
  430.      * drive.   
  431.      * 
  432.      * For the partition 2 entry, the Relative Sectors field is 
  433.      * the offset from the beginning of the extended partition 
  434.      * to the sector containing the Partition Table for the logical 
  435.      * drive defined in the Partition 2 entry. The Total Sectors 
  436.      * field is the total size of the logical drive defined in 
  437.      * the Partition 2 entry.
  438.      */
  439.     if (startBlock == 0)  /* In the MBR, logical sector zero */
  440. {  
  441. extStartBlock = DISK_TO_VX_32
  442. (&secBuf[ partOffset + NSECTORS_OFFSET]);
  443. startBlock = extStartBlock; /* startBlock = extended start */
  444. }
  445.     else /* In extended partition/logical drive */
  446. {
  447. startBlock = DISK_TO_VX_32
  448. (&secBuf[ partOffset + NSECTORS_OFFSET]);
  449. startBlock += extStartBlock;
  450. }
  451.             /* Call ourselves to parse extended (sub) partition table */
  452.             stat = useFdiskPartParse (dev, /* same device */
  453. pCbioParams, /* CBIO device parameters */
  454. pPartTab + tableIndex, /* next tab entry to fill */
  455. nPart - tableIndex, /* # left entries */
  456. startBlock,  /* where ext starts */
  457. extStartBlock /* where main ext starts */
  458. );
  459.     if( stat == ERROR )
  460. {
  461. KHEAP_FREE(secBuf);
  462. return ERROR ;
  463. }
  464.     tableIndex += stat ;
  465.             }
  466. else
  467.     {
  468.     printErr("usrFdiskPartLib: warning: "
  469.     "invalid partition entry encountered "
  470.     "block %d, entry %d, sys type %x, Skippedn",
  471.     startBlock, i, partSysType );
  472.     }
  473. /* check for max # of partitions */
  474. if( tableIndex >= nPart )
  475.     {
  476.            KHEAP_FREE(secBuf);
  477.     return tableIndex ;
  478.             }
  479.         /* loop here to next part or end looping */
  480.         }
  481.     /*
  482.      * if signature is ok, but no partitions where found
  483.      * on the first level, assume the entire disk is
  484.      * one big file system
  485.      */
  486.     if (tableIndex == 0 && startBlock == 0)
  487. {
  488. pPartTab [ tableIndex ].nBlocks = pCbioParams->nBlocks;
  489. pPartTab [ tableIndex ].offset = 0;
  490. pPartTab [ tableIndex ].flags = 0x55aa ;
  491. tableIndex ++;
  492. }
  493.     KHEAP_FREE(secBuf);
  494.     return (tableIndex);
  495.     }
  496. /*****************************************************************************
  497. *
  498. * usrFdiskPartRead - read an FDISK-style partition table
  499. *
  500. * This function will read and decode a PC formatted partition table
  501. * on a disk, and fill the appropriate partition table array with
  502. * the resulting geometry, which should be used by the dpartCbio
  503. * partition manager to access a partitioned disk with a shared disk
  504. * cache.
  505. *
  506. * EXAMPLE:
  507. * The following example shows how a hard disk which is expected to have
  508. * up to two partitions might be configured, assuming the physical
  509. * level initialization resulted in the <blkIoDevId> handle:
  510. *
  511. * .CS
  512. * devCbio = dcacheDevCreate( blkIoDevId, 0, 0x20000, "Hard Disk");
  513. * mainDevId = dpartDevCreate( devCbio, 2, usrFdiskPartRead )
  514. * dosFsDevCreate(  "/disk0a", dpartPartGet (mainDevId, 0), 0,0,0);
  515. * dosFsDevCreate(  "/disk0b", dpartPartGet (mainDevId, 1), 0,0,0);
  516. * .CE
  517. * RETURNS: OK or ERROR if partition table is corrupt
  518. *
  519. */
  520. STATUS usrFdiskPartRead
  521.     (
  522.     CBIO_DEV_ID cDev,        /* device from which to read blocks */
  523.     PART_TABLE_ENTRY *pPartTab, /* table where to fill results */
  524.     int nPart               /* # of entries in <pPartTable> */
  525.     )
  526.     {
  527.     CBIO_DEV_ID dev = cDev;
  528.     CBIO_PARAMS cbioParams;
  529.     /* Verify the device handle, possibly create wrapper */
  530.     if (ERROR == cbioDevVerify( dev ))                 
  531.         {                                                 
  532.         /* attempt to handle BLK_DEV subDev */            
  533.         dev = cbioWrapBlkDev ((BLK_DEV *) cDev);
  534.         if( NULL != dev )
  535.             {
  536.             /* SPR#71633, clear the errno set in cbioDevVerify() */
  537.             errno = 0;
  538.             }
  539.         }                                                 
  540.     if (dev == NULL)
  541. {
  542. return (ERROR);
  543. }
  544.     /* The main device has already been RESET before this is called */
  545.     if (TRUE == cbioRdyChgdGet(dev))
  546. {
  547. return (ERROR);
  548. }
  549.     /* Get CBIO device parameters */
  550.     if (ERROR == cbioParamsGet (dev, &cbioParams))
  551. {
  552. return (ERROR);
  553. }
  554.     /* parse the boot partition and fill table with valid partitions */
  555.     if  ((useFdiskPartParse(dev, &cbioParams, pPartTab, nPart, 0, 0)) == ERROR)
  556. {
  557. printErr ("useFdiskPartParse errorn");
  558. return (ERROR);
  559. }
  560.     
  561.     return (OK);
  562.     }
  563. /*****************************************************************************
  564. *
  565. * usrFdiskPartCreate - create an FDISK-like partition table on a disk
  566. *
  567. * This function may be used to create a basic PC partition table.
  568. * Such partition table however is not intended to be compatible with
  569. * other operating systems, it is intended for disks connected to a
  570. * VxWorks target, but without the access to a PC which may be used to
  571. * create the partition table.
  572. *
  573. * This function is capable of creating only one partition table - the
  574. * MBR, and will not create any Bootable or Extended partitions.
  575. * Therefore, 4 partitions are supported.
  576. *
  577. * <dev> is a CBIO device handle for an entire disk, e.g. a handle
  578. * returned by dcacheDevCreate(), or if dpartCbio is used, it can be either
  579. * the Master partition manager handle, or the one of the 0th partition
  580. * if the disk does not contain a partition table at all.
  581. *
  582. * The <nPart> argument contains the number of partitions to create. If
  583. * <nPart> is 0 or 1, then a single partition covering the entire disk is
  584. * created.
  585. * If <nPart> is between 2 and 4, then the arguments <size1>, <size2>
  586. * and <size3> contain the 
  587. * .I percentage
  588. * of disk space to be assigned to the 2nd, 3rd, and 4th partitions
  589. * respectively. The first partition (partition 0) will be assigned the
  590. * remainder of space left (space hog).
  591. *
  592. * Partition sizes will be round down to be multiple of whole tracks
  593. * so that partition Cylinder/Head/Track fields will be initialized 
  594. * as well as the LBA fields. Although the CHS fields are written they
  595. * are not used in VxWorks, and can not be guaranteed to work correctly
  596. * on other systems.
  597. *
  598. * RETURNS: OK or ERROR writing a partition table to disk
  599. *
  600. */
  601. STATUS usrFdiskPartCreate
  602.     (
  603.     CBIO_DEV_ID cDev,  /* device representing the entire disk */
  604.     int nPart, /* how many partitions needed, default=1, max=4 */
  605.     int size1, /* space percentage for second partition */
  606.     int size2, /* space percentage for third partition */
  607.     int size3 /* space percentage for fourth partition */
  608.     )
  609.     {
  610.     PART_TABLE_ENTRY partTbl[4];
  611.     UINT32 totalSecs, trackSecs, cylSecs, totalTracks, i;
  612.     caddr_t secBuf = NULL ;
  613.     const char dummyString[] =
  614.              "Wind River Systems Inc., DosFs 2.0 Partition Table";
  615.     STATUS stat = OK;
  616.     CBIO_PARAMS cbioParams;
  617.     CBIO_DEV_ID dev = cDev;
  618.     bzero((caddr_t) partTbl, sizeof(partTbl));
  619.     /* Verify the device handle, possibly create wrapper */
  620.     if (ERROR == cbioDevVerify( dev ))
  621.         {
  622.         /* attempt to handle BLK_DEV subDev */
  623.         dev = cbioWrapBlkDev ((BLK_DEV *) cDev);
  624.         if( NULL != dev )
  625.             {
  626.             /* SPR#71633, clear the errno set in cbioDevVerify() */
  627.             errno = 0;
  628.             }
  629.         }
  630.     else
  631. {
  632. dev = cDev;
  633. }
  634.     if (dev == NULL)
  635.         {
  636.         printErr ("usrFdiskPartCreate error: bad handlen");
  637.         return (ERROR);
  638.         }
  639.     /* if first time usage, a RESET may be needed on the device */
  640.     if( cbioIoctl( dev, CBIO_RESET, 0) == ERROR )
  641.         {
  642.         printErr ("usrFdiskPartCreate error: device is not readyn");
  643.         return (ERROR);
  644. }
  645.     /* Get CBIO device parameters */
  646.     if (ERROR == cbioParamsGet (dev, &cbioParams))
  647. {
  648.         printErr ("usrFdiskPartCreate error: cbioParamsGet returned errorn");
  649. return (ERROR);
  650. }
  651.     if( cbioParams.blockOffset != 0 )
  652. {
  653. printErr ("usrFdiskPartCreate error: disk is already partitionedn");
  654. errno = EINVAL;
  655. return (ERROR);
  656. }
  657.     totalSecs = cbioParams.nBlocks ;
  658.     trackSecs = cbioParams.blocksPerTrack;
  659.     if( trackSecs < 1)
  660. trackSecs = 1;
  661.     cylSecs = trackSecs * cbioParams.nHeads ;
  662.     if( totalSecs < trackSecs * 4 )
  663. {
  664. printErr ("usrFdiskPartCreate error: disk too small %d blocksn",
  665.     totalSecs);
  666. errno = EINVAL;
  667. return (ERROR);
  668. }
  669.     /* also, part table CHS fields have certain limitations for CHS values */
  670.     if( trackSecs < 1 || trackSecs > 63 )
  671. {
  672. trackSecs = 64 ;
  673. cylSecs = trackSecs * cbioParams.nHeads ;
  674. }
  675.     if( cylSecs < 1 )
  676. cylSecs = trackSecs ;
  677.     while((totalSecs/cylSecs) > 1023 )
  678. cylSecs = cylSecs << 1 ;
  679.     /* rest of calculation made in tracks, round, less chance of overflowing */
  680.     totalTracks = totalSecs / trackSecs ;
  681. #ifdef DEBUG
  682.     printErr( "  totalTracks %d, trackSecs %d, cylSecs %dn",
  683. totalTracks, trackSecs, cylSecs );
  684. #endif
  685.     /* reserve one track for MBR */
  686.     i = totalTracks = totalTracks - 1 ;
  687.     /* 
  688.      * SPR#66973.  The lines inside case statements were of the form
  689.      * partTbl[3].spare = (i * size3)/100 ;
  690.      * which led to overflows on signed 32 bit machines when i and size3
  691.      * were of a certain size (70+Gb harddrives, for example).  'i' is 
  692.      * totalTracks - 1, sizeN represents the percentage portion of that.  
  693.      * sizeN is an integer value < 100, not a float value < 1.
  694.      * Since i is the larger of the two, the reduction in absolute terms 
  695.      * by dividing it (instead of sizeN) will be greater.
  696.      * Other option is to use 64bit math temporarily, which you could do 
  697.      * by simply casting, forcing the compiler to promote it:
  698.      *
  699.      *           partTbl[3].spare = ((long long)i * size3)/100 ;  
  700.      *
  701.      * but that takes extra instructions, cycles, etc, also the receptacle
  702.      * (partTbl[N].spare) is declared an int so the demotion back to a 32
  703.      * bits might cause trouble depending on the compiler implementation.
  704.      *
  705.      */
  706.     switch (nPart)
  707. {
  708. case 4:
  709.     partTbl[3].spare = size3 * (i/100) ; /* SPR 66973 */
  710.     totalTracks -= partTbl[3].spare ;
  711.     /*FALLTHROUGH*/
  712. case 3:
  713.     partTbl[2].spare = size2 * (i/100) ; /* SPR 66973 */
  714.     totalTracks -= partTbl[2].spare ;
  715.     /*FALLTHROUGH*/
  716. case 2:
  717.     partTbl[1].spare = size1 * (i/100) ; /* SPR 66973 */
  718.     totalTracks -= partTbl[1].spare ;
  719.     /*FALLTHROUGH*/
  720. case 0:
  721. case 1:
  722.     if( totalTracks <= 0 )
  723. {
  724. /* partition sizes dont sum up */
  725. /* printErr("  EINVAL:  totalTracks %dn", totalTracks ); */
  726. errno = EINVAL;
  727. return (ERROR);
  728. }
  729.     partTbl[0].spare = totalTracks ;
  730.     break ;
  731. default:
  732.     errno = EINVAL;
  733.     return (ERROR);
  734. }
  735.     /* normalize the entire partition table, calc offset etc.*/
  736.     for(i=0, totalTracks = 1; i<4; i++)
  737. {
  738. if( partTbl[i].spare == 0 )
  739.     continue ;
  740. partTbl[i].offset = totalTracks * trackSecs ;
  741. partTbl[i].nBlocks = partTbl[i].spare * trackSecs ;
  742. totalTracks += partTbl[i].spare ;
  743. /*
  744.  * If the partition is greater than or equal to 2GB,
  745.  * use FAT32x partition type.  Else if the partition 
  746.  * is greater than or equal to 65536, use BIGDOS FAT 
  747.  * 16bit FAT, 32Bit sector number.  Else if the partition 
  748.  * is and greater or equal to 32680 use SMALLDOS FAT, 
  749.  * 16bit FAT, 16bit sector num.  Else use FAT12 for 
  750.  * anything smaller than 32680.  Note: some systems 
  751.    * may want to change this to use the Windows95 partiton 
  752.  * types that support (LBA) INT 13 extensions, since the 
  753.  * only thing VxWorks can truely ensure is the LBA fields, 
  754.  * mostly since vxWorks does not use the BIOS (PC BIOS is 
  755.  * NOT deterministic, bad for a RTOS, plus they tend not 
  756.          * to be present on non-x86 targets.) and cannot ensure
  757.  * the BIOS translation of CHS.  Of course, the 32bit VxWorks
  758.  * RTOS would never need such a hack as CHS translation.  
  759.  * The reason we don't use the LBA field now is that 
  760.  * NT 3.51 and NT 4.0 will not recognize the new partition 
  761.  * types (0xb-0xf).   That is one reason this is shipped 
  762.  * in source.
  763.  * 
  764.  * TODO: Reconsider using partition types 0xb-0xf when 
  765.  * MS gets their trip together.
  766.  */
  767. if(partTbl[i].nBlocks >= 0x400000) 
  768.     partTbl[i].flags = PART_TYPE_DOS32X;
  769. else if (partTbl[i].nBlocks >= 65536)  
  770.     partTbl[i].flags = PART_TYPE_DOS4; 
  771. else if (partTbl[i].nBlocks >= 32680) 
  772.     partTbl[i].flags = PART_TYPE_DOS3; 
  773. else
  774.     partTbl[i].flags = PART_TYPE_DOS12;
  775. }
  776.     /* allocate a local secBuf for the read sectors MBR/Part data */
  777.     if  ((secBuf = KHEAP_ALLOC(cbioParams.bytesPerBlk)) == NULL)
  778.         {
  779.         printErr ("usrFdiskPartCreate: Error allocating sector buffer.n");
  780.         return (ERROR);
  781.         }
  782.     /* start filling the MBR buffer */
  783.     bzero( secBuf, cbioParams.bytesPerBlk);
  784.     /* fill the top with a silly RET sequence, not JMP */
  785.     secBuf[0] = 0x90 ; /* NOP */
  786.     secBuf[1] = 0x90 ; /* NOP */
  787.     secBuf[2] = 0xc3 ; /* RET */
  788.     bcopy( dummyString, secBuf+3, sizeof(dummyString));
  789.     /* write bottom 0x55aa signature */
  790.     secBuf[ PART_SIG_ADRS ]     = PART_SIG_MSB; /* 0x55 */
  791.     secBuf[ PART_SIG_ADRS + 1 ] = PART_SIG_LSB; /* 0xaa */
  792.     /* 
  793.      * When the sector size is larger than 512 bytesPerSector we write the 
  794.      * signature to the end of the sector as well as at offset 510/511.
  795.      */
  796.     if (512 < cbioParams.bytesPerBlk)
  797. {
  798. secBuf[ cbioParams.bytesPerBlk - 2 ] = PART_SIG_MSB; /* 0x55 */
  799. secBuf[ cbioParams.bytesPerBlk - 1 ] = PART_SIG_LSB; /* 0xAA */
  800. }
  801.     /* Now, fill the 4 partition entries, careful with byte ordering */
  802.     for(i = 0; i < 4; i ++ )
  803. {
  804. int cyl, head, tsec, s1 ;
  805. /* calculate offset of current partition table entry */
  806. int partOffset = DOS_BOOT_PART_TBL + i * 16 ;
  807. /* fill in fields */
  808. secBuf[ partOffset + BOOT_TYPE_OFFSET]  = 
  809. (i) ? PART_NOT_BOOTABLE : PART_IS_BOOTABLE;
  810. secBuf[ partOffset + SYSTYPE_OFFSET]  = partTbl[i].flags ;
  811. /* LBA number of sectors */
  812. VX_TO_DISK_32( partTbl [ i ].nBlocks,
  813. &secBuf[ partOffset + NSECTORS_TOTAL]);
  814. /* LBA offset */
  815. VX_TO_DISK_32( partTbl [ i ].offset,
  816. &secBuf[ partOffset + NSECTORS_OFFSET]);
  817. /* beginning of partition in CHS */
  818. if( partTbl [ i ].nBlocks > 0)
  819.     {
  820.     s1 = partTbl [ i ].offset ;
  821.     cyl = s1 / cylSecs ;
  822.     head = (s1 - (cyl * cylSecs)) / trackSecs ;
  823.     tsec = 1 + s1 - (cyl * cylSecs) - (head*trackSecs);
  824.     }
  825. else
  826.     {
  827.     cyl = head = tsec = 0 ; /* unused table entry */
  828.     }
  829. #ifdef DEBUG
  830. printErr("  start cyl %d hd %d s %dn", cyl, head, tsec );
  831. #endif
  832.         secBuf[ partOffset + STARTSEC_CYL_OFFSET ] = cyl & 0xff ;
  833.         secBuf[ partOffset + STARTSEC_SEC_OFFSET ] = ((cyl>>2) & 0xc0) | tsec ;
  834.         secBuf[ partOffset + STARTSEC_HD_OFFSET ] = head ;
  835. /* end of partition in CHS */
  836. if( partTbl [ i ].nBlocks > 0)
  837.     {
  838.     s1 = partTbl [ i ].offset + partTbl [ i ].nBlocks - 1  ;
  839.     cyl = s1 / cylSecs ;
  840.     head = (s1 - (cyl * cylSecs)) / trackSecs ;
  841.     tsec = 1 + s1 - (cyl * cylSecs) - (head*trackSecs);
  842.     }
  843. else
  844.     {
  845.     cyl = head = tsec = 0 ; /* unused table entry */
  846.     }
  847. #ifdef DEBUG
  848. printErr("  end   cyl %d hd %d s %dn", cyl, head, tsec );
  849. #endif
  850.         secBuf[ partOffset + ENDSEC_CYL_OFFSET ] = cyl & 0xff ;
  851.         secBuf[ partOffset + ENDSEC_SEC_OFFSET ] = ((cyl>>2) & 0xc0) | tsec ;
  852.         secBuf[ partOffset + ENDSEC_HD_OFFSET ] = head ;
  853. }
  854.     (void)  cbioIoctl( dev, CBIO_DEVICE_LOCK, 0) ;
  855.     /* Last but not least, write the MBR to disk */
  856.     stat = cbioBlkRW( dev, 0 , 1, secBuf, CBIO_WRITE, NULL ) ;
  857.     /* flush and invalidate cache immediately */
  858.     stat |= cbioIoctl( dev, CBIO_CACHE_INVAL, 0) ;
  859.     cbioRdyChgdSet (dev, TRUE) ; /* force re-mount */
  860.     (void)  cbioIoctl( dev, CBIO_DEVICE_UNLOCK, 0) ;
  861.     KHEAP_FREE(secBuf);
  862.     return stat;
  863.     }
  864. #if defined(INCLUDE_PART_SHOW)
  865. /*****************************************************************************
  866. *
  867. * usrFdiskPartShow - parse and display partition data
  868. *
  869. * This routine is intended to be user callable.
  870. *
  871. * A device dependent partition table show routine.  This 
  872. * routine outputs formatted data for all partition table 
  873. * fields for every partition table found on a given disk,
  874. * starting with the MBR sectors partition table.  This code can be 
  875. * removed to reduce code size by undefining: INCLUDE_PART_SHOW
  876. * and rebuilding this library and linking to the new library.
  877. * This routine takes three arguments. First, a CBIO pointer 
  878. * (assigned for the entire physical disk) usually obtained 
  879. * from dcacheDevCreate().  It also takes two block_t type 
  880. * arguments and one signed int, the user shall pass zero 
  881. * in these paramaters.
  882. * For example:
  883. * .CS
  884. * sp usrFdiskPartShow (pCbio,0,0,0)
  885. * .CE
  886. *
  887. * Developers may use size<arch> to view code size.
  888. * NOTE
  889. *
  890. * RETURNS: OK or ERROR
  891. *
  892. * INTERNAL
  893. * This function was adopted from jkf with minimal changes
  894. */
  895. STATUS usrFdiskPartShow
  896.     (
  897.     CBIO_DEV_ID cbio,         /* device CBIO handle */
  898.     block_t extPartOffset,    /* user should pass zero */
  899.     block_t currentOffset,    /* user should pass zero */
  900.     int extPartLevel          /* user should pass zero */
  901.     )
  902.     {
  903.     block_t tmpVal;    
  904.     UCHAR * secBuf;             /* a secBuf for the sector data */
  905.     size_t numNames;       /* partition name array entries */
  906.     UINT8 dosSec;               /* for temp use. Sector         */
  907.     UINT8 dosCyl;               /* for temp use. Cylinder       */
  908.     STATUS stat; /* for return status of called  */
  909.     int i;                      /* used for loop through parts  */
  910.     size_t ix;                  /* used for loop through parts  */
  911.     int partOffset;             /* offset from partition tbl ent*/
  912.     CBIO_PARAMS cbioParams;
  913.     CBIO_DEV_ID cbioDev = cbio;
  914.     /* Verify the device handle, possibly create wrapper */
  915.     if (ERROR == cbioDevVerify( cbio ))
  916.         {
  917.         /* attempt to handle BLK_DEV subDev */
  918.         cbioDev = cbioWrapBlkDev ((BLK_DEV *) cbio);
  919.         if( NULL != cbioDev )
  920.             {
  921.             /* SPR#71633, clear the errno set in cbioDevVerify() */
  922.             errno = 0;
  923.             }
  924.         }
  925.     else
  926. {
  927. cbioDev = cbio;
  928. }
  929.     if (cbioDev == NULL)
  930.         {
  931.         return (ERROR);
  932.         }
  933.     if (ERROR == cbioParamsGet (cbioDev, &cbioParams))
  934. {
  935. return (ERROR);
  936. }
  937.     /* get number of partition type entries */
  938.     numNames = ((sizeof (partNames)) / (sizeof (struct partType)));
  939.     /* allocate a local secBuf for the read sectors MBR/Part data */
  940.     if  ((secBuf = KHEAP_ALLOC(cbioParams.bytesPerBlk)) == NULL)
  941.         {
  942.         printErr ("usrFdiskPartShow: Error allocating sector buffer.n");
  943.         return (ERROR);
  944.         }
  945.     /* cbio reads the partition sector into a secBuf */
  946.     stat = cbioBlkRW( cbioDev, currentOffset, 1, (addr_t)secBuf,
  947. CBIO_READ, NULL );
  948.     if (stat == ERROR)
  949.         {
  950.         /* if first time reading, a RESET may be needed on the device */
  951.         if( cbioIoctl( cbioDev, CBIO_RESET, 0) == ERROR )
  952.             {
  953.             printErr ("usrFdiskPartShow: error reading"
  954.                       " sector %ld, errno %xn", currentOffset, errno);
  955.             printErr ("usrFdiskPartShow: device is not readyn");
  956.             return (ERROR);
  957.     }
  958. else /* Reset OK, try read again */
  959.     {
  960.     stat = cbioBlkRW( cbioDev, currentOffset, 1, (addr_t)secBuf,
  961. CBIO_READ, NULL );
  962.     if (stat == ERROR)
  963. {
  964.                 printErr ("usrFdiskPartShow: error reading "
  965.   "sector %ld, errno %xn", currentOffset, errno);
  966. return (ERROR);
  967. }
  968.     }
  969.         } 
  970.     /* Check the validity of partition data with 0x55aa signature */
  971.     if ((secBuf[cbioParams.bytesPerBlk - 2] != PART_SIG_MSB) || 
  972.         (secBuf[cbioParams.bytesPerBlk - 1] != PART_SIG_LSB))
  973. {
  974. if ((secBuf[PART_SIG_ADRS]     != PART_SIG_MSB) || 
  975.             (secBuf[PART_SIG_ADRS + 1] != PART_SIG_LSB))
  976.             {
  977.             printErr ("usrFdiskPartShow: "
  978.                   "Sector %ld contains an invalid signature 0x55aa.n",
  979.   currentOffset);
  980.             return (ERROR);
  981.             }
  982. }
  983.     /* Loop through and display data for all partitions in the list */
  984.     for (i=0 ; i<4 ; i++)
  985.         {
  986. /* setup an offset relative to DOS_BOOT_PART_TBL to entry */
  987. partOffset = i * 16;
  988.         /* Display extended or MBR */
  989.         if (currentOffset == 0x0)
  990.             {
  991.             printf ("n");
  992.             printf ("Master Boot Record - Partition Table n");
  993.             printf ("--------------------------------------n");
  994.             }
  995.         else 
  996.             {
  997.             printf ("n");
  998.             printf ("Extended Partition Table %02d n", extPartLevel);
  999.             printf ("--------------------------------------n");
  1000.             }
  1001.         
  1002.         /* display partition entry and offset */
  1003.         printf ("  Partition Entry number %02d    ", i);
  1004.         switch (i)
  1005.             {
  1006.             case 3:
  1007.                 printf (" Partition Entry offset 0x1een");
  1008.                 break;
  1009.             case 2:
  1010.                 printf (" Partition Entry offset 0x1den");
  1011.                 break;
  1012.             case 1:
  1013.                 printf (" Partition Entry offset 0x1cen");
  1014.                 break;
  1015.             case 0:
  1016.                 printf (" Partition Entry offset 0x1ben");
  1017.                 break; 
  1018.             }
  1019.         printf ("  Status field = 0x%02x          ",
  1020.                 secBuf[DOS_BOOT_PART_TBL + partOffset + 
  1021.                        BOOT_TYPE_OFFSET]);
  1022.         
  1023.         if ((secBuf[DOS_BOOT_PART_TBL + partOffset + 
  1024.              BOOT_TYPE_OFFSET]) == (PART_IS_BOOTABLE))
  1025.             {
  1026.             printf (" Primary (bootable) Partition n");
  1027.             }
  1028.         else
  1029.             {
  1030.             printf (" Non-bootable Partition       n");
  1031.             }
  1032.         /* print partition type name from array */
  1033.         for (ix=0; ix < numNames; ix++)
  1034.             {
  1035.             if ((partNames[ix].partTypeNum) == 
  1036.                 (secBuf[DOS_BOOT_PART_TBL + partOffset + 
  1037.                         SYSTYPE_OFFSET]))
  1038.                 {
  1039.                 printf ("  Type 0x%02x: ",secBuf[DOS_BOOT_PART_TBL
  1040.                                                  + partOffset
  1041.                                                  + SYSTYPE_OFFSET]);
  1042.                 printf ("%sn",partNames[ix].partTypeName);
  1043.                 break;  /*  found type, so fall out of loop. */
  1044.                 }
  1045.     }
  1046.         /* Skip the rest of a NULL/empty partition */
  1047.         if (secBuf[DOS_BOOT_PART_TBL + partOffset + SYSTYPE_OFFSET] 
  1048.             == 0x0)
  1049.             {
  1050.             printf ("n");
  1051.             continue;
  1052.             }
  1053.         /* Print out the CHS information */
  1054.         dosSec = (secBuf[DOS_BOOT_PART_TBL + partOffset
  1055.                   + STARTSEC_SEC_OFFSET] & 0x3f);
  1056.         dosCyl =  ((((secBuf[DOS_BOOT_PART_TBL + partOffset
  1057.                       + STARTSEC_SEC_OFFSET]) & 0xc0) << 2)|
  1058.                    (((secBuf[DOS_BOOT_PART_TBL + partOffset + 
  1059.                       STARTSEC_CYL_OFFSET]) & 0xff) >> 8));
  1060.         printf ("  Partition start LCHS: Cylinder %04d, Head %03d,",
  1061.                  dosCyl, secBuf[DOS_BOOT_PART_TBL + partOffset + 
  1062.                  STARTSEC_HD_OFFSET]);
  1063.         printf (" Sector %02d   n", dosSec);
  1064.         /*
  1065.          * Print out the ending sector CHS information for partition
  1066.          * calculate the actual DOS CHS sector and cylinder values.
  1067.          */
  1068.         dosSec = (secBuf[DOS_BOOT_PART_TBL + partOffset
  1069.                   + ENDSEC_SEC_OFFSET] & 0x3f);
  1070.         dosCyl =  ((((secBuf[DOS_BOOT_PART_TBL + partOffset 
  1071.                              + ENDSEC_SEC_OFFSET]) & 0xc0) << 2) | 
  1072.                    (((secBuf[DOS_BOOT_PART_TBL + partOffset
  1073.                              + ENDSEC_CYL_OFFSET]) & 0xff) ));
  1074.         printf ("  Partition end   LCHS: Cylinder %04d, Head %03d,",
  1075.                 dosCyl, secBuf[DOS_BOOT_PART_TBL + partOffset
  1076.                                + ENDSEC_HD_OFFSET]);
  1077.         printf (" Sector %02d   n", dosSec);
  1078.         /* Print offsets */
  1079. tmpVal = DISK_TO_VX_32( &secBuf[DOS_BOOT_PART_TBL + partOffset
  1080.                  + NSECTORS_OFFSET]) ;
  1081.         if (extPartLevel == 0x0)
  1082.             {
  1083.             printf ("  Sectors offset from MBR partition 0x%08lxn",tmpVal);
  1084.             }
  1085.         else 
  1086.             {
  1087.             printf ("  Sectors offset from the extended partition 0x%08lxn",
  1088. tmpVal);
  1089.             }
  1090. tmpVal = DISK_TO_VX_32( &secBuf[DOS_BOOT_PART_TBL + partOffset 
  1091.                  + NSECTORS_TOTAL]) ;
  1092.         printf ("  Number of sectors in partition 0x%08lxn", tmpVal);
  1093. tmpVal = DISK_TO_VX_32( &secBuf[DOS_BOOT_PART_TBL + partOffset 
  1094.                  + NSECTORS_OFFSET]) ;
  1095. printf ("  Sectors offset from start of disk 0x%08lxn",
  1096. (tmpVal + currentOffset));
  1097.         }
  1098.     /* Loop through all partitions in the list to find extended */
  1099.     for (i=0 ; i<4 ; i++)
  1100.         {
  1101. /* setup an offset relative to DOS_BOOT_PART_TBL to entry */
  1102. partOffset = i * 16;
  1103.         if ((secBuf[DOS_BOOT_PART_TBL + partOffset + SYSTYPE_OFFSET]
  1104.              == PART_TYPE_DOSEXT) ||
  1105.             (secBuf[DOS_BOOT_PART_TBL + partOffset + SYSTYPE_OFFSET]
  1106.              == PART_TYPE_WIN95_EXT))
  1107.             {
  1108.     /* found an extended partition, call ourselves to parse.
  1109.      * For primary partitions, the Relative Sectors 
  1110.      * field represents the offset from the beginning 
  1111.      * of the disk to the beginning of the partition, 
  1112.      * counting by sectors. The Number of Sectors field 
  1113.      * represents the total number of sectors in the partition. 
  1114.      * Extended partition have the System ID byte in the 
  1115.      * Partition Table entry is set to 5.  Within the extended 
  1116.      * partition, you can create any number of logical drives. 
  1117.      * The primary partition points to an extended which can have
  1118.      * multiple "logical drives".
  1119.      * When you have an extended partition on the hard disk, 
  1120.      * the entry for that partition in the Partition Table 
  1121.      * (at the end of the Master Boot Record) points to the 
  1122.      * first disk sector in the extended partition.  
  1123.      * The first sector of each logical drive in an extended 
  1124.      * partition also has a Partition Table, with four entries 
  1125.      * (just like the others).  The first entry is for the 
  1126.      * current logical drive.  The second entry contains 
  1127.      * information about the next logical drive in the 
  1128.      * extended partition. Entries three and four are all 
  1129.      * zeroes.  This format repeats for every logical drive. 
  1130.      * The last logical drive has only its own partition entry 
  1131.      * listed. The entries for partitions 2-4 are all zeroes.  
  1132.      * The Partition Table entry is the only information 
  1133.      * on the first side of the first cylinder of each 
  1134.      * logical drive in the extended partition. The entry 
  1135.      * for partition 1 in each Partition Table contains the 
  1136.      * starting address for data on the current logical drive. 
  1137.      * And the entry for partition 2 is the address of the 
  1138.      * sector that contains the Partition Table for the next 
  1139.      * logical drive. 
  1140.      * 
  1141.      * The use of the Relative Sector and Total Sectors 
  1142.      * fields for logical drives in an extended partition 
  1143.      * is different than for primary partitions. 
  1144.      * 
  1145.      * For the partition 1 entry of each logical drive, the 
  1146.      * Relative Sectors field is the sector from the beginning 
  1147.      * of the logical drive that contains the Partition Boot 
  1148.      * Sector. The Total Sectors field is the number of sectors 
  1149.      * from the Partition Boot Sector to the end of the logical 
  1150.      * drive.   
  1151.      * 
  1152.      * For the partition 2 entry, the Relative Sectors field is 
  1153.      * the offset from the beginning of the extended partition 
  1154.      * to the sector containing the Partition Table for the logical 
  1155.      * drive defined in the Partition 2 entry. The Total Sectors 
  1156.      * field is the total size of the logical drive defined in 
  1157.      * the Partition 2 entry.
  1158.      */
  1159.     if (currentOffset == 0)  /* In the MBR, logical sector zero */
  1160. {  
  1161. extPartOffset = DISK_TO_VX_32
  1162. (&secBuf[DOS_BOOT_PART_TBL + partOffset 
  1163.          + NSECTORS_OFFSET]);
  1164. currentOffset = extPartOffset; /* startBlock = ext. start */
  1165. }
  1166.     else /* In extended partition/logical drive */
  1167. {
  1168. currentOffset = DISK_TO_VX_32
  1169. (&secBuf[DOS_BOOT_PART_TBL + partOffset 
  1170.          + NSECTORS_OFFSET]);
  1171. currentOffset += extPartOffset;
  1172. }
  1173.             /* Update extPartLevel and parse found extended partition */
  1174.             extPartLevel++;
  1175.             usrFdiskPartShow (cbioDev, currentOffset, extPartOffset, 
  1176.       extPartLevel);
  1177.             extPartLevel--;
  1178.             }
  1179.         /* next part or end looping */
  1180.         }
  1181.     /* Clean up */
  1182.     KHEAP_FREE(secBuf);  
  1183.     return (OK);
  1184.     }
  1185. #endif /* INCLUDE_DOS_PART_SHOW */