📄 usrfdiskpartlib.c
字号:
/* Verify the device handle, possibly create wrapper */ if (ERROR == cbioDevVerify( dev )) { /* attempt to handle BLK_DEV subDev */ dev = cbioWrapBlkDev ((BLK_DEV *) cDev); if( NULL != dev ) { /* SPR#71633, clear the errno set in cbioDevVerify() */ errno = 0; } } else { dev = cDev; } if (dev == NULL) { printErr ("usrFdiskPartCreate error: bad handle\n"); return (ERROR); } /* if first time usage, a RESET may be needed on the device */ if( cbioIoctl( dev, CBIO_RESET, 0) == ERROR ) { printErr ("usrFdiskPartCreate error: device is not ready\n"); return (ERROR); } /* Get CBIO device parameters */ if (ERROR == cbioParamsGet (dev, &cbioParams)) { printErr ("usrFdiskPartCreate error: cbioParamsGet returned error\n"); return (ERROR); } if( cbioParams.blockOffset != 0 ) { printErr ("usrFdiskPartCreate error: disk is already partitioned\n"); errno = EINVAL; return (ERROR); } totalSecs = cbioParams.nBlocks ; trackSecs = cbioParams.blocksPerTrack; if( trackSecs < 1) trackSecs = 1; cylSecs = trackSecs * cbioParams.nHeads ; if( totalSecs < trackSecs * 4 ) { printErr ("usrFdiskPartCreate error: disk too small %d blocks\n", totalSecs); errno = EINVAL; return (ERROR); } /* also, part table CHS fields have certain limitations for CHS values */ if( trackSecs < 1 || trackSecs > 63 ) { trackSecs = 64 ; cylSecs = trackSecs * cbioParams.nHeads ; } if( cylSecs < 1 ) cylSecs = trackSecs ; while((totalSecs/cylSecs) > 1023 ) cylSecs = cylSecs << 1 ; /* rest of calculation made in tracks, round, less chance of overflowing */ totalTracks = totalSecs / trackSecs ;#ifdef DEBUG printErr( " totalTracks %d, trackSecs %d, cylSecs %d\n", totalTracks, trackSecs, cylSecs );#endif /* reserve one track for MBR */ i = totalTracks = totalTracks - 1 ; /* * SPR#66973. The lines inside case statements were of the form * partTbl[3].spare = (i * size3)/100 ; * which led to overflows on signed 32 bit machines when i and size3 * were of a certain size (70+Gb harddrives, for example). 'i' is * totalTracks - 1, sizeN represents the percentage portion of that. * sizeN is an integer value < 100, not a float value < 1. * Since i is the larger of the two, the reduction in absolute terms * by dividing it (instead of sizeN) will be greater. * Other option is to use 64bit math temporarily, which you could do * by simply casting, forcing the compiler to promote it: * * partTbl[3].spare = ((long long)i * size3)/100 ; * * but that takes extra instructions, cycles, etc, also the receptacle * (partTbl[N].spare) is declared an int so the demotion back to a 32 * bits might cause trouble depending on the compiler implementation. * */ switch (nPart) { case 4: partTbl[3].spare = size3 * (i/100) ; /* SPR 66973 */ totalTracks -= partTbl[3].spare ; /*FALLTHROUGH*/ case 3: partTbl[2].spare = size2 * (i/100) ; /* SPR 66973 */ totalTracks -= partTbl[2].spare ; /*FALLTHROUGH*/ case 2: partTbl[1].spare = size1 * (i/100) ; /* SPR 66973 */ totalTracks -= partTbl[1].spare ; /*FALLTHROUGH*/ case 0: case 1: if( totalTracks <= 0 ) { /* partition sizes dont sum up */ /* printErr(" EINVAL: totalTracks %d\n", totalTracks ); */ errno = EINVAL; return (ERROR); } partTbl[0].spare = totalTracks ; break ; default: errno = EINVAL; return (ERROR); } /* normalize the entire partition table, calc offset etc.*/ for(i=0, totalTracks = 1; i<4; i++) { if( partTbl[i].spare == 0 ) continue ; partTbl[i].offset = totalTracks * trackSecs ; partTbl[i].nBlocks = partTbl[i].spare * trackSecs ; totalTracks += partTbl[i].spare ; /* * If the partition is greater than or equal to 2GB, * use FAT32x partition type. Else if the partition * is greater than or equal to 65536, use BIGDOS FAT * 16bit FAT, 32Bit sector number. Else if the partition * is and greater or equal to 32680 use SMALLDOS FAT, * 16bit FAT, 16bit sector num. Else use FAT12 for * anything smaller than 32680. Note: some systems * may want to change this to use the Windows95 partiton * types that support (LBA) INT 13 extensions, since the * only thing VxWorks can truely ensure is the LBA fields, * mostly since vxWorks does not use the BIOS (PC BIOS is * NOT deterministic, bad for a RTOS, plus they tend not * to be present on non-x86 targets.) and cannot ensure * the BIOS translation of CHS. Of course, the 32bit VxWorks * RTOS would never need such a hack as CHS translation. * The reason we don't use the LBA field now is that * NT 3.51 and NT 4.0 will not recognize the new partition * types (0xb-0xf). That is one reason this is shipped * in source. * * TODO: Reconsider using partition types 0xb-0xf when * MS gets their trip together. */ if(partTbl[i].nBlocks >= 0x400000) partTbl[i].flags = PART_TYPE_DOS32X; else if (partTbl[i].nBlocks >= 65536) partTbl[i].flags = PART_TYPE_DOS4; else if (partTbl[i].nBlocks >= 32680) partTbl[i].flags = PART_TYPE_DOS3; else partTbl[i].flags = PART_TYPE_DOS12; } /* allocate a local secBuf for the read sectors MBR/Part data */ if ((secBuf = KHEAP_ALLOC(cbioParams.bytesPerBlk)) == NULL) { printErr ("usrFdiskPartCreate: Error allocating sector buffer.\n"); return (ERROR); } /* start filling the MBR buffer */ bzero( secBuf, cbioParams.bytesPerBlk); /* fill the top with a silly RET sequence, not JMP */ secBuf[0] = 0x90 ; /* NOP */ secBuf[1] = 0x90 ; /* NOP */ secBuf[2] = 0xc3 ; /* RET */ bcopy( dummyString, secBuf+3, sizeof(dummyString)); /* write bottom 0x55aa signature */ secBuf[ PART_SIG_ADRS ] = PART_SIG_MSB; /* 0x55 */ secBuf[ PART_SIG_ADRS + 1 ] = PART_SIG_LSB; /* 0xaa */ /* * When the sector size is larger than 512 bytesPerSector we write the * signature to the end of the sector as well as at offset 510/511. */ if (512 < cbioParams.bytesPerBlk) { secBuf[ cbioParams.bytesPerBlk - 2 ] = PART_SIG_MSB; /* 0x55 */ secBuf[ cbioParams.bytesPerBlk - 1 ] = PART_SIG_LSB; /* 0xAA */ } /* Now, fill the 4 partition entries, careful with byte ordering */ for(i = 0; i < 4; i ++ ) { int cyl, head, tsec, s1 ; /* calculate offset of current partition table entry */ int partOffset = DOS_BOOT_PART_TBL + i * 16 ; /* fill in fields */ secBuf[ partOffset + BOOT_TYPE_OFFSET] = (i) ? PART_NOT_BOOTABLE : PART_IS_BOOTABLE; secBuf[ partOffset + SYSTYPE_OFFSET] = partTbl[i].flags ; /* LBA number of sectors */ VX_TO_DISK_32( partTbl [ i ].nBlocks, &secBuf[ partOffset + NSECTORS_TOTAL]); /* LBA offset */ VX_TO_DISK_32( partTbl [ i ].offset, &secBuf[ partOffset + NSECTORS_OFFSET]); /* beginning of partition in CHS */ if( partTbl [ i ].nBlocks > 0) { s1 = partTbl [ i ].offset ; cyl = s1 / cylSecs ; head = (s1 - (cyl * cylSecs)) / trackSecs ; tsec = 1 + s1 - (cyl * cylSecs) - (head*trackSecs); } else { cyl = head = tsec = 0 ; /* unused table entry */ }#ifdef DEBUG printErr(" start cyl %d hd %d s %d\n", cyl, head, tsec );#endif secBuf[ partOffset + STARTSEC_CYL_OFFSET ] = cyl & 0xff ; secBuf[ partOffset + STARTSEC_SEC_OFFSET ] = ((cyl>>2) & 0xc0) | tsec ; secBuf[ partOffset + STARTSEC_HD_OFFSET ] = head ; /* end of partition in CHS */ if( partTbl [ i ].nBlocks > 0) { s1 = partTbl [ i ].offset + partTbl [ i ].nBlocks - 1 ; cyl = s1 / cylSecs ; head = (s1 - (cyl * cylSecs)) / trackSecs ; tsec = 1 + s1 - (cyl * cylSecs) - (head*trackSecs); } else { cyl = head = tsec = 0 ; /* unused table entry */ }#ifdef DEBUG printErr(" end cyl %d hd %d s %d\n", cyl, head, tsec );#endif secBuf[ partOffset + ENDSEC_CYL_OFFSET ] = cyl & 0xff ; secBuf[ partOffset + ENDSEC_SEC_OFFSET ] = ((cyl>>2) & 0xc0) | tsec ; secBuf[ partOffset + ENDSEC_HD_OFFSET ] = head ; } (void) cbioIoctl( dev, CBIO_DEVICE_LOCK, 0) ; /* Last but not least, write the MBR to disk */ stat = cbioBlkRW( dev, 0 , 1, secBuf, CBIO_WRITE, NULL ) ; /* flush and invalidate cache immediately */ stat |= cbioIoctl( dev, CBIO_CACHE_INVAL, 0) ; cbioRdyChgdSet (dev, TRUE) ; /* force re-mount */ (void) cbioIoctl( dev, CBIO_DEVICE_UNLOCK, 0) ; KHEAP_FREE(secBuf); return stat; }#if defined(INCLUDE_PART_SHOW)/******************************************************************************* usrFdiskPartShow - parse and display partition data** This routine is intended to be user callable.** A device dependent partition table show routine. This * routine outputs formatted data for all partition table * fields for every partition table found on a given disk,* starting with the MBR sectors partition table. This code can be * removed to reduce code size by undefining: INCLUDE_PART_SHOW* and rebuilding this library and linking to the new library.* * This routine takes three arguments. First, a CBIO pointer * (assigned for the entire physical disk) usually obtained * from dcacheDevCreate(). It also takes two block_t type * arguments and one signed int, the user shall pass zero * in these paramaters.* * For example:* .CS* sp usrFdiskPartShow (pCbio,0,0,0)* .CE** Developers may use size<arch> to view code size.* * NOTE** RETURNS: OK or ERROR** INTERNAL* This function was adopted from jkf with minimal changes*/STATUS usrFdiskPartShow ( CBIO_DEV_ID cbio, /* device CBIO handle */ block_t extPartOffset, /* user should pass zero */ block_t currentOffset, /* user should pass zero */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -