diff -r 000000000000 -r a41df078684a kerneltest/f32test/tools/mbrutil.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/tools/mbrutil.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,549 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ +// +// MbrUtil.cpp +// + + +#define _WIN32_WINNT 0x0400 +#include + +#pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union +#include + +#include + + +const int KSectorSize = 512; +BYTE TheBuffer[KSectorSize]; + +template +T Min(T aLeft,T aRight) + {return(aLeft> KMegaByteToSectorSizeShift; + +const int KMaxPartitionEntries=0x4; +const int KMBRFirstPartitionOffset=0x1BE; +const int KMBRSignatureOffset=0x1FE; + +inline BOOL PartitionIsFAT(unsigned char a) + { + return ( + a==KPartitionTypeFAT12 || + a==KPartitionTypeFAT16small || + a==KPartitionTypeFAT16 || + a==KPartitionTypeFAT16 || + a==KPartitionTypeWin95FAT16LBA || + a==KPartitionTypeHiddenFAT12 || + a==KPartitionTypeHiddenFAT16small || + a==KPartitionTypeHiddenFAT16 || + a==KPartitionTypeHiddenWin95FAT16LBA + ); + } + +inline BOOL PartitionIsFAT32(unsigned char a) + { + return ( + a==KPartitionTypeWin95FAT32 || + a==KPartitionTypeWin95FAT32LBA || + a==KPartitionTypeHiddenWin95FAT32 || + a==KPartitionTypeHiddenWin95FAT32LBA + ); + } + +inline BOOL PartitionIsNTFS(unsigned char a) + { + return ( + a==KPartitionTypeNTFS || + a==KPartitionTypeHiddenNTFS + ); + } + +class TMBRPartitionEntry + { +public: + BOOL IsValidPartition() + { return (iNumSectors>0 && iPartitionType!=KPartitionTypeEmpty); } + BOOL IsValidDosPartition() + { return (iNumSectors>0 && PartitionIsFAT(iPartitionType)); } + BOOL IsDefaultBootPartition() + { return(iX86BootIndicator==KBootIndicatorBootable && (IsValidDosPartition() || IsValidFAT32Partition())); } + BOOL IsValidFAT32Partition() + { return (iNumSectors>0 && PartitionIsFAT32(iPartitionType)); } +public: + unsigned char iX86BootIndicator; + unsigned char iStartHead; + unsigned char iStartSector; + unsigned char iStartCylinder; + unsigned char iPartitionType; + unsigned char iEndHead; + unsigned char iEndSector; + unsigned char iEndCylinder; + DWORD iFirstSector; + DWORD iNumSectors; + }; + + +char* GetPartitionType(unsigned char aType) + { + switch (aType) + { + case KPartitionTypeFAT12: return "FAT12"; + case KPartitionTypeFAT16: return "FAT16"; + case KPartitionTypeFAT16small: return "FAT16"; + case KPartitionTypeWin95FAT32: return "FAT32"; + default: + return "????"; + + } + } + +void ReadMbr(unsigned char* aMbrBuf, int aDiskSizeInSectors, BOOL aHexDump) + { +// printf("Reading MBR...\n"); + if (aHexDump) + { + int n; + for (n=0; niPartitionType != 0; i++, pe++) + { + if (pe->iFirstSector + pe->iNumSectors > (DWORD) aDiskSizeInSectors) + { + printf("No valid MBR\n"); + return; + } + } + + printf("Partitions: \n"); + printf(" # Name Type Fat BtI Hed Sct Cyl Hed Sct Cyl FirstSect NumSectors\n"); + + for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++) + { + char* partitionName = GetPartitionType(pe->iPartitionType); + printf("%3d: %-6s %3u %3u %3u %3u %3u %3u %3u %3u %3u %10u %10u (%u MB)\n", + i, + partitionName, + pe->iPartitionType, + pe->IsValidDosPartition() || pe->IsValidFAT32Partition() ? 1 : 0, + pe->iX86BootIndicator, + pe->iStartHead, + pe->iStartSector, + pe->iStartCylinder, + pe->iEndHead, + pe->iEndSector, + pe->iEndCylinder, + pe->iFirstSector, + pe->iNumSectors, + pe->iNumSectors >> KMegaByteToSectorSizeShift); + + if (pe->iPartitionType == KPartitionTypeHiddenNTFS) + { + printf("Drive contains an NTFS partition, aborting for safety\n"); + return; + } + } + } + + +BOOL WriteMbr(unsigned char* aMbrBuf, int aFatSectorCount) + { + TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); + + // first partition starts at one MB + int sectorStart = KMegaByteInSectors; + + // Create FAT partition + pe->iFirstSector = sectorStart; + + + pe->iNumSectors = aFatSectorCount; + pe->iX86BootIndicator = 0x00; + if (pe->iNumSectors < 32680) + pe->iPartitionType = KPartitionTypeFAT12; + else if(pe->iNumSectors < 65536) + pe->iPartitionType = KPartitionTypeFAT16small; + else if (pe->iNumSectors < 1048576) + pe->iPartitionType = KPartitionTypeFAT16; + else + pe->iPartitionType = KPartitionTypeWin95FAT32; + sectorStart+= pe->iNumSectors; + + aMbrBuf[KMBRSignatureOffset+0] = 0x55; + aMbrBuf[KMBRSignatureOffset+1] = 0xAA; + + return true; + } + + +int main(int argc,char *argv[]) + { + + if (argc < 2) + { + printf("MbrUtil - Decodes and optionally writes or erases the Master Boot Record on a removable drive\n"); + printf("Syntax : MbrUtil [-e] [-w ] [FAT] [FAT32]\n"); + printf("Where :\n"); + printf("-e : erase Master Boot Record:\n"); + printf("-w : create FAT partition of size :\n"); + printf("E.g. : MbrUtil f:\n"); + printf(" : MbrUtil f: -w 16 FAT\n"); + exit(0); + } + + bool writeMbr = false; + bool eraseMbr = false; + int fatSectorCount = 0; + char* fatType = "FAT"; + + char driveLetter = (char) toupper(argv[1][0]); + if ((strlen(argv[1]) > 2) || + (strlen(argv[1]) == 2 && argv[1][1] != ':') || + (driveLetter < 'A' || driveLetter > 'Z')) + { + printf("invalid drive letter"); + exit(4); + } + + for (int i=2; i= argc) + { + printf("no drive size specified"); + exit(4); + } + int fatSizeInMegabytes = atoi(argv[i]); + fatSectorCount = fatSizeInMegabytes << KMegaByteToSectorSizeShift; +// printf("fatSizeInMegabytes %d, fatSectorCount %d\n", fatSizeInMegabytes, fatSectorCount); + } + else if (strcmpi(argv[i], "FAT") == 0) + { + } + else if (strcmpi(argv[i], "FAT32") == 0) + { + fatType = argv[i]; + } + else + { + printf("invalid option"); + exit(4); + } + } + + + char diskName[10] = "\\\\.\\?:"; + diskName[4] = driveLetter; + char physDiskName[20] = "\\\\.\\PHYSICALDRIVE?"; + + + + DISK_GEOMETRY geometry; + DWORD dummy; + HANDLE logDeviceHandle; + HANDLE physDeviceHandle; + BOOL b; + DWORD bytesRead; + DWORD bytesWritten; + DWORD dwRet; + + //***************************************************************************************** + // open logical drive... + //***************************************************************************************** + printf("Opening %s...\n", diskName); + logDeviceHandle = CreateFileA( + diskName, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , + NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); + if (logDeviceHandle == INVALID_HANDLE_VALUE) + { + printf("CreateFileA() returned INVALID_HANDLE_VALUE\n"); + exit(4); + } + + // query geometry + b = DeviceIoControl( + logDeviceHandle, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &geometry, + sizeof(geometry), + &dummy, + (LPOVERLAPPED)NULL); + if (!b) + { + printf("IOCTL_DISK_GET_DRIVE_GEOMETRY failed error %x", GetLastError()); + CloseHandle(logDeviceHandle); + exit(4); + } + + LONGLONG diskSizeInBytes = geometry.Cylinders.QuadPart * geometry.TracksPerCylinder * geometry.SectorsPerTrack * KDiskSectorSize; + int diskSizeInMegaBytes = (int) (diskSizeInBytes / KMegaByte); + int diskSizeInSectors = (int) (diskSizeInBytes / KDiskSectorSize); + + + printf("Drive %c MediaType: %d (%s). Size: %ld MBytes, %lu sectors\n", + driveLetter, + geometry.MediaType, + geometry.MediaType==RemovableMedia ? "RemovableMedia" : + geometry.MediaType==FixedMedia ? "FixedMedia" : "?", + diskSizeInMegaBytes, + diskSizeInSectors + ); +// printf("Size: %llu sectors\n", diskSizeInSectors); + + if (geometry.MediaType != RemovableMedia) + { + printf("Drive is not removable, exiting"); + CloseHandle(logDeviceHandle); + exit(4); + } + + if (fatSectorCount + KMegaByteInSectors > diskSizeInSectors) + { + printf("Specified size is too big"); + CloseHandle(logDeviceHandle); + exit(4); + } + + //***************************************************************************************** + // Get physical device number + //***************************************************************************************** + STORAGE_DEVICE_NUMBER storageDeviceNumber; + b = IOCTL_STORAGE_GET_DEVICE_NUMBER; + b = DeviceIoControl( + logDeviceHandle, + IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof(storageDeviceNumber), &bytesRead, 0); +// printf("IOCTL_STORAGE_GET_DEVICE_NUMBER b %d DeviceNumber %d\n", b, storageDeviceNumber.DeviceNumber); + if (!b) + { + printf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed error %x", GetLastError()); + CloseHandle(logDeviceHandle); + exit(4); + } + + + + //***************************************************************************************** + // open physical drive... + //***************************************************************************************** + physDiskName[strlen(physDiskName)-1] = (char) ('0' + storageDeviceNumber.DeviceNumber); + + printf("Opening %s...\n", physDiskName); + physDeviceHandle = CreateFileA( + physDiskName, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , + NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); + if (physDeviceHandle == INVALID_HANDLE_VALUE) + { + printf("CreateFileA() returned INVALID_HANDLE_VALUE\n"); + exit(4); + } + + + + + //******************************************************* + // Read first sector + //******************************************************* + dwRet = SetFilePointer( + physDeviceHandle, 0, 0, FILE_BEGIN); + if (dwRet != 0) + { + printf("Unable to set file pointer, exiting"); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + if (!ReadFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesRead, NULL) ) + { + printf("ReadFile failed with %d", GetLastError()); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + if(bytesRead != KSectorSize) + { + printf("ReadFile length too small: %d", bytesRead); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + + //******************************************************* + // Interpret MBR + //******************************************************* + ReadMbr(TheBuffer, diskSizeInSectors, false); + + //******************************************************* + // Write new MBR + //******************************************************* + if (writeMbr) + { + printf("Writing MBR...\n"); + memset(TheBuffer, 0, sizeof(TheBuffer)); + b = WriteMbr(TheBuffer, fatSectorCount); + if (!b) + writeMbr = eraseMbr = false; + } + if (eraseMbr) + { + printf("Erasing MBR...\n"); + memset(TheBuffer, 0, sizeof(TheBuffer)); + } + if (writeMbr || eraseMbr) + { + // Write first sector + dwRet = SetFilePointer( + physDeviceHandle, 0, 0, FILE_BEGIN); + if (dwRet != 0) + { + printf("Unable to set file pointer, exiting"); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + if (!WriteFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesWritten, NULL) ) + { + printf("WriteFile failed with %d", GetLastError()); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + if(bytesWritten != KSectorSize) + { + printf("WriteFile length too small: %d", bytesWritten); + CloseHandle(physDeviceHandle); + CloseHandle(logDeviceHandle); + exit(4); + } + if (writeMbr) + ReadMbr(TheBuffer, diskSizeInSectors, false); + } + + + CloseHandle(physDeviceHandle); + + + if (writeMbr || eraseMbr) + { + printf("Dismounting %s...\n", diskName); + b = DeviceIoControl( + logDeviceHandle, + FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesRead, 0); + if (!b) + printf("FSCTL_DISMOUNT_VOLUME b %d err %d\n", b, GetLastError()); + } + + CloseHandle(logDeviceHandle); + + //******************************************************* + // Format the disk + //******************************************************* + if (writeMbr || eraseMbr) + { + printf("\n"); + char prompt[80]; + sprintf(prompt, "Eject card from drive %C: and press ENTER when ready...\n", driveLetter); + printf(prompt); + getchar(); + + char winCmd[1024]; + char cmdArgs[1024]; + STARTUPINFO si = {0,}; + PROCESS_INFORMATION pi; + + GetWindowsDirectory(winCmd, sizeof(winCmd)); + strncat(winCmd, "\\system32\\cmd.exe", sizeof(winCmd)); + sprintf(cmdArgs, "/C format %c: /FS:%s /Q /X", driveLetter, fatType); + printf("Executing : %s %s\n", winCmd, cmdArgs); + b = CreateProcessA( + winCmd, //__in_opt LPCTSTR lpApplicationName, + cmdArgs, //__inout_opt LPTSTR lpCommandLine, + NULL, //__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + NULL, //__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + FALSE, //__in BOOL bInheritHandles, + 0, //__in DWORD dwCreationFlags, + NULL, //__in_opt LPVOID lpEnvironment, + NULL, //__in_opt LPCTSTR lpCurrentDirectory, + &si, //__in LPSTARTUPINFO lpStartupInfo, + &pi); //__out LPPROCESS_INFORMATION lpProcessInformation + if (!b) + printf("CreateProcess failed with %d", GetLastError()); + + dwRet = WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + } + + return 0; + } \ No newline at end of file