/* bmff : Blackbox Media Works Format Free jykang 20190923 */ #if (SUPPORT_FORMAT_FREE) #include "bmff.h" //#include #ifdef WIN32 //#define BLKGETSIZE 4096 #define BLKGETSIZE 4096 //_IO(0x12,96) // return device size /512 (long *arg) */ #define BLKFLSBUF 4096 //_IO(0x12,97) // flush buffer cache */ #define EVENT_FILE_SEC 60 typedef __int64 ssize_t; typedef __int64 loff_t; typedef __int64 off64_t; // off64_t static loff_t toInteger(LARGE_INTEGER const & integer) { #ifdef INT64_MAX // Does the compiler natively support 64-bit integers? return integer.QuadPart; #else return (static_cast(integer.HighPart) << 32) | integer.LowPart; #endif } // signed long long to LARGE_INTEGER object: static LARGE_INTEGER toLargeInteger(loff_t value) { LARGE_INTEGER result; #ifdef INT64_MAX // Does the compiler natively support 64-bit integers? result.QuadPart = value; #else result.HighPart = (value >> 32) & 0xFFFFFFFF;// & 0xFFFFFFFF00000000); result.LowPart = value & 0xFFFFFFFF; #endif return result; } int GetPhysicalDrive(WCHAR DL) { int ret = -1; WCHAR sBuf[1000]; WCHAR sBuffer1[255] = {0,}; WCHAR sBuffer2[50] = {0,}; DWORD nSize, nCpt; nSize = ::GetLogicalDriveStrings(1000, sBuf); nCpt = 0; while (nCpt < nSize) { if(sBuf[nCpt] != DL) { nCpt += lstrlen(&sBuf[nCpt]) + 1; continue; } //wsprintf(sBuffer1, L"\\\\.\\%c:", DL); //OutputDebugString(sBuffer1); wsprintf(sBuffer1, L"\\\\.\\%s", &sBuf[nCpt]); sBuffer1[6] = 0; // strcpy(sBuffer1, &num[6]); HANDLE hVol = NULL; hVol = ::CreateFile(sBuffer1, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); int maxDisks; BOOL b; DWORD cbBytes; PVOLUME_DISK_EXTENTS PVolDiskExtent; PVolDiskExtent = (PVOLUME_DISK_EXTENTS)::LocalAlloc(LMEM_FIXED, sizeof(VOLUME_DISK_EXTENTS)); STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned = 0; b = ::DeviceIoControl(hVol, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); int nType = sdn.DeviceType; b = ::DeviceIoControl(hVol, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, PVolDiskExtent, sizeof(VOLUME_DISK_EXTENTS), &cbBytes, NULL); int nDiskNumber = 0; if (!b) { int n = ::GetLastError(); if (n == ERROR_MORE_DATA) { maxDisks = PVolDiskExtent->NumberOfDiskExtents; ::LocalFree(PVolDiskExtent); PVolDiskExtent = (PVOLUME_DISK_EXTENTS)LocalAlloc(LMEM_FIXED, sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * maxDisks)); b = DeviceIoControl(hVol, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, PVolDiskExtent, sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * maxDisks), &cbBytes, NULL); nDiskNumber = PVolDiskExtent->Extents[0].DiskNumber; } else nDiskNumber = -1; } else { nDiskNumber = PVolDiskExtent->Extents[0].DiskNumber; } // Disk : C:\ - Disk Number : 0 - Type : 7 // Disk : F:\ - Disk Number : 1 - Type : 7 // WCHAR wsText[255] = L""; // wsprintf(wsText, L"Disk : %s - Disk Number : %d - Type : %d\n", &sBuf[nCpt], nDiskNumber, nType); // OutputDebugString(wsText); ::CloseHandle(hVol); if(DL == sBuf[nCpt]) { return nDiskNumber; } nCpt += lstrlen(&sBuf[nCpt]) + 1; } return -1; } //int open64(const char *pathname, int oflag,...) //{ // return 0; //} //int close(int fd) //{ // return 0; //} //int fsync(int fd) //{ // return 0; //} void usleep(int m) {} int ioctl(HANDLE fd, unsigned long request,unsigned long* ret) { // SECTOR SIZE 는 512로 되어 있으니 확인할 필요 없음 /* Q_UNUSED(request) DWORD outsize; STORAGE_PROPERTY_QUERY storageQuery; ::ZeroMemory(&storageQuery, sizeof(STORAGE_PROPERTY_QUERY)); storageQuery.PropertyId = StorageAccessAlignmentProperty; storageQuery.QueryType = PropertyStandardQuery; STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment = {0}; ::ZeroMemory(&diskAlignment, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)); if (!::DeviceIoControl(fd, IOCTL_STORAGE_QUERY_PROPERTY, &storageQuery, sizeof(STORAGE_PROPERTY_QUERY), &diskAlignment, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), &outsize, NULL) ) { return -1; } // 512, 512, SIZE: 28 // 실제 SECTOR 크기만 확인가능 DWORD sectorSize =diskAlignment.BytesPerPhysicalSector; // 512 Return the device size, expressed in sectors */ DISK_GEOMETRY stDiskGeometry; ::ZeroMemory(&stDiskGeometry, sizeof(DISK_GEOMETRY)); DWORD dwjunk = 0; if(!::DeviceIoControl(fd, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, // no input buffer &stDiskGeometry, sizeof(DISK_GEOMETRY), &dwjunk, (LPOVERLAPPED) NULL)) { return -1; } // Cylinders: 482 SectorsPerTrack: 63 TracksPerCylinder: 255 ioctl //qInfo() << "Cylinders:" << toInteger(stDiskGeometry.Cylinders) << "SectorsPerTrack:" << stDiskGeometry.SectorsPerTrack << "TracksPerCylinder:" << stDiskGeometry.TracksPerCylinder << __FUNCTION__; int64_t sz = toInteger(stDiskGeometry.Cylinders) * stDiskGeometry.SectorsPerTrack * stDiskGeometry.TracksPerCylinder; // *ret = sz; int64_t numCluster = sz / SECTORS_PER_CLUSTER; *ret = numCluster * SECTORS_PER_CLUSTER; // *ret /= 8; // *ret = (int64_t)(*ret / SECTOR_SIZE) * SECTOR_SIZE; // 512??? if((*ret < MIN_SECTORS) || (*ret > MAX_SECTORS)) { return -1; } return 0; } ssize_t read(HANDLE fd, void* buffer, size_t count){ DWORD dwRead; if(!::ReadFile(fd, buffer, count, &dwRead, NULL)) { return -1; } return dwRead; } ssize_t write(HANDLE fd, void* buffer, size_t count){ // , OVERLAPPED* pOV //return count; DWORD dwWrite; LPVOID nb = ::VirtualAlloc(NULL,count,MEM_COMMIT,PAGE_READWRITE); ::CopyMemory(nb,buffer,count); // (LPOVERLAPPED)&m_ov[page]) // OVERLAPPED ol = {0,}; // LARGE_INTEGER move = {0,}; // LARGE_INTEGER np; // ::SetFilePointerEx(fd,move,&np,FILE_CURRENT); // pOV->Offset = lp.LowPart; // pOV->OffsetHigh = lp.HighPart; // ol.Offset = np.LowPart; // ol.OffsetHigh = np.HighPart; // printf("FP:%X:%X\n",ol.Offset, ol.OffsetHigh); if(!::WriteFile(fd,nb,count,&dwWrite,NULL)) { //if(!::WriteFileEx(fd,buffer,count,pOV,NULL)) { DWORD dwError = ::GetLastError(); wchar_t buf[256] = {0,}; ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), // LANG_NEUTRAL buf, (sizeof(buf) / sizeof(wchar_t)), NULL); wprintf(buf); ::VirtualFree(nb,count,0); return -1; } ::VirtualFree(nb,count,0); // lp.QuadPart += dwWrite; // ::SetFilePointerEx(fd,lp,&dummy,FILE_CURRENT); return ((ssize_t)dwWrite); } off64_t lseek64(HANDLE fd, off64_t offset, int whence) { DWORD dwMoveMethod = FILE_BEGIN; if(whence == SEEK_CUR) { dwMoveMethod = FILE_CURRENT; } else if(whence == SEEK_END) { dwMoveMethod = FILE_END; } //loff_t pos = FIRST_SECTOR * SECTOR_SIZE; LARGE_INTEGER liSize = toLargeInteger(offset); // liSize.LowPart = (int)(offset & 0xFFFFFFFF); // liSize.HighPart = (int)(offset >> 32); LARGE_INTEGER offsetL; offsetL.LowPart = ::SetFilePointer(fd,liSize.LowPart,&liSize.HighPart,dwMoveMethod); offsetL.HighPart = liSize.HighPart; if(offsetL.QuadPart != liSize.QuadPart) //if(!::SetFilePointerEx(fd,liSize,&offsetL,dwMoveMethod)) { printf("LSEEK ERROR:%I64d",offset); return -1; } return (off64_t)offsetL.QuadPart;// toInteger(offsetL); //loff_t offset = lseek64(mFd, (loff_t)FIRST_SECTOR * SECTOR_SIZE, SEEK_SET); //return 0; } #else // WIN32 #include "bmconfig.h" #include #endif // WIN32 #include BmFF::BmFF() { setbuf(stdout, NULL); // C99 오류 mNoPrintFlag = false; FIRST_SECTOR = 2048; mMstarPark = false; mEmmc = false; mRootDirectoryStartCluster = 2; mRootDirectoryClusters = 1; mLogDirectoryClusters = 1; mNormalPercent = 60; mEventPercent = 15; mManualPercent = 5; mPtTotalSectors = 0; mSectorsPerFat = 0; #if(MODEL_CONFIG == MH3000) mParkingNormalPercent = 0; #else mParkingNormalPercent = 18; #endif // mParkingEventPercent = 2; mRecoverFlag = false; mFormatFlag = false; mRecovered = false; mSerialNumber = 0; mMakeFactoryAging = false; mFd = NULL; } int BmFF::Init(const char *device, int normalFrontFileSize, int normalRearFileSize, int eventFrontFileSize, int eventRearFileSize, int parkFrontFileSize, int parkRearFileSize) { mDeviceName = device; mNormalFrontFileClusters = normalFrontFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(normalFrontFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mNormalFrontFileClusters; mNormalRearFileClusters = normalRearFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(normalRearFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mNormalRearFileClusters; mEventFrontFileClusters = eventFrontFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(eventFrontFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mEventFrontFileClusters; mEventRearFileClusters = eventRearFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(eventRearFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mEventRearFileClusters; mParkingFrontFileClusters = parkFrontFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(parkFrontFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mParkingFrontFileClusters; mParkingRearFileClusters = parkRearFileSize / (SECTORS_PER_CLUSTER * SECTOR_SIZE); if(parkRearFileSize % (SECTORS_PER_CLUSTER * SECTOR_SIZE) != 0) ++mParkingRearFileClusters; mManualFrontFileClusters = mEventFrontFileClusters; mManualRearFileClusters = mEventRearFileClusters; mFlushStartOffset = 0; if(!mNoPrintFlag) printf("NF_Clusters:%d, NR_Clusters:%d, EF_Clusters:%d, ER_Clusters:%d, PF_Clusters:%d, PR_Clusters=%d\n", mNormalFrontFileClusters, mNormalRearFileClusters, mEventFrontFileClusters, mEventRearFileClusters, mParkingFrontFileClusters, mParkingRearFileClusters); return 0; } void BmFF::SetStoragePercent(bool park) { if(mMstarPark) { #if (MODEL_CONFIG == UPK045) if(park) { mNormalPercent = 55; mParkingNormalPercent = 20; mEventPercent = 20; } else { mNormalPercent = 65; mParkingNormalPercent = 0; mEventPercent = 30; } mManualPercent = 5; mParkingEventPercent = 0; #elif (MODEL_CONFIG == MH3000) mNormalPercent = 88; mParkingNormalPercent = 0; mEventPercent = 12; mManualPercent = 0; mParkingEventPercent = 0; #elif (MODEL_CONFIG == BV3000 || MODEL_CONFIG == BV600) if(park) { mNormalPercent = 50; mParkingNormalPercent = 20; } else { mNormalPercent = 70; mParkingNormalPercent = 0; } mEventPercent = 20; mManualPercent = 10; mParkingEventPercent = 0; #elif (MODEL_CONFIG == R093) if(park) { mNormalPercent = 60; mParkingNormalPercent = 15; mEventPercent = 20; } else { mNormalPercent = 65; mParkingNormalPercent = 0; mEventPercent = 30; } mManualPercent = 5; mParkingEventPercent = 0; #elif (MODEL_CONFIG == FRC) // if(park) // { // mNormalPercent = 50; // mParkingNormalPercent = 20; // } // else // { // mNormalPercent = 70; // mParkingNormalPercent = 0; // } // mEventPercent = 20; // mManualPercent = 10; // mParkingEventPercent = 0; if(access("/tmp/bmff_frc_65_15_5_15", F_OK) == 0) { mNormalPercent = 65; mEventPercent = 15; mManualPercent = 5; mParkingNormalPercent = 15; mParkingEventPercent = 0; printf("frc partition: 65, 15, 5, 15\n"); } else if(access("/tmp/bmff_frc_20_75_5_0", F_OK) == 0) { mNormalPercent = 20; mEventPercent = 75; mManualPercent = 5; mParkingNormalPercent = 0; mParkingEventPercent = 0; printf("frc partition: 20, 75, 5, 0\n"); } else if(access("/tmp/bmff_frc_20_60_5_15", F_OK) == 0) { mNormalPercent = 20; mEventPercent = 60; mManualPercent = 5; mParkingNormalPercent = 15; mParkingEventPercent = 0; printf("frc partition: 20, 60, 5, 15\n"); } else if(access("/tmp/bmff_frc_20_20_5_55", F_OK) == 0) { mNormalPercent = 20; mEventPercent = 20; mManualPercent = 5; mParkingNormalPercent = 55; mParkingEventPercent = 0; printf("frc partition: 20, 20, 5, 55\n"); } else // 80_15_5_0 { mNormalPercent = 80; mEventPercent = 15; mManualPercent = 5; mParkingNormalPercent = 0; mParkingEventPercent = 0; printf("frc partition: 80, 15, 5, 0\n"); } #else int ret; ret = OpenDevice(); if(ret != 0) return; ret = GetBlocksFirst(); CloseDevice(); if(mBlocks > 100 * 1024 * 1024 * 2) // if bigger then 100GB { if(park) { mNormalPercent = 60; mParkingNormalPercent = 30; } else { mNormalPercent = 90; mParkingNormalPercent = 0; } mEventPercent = 8; mManualPercent = 2; mParkingEventPercent = 0; } else { if(park) { mNormalPercent = 55; mParkingNormalPercent = 30; } else { mNormalPercent = 85; mParkingNormalPercent = 0; } mEventPercent = 13; mManualPercent = 2; mParkingEventPercent = 0; } #endif } else if(park) { mNormalPercent = 60; mEventPercent = 15; mManualPercent = 5; mParkingNormalPercent = 18; mParkingEventPercent = 2; } else { mNormalPercent = 80; mEventPercent = 15; mManualPercent = 5; mParkingNormalPercent = 0; mParkingEventPercent = 0; } } int BmFF::Init2(const char *device, int frontHeight, int rearHeight, int frontFps, int parkFps) { int frontFileSize, rearFileSize; int frontParkFileSize, rearParkFileSize; int frontEventFileSize, rearEventFileSize; #if EVENT_FILE_SEC int event_sec = EVENT_FILE_SEC; #else int event_sec = 30; #endif #if (MODEL_CONFIG == FRC) int rearFps = 27; #elif (MODEL_CONFIG == MH3000) int rearFps = 24; #else int rearFps = 30; #endif frontFileSize = GetFileSize(frontHeight, frontFps); rearFileSize = GetFileSize(rearHeight, rearFps); if(parkFps > 0) { frontParkFileSize = GetFileSize(frontHeight, parkFps); if(mMstarPark) { #if (MODEL_CONFIG == UPK045 || MODEL_CONFIG == BV3000 || MODEL_CONFIG == BV600) rearParkFileSize = rearFileSize; #elif (MODEL_CONFIG == FRC) rearParkFileSize = rearFileSize; #elif (MODEL_CONFIG == MH6200E) rearParkFileSize = rearFileSize; #else rearParkFileSize = GetFileSize(rearHeight, parkFps); #endif frontParkFileSize = (frontParkFileSize > 0) ? GET_FILE_SIZE_BY_SEC(frontParkFileSize, event_sec) : 0; rearParkFileSize = (rearParkFileSize > 0) ? GET_FILE_SIZE_BY_SEC(rearParkFileSize, event_sec) : 0; } else rearParkFileSize = rearFileSize; } else { frontParkFileSize = 0; rearParkFileSize = 0; } if(mMstarPark) { frontEventFileSize = (frontFileSize > 0) ? GET_FILE_SIZE_BY_SEC(frontFileSize, event_sec) : 0; rearEventFileSize = (rearFileSize > 0) ? GET_FILE_SIZE_BY_SEC(rearFileSize, event_sec) : 0; } else { frontEventFileSize = frontFileSize; rearEventFileSize = rearFileSize; } mDeviceName = device; SetStoragePercent(parkFps > 0); UpdateInfoFirst(); if(!mNoPrintFlag) printf("================================================================\n"); if(!mNoPrintFlag) printf(" frontHeight = %d, rearHeight = %d\n", frontHeight, rearHeight); if(!mNoPrintFlag) printf(" frontFileSize = %dMb, rearFileSize = %dMb\n", frontFileSize / MiB, rearFileSize / MiB); if(!mNoPrintFlag) printf(" frontParkFileSize = %dMb, rearParkFileSize = %dMb\n", frontParkFileSize / MiB, rearParkFileSize / MiB); if(!mNoPrintFlag) printf(" frontEventFileSize = %dMb, rearEventFileSize = %dMb\n", frontEventFileSize / MiB, rearEventFileSize / MiB); if(!mNoPrintFlag) printf("================================================================\n"); return Init(device, frontFileSize, rearFileSize, frontEventFileSize, rearEventFileSize, frontParkFileSize, rearParkFileSize); } int BmFF::GetFileSize(int height, int fps) { int fileSize = -1; switch(height) { case 1920: switch(fps) { case 30: fileSize = SQ1920_30_FILE_SIZE; break; case 29: fileSize = SQ1920_30_FILE_SIZE; break; case 27: fileSize = SQ1920_27_FILE_SIZE; break; case 25: case 24: fileSize = SQ1920_25_FILE_SIZE; break; case 22: fileSize = SQ1920_22_FILE_SIZE; break; case 16: fileSize = SQ1920_16_FILE_SIZE; break; case 7: fileSize = SQ1920_07_FILE_SIZE; break; case 6: fileSize = SQ1920_06_FILE_SIZE; break; default: goto error; } break; case 1440: switch(fps) { case 30: fileSize = WQHD30_FILE_SIZE; break; case 29: fileSize = WQHD30_FILE_SIZE; break; case 27: fileSize = WQHD27_FILE_SIZE; break; case 25: case 24: fileSize = WQHD25_FILE_SIZE; break; case 22: fileSize = WQHD22_FILE_SIZE; break; case 16: fileSize = WQHD16_FILE_SIZE; break; case 7: fileSize = WQHD07_FILE_SIZE; break; case 6: fileSize = WQHD06_FILE_SIZE; break; default: goto error; } break; case 1296: switch(fps) { case 30: fileSize = SHD30_FILE_SIZE; break; case 29: fileSize = SHD30_FILE_SIZE; break; case 27: fileSize = SHD27_FILE_SIZE; break; case 25: case 24: fileSize = SHD25_FILE_SIZE; break; case 22: fileSize = SHD22_FILE_SIZE; break; case 16: fileSize = SHD16_FILE_SIZE; break; case 7: fileSize = SHD07_FILE_SIZE; break; case 6: fileSize = SHD06_FILE_SIZE; break; default: goto error; } break; case 1600: switch(fps) { case 30: fileSize = SQ1600_30_FILE_SIZE; break; case 29: fileSize = SQ1600_30_FILE_SIZE; break; case 27: fileSize = SQ1600_27_FILE_SIZE; break; case 25: case 24: fileSize = SQ1600_25_FILE_SIZE; break; case 22: fileSize = SQ1600_22_FILE_SIZE; break; case 16: fileSize = SQ1600_16_FILE_SIZE; break; case 7: fileSize = SQ1600_07_FILE_SIZE; break; case 6: fileSize = SQ1600_06_FILE_SIZE; break; default: goto error; } break; case 1080: switch(fps) { case 30: fileSize = FHD30_FILE_SIZE; break; case 29: fileSize = FHD30_FILE_SIZE; break; case 27: fileSize = FHD27_FILE_SIZE; break; case 25: case 24: fileSize = FHD25_FILE_SIZE; break; case 22: fileSize = FHD22_FILE_SIZE; break; case 16: fileSize = FHD16_FILE_SIZE; break; case 7: fileSize = FHD07_FILE_SIZE; break; case 6: fileSize = FHD06_FILE_SIZE; break; default: goto error; } break; case 720: switch(fps) { case 30: fileSize = HD30_FILE_SIZE; break; case 29: fileSize = HD30_FILE_SIZE; break; case 27: fileSize = HD27_FILE_SIZE; break; case 25: case 24: fileSize = HD25_FILE_SIZE; break; case 22: fileSize = HD22_FILE_SIZE; break; case 16: fileSize = HD16_FILE_SIZE; break; case 7: fileSize = HD07_FILE_SIZE; break; case 6: fileSize = HD06_FILE_SIZE; break; default: goto error; } break; case 0: fileSize = 0; break; default: goto error; } return fileSize; error: printf("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"); printf(" Error GetFileSize()..height=%d, fps=%d\n", height, fps); printf("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"); return -1; } int BmFF::MakeDisk(void) { mFormatFlag = true; UpdateInfo(); MakeMBR(); MakeFATBS(); WriteAll(); mFormatFlag = false; // usleep(1000 * 1000); // WriteAll(); // usleep(1000 * 1000); // VerifyDisk(); return 0; } int BmFF::InvalidateDisk(void) { UpdateInfo(); MakeMBR(); MakeFATBS(); memset(mWrMasterBootRecord, 0xff, sizeof(mWrMasterBootRecord)); WriteAll(); return 0; } bool BmFF::VerifyDisk(void) { int ret; ret = OpenDevice(false); if(ret != 0) return false; ret = GetBlocks(); if(ret != 0) goto error; AllocMem(); if(mEmmc == false) { ret = GetMBR(); if(ret != 0) goto error_mem; } ret = GetFATBS(); if(ret != 0) goto error_mem; MakeMemDirectories(); if(mEmmc == false) { if(!VerifyMBR()) goto error_mem; } if(!VerifyFATBS()) goto error_mem; if(!VerifyFAT()) goto error_mem; if(!VerifyDirectories()) { #if BMFF_RECOVER mRecoverFlag = true; RecoverDirectories(); if(!VerifyDirectories()) goto error_mem; else mRecovered = true; #else goto error_mem; #endif } CloseDevice(); FreeMem(); return true; error_mem: FreeMem(); error: CloseDevice(); return false; } void BmFF::CalcFat(void) { #ifdef WIN32 unsigned __int64 fatSectors = mBlocks - FIRST_SECTOR; unsigned __int64 dataClusters1 = (((fatSectors - FAT_RESERVED_SECTORS) * SECTORS_PER_CLUSTER) - 4) / ((SECTORS_PER_CLUSTER * SECTORS_PER_CLUSTER) + 2); unsigned __int64 sectorsPerFat = ((dataClusters1 + 2) * 4) / SECTOR_SIZE; unsigned __int64 logFilesClusters = (LOG0_FILE_SIZE / CLUSTER_SIZE) + (LOG1_FILE_SIZE / CLUSTER_SIZE) + (LOG2_FILE_SIZE / CLUSTER_SIZE); if((dataClusters1 + 2) * 4 % SECTOR_SIZE != 0) ++sectorsPerFat; if(sectorsPerFat % SPF_UNIT != 0) { sectorsPerFat /= SPF_UNIT; sectorsPerFat *= SPF_UNIT; sectorsPerFat += SPF_UNIT; } unsigned long dataClusters2 = ((fatSectors - FAT_RESERVED_SECTORS - (sectorsPerFat * 2)) / SECTORS_PER_CLUSTER); unsigned long dataSectors = dataClusters2 * SECTORS_PER_CLUSTER; mPtTotalSectors = (unsigned long)(dataSectors + FAT_RESERVED_SECTORS + (sectorsPerFat * 2)); mSectorsPerFat = sectorsPerFat; #else unsigned long long fatSectors = mBlocks - FIRST_SECTOR; unsigned long long dataClusters1 = ((fatSectors - FAT_RESERVED_SECTORS) * SECTORS_PER_CLUSTER - 4) / (SECTORS_PER_CLUSTER * SECTORS_PER_CLUSTER + 2); unsigned long long sectorsPerFat = (dataClusters1 + 2) * 4 / SECTOR_SIZE; int logFilesClusters = (LOG0_FILE_SIZE / CLUSTER_SIZE) + (LOG1_FILE_SIZE / CLUSTER_SIZE) + (LOG2_FILE_SIZE / CLUSTER_SIZE); if((dataClusters1 + 2) * 4 % SECTOR_SIZE != 0) ++sectorsPerFat; if(sectorsPerFat % SPF_UNIT != 0) { sectorsPerFat /= SPF_UNIT; sectorsPerFat *= SPF_UNIT; sectorsPerFat += SPF_UNIT; } unsigned int dataClusters2 = (fatSectors - FAT_RESERVED_SECTORS - sectorsPerFat * 2) / SECTORS_PER_CLUSTER; unsigned int dataSectors = dataClusters2 * SECTORS_PER_CLUSTER; mPtTotalSectors = dataSectors + FAT_RESERVED_SECTORS + sectorsPerFat * 2; mSectorsPerFat = sectorsPerFat; #endif mDataTotalClusters = dataClusters2; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // unsigned int dataSectors = mPtTotalSectors - FAT_RESERVED_SECTORS - mSectorsPerFat * 2; // unsigned int dataClusters = dataSectors / SECTORS_PER_CLUSTER; unsigned int directoryReservedClusters = 4 * MiB / CLUSTER_SIZE; unsigned int logDirectoryFileClusters = (LOG0_FILE_SIZE + LOG1_FILE_SIZE + LOG2_FILE_SIZE) * 2 / CLUSTER_SIZE + 1; unsigned int availableDataClusters = dataClusters2 - directoryReservedClusters - logDirectoryFileClusters - 1 - FREE_SPACE_CLUSTERS; unsigned int totalEventFileClusters = 1LL * availableDataClusters * mEventPercent / 100; unsigned int totalManualFileClusters = 1LL * availableDataClusters * mManualPercent / 100; unsigned int totalParkingNormalFileClusters = 1LL * availableDataClusters * mParkingNormalPercent / 100; unsigned int totalParkingEventFileClusters = 1LL * availableDataClusters * mParkingEventPercent / 100; unsigned int totalNormalFileClusters; mEventFiles = (totalEventFileClusters / (mEventFrontFileClusters + mEventRearFileClusters)); if(mEventRearFileClusters > 0) mEventFiles *= 2; mEventRecords = (mEventRearFileClusters > 0) ? mEventFiles / 2 : mEventFiles; totalEventFileClusters = (mEventFrontFileClusters + mEventRearFileClusters) * mEventRecords; mManualFiles = (totalManualFileClusters / (mManualFrontFileClusters + mManualRearFileClusters)); if(mManualRearFileClusters > 0) mManualFiles *= 2; mManualRecords = (mManualRearFileClusters > 0) ? mManualFiles / 2 : mManualFiles; totalManualFileClusters = (mManualFrontFileClusters + mManualRearFileClusters) * mManualRecords; if(mParkingNormalPercent > 0) { mParkingNormalFiles = (totalParkingNormalFileClusters / (mParkingFrontFileClusters + mParkingRearFileClusters)); if(mParkingRearFileClusters > 0) mParkingNormalFiles *= 2; mParkingNormalRecords = (mParkingRearFileClusters > 0) ? mParkingNormalFiles / 2 : mParkingNormalFiles; totalParkingNormalFileClusters = (mParkingFrontFileClusters + mParkingRearFileClusters) * mParkingNormalRecords; mParkingEventFiles = (totalParkingEventFileClusters / (mParkingFrontFileClusters + mParkingRearFileClusters)); if(mParkingRearFileClusters > 0) mParkingEventFiles *= 2; mParkingEventRecords = (mParkingRearFileClusters > 0) ? mParkingEventFiles / 2 : mParkingEventFiles; totalParkingEventFileClusters = (mParkingFrontFileClusters + mParkingRearFileClusters) * mParkingEventRecords; } else { mParkingNormalFiles = 0; mParkingNormalRecords = 0; totalParkingNormalFileClusters = 0; mParkingEventFiles = 0; mParkingEventRecords = 0; totalParkingEventFileClusters = 0; } totalNormalFileClusters = availableDataClusters - (totalEventFileClusters + totalManualFileClusters + totalParkingNormalFileClusters + totalParkingEventFileClusters); mNormalFiles = (totalNormalFileClusters / (mNormalFrontFileClusters + mNormalRearFileClusters)); if(mNormalRearFileClusters > 0) mNormalFiles *= 2; mNormalRecords = (mNormalRearFileClusters > 0) ? mNormalFiles / 2 : mNormalFiles; totalNormalFileClusters = (mNormalFrontFileClusters + mNormalRearFileClusters) * mNormalRecords; mNormalDirectoryClusters = (mNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mNormalDirectoryClusters; mEventDirectoryClusters = (mEventFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mEventFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mEventDirectoryClusters; mManualDirectoryClusters = (mManualFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mManualFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mManualDirectoryClusters; if(mParkingNormalPercent > 0) { if(mMstarPark) { mParkingDirectoryClusters = 0; mParkingNormalDirectoryClusters = (mParkingNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mParkingNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mParkingNormalDirectoryClusters; mParkingEventDirectoryClusters = 0; } else { mParkingDirectoryClusters = 1; mParkingNormalDirectoryClusters = (mParkingNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mParkingNormalFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mParkingNormalDirectoryClusters; mParkingEventDirectoryClusters = (mParkingEventFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) / CLUSTER_SIZE; if((mParkingEventFiles * 0x60 + 0x40 + DIRECTORY_OVERHEAD) % CLUSTER_SIZE != 0) ++mParkingEventDirectoryClusters; } } else { mParkingDirectoryClusters = 0; mParkingNormalDirectoryClusters = 0; mParkingEventDirectoryClusters = 0; } mLogDirectoryStartCluster = mRootDirectoryStartCluster + mRootDirectoryClusters; mLogFilesStartCluster = mLogDirectoryStartCluster + mLogDirectoryClusters; mParkingDirectoryStartCluster = mLogFilesStartCluster + logFilesClusters; mNormalDirectoryStartCluster = mParkingDirectoryStartCluster + mParkingDirectoryClusters; mEventDirectoryStartCluster = mNormalDirectoryStartCluster + mNormalDirectoryClusters; mManualDirectoryStartCluster = mEventDirectoryStartCluster + mEventDirectoryClusters; mParkingNormalDirectoryStartCluster = mManualDirectoryStartCluster + mManualDirectoryClusters; mParkingEventDirectoryStartCluster = mParkingNormalDirectoryStartCluster + mParkingNormalDirectoryClusters; mRootDirectoryStartSector = FIRST_SECTOR + FAT_RESERVED_SECTORS + mSectorsPerFat * 2; mLogDirectoryStartSector = mRootDirectoryStartSector + (mRootDirectoryClusters) * SECTORS_PER_CLUSTER; mLogFilesStartSector = mLogDirectoryStartSector + (mLogDirectoryClusters) * SECTORS_PER_CLUSTER; mParkingDirectoryStartSector = mLogFilesStartSector + (logFilesClusters) * SECTORS_PER_CLUSTER; mNormalDirectoryStartSector = mParkingDirectoryStartSector + (mParkingDirectoryClusters) * SECTORS_PER_CLUSTER; mEventDirectoryStartSector = mNormalDirectoryStartSector + (mNormalDirectoryClusters) * SECTORS_PER_CLUSTER; mManualDirectoryStartSector = mEventDirectoryStartSector + (mEventDirectoryClusters) * SECTORS_PER_CLUSTER; mParkingNormalDirectoryStartSector = mManualDirectoryStartSector + (mManualDirectoryClusters) * SECTORS_PER_CLUSTER; mParkingEventDirectoryStartSector = mParkingNormalDirectoryStartSector + (mParkingNormalDirectoryClusters) * SECTORS_PER_CLUSTER; if(!mNoPrintFlag) printf("DataSectors = %ld, DataClusters = %ld, SectorsPerFat = %d\n", dataSectors, dataClusters2, mSectorsPerFat); if(!mNoPrintFlag) printf("AvailableDataClusters = %d, ScrapsClusters = %d\n", availableDataClusters, availableDataClusters - (totalNormalFileClusters + totalEventFileClusters + totalManualFileClusters + totalParkingNormalFileClusters + totalParkingEventFileClusters)); if(!mNoPrintFlag) printf("NormalPercent = %d%%, EventPercent = %d%%, ManualPercent = %d%%, ParkingNormalPercent = %d%%, ParkingEventPercent = %d%%\n", mNormalPercent, mEventPercent, mManualPercent, mParkingNormalPercent, mParkingEventPercent); if(!mNoPrintFlag) printf("TotalNormalFileClusters = %d, TotalEventFileClusters = %d, TotalManualFileClusters = %d, TotalParkingNormalFileClusters = %d, TotalParkingEventFileClusters = %d\n", totalNormalFileClusters, totalEventFileClusters, totalManualFileClusters, totalParkingNormalFileClusters, totalParkingEventFileClusters); printf("NormalFiles = %d, EventFiles = %d, ManualFiles = %d, ParkingNormalFiles = %d, ParkingEventFiles = %d\n", mNormalFiles, mEventFiles, mManualFiles, mParkingNormalFiles, mParkingEventFiles); printf("NormalRecords = %d, EventRecords = %d, ManualRecords = %d, ParkingNormalRecords = %d, ParkingEventRecords = %d\n", mNormalRecords, mEventRecords, mManualRecords, mParkingNormalRecords, mParkingEventRecords); if(!mNoPrintFlag) printf("NormalDirectoryClusters = %d, EventDirectoryClusters = %d\n", mNormalDirectoryClusters, mEventDirectoryClusters); if(!mNoPrintFlag) printf("RootDirectoryStartCluster = %d, clusters = %d\n", mRootDirectoryStartCluster, mRootDirectoryClusters); if(!mNoPrintFlag) printf("LogDirectoryStartCluster = %d, clusters = %d\n", mLogDirectoryStartCluster, mLogDirectoryClusters); if(!mNoPrintFlag) printf("LogFilesStartCluster = %d, clusters = %d\n", mLogFilesStartCluster, logFilesClusters); if(!mNoPrintFlag) printf("ParkingDirectoryStartCluster = %d, clusters = %d\n", mParkingDirectoryStartCluster, mParkingDirectoryClusters); if(!mNoPrintFlag) printf("NormalDirectoryStartCluster = %d, clusters = %d\n", mNormalDirectoryStartCluster, mNormalDirectoryClusters); if(!mNoPrintFlag) printf("EventDirectoryStartCluster = %d, clusters = %d\n", mEventDirectoryStartCluster, mEventDirectoryClusters); if(!mNoPrintFlag) printf("ManualDirectoryStartCluster = %d, clusters = %d\n", mManualDirectoryStartCluster, mManualDirectoryClusters); if(!mNoPrintFlag) printf("ParkingNormalDirectoryStartCluster = %d, clusters = %d\n", mParkingNormalDirectoryStartCluster, mParkingNormalDirectoryClusters); if(!mNoPrintFlag) printf("ParkingEventDirectoryStartCluster = %d, clusters = %d\n", mParkingEventDirectoryStartCluster, mParkingEventDirectoryClusters); if(!mNoPrintFlag) printf("\n"); if(!mNoPrintFlag) printf("RootDirectoryStartSector = %d\n", mRootDirectoryStartSector); if(!mNoPrintFlag) printf("LogDirectoryStartSector = %d\n", mLogDirectoryStartSector); if(!mNoPrintFlag) printf("LogFilesStartSector = %d\n", mLogFilesStartSector); if(!mNoPrintFlag) printf("ParkingDirectoryStartSector = %d\n", mParkingDirectoryStartSector); if(!mNoPrintFlag) printf("NormalDirectoryStartSector = %d\n", mNormalDirectoryStartSector); if(!mNoPrintFlag) printf("EventDirectoryStartSector = %d\n", mEventDirectoryStartSector); if(!mNoPrintFlag) printf("ManualDirectoryStartSector = %d\n", mManualDirectoryStartSector); if(!mNoPrintFlag) printf("ParkingNormalDirectoryStartSector = %d\n", mParkingNormalDirectoryStartSector); if(!mNoPrintFlag) printf("ParkingEventDirectoryStartSector = %d\n", mParkingEventDirectoryStartSector); } void BmFF::AllocMem(void) { mMemFat = (unsigned int *)malloc(mSectorsPerFat * SECTOR_SIZE); memset(mMemFat, 0, mSectorsPerFat * SECTOR_SIZE); mMemFat[0] = 0x0ffffff8; mMemFat[1] = 0xffffffff; mCurrentFatOffset = mRootDirectoryStartCluster; mMemRootDirectory = (char *)malloc(mRootDirectoryClusters * CLUSTER_SIZE); memset(mMemRootDirectory, 0, mRootDirectoryClusters * CLUSTER_SIZE); mMemLogDirectory = (char *)malloc(mLogDirectoryClusters * CLUSTER_SIZE); memset(mMemLogDirectory, 0, mLogDirectoryClusters * CLUSTER_SIZE); mMemNormalDirectory = (char *)malloc(mNormalDirectoryClusters * CLUSTER_SIZE); memset(mMemNormalDirectory, 0, mNormalDirectoryClusters * CLUSTER_SIZE); mMemEventDirectory = (char *)malloc(mEventDirectoryClusters * CLUSTER_SIZE); memset(mMemEventDirectory, 0, mEventDirectoryClusters * CLUSTER_SIZE); mMemManualDirectory = (char *)malloc(mManualDirectoryClusters * CLUSTER_SIZE); memset(mMemManualDirectory, 0, mManualDirectoryClusters * CLUSTER_SIZE); if(mParkingNormalPercent > 0) { mMemParkingDirectory = (char *)malloc(mParkingDirectoryClusters * CLUSTER_SIZE); memset(mMemParkingDirectory, 0, mParkingDirectoryClusters * CLUSTER_SIZE); mMemParkingNormalDirectory = (char *)malloc(mParkingNormalDirectoryClusters * CLUSTER_SIZE); memset(mMemParkingNormalDirectory, 0, mParkingNormalDirectoryClusters * CLUSTER_SIZE); mMemParkingEventDirectory = (char *)malloc(mParkingEventDirectoryClusters * CLUSTER_SIZE); memset(mMemParkingEventDirectory, 0, mParkingEventDirectoryClusters * CLUSTER_SIZE); } else { mMemParkingDirectory = NULL; mMemParkingNormalDirectory = NULL; mMemParkingEventDirectory = NULL; } } void BmFF::FreeMem(void) { free(mMemRootDirectory); free(mMemLogDirectory); free(mMemNormalDirectory); free(mMemEventDirectory); free(mMemManualDirectory); if(mParkingNormalPercent > 0) { free(mMemParkingDirectory); free(mMemParkingNormalDirectory); free(mMemParkingEventDirectory); } } int BmFF::OpenDevice(bool bWrite) { #ifdef _WIN32 // 포맷되어 있지 않은 경우 사용할 수 없음 /* DWORD lpSectorsPerCluster = 0; DWORD lpBytesPerSector = 0; DWORD lpNumberOfFreeClusters = 0; DWORD lpTotalNumberOfClusters = 0; QString disk = "F:\\"; ::GetDiskFreeSpace(reinterpret_cast(disk.utf16()),&lpSectorsPerCluster,&lpBytesPerSector,&lpNumberOfFreeClusters,&lpTotalNumberOfClusters); mBlocks = lpSectorsPerCluster * lpTotalNumberOfClusters; */ //qInfo() << "lpSectorsPerCluster:" << lpSectorsPerCluster << "lpTotalNumberOfClusters:" << lpTotalNumberOfClusters << "lpBytesPerSector:" << lpBytesPerSector << "lpNumberOfFreeClusters:" << lpNumberOfFreeClusters << __FUNCTION__; // lpSectorsPerCluster: 64 lpNumberOfFreeClusters: 485606 BmFF::OpenDevice if(mFd != NULL) { CloseDevice(); } // FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH if(bWrite) { mFd = ::CreateFile( reinterpret_cast(mDeviceName.utf16()), GENERIC_WRITE,// | GENERIC_WRITE, 0,// | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); } else { mFd = ::CreateFile( reinterpret_cast(mDeviceName.utf16()), GENERIC_READ,// | GENERIC_WRITE, FILE_SHARE_READ,// | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); } if(mFd == INVALID_HANDLE_VALUE) { return -1; } if(bWrite) { //::ZeroMemory(&mOV, sizeof(OVERLAPPED)); // dismount output if (!::DeviceIoControl(mFd, FSCTL_DISMOUNT_VOLUME,NULL, 0, NULL, 0, NULL, NULL)) { return -1; } // lock output if (!::DeviceIoControl(mFd, FSCTL_LOCK_VOLUME,NULL, 0, NULL, 0, NULL, NULL)) { return -1; } } #else // _WIN32 mFd = open64(mDeviceName.c_str(), O_RDWR); if(mFd < 0) { printf("OpenDevice error...%s\n", mDeviceName.c_str()); return -1; } if(!mNoPrintFlag) printf("OpenDevice OK...%s\n", mDeviceName.c_str()); #endif // _WIN32 return 0; } void BmFF::CloseDevice(void) { #if _WIN32 if(mFd != INVALID_HANDLE_VALUE && mFd != NULL) { ::DeviceIoControl(mFd, FSCTL_UNLOCK_VOLUME,NULL, 0, NULL, 0, NULL, NULL); ::CloseHandle(mFd); } mFd = NULL; #else // WIN32 fsync(mFd); close(mFd); #endif // WIN32 } int BmFF::GetBlocks(void) { // 7,743,300 ioctl(mFd, BLKGETSIZE, &mBlocks); printf("mblocks = %d(%dMiB)\n", mBlocks, (int)(1LL * mBlocks * SECTOR_SIZE / MiB)); if((mBlocks < MIN_SECTORS) || (mBlocks > MAX_SECTORS)) { return -1; } CalcFat(); return 0; } int BmFF::GetBlocksFirst(void) { ioctl(mFd, BLKGETSIZE, &mBlocks); printf("mblocks = %d(%dMiB)\n", mBlocks, (int)(1LL * mBlocks * SECTOR_SIZE / MiB)); if((mBlocks < MIN_SECTORS) || (mBlocks > MAX_SECTORS)) { return -1; } return 0; } int BmFF::GetMBR(void) { int readed = read(mFd, mRdMasterBootRecord, SECTOR_SIZE); if(readed != SECTOR_SIZE) { printf("read error : readed=%d\n", readed); return -1; } //HexDump(mRdMasterBootRecord, SECTOR_SIZE); if(ChkMBR() != 0) { printf("ChkMBR() error \n"); return -1; } if(ChkPT() != 0) { printf("ChkPT() error \n"); return -1; } // CalcFat(); if(!mNoPrintFlag) printf("serial number = 0x%08x\n", MBR_DISK_SERIAL_NUMBER(mRdMasterBootRecord)); if(!mNoPrintFlag) printf("FAT total sectors = %ld\n", mPtTotalSectors); if(!mNoPrintFlag) printf("sectors per FAT = %d\n", mSectorsPerFat); return 0; } int BmFF::GetFATBS(void) { loff_t offset = lseek64(mFd, ((loff_t)FIRST_SECTOR) * ((loff_t)SECTOR_SIZE), SEEK_SET); if(offset < 0) { printf("GetFATBS()...Error: lseek()\n"); return -1; } int readed = read(mFd, mRdFat32BootSector, SECTOR_SIZE); if(readed != SECTOR_SIZE) { printf("GetFATBS()...Error: read(). readed=%d, expected=%d\n", readed, SECTOR_SIZE); return -1; } return 0; } int BmFF::GetFAT(void) { return 0; } int BmFF::UpdateInfo(void) { int ret; ret = OpenDevice(false); if(ret != 0) return -1; ret = GetBlocks(); if(mEmmc == false) { if(ret == 0) ret = GetMBR(); if(ret == 0) ret = GetFAT(); } CloseDevice(); return ret; } int BmFF::UpdateInfoFirst(void) { int ret; ret = OpenDevice(false); if(ret != 0) return -1; ret = GetBlocksFirst(); if(mEmmc == false) { if(ret == 0) ret = GetMBR(); if(ret == 0) ret = GetFAT(); } CloseDevice(); return ret; } void BmFF::HexDump(char *buff, int size) { for(int i = 0; i < size; ++i) { if(i % 16 == 0) printf("\n0x%08x :", i); else if(i % 4 == 0) printf(","); printf(" %02x", buff[i]); } printf("\n"); fflush(stdout); } int BmFF::ChkMBR(void) { if(MBR_SIGNATURE(mRdMasterBootRecord) != SIGNATURE) { printf("ChkMBR() error... SIGNATURE = %04x\n", (int)MBR_SIGNATURE(mRdMasterBootRecord)); return -1; } mSerialNumber = MBR_DISK_SERIAL_NUMBER(mRdMasterBootRecord); return 0; } int BmFF::ChkPT(void) { // + 0x1be(446) + (0x10(16) * index) // ((char*)(mbr) + 0x1be + (0x10 * (index))) if(PT_ACTIVE_PARTITION_FLAG(mRdMasterBootRecord, 0) != ACTIVE_PARTITION_FLAG) { printf("ChkPT() error... ACTIVE_PARTITION_FLAG = 0x%02x\n", (int)PT_ACTIVE_PARTITION_FLAG(mRdMasterBootRecord, 0)); return -1; } if(PT_FILE_SYSTEM_ID(mRdMasterBootRecord, 0) != FILE_SYSTEM_ID) { printf("ChkPT() error... FILE_SYSTEM_ID = 0x%02x\n", (int)PT_FILE_SYSTEM_ID(mRdMasterBootRecord, 0)); return -1; } if(PT_FIRST_SECTOR(mRdMasterBootRecord, 0) != FIRST_SECTOR) { printf("ChkPT() error... FIRST_SECTOR = %d\n", (int)PT_FIRST_SECTOR(mRdMasterBootRecord, 0)); return -1; } return 0; } char BmFF::GetFileSystem() { return (char)PT_FILE_SYSTEM_ID(mRdMasterBootRecord, 0); } void BmFF::MakeMBR(void) { memset(mWrMasterBootRecord, 0, sizeof(mWrMasterBootRecord)); // 1B8 -> OK MBR_DISK_SERIAL_NUMBER(mWrMasterBootRecord) = (mSerialNumber == BM_FACTORY_SERIAL_NUMBER || mMakeFactoryAging) ? BM_FACTORY_SERIAL_NUMBER : BM_SERIAL_NUMBER; // 1BE + 4 = 1C2:C -> OK PT_FILE_SYSTEM_ID(mWrMasterBootRecord, 0) = FILE_SYSTEM_ID; // 1BE + 8 = 1C6: 0x800=2048 -> OK PT_FIRST_SECTOR(mWrMasterBootRecord, 0) = FIRST_SECTOR; // PT_TOTAL_SECTORS(mWrMasterBootRecord, 0) = (unsigned int)mBlocks; // 1BE + 12 = 1CA:7,742,464 ??? 7,741,248 PT_TOTAL_SECTORS(mWrMasterBootRecord, 0) = (unsigned int)mPtTotalSectors; // jykang 20200609 // 1FE = AA55 MBR_SIGNATURE(mWrMasterBootRecord) = SIGNATURE; } void BmFF::MakeFATBS(void) { char fatbs[512] = { // 0xEB, 0x58, 0x90, 0x64, 0x65, 0x64, 0x69, 0x61, 0x68, 0x69, 0x6C, 0x00, 0x02, 0x80, 0x80, 0x00, 0xEB, 0x58, 0x90, 0x6D, 0x6B, 0x64, 0x6F, 0x73, 0x66, 0x73, 0x00, 0x00, 0x02, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x3B, 0x80, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xEE, 0xEE, 0xEE, 0xEE, 0x44, 0x56, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0x0E, 0x1F, 0xBE, 0x77, 0x7C, 0xAC, 0x22, 0xC0, 0x74, 0x0B, 0x56, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0x5E, 0xEB, 0xF0, 0x32, 0xE4, 0xCD, 0x16, 0xCD, 0x19, 0xEB, 0xFE, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x2E, 0x20, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6E, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x66, 0x6C, 0x6F, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6E, 0x64, 0x0D, 0x0A, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x2E, 0x2E, 0x2E, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA }; fatbs[13] = SECTORS_PER_CLUSTER; memcpy(mWrFat32BootSector, fatbs, sizeof(mWrFat32BootSector)); BS_TOTAL_SECTORS(mWrFat32BootSector) = (unsigned int)mPtTotalSectors; BS_SECTORS_PER_FAT(mWrFat32BootSector) = (unsigned int)mSectorsPerFat; } void BmFF::MakeSIS(void) { memset(mWrSystemInformationSector, 0, sizeof(mWrSystemInformationSector)); SIS_SIGNATURE_FIRST(mWrSystemInformationSector) = 0x41615252; SIS_SIGNATURE_MIDDLE(mWrSystemInformationSector) = 0x61417272; SIS_LAST_FREE_CLUSTER(mWrSystemInformationSector) = mDataTotalClusters - mCurrentFatOffset + mRootDirectoryStartCluster; SIS_LAST_ALLOCATED_CLUSTER(mWrSystemInformationSector) = 0xffffffff; SIS_SIGNATURE_LAST(mWrSystemInformationSector) = 0xaa550000; } int BmFF::WriteAll(void) { ssize_t written; loff_t offset; if(OpenDevice(true) != 0) { printf("OPEN(WRITE) FAILED"); return -1; } // 강제로 다시 이동??? //lseek64(mFd,0,SEEK_SET); if(mEmmc == false) { written = write(mFd, mWrMasterBootRecord, sizeof(mWrMasterBootRecord)); // ,&mOV printf("BS SIZE: %d 1476\n",sizeof(mWrFat32BootSector)); if(written != sizeof(mWrMasterBootRecord)) { printf("MBR write error...\n"); return -1; } if(!mNoPrintFlag) printf("MBR write OK...\n"); usleep(1); ZeroBlocks(1, FIRST_SECTOR - 1); ZeroBlocks(mBlocks - 128, 128); usleep(1); } printf("BS SIZE: %d 1489\n",sizeof(mWrFat32BootSector)); // 2048 offset = lseek64(mFd, ((loff_t)FIRST_SECTOR) * SECTOR_SIZE, SEEK_SET); if(offset != (off_t)FIRST_SECTOR * SECTOR_SIZE) { printf("lseek error...offset=%lld\n", ((off_t)FIRST_SECTOR) * SECTOR_SIZE); goto error; } //printf("BS SIZE: %d %d 1498\n",sizeof(mWrFat32BootSector),::SetFilePointer(mFd,0,NULL,FILE_CURRENT)); written = write(mFd, mWrFat32BootSector, sizeof(mWrFat32BootSector));// ,&mOV if(written != sizeof(mWrFat32BootSector)) { printf("FATBS1 write error %d != %d...\n",written,SECTOR_SIZE); goto error; } usleep(1); // written = write(mFd, mWrSystemInformationSector, sizeof(mWrSystemInformationSector)); // if(written != sizeof(mWrSystemInformationSector)) // { // printf("SIS write error...\n"); // goto error; // } offset = lseek64(mFd, (off_t)FIRST_SECTOR * SECTOR_SIZE + (loff_t)FAT_BOOT_SECTOR_COPY_POSITION * SECTOR_SIZE, SEEK_SET); if(offset != (loff_t)FIRST_SECTOR * SECTOR_SIZE + (loff_t)FAT_BOOT_SECTOR_COPY_POSITION * SECTOR_SIZE) { printf("lseek error...offset=%lld\n", (loff_t)FIRST_SECTOR * SECTOR_SIZE + (loff_t)FAT_BOOT_SECTOR_COPY_POSITION * SECTOR_SIZE); goto error; } written = write(mFd, mWrFat32BootSector, sizeof(mWrFat32BootSector)); // ,&mOV if(written != sizeof(mWrFat32BootSector)) { printf("FATBS2 write error...\n"); goto error; } usleep(1); WriteDirectories(); MakeSIS(); offset = lseek64(mFd, (loff_t)(FIRST_SECTOR + 1) * SECTOR_SIZE, SEEK_SET); if(offset != (loff_t)(FIRST_SECTOR + 1) * SECTOR_SIZE) { printf("lseek error...offset=%lld\n", (loff_t)(FIRST_SECTOR + 1) * SECTOR_SIZE); goto error; } written = write(mFd, mWrSystemInformationSector, sizeof(mWrSystemInformationSector)); // ,&mOV if(written != sizeof(mWrSystemInformationSector)) { printf("SIS write error...\n"); goto error; } usleep(1); printf("Free Clusters = %d\n", SIS_LAST_FREE_CLUSTER(mWrSystemInformationSector)); CloseDevice(); ForceFlush(); printf("Write OK\n"); return 0; error: CloseDevice(); printf("Write FAIL\n"); return -1; } void BmFF::MakeMemDirectories(void) { MakeRootDirectory(); if(!mMstarPark) if(mParkingNormalPercent > 0) MakeParkingDirectory(); #if (MODEL_CONFIG == BV3000) MakeRecordDirectory(mMemNormalDirectory, mNormalDirectoryStartCluster, ".NORM90925-%06dW.TMP", "N%06dWTMP", ".NORM90925-%06dI.TMP", "N%06dITMP", mNormalRecords, mNormalFrontFileClusters, mNormalRearFileClusters, 0); MakeRecordDirectory(mMemEventDirectory, mEventDirectoryStartCluster, ".EVEN90925-%06dW.TMP", "E%06dWTMP", ".EVEN90925-%06dI.TMP", "E%06dITMP", mEventRecords, mEventFrontFileClusters, mEventRearFileClusters, 0); MakeRecordDirectory(mMemManualDirectory, mManualDirectoryStartCluster, ".MANU90925-%06dW.TMP", "M%06dWTMP", ".MANU90925-%06dI.TMP", "M%06dITMP", mManualRecords, mManualFrontFileClusters, mManualRearFileClusters, 0); if(mParkingNormalPercent > 0) { if(mMstarPark) { MakeRecordDirectory(mMemParkingNormalDirectory, mParkingNormalDirectoryStartCluster, ".PARK90925-%06dW.TMP", "P%06dWTMP", ".PARK90925-%06dI.TMP", "P%06dITMP", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters, 0); } else { MakeRecordDirectory(mMemParkingNormalDirectory, mParkingNormalDirectoryStartCluster, ".PNOR90925-%06dW.TMP", "P%06dWTMP", ".PNOR90925-%06dI.TMP", "P%06dITMP", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters, mParkingDirectoryStartCluster); MakeRecordDirectory(mMemParkingEventDirectory, mParkingEventDirectoryStartCluster, ".PEVE90925-%06dW.TMP", "P%06dWTMP", ".PEVE90925-%06dI.TMP", "P%06dITMP", mParkingEventRecords, mParkingFrontFileClusters, mParkingRearFileClusters, mParkingDirectoryStartCluster); } } #else MakeRecordDirectory(mMemNormalDirectory, mNormalDirectoryStartCluster, ".NORM90925-%06dW.TMP", "N%06dWTMP", ".NORM90925-%06dR.TMP", "N%06dRTMP", mNormalRecords, mNormalFrontFileClusters, mNormalRearFileClusters, 0); MakeRecordDirectory(mMemEventDirectory, mEventDirectoryStartCluster, ".EVEN90925-%06dW.TMP", "E%06dWTMP", ".EVEN90925-%06dR.TMP", "E%06dRTMP", mEventRecords, mEventFrontFileClusters, mEventRearFileClusters, 0); if(mManualPercent > 0) { MakeRecordDirectory(mMemManualDirectory, mManualDirectoryStartCluster, ".MANU90925-%06dW.TMP", "M%06dWTMP", ".MANU90925-%06dR.TMP", "M%06dRTMP", mManualRecords, mManualFrontFileClusters, mManualRearFileClusters, 0); } if(mParkingNormalPercent > 0) { if(mMstarPark) { MakeRecordDirectory(mMemParkingNormalDirectory, mParkingNormalDirectoryStartCluster, ".PARK90925-%06dW.TMP", "P%06dWTMP", ".PARK90925-%06dR.TMP", "P%06dRTMP", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters, 0); } else { MakeRecordDirectory(mMemParkingNormalDirectory, mParkingNormalDirectoryStartCluster, ".PNOR90925-%06dW.TMP", "P%06dWTMP", ".PNOR90925-%06dR.TMP", "P%06dRTMP", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters, mParkingDirectoryStartCluster); MakeRecordDirectory(mMemParkingEventDirectory, mParkingEventDirectoryStartCluster, ".PEVE90925-%06dW.TMP", "P%06dWTMP", ".PEVE90925-%06dR.TMP", "P%06dRTMP", mParkingEventRecords, mParkingFrontFileClusters, mParkingRearFileClusters, mParkingDirectoryStartCluster); } } #endif } int BmFF::WriteDirectories(void) { int ret; off_t fatStartSector = (off_t)(FIRST_SECTOR + FAT_RESERVED_SECTORS); AllocMem(); MakeMemDirectories(); if(!mRecoverFlag) ret = WriteSectors(mMemRootDirectory, mRootDirectoryStartSector, mRootDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemLogDirectory, mLogDirectoryStartSector, mLogDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) if(!mMstarPark) if(mParkingNormalPercent > 0) ret = WriteSectors(mMemParkingDirectory, mParkingDirectoryStartSector, mParkingDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemNormalDirectory, mNormalDirectoryStartSector, mNormalDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemEventDirectory, mEventDirectoryStartSector, mEventDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemManualDirectory, mManualDirectoryStartSector, mManualDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) { if(mParkingNormalPercent > 0) { if(mMstarPark) { ret = WriteSectors(mMemParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); } else { ret = WriteSectors(mMemParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); ret = WriteSectors(mMemParkingEventDirectory, mParkingEventDirectoryStartSector, mParkingEventDirectoryClusters * SECTORS_PER_CLUSTER); } } } if(ret == 0) ret = WriteSectors((char*)mMemFat, fatStartSector, mSectorsPerFat); if(ret == 0) ret = WriteSectors((char*)mMemFat, fatStartSector + mSectorsPerFat, mSectorsPerFat); FreeMem(); return ret; } void BmFF::MakeRootDirectory(void) { int rootDirectorySize = mRootDirectoryClusters * CLUSTER_SIZE; char fileContext[] = { 0x4C, 0x4F, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x64, 0x40, 0x13, 0x39, 0x4F, 0x39, 0x4F, 0x00, 0x00, 0x40, 0x13, 0x39, 0x4F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }; int offsetByParking = (!mMstarPark && mParkingNormalPercent > 0) ? 0x20 : 0; AddFatElement(mMemFat, mRootDirectoryClusters); // mLogDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, LOG_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mLogDirectoryStartCluster); memcpy(mMemRootDirectory + offsetByParking, fileContext, 0x20); AddFatElement(mMemFat, mLogDirectoryClusters); MakeLogDirectory(); if(!mMstarPark) if(mParkingNormalPercent > 0) { // mParkingDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, PARKING_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mParkingDirectoryStartCluster); memcpy(mMemRootDirectory, fileContext, 0x20); AddFatElement(mMemFat, mParkingDirectoryClusters); } // mNormalDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, NORMAL_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mNormalDirectoryStartCluster); memcpy(mMemRootDirectory + offsetByParking + 0x20, fileContext, 0x20); AddFatElement(mMemFat, mNormalDirectoryClusters); // mEventDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, EVENT_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mEventDirectoryStartCluster); memcpy(mMemRootDirectory + offsetByParking + 0x40, fileContext, 0x20); AddFatElement(mMemFat, mEventDirectoryClusters); if(mManualPercent > 0) { // mManualDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, MANUAL_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mManualDirectoryStartCluster); memcpy(mMemRootDirectory + offsetByParking + 0x60, fileContext, 0x20); AddFatElement(mMemFat, mManualDirectoryClusters); } if(mMstarPark) if(mParkingNormalPercent > 0) { // mParkingDirectoryStartCluster = mCurrentFatOffset; SetDirFileName(fileContext, PARKING_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mParkingNormalDirectoryStartCluster); memcpy(mMemRootDirectory + offsetByParking + 0x80, fileContext, 0x20); AddFatElement(mMemFat, mParkingNormalDirectoryClusters); } } void BmFF::MakeLogDirectory(void) { int log0FileClusters = LOG0_FILE_SIZE / CLUSTER_SIZE; int log1FileClusters = LOG1_FILE_SIZE / CLUSTER_SIZE; int log2FileClusters = LOG2_FILE_SIZE / CLUSTER_SIZE; char defautlDirectoryContext[0x20] = { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0x3A, 0x4F, 0x54, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0xB4, 0x22, 0x00, 0x00, 0x00, 0x00 }; char fileContext[0x20] = { 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x31, 0x20, 0x4C, 0x4F, 0x47, 0x20, 0x00, 0x64, 0x4D, 0x44, 0x39, 0x4F, 0x39, 0x4F, 0x00, 0x00, 0x4D, 0x44, 0x39, 0x4F, 0x15, 0x00, 0x53, 0x00, 0x00, 0x00 }; SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ". "); SetDirFirstCluster(defautlDirectoryContext, mLogDirectoryStartCluster); memcpy(mMemLogDirectory, defautlDirectoryContext, 0x20); SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ".. "); SetDirFirstCluster(defautlDirectoryContext, 0); memcpy(mMemLogDirectory + 0x20, defautlDirectoryContext, 0x20); SetDirFileAttribute(fileContext, 0x20); SetDirFileName(fileContext, LOG_SYSTEM0_FILE); SetDirFileSize(fileContext, LOG0_FILE_SIZE); SetDirFirstCluster(fileContext, mCurrentFatOffset); AddFatElement(mMemFat, log0FileClusters); memcpy(mMemLogDirectory + 0x40, fileContext, 0x20); SetDirFileAttribute(fileContext, 0x20); SetDirFileName(fileContext, LOG_SYSTEM1_FILE); SetDirFileSize(fileContext, LOG1_FILE_SIZE); SetDirFirstCluster(fileContext, mCurrentFatOffset); AddFatElement(mMemFat, log1FileClusters); memcpy(mMemLogDirectory + 0x60, fileContext, 0x20); SetDirFileAttribute(fileContext, 0x20); SetDirFileName(fileContext, LOG_SYSTEM2_FILE); SetDirFileSize(fileContext, LOG2_FILE_SIZE); SetDirFirstCluster(fileContext, mCurrentFatOffset); AddFatElement(mMemFat, log2FileClusters); memcpy(mMemLogDirectory + 0x80, fileContext, 0x20); // SetDirFileAttribute(fileContext, 0x20); // SetDirFileName(fileContext, LOG_RECORD1_FILE); // SetDirFileSize(fileContext, LOG_FILE_SIZE); // SetDirFirstCluster(fileContext, mCurrentFatOffset); // AddFatElement(mMemFat, logFileClusters); // memcpy(mMemLogDirectory + 0x80, fileContext, 0x20); // SetDirFileAttribute(fileContext, 0x20); // SetDirFileName(fileContext, LOG_RECORD2_FILE); // SetDirFileSize(fileContext, LOG_FILE_SIZE); // SetDirFirstCluster(fileContext, mCurrentFatOffset); // AddFatElement(mMemFat, logFileClusters); // memcpy(mMemLogDirectory + 0xa0, fileContext, 0x20); // SetDirFileAttribute(fileContext, 0x20); // SetDirFileName(fileContext, PARAM_FILE); // SetDirFileSize(fileContext, LOG_FILE_SIZE); // SetDirFirstCluster(fileContext, mCurrentFatOffset); // AddFatElement(mMemFat, logFileClusters); // memcpy(mMemLogDirectory + 0xc0, fileContext, 0x20); } void BmFF::MakeParkingDirectory(void) { int parkingDirectorySize = mParkingDirectoryClusters * CLUSTER_SIZE; char defautlDirectoryContext[0x20] = { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0x3A, 0x4F, 0x54, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0xB4, 0x22, 0x00, 0x00, 0x00, 0x00 }; char fileContext[0x20] = { 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x31, 0x20, 0x4C, 0x4F, 0x47, 0x20, 0x00, 0x64, 0x4D, 0x44, 0x39, 0x4F, 0x39, 0x4F, 0x00, 0x00, 0x4D, 0x44, 0x39, 0x4F, 0x15, 0x00, 0x53, 0x00, 0x00, 0x00 }; SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ". "); SetDirFirstCluster(defautlDirectoryContext, mParkingDirectoryStartCluster); memcpy(mMemParkingDirectory, defautlDirectoryContext, 0x20); SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ".. "); SetDirFirstCluster(defautlDirectoryContext, 0); memcpy(mMemParkingDirectory + 0x20, defautlDirectoryContext, 0x20); SetDirFileName(fileContext, PARKING_NORMAL_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mParkingNormalDirectoryStartCluster); memcpy(mMemParkingDirectory + 0x40, fileContext, 0x20); AddFatElement(mMemFat, mParkingNormalDirectoryClusters); SetDirFileName(fileContext, PARKING_EVENT_DIRECTORY); SetDirFileAttribute(fileContext, 0x10); SetDirFileSize(fileContext, 0); SetDirFirstCluster(fileContext, mParkingEventDirectoryStartCluster); memcpy(mMemParkingDirectory + 0x60, fileContext, 0x20); AddFatElement(mMemFat, mParkingEventDirectoryClusters); } void BmFF::MakeRecordDirectory(char *data, int directoryStartCluster, const char *fileFullNameFront, const char *fileName83Front, const char *fileFullNameRear, const char *fileName83Rear, int nRecords, int frontFileClusters, int rearFileClusters, int parentStartCluster) { char defautlDirectoryContext[0x20] = { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0x3A, 0x4F, 0x54, 0x00, 0x63, 0x52, 0x3A, 0x4F, 0xB4, 0x22, 0x00, 0x00, 0x00, 0x00 }; char fileContext[0x60] = { 0x42, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x46, 0x00, 0x0F, 0x00, 0xDC, 0x2E, 0x00, 0x4D, 0x00, 0x4F, 0x00, 0x56, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x2E, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x4D, 0x00, 0x31, 0x00, 0x0F, 0x00, 0xDC, 0x39, 0x00, 0x30, 0x00, 0x39, 0x00, 0x32, 0x00, 0x35, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x4F, 0x52, 0x4D, 0x31, 0x39, 0x30, 0x7E, 0x31, 0x4D, 0x4F, 0x56, 0x22, 0x00, 0x64, 0x04, 0x43, 0x39, 0x4F, 0x39, 0x4F, 0x54, 0x00, 0x04, 0x43, 0x39, 0x4F, 0xB4, 0x22, 0x20, 0x00, 0x00, 0x00 }; int i; char ffn[32]; char fn83[16]; unsigned int frontFileSize = frontFileClusters * CLUSTER_SIZE; unsigned int rearFileSize = rearFileClusters * CLUSTER_SIZE; SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ". "); SetDirFirstCluster(defautlDirectoryContext, directoryStartCluster); memcpy(data, defautlDirectoryContext, 0x20); data += 0x20; SetDirFileAttribute(defautlDirectoryContext, 0x10); SetDirFileName(defautlDirectoryContext, ".. "); SetDirFirstCluster(defautlDirectoryContext, parentStartCluster); memcpy(data, defautlDirectoryContext, 0x20); data += 0x20; for(i = 0; i < nRecords; ++i) { string backup_file_name = ""; sprintf(ffn, fileFullNameFront, i); sprintf(fn83, fileName83Front, i); if(mFormatFlag) WriteFileName(ffn, mCurrentFatOffset); else if(mRecoverFlag) backup_file_name = ReadFileName(mCurrentFatOffset); if(backup_file_name.empty()) { SetDirFileNameLong(fileContext, fn83, ffn); SetDirFileAttributeLong(fileContext, /*0x22*/0x20); } else { SetDirFileNameLong(fileContext, fn83, backup_file_name.c_str()); SetDirFileAttributeLong(fileContext, 0x20); printf("Recover file name front(%d)...%s\n", i, backup_file_name.c_str()); } SetDirFileSizeLong(fileContext, frontFileSize); SetDirFirstClusterLong(fileContext, mCurrentFatOffset); AddFatElement(mMemFat, frontFileClusters); memcpy(data, fileContext, 0x60); data += 0x60; // HexDump(fileContext, 0x60); if(mFlushStartOffset == 0) mFlushStartOffset = mCurrentFatOffset; if(rearFileClusters > 0) { backup_file_name = ""; sprintf(ffn, fileFullNameRear, i); sprintf(fn83, fileName83Rear, i); if(mFormatFlag) WriteFileName(ffn, mCurrentFatOffset); else if(mRecoverFlag) backup_file_name = ReadFileName(mCurrentFatOffset); if(backup_file_name.empty()) { SetDirFileNameLong(fileContext, fn83, ffn); SetDirFileAttributeLong(fileContext, /*0x22*/0x20); } else { SetDirFileNameLong(fileContext, fn83, backup_file_name.c_str()); SetDirFileAttributeLong(fileContext, 0x20); printf("Recover file name rear(%d)...%s\n", i, backup_file_name.c_str()); } SetDirFileAttributeLong(fileContext, 0x22); SetDirFileSizeLong(fileContext, rearFileSize); SetDirFirstClusterLong(fileContext, mCurrentFatOffset); AddFatElement(mMemFat, rearFileClusters); memcpy(data, fileContext, 0x60); data += 0x60; } } } int BmFF::WriteSectors(char *data, unsigned int startSector, unsigned int sectors) { ssize_t written; loff_t offset; loff_t start = ((loff_t)startSector) * SECTOR_SIZE; // unsigned int size = sectors * SECTOR_SIZE; int i; offset = lseek64(mFd, start, SEEK_SET); if(offset != start) { printf("WriteSectors lseek error...start sector=%u, nsectors=%u to:%lld seek:%lld \n", startSector, sectors,start,offset); return -1; } for(i = 0; i < sectors; ++i) { written = write(mFd, data + i * SECTOR_SIZE, SECTOR_SIZE); // ,&mOV if(written != SECTOR_SIZE) { printf("WriteSectors write error...start sector=%u, nsectors=%u\n", startSector, sectors); return -1; } usleep(1); } // if(!mNoPrintFlag) printf("WriteSectors OK. start sector=%u, nsectors=%u\n", startSector, sectors); return 0; } void BmFF::SetFatElement(unsigned int *pFatBuff, unsigned int startCluster, int size) { for(int i = 0; i < (size - 1); ++i) { pFatBuff[startCluster + i] = startCluster + i + 1; } pFatBuff[startCluster + size - 1] = 0x0ffffff8; } void BmFF::AddFatElement(unsigned int *pFatBuff, int size) { for(int i = 0; i < (size - 1); ++i) { pFatBuff[mCurrentFatOffset + i] = mCurrentFatOffset + i + 1; } pFatBuff[mCurrentFatOffset + size - 1] = 0x0ffffff8; mCurrentFatOffset += size; } void BmFF::SetDirFirstCluster(char *pDirBuff, unsigned int cluster) { unsigned short highWord = (cluster >> 16) & 0xffff; unsigned short lowWord = cluster & 0xffff; *(unsigned short*)(pDirBuff + 0x14) = highWord; *(unsigned short*)(pDirBuff + 0x1A) = lowWord; } void BmFF::SetDirFirstClusterLong(char *pDirBuff, unsigned int cluster) { unsigned short highWord = (cluster >> 16) & 0xffff; unsigned short lowWord = cluster & 0xffff; *(unsigned short*)(pDirBuff + 0x54) = highWord; *(unsigned short*)(pDirBuff + 0x5A) = lowWord; } void BmFF::SetDirFileAttribute(char *pDirBuff, unsigned char attribute) { pDirBuff[0xb] = attribute; } void BmFF::SetDirFileAttributeLong(char *pDirBuff, unsigned char attribute) { pDirBuff[0x4b] = attribute; } void BmFF::SetDirFileSize(char *pDirBuff, unsigned int filesize) { *(unsigned int*)(pDirBuff + 0x1C) = filesize; } void BmFF::SetDirFileSizeLong(char *pDirBuff, unsigned int filesize) { *(unsigned int*)(pDirBuff + 0x5C) = filesize; } void BmFF::SetDirFileName(char *pDirBuff, const char *fileName83) { memcpy(pDirBuff, fileName83, 11); } void BmFF::SetDirFileNameLong(char *pDirBuff, const char *fileName83, const char *fileFullName) { unsigned char checksum = FileNameChecksum(fileName83); char ffn[26]; memset(ffn, 0xff, sizeof(ffn)); memcpy(ffn, fileFullName, strlen(fileFullName) + 1); pDirBuff[0x0d] = checksum; pDirBuff[0x2d] = checksum; memcpy(pDirBuff + 0x40, fileName83, 11); UTF8CharCopy(pDirBuff + 0x21, ffn, 5); UTF8CharCopy(pDirBuff + 0x2e, ffn + 5, 6); UTF8CharCopy(pDirBuff + 0x3c, ffn + 5 + 6, 2); UTF8CharCopy(pDirBuff + 0x1, ffn + 5 + 6 + 2, 5); UTF8CharCopy(pDirBuff + 0xe, ffn + 5 + 6 + 2 + 5, 6); UTF8CharCopy(pDirBuff + 0x1c, ffn + 5 + 6 + 2 + 5 + 6, 2); } void BmFF::UTF8CharCopy(char *target_u, const char *source_c, int size) { for(int i = 0; i < size; ++i) { if(*source_c != 0xff) { *target_u++ = *source_c++; *target_u++ = 0; } else { *target_u++ = *source_c++; *target_u++ = 0xff; } } } void BmFF::CharUTF8Copy(char *target_c, const char *source_u, int size) { for(int i = 0; i < size; ++i) { *target_c++ = *source_u++; source_u++; } } void BmFF::GetDirFirstCluster(char *pDirBuff, unsigned int &cluster) { unsigned short highWord = (cluster >> 16) & 0xffff; unsigned short lowWord = cluster & 0xffff; highWord = *(unsigned short*)(pDirBuff + 0x14); lowWord = *(unsigned short*)(pDirBuff + 0x1A); cluster = (((unsigned int)highWord) << 16) + lowWord; } void BmFF::GetDirFirstClusterLong(char *pDirBuff, unsigned int &cluster) { unsigned short highWord = (cluster >> 16) & 0xffff; unsigned short lowWord = cluster & 0xffff; highWord = *(unsigned short*)(pDirBuff + 0x54); lowWord = *(unsigned short*)(pDirBuff + 0x5A); cluster = (((unsigned int)highWord) << 16) + lowWord; } void BmFF::GetDirFileAttribute(char *pDirBuff, unsigned char &attribute) { attribute = pDirBuff[0xb]; } void BmFF::GetDirFileAttributeLong(char *pDirBuff, unsigned char &attribute) { attribute = pDirBuff[0x4b]; } void BmFF::GetDirFileSize(char *pDirBuff, unsigned int &filesize) { filesize = *(unsigned int*)(pDirBuff + 0x1C); } void BmFF::GetDirFileSizeLong(char *pDirBuff, unsigned int &filesize) { filesize = *(unsigned int*)(pDirBuff + 0x5C); // filesize = (*(pDirBuff + 0x5C)) + // (*(pDirBuff + 0x5D) << 8) + // (*(pDirBuff + 0x5E) << 16) + // (*(pDirBuff + 0x5F) << 24); } void BmFF::GetDirFileName(char *pDirBuff, char *fileName83) { memcpy(fileName83, pDirBuff, 11); fileName83[11] = 0; } void BmFF::GetDirFileNameLong(char *pDirBuff, char *fileName83, char *fileFullName) { char ffn[32]; memset(ffn, 0, sizeof(ffn)); memcpy(fileName83, pDirBuff + 0x40, 11); fileName83[11] = 0; CharUTF8Copy(ffn, pDirBuff + 0x21, 5); CharUTF8Copy(ffn + 5, pDirBuff + 0x2e, 6); CharUTF8Copy(ffn + 5 + 6, pDirBuff + 0x3c, 2); CharUTF8Copy(ffn + 5 + 6 + 2, pDirBuff + 0x1, 5); CharUTF8Copy(ffn + 5 + 6 + 2 + 5, pDirBuff + 0xe, 6); CharUTF8Copy(ffn + 5 + 6 + 2 + 5 + 6, pDirBuff + 0x1c, 2); *(ffn + 5 + 6 + 2 + 5 + 6 + 2) = 0; strcpy(fileFullName, ffn); } unsigned char BmFF::FileNameChecksum(const char *fileName83) { int i; unsigned char sum = 0; for (i = 11; i; i--) sum = ((sum & 1) << 7) + (sum >> 1) + *fileName83++; return sum; } bool BmFF::VerifyMBR(void) { if(MBR_DISK_SERIAL_NUMBER(mRdMasterBootRecord) != BM_SERIAL_NUMBER && MBR_DISK_SERIAL_NUMBER(mRdMasterBootRecord) != BM_FACTORY_SERIAL_NUMBER) { printf("VerifyMBR()...Error: Disk serial number %u.\n", MBR_DISK_SERIAL_NUMBER(mRdMasterBootRecord)); return false; } return true; } bool BmFF::VerifyFATBS(void) { if(BS_TOTAL_SECTORS(mRdFat32BootSector) != (unsigned int)mPtTotalSectors) { printf("VerifyFATBS()...Error: total sector. readed = %u, expected = %u\n", BS_TOTAL_SECTORS(mRdFat32BootSector), (unsigned int)mPtTotalSectors); return false; } if(BS_SECTORS_PER_FAT(mRdFat32BootSector) != (unsigned int)mSectorsPerFat) { printf("VerifyFATBS()...Error: sector per fat. readed = %u, expected = %u\n", BS_SECTORS_PER_FAT(mRdFat32BootSector), (unsigned int)mSectorsPerFat); return false; } return true; } bool BmFF::VerifyFAT(void) { bool ret; off_t fatStartSector = (off_t)(FIRST_SECTOR + FAT_RESERVED_SECTORS); char *readFat0 = (char *)malloc(mSectorsPerFat * SECTOR_SIZE), *readFat1 = (char *)malloc(mSectorsPerFat * SECTOR_SIZE); int i, count; unsigned int *rf, *wf; ret = ReadSectors((char*)readFat0, fatStartSector, mSectorsPerFat); if(ret == false) goto error; ret = ReadSectors((char*)readFat1, fatStartSector + mSectorsPerFat, mSectorsPerFat); if(ret == false) goto error; count = mSectorsPerFat * SECTOR_SIZE / 4; ret = true; rf = (unsigned int *)readFat0; wf = (unsigned int *)mMemFat; for(i = 0; i < count; ++i) { // if(i <= 132) // { // if(i % 8 == 0) // printf("\n"); // printf("(i=%03d,w=0x%08x,r=0x%08x) ", i, *wf, *rf); // } if(*wf != 0) if(*wf != *rf) { printf("VerifyFAT0...i=%d, wf=0x%08x, rf=0x%08x\n", i, *wf, *rf); ret = false; break; } ++wf; ++rf; } if(ret == true) { rf = (unsigned int *)readFat1; wf = (unsigned int *)mMemFat; for(i = 0; i < count; ++i) { if(*wf != 0) if(*wf != *rf) { printf("VerifyFAT1...i=%d, wf=0x%08x, rf=0x%08x\n", i, *wf, *rf); ret = false; break; } ++wf; ++rf; } } free(readFat0); free(readFat1); if(ret == true) printf("VerifyFAT OK.\n"); return ret; error: free(readFat0); free(readFat1); return false; } bool BmFF::VerifyDirectories(void) { bool ret; int i, count; unsigned int *rf, *wf; char *readRootDirectory = (char *)malloc(mRootDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE), *readLogDirectory = (char *)malloc(mLogDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE), *readNormalDirectory = (char *)malloc(mNormalDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE), *readEventDirectory = (char *)malloc(mEventDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE), *readManualDirectory = (char *)malloc(mManualDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE), *readParkingDirectory = (mParkingNormalPercent > 0) ? (char *)malloc(mParkingDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE) : NULL, *readParkingNormalDirectory = (mParkingNormalPercent > 0) ? (char *)malloc(mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE) : NULL, *readParkingEventDirectory = (mParkingEventPercent > 0) ? (char *)malloc(mParkingEventDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE) : NULL; ret = ReadSectors(readRootDirectory, mRootDirectoryStartSector, mRootDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) ret = ReadSectors(readLogDirectory, mLogDirectoryStartSector, mLogDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) if(!mMstarPark) if(mParkingNormalPercent > 0) ret = ReadSectors(readParkingDirectory, mParkingDirectoryStartSector, mParkingDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) ret = ReadSectors(readNormalDirectory, mNormalDirectoryStartSector, mNormalDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) ret = ReadSectors(readEventDirectory, mEventDirectoryStartSector, mEventDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) if(mManualPercent > 0) ret = ReadSectors(readManualDirectory, mManualDirectoryStartSector, mManualDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == true) { if(mParkingNormalPercent > 0) { if(mMstarPark) { ret = ReadSectors(readParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); } else { ret = ReadSectors(readParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); ret = ReadSectors(readParkingEventDirectory, mParkingEventDirectoryStartSector, mParkingEventDirectoryClusters * SECTORS_PER_CLUSTER); } } } if(ret == false) goto error; count = mRootDirectoryClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE / 4; ret = true; // if(ret == true) // ret = VerifyRootDirectory(readRootDirectory); if(ret == true) ret = VerifyLogDirectory(readLogDirectory); if(ret == true) if(!mMstarPark) if(mParkingNormalPercent > 0) ret = VerifyParkingDirectory(readParkingDirectory); if(ret == true) { if(!mNoPrintFlag) printf("VerifyNormal. records=%d, front_file_size=%d, rear_file_size=%d\n", mNormalRecords, mNormalFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mNormalRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readNormalDirectory, mNormalDirectoryClusters * CLUSTER_SIZE, (char*)".NORM", (char*)"NORM", mNormalRecords, mNormalFrontFileClusters, mNormalRearFileClusters); } if(ret == true) { if(!mNoPrintFlag) printf("VerifyEvent. records=%d, front_file_size=%d, rear_file_size=%d\n", mEventRecords, mEventFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mEventRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readEventDirectory, mEventDirectoryClusters * CLUSTER_SIZE, (char*)".EVEN", (char*)"EVEN", mEventRecords, mEventFrontFileClusters, mEventRearFileClusters); } if(ret == true) { if(mManualPercent > 0) { if(!mNoPrintFlag) printf("VerifyManual. records=%d, front_file_size=%d, rear_file_size=%d\n", mManualRecords, mManualFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mManualRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readManualDirectory, mManualDirectoryClusters * CLUSTER_SIZE, (char*)".MANU", (char*)"MANU", mManualRecords, mManualFrontFileClusters, mManualRearFileClusters); } } if(ret == true) { if(mParkingNormalPercent > 0) { if(mMstarPark) { if(!mNoPrintFlag) printf("VerifyParking. records=%d, front_file_size=%d, rear_file_size=%d\n", mParkingNormalRecords, mParkingFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mParkingRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readParkingNormalDirectory, mParkingNormalDirectoryClusters * CLUSTER_SIZE, (char*)".PARK", (char*)"PARK", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters); } else { if(!mNoPrintFlag) printf("VerifyParkingNormal. records=%d, front_file_size=%d, rear_file_size=%d\n", mParkingNormalRecords, mParkingFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mParkingRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readParkingNormalDirectory, mParkingNormalDirectoryClusters * CLUSTER_SIZE, (char*)".PNOR", (char*)"PNOR", mParkingNormalRecords, mParkingFrontFileClusters, mParkingRearFileClusters); if(!mNoPrintFlag) printf("VerifyParkingEvent. records=%d, front_file_size=%d, rear_file_size=%d\n", mParkingEventRecords, mParkingFrontFileClusters * SECTORS_PER_CLUSTER * SECTOR_SIZE, mParkingRearFileClusters *SECTORS_PER_CLUSTER * SECTOR_SIZE); ret = VerifyRecordDirectory(readParkingEventDirectory, mParkingEventDirectoryClusters * CLUSTER_SIZE, (char*)".PEVE", (char*)"PEVE", mParkingEventRecords, mParkingFrontFileClusters, mParkingRearFileClusters); } } } free(readRootDirectory); free(readLogDirectory); free(readNormalDirectory); free(readEventDirectory); if(mManualPercent > 0) free(readManualDirectory); if(mParkingNormalPercent > 0) { free(readParkingDirectory); free(readParkingNormalDirectory); free(readParkingEventDirectory); } return ret; error: free(readRootDirectory); free(readLogDirectory); free(readNormalDirectory); free(readEventDirectory); if(mManualPercent > 0) free(readManualDirectory); if(mParkingNormalPercent > 0) { free(readParkingDirectory); free(readParkingNormalDirectory); free(readParkingEventDirectory); } return false; } bool BmFF::VerifyRootDirectory(char *buff) { bool ret = true; unsigned char attribute; char fn83[32]; int offsetByParking = (mParkingNormalPercent > 0) ? 0x20 : 0; if(!mMstarPark) if(mParkingNormalPercent > 0) { if(ret == true) { GetDirFileAttribute(buff + 0x00, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", PARKING_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + 0x00, fn83); if(strcmp(fn83, PARKING_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", PARKING_DIRECTORY, fn83); ret = false; } } } if(ret == true) { GetDirFileAttribute(buff + offsetByParking + 0x00, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", LOG_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + offsetByParking + 0x00, fn83); if(strcmp(fn83, LOG_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", LOG_DIRECTORY, fn83); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + offsetByParking + 0x20, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", NORMAL_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + offsetByParking + 0x20, fn83); if(strcmp(fn83, NORMAL_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", NORMAL_DIRECTORY, fn83); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + offsetByParking + 0x40, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", EVENT_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + offsetByParking + 0x40, fn83); if(strcmp(fn83, EVENT_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", EVENT_DIRECTORY, fn83); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + offsetByParking + 0x60, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", MANUAL_DIRECTORY, attribute); ret = false; } } if(ret == true) { if(mManualPercent > 0) { GetDirFileName(buff + offsetByParking + 0x60, fn83); if(strcmp(fn83, MANUAL_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", MANUAL_DIRECTORY, fn83); ret = false; } } } if(mMstarPark) if(mParkingNormalPercent > 0) { if(ret == true) { GetDirFileAttribute(buff + offsetByParking + 0x80, attribute); if(attribute != 0x10) { printf("VerifyRootDirectory error. %s_attr=0x%02x\n", PARKING_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + offsetByParking + 0x80, fn83); if(strcmp(fn83, PARKING_DIRECTORY) != 0) { printf("VerifyRootDirectory error. %s_dirname=%s\n", PARKING_DIRECTORY, fn83); ret = false; } } } if(ret) printf("VerifyRootDirectory OK.\n"); return ret; } bool BmFF::VerifyLogDirectory(char *buff) { bool ret = true; unsigned char attribute; char fn83[32]; unsigned int fileSize; // if(ret == true) // { // GetDirFileName(buff + 0x40, fn83); // if(strcmp(fn83, LOG_SYSTEM1_FILE) != 0) // { // printf("VerifyLogDirectory error. %s_filename=%s\n", LOG_SYSTEM1_FILE, fn83); // ret = false; // } // } if(ret == true) { GetDirFileSize(buff + 0x40, fileSize); if(fileSize != LOG0_FILE_SIZE) { printf("VerifyLogDirectory error. %s_fileSize=%d\n", LOG_SYSTEM0_FILE, fileSize); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + 0x40, attribute); if(attribute != 0x20) { printf("VerifyLogDirectory error. %s_attr=0x%02x\n", LOG_SYSTEM0_FILE, attribute); ret = false; } } // if(ret == true) // { // GetDirFileName(buff + 0x60, fn83); // if(strcmp(fn83, LOG_SYSTEM2_FILE) != 0) // { // printf("VerifyLogDirectory error. %s_filename=%s\n", LOG_SYSTEM2_FILE, fn83); // ret = false; // } // } if(ret == true) { GetDirFileSize(buff + 0x60, fileSize); if(fileSize != LOG1_FILE_SIZE) { printf("VerifyLogDirectory error. %s_fileSize=%d\n", LOG_SYSTEM1_FILE, fileSize); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + 0x60, attribute); if(attribute != 0x20) { printf("VerifyLogDirectory error. %s_attr=0x%02x\n", LOG_SYSTEM1_FILE, attribute); ret = false; } } if(ret == true) { GetDirFileSize(buff + 0x80, fileSize); if(fileSize != LOG2_FILE_SIZE) { printf("VerifyLogDirectory error. %s_fileSize=%d\n", LOG_SYSTEM2_FILE, fileSize); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + 0x80, attribute); if(attribute != 0x20) { printf("VerifyLogDirectory error. %s_attr=0x%02x\n", LOG_SYSTEM2_FILE, attribute); ret = false; } } if(ret) if(!mNoPrintFlag) printf("VerifyLogDirectory OK.\n"); return ret; } bool BmFF::VerifyParkingDirectory(char *buff) { bool ret = true; unsigned char attribute; char fn83[32]; unsigned int fileSize; if(ret == true) { GetDirFileAttribute(buff + 0x40, attribute); if(attribute != 0x10) { if(!mNoPrintFlag) printf("VerifyParkingDirectory error. %s_attr=0x%02x\n", PARKING_NORMAL_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + 0x40, fn83); if(strcmp(fn83, PARKING_NORMAL_DIRECTORY) != 0) { if(!mNoPrintFlag) printf("VerifyParkingDirectory error. %s_dirname=%s\n", PARKING_NORMAL_DIRECTORY, fn83); ret = false; } } if(ret == true) { GetDirFileAttribute(buff + 0x60, attribute); if(attribute != 0x10) { if(!mNoPrintFlag) printf("VerifyParkingDirectory error. %s_attr=0x%02x\n", PARKING_EVENT_DIRECTORY, attribute); ret = false; } } if(ret == true) { GetDirFileName(buff + 0x60, fn83); if(strcmp(fn83, PARKING_EVENT_DIRECTORY) != 0) { if(!mNoPrintFlag) printf("VerifyParkingDirectory error. %s_dirname=%s\n", PARKING_EVENT_DIRECTORY, fn83); ret = false; } } if(ret) if(!mNoPrintFlag) printf("VerifyParkingDirectory OK.\n"); return ret; } bool BmFF::VerifyRecordDirectory(char *buff, int buffSize, char *headNameHidden, char *headNameNormal, int nRecords, int frontFileClusters, int rearFileClusters) { int i; bool ret = true; unsigned char attribute; char fn83[32]; char ffn[64]; unsigned int fileSize; unsigned int frontFileSize = frontFileClusters * CLUSTER_SIZE; unsigned int rearFileSize = rearFileClusters * CLUSTER_SIZE; int fileNameLength; int nHidden = strlen(headNameHidden), nNormal = strlen(headNameNormal); bool front = true; buff += 0x40; buffSize -= 0x40; if(rearFileClusters > 0) nRecords *= 2; for(i = 0; i < nRecords; ++i) { while((buff[0] != 0x42) && (buffSize >= 0x60)) { buff += 0x60; buffSize -= 0x60; } if(buffSize < 0x60) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error. too many sequence code error.\n"); ret = false; break; } if(ret == true) { GetDirFileAttributeLong(buff, attribute); if(attribute != 0x20/* && attribute != 0x22*/) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error. %s_%d_attr=0x%02x\n", headNameNormal, i, attribute); ret = false; break; } } if(ret == true) { GetDirFileNameLong(buff, fn83, ffn); fileNameLength = strlen(ffn); if(fileNameLength < 20) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error. %s_%d_filename=%s, len=%d\n", headNameNormal, i, ffn, fileNameLength); ret = false; break; } if(ffn[0] != '.') // if(attribute == 0x20) { if(strncmp(ffn, headNameNormal, nNormal) != 0) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error(1). %s_%d_filename=%s\n", headNameNormal, i, ffn); ret = false; break; } if(strncmp(ffn + fileNameLength - 5, "W.MP4", 5) == 0) { front = true; } #if (MODEL_CONFIG == BV3000) else if(strncmp(ffn + fileNameLength - 5, "I.MP4", 5) == 0) #else else if(strncmp(ffn + fileNameLength - 5, "R.MP4", 5) == 0) #endif { front = false; } else { if(!mNoPrintFlag) printf("VerifyRecordDirectory error(2). %s_%d_filename=%s\n", headNameHidden, i, ffn); ret = false; break; } } else // if(attribute == 0x22) { if(strncmp(ffn, headNameHidden, nHidden) != 0) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error(3). %s_%d_filename=%s\n", headNameHidden, i, ffn); ret = false; break; } if(strncmp(ffn + fileNameLength - 5, "W.TMP", 5) == 0) { front = true; } #if (MODEL_CONFIG == BV3000) else if(strncmp(ffn + fileNameLength - 5, "I.TMP", 5) == 0) #else else if(strncmp(ffn + fileNameLength - 5, "R.TMP", 5) == 0) #endif { front = false; } else { if(!mNoPrintFlag) printf("VerifyRecordDirectory error(4). %s_%d_filename=%s\n", headNameHidden, i, ffn); ret = false; break; } } } if(ret == true) { GetDirFileSizeLong(buff, fileSize); if(front == true) { if(fileSize != frontFileSize) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error. %s_%dF_filesize=%d/%d\n", headNameNormal, i, fileSize, frontFileSize); ret = false; break; } } else { if(fileSize != rearFileSize) { if(!mNoPrintFlag) printf("VerifyRecordDirectory error. %s_%dR_filesize=%d/%d\n", headNameNormal, i, fileSize, rearFileSize); ret = false; break; } } } buff += 0x60; buffSize -= 0x60; } if(ret) if(!mNoPrintFlag) printf("VerifyRecordDirectory_%s nFiles = %d OK.\n", headNameNormal, nRecords); return ret; } bool BmFF::ReadSectors(char *data, unsigned int startSector, unsigned int sectors) { ssize_t readed; loff_t offset; loff_t start = (loff_t)startSector * SECTOR_SIZE; unsigned int size = sectors * SECTOR_SIZE; offset = lseek64(mFd, start, SEEK_SET); if(offset != start) { printf("ReadSectors lseek error...start sector=%u, nsectors=%u\n", startSector, sectors); return false; } readed = read(mFd, data, size); if(readed != size) { printf("ReadSectors read error...start sector=%u, nsectors=%u\n", startSector, sectors); return false; } // if(!mNoPrintFlag) printf("ReadSectors OK. start sector=%u, nsectors=%u\n", startSector, sectors); return true; } void BmFF::ForceFlush(void) { #if !(_WIN32) int result; OpenDevice(); errno = 0; result = ioctl(mFd, BLKFLSBUF); if (result && errno) { printf("=========================================================================\n"); printf(" BmFF::ForceFlush() Cannot flush. errno=%d\n", errno); printf(" error=%s\n", strerror(errno)); printf("=========================================================================\n"); } else if (result) { printf("=========================================================================\n"); printf(" BmFF::ForceFlush() Flush returned. result=%d\n", result); printf("=========================================================================\n"); } else if (errno) { printf("=========================================================================\n"); printf(" BmFF::ForceFlush() Flush returned. zero, but with errno=%d\n", errno); printf(" error=%s\n", strerror(errno)); printf("=========================================================================\n"); } else { printf("=========================================================================\n"); printf(" BmFF::ForceFlush() OK\n"); printf("=========================================================================\n"); } CloseDevice(); #endif // #if !(_WIN32) } bool BmFF::GetDirStartAndSectors(string fileName, int &startSector, int &nSectors, int &nFiles) { bool ret = false; if((fileName.compare(0, 4, "NORM") == 0) || (fileName.compare(0, 4, ".NOR") == 0)) { startSector = mNormalDirectoryStartSector; nSectors = mNormalDirectoryClusters * SECTORS_PER_CLUSTER; nFiles = mNormalFiles; ret = true; } else if((fileName.compare(0, 4, "EVEN") == 0) || (fileName.compare(0, 4, ".EVE") == 0)) { startSector = mEventDirectoryStartSector; nSectors = mEventDirectoryClusters * SECTORS_PER_CLUSTER; nFiles = mEventFiles; ret = true; } else if((fileName.compare(0, 4, "MANU") == 0) || (fileName.compare(0, 4, ".MAN") == 0)) { startSector = mManualDirectoryStartSector; nSectors = mManualDirectoryClusters * SECTORS_PER_CLUSTER; nFiles = mManualFiles; ret = true; } else if((fileName.compare(0, 4, "PNOR") == 0) || (fileName.compare(0, 4, ".PNO") == 0)) { startSector = mParkingNormalDirectoryStartSector; nSectors = mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER; nFiles = mParkingNormalFiles; ret = true; } else if((fileName.compare(0, 4, "PEVE") == 0) || (fileName.compare(0, 4, ".PEV") == 0)) { startSector = mParkingEventDirectoryStartSector; nSectors = mParkingEventDirectoryClusters * SECTORS_PER_CLUSTER; nFiles = mParkingEventFiles; ret = true; } return ret; } #if 0 bool BmFF::RenameRecordFile(string srcFileName, string trgFileName) { int dirStartSector; int dirSectorSize; int nFiles; char *dirBuff, *data; int i; bool ret = false; if(GetDirStartAndSectors(srcFileName, dirStartSector, dirSectorSize, nFiles) == false) { printf("==================================================================\n"); printf(" BmFF::RenameRecordFile error...src=%s\n", srcFileName.c_str()); printf("==================================================================\n"); return false; } dirBuff = (char*)malloc(dirSectorSize * SECTOR_SIZE); if(dirBuff == NULL) { printf("==================================================================\n"); printf(" BmFF::RenameRecordFile...malloc error...src=%s\n", srcFileName.c_str()); printf("==================================================================\n"); return false; } mFd = open(mDeviceName.c_str(), O_RDWR); if(mFd < 0) { printf("==================================================================\n"); printf(" BmFF::RenameRecordFile...OpenDevice error. src=%s\n", srcFileName.c_str()); printf("==================================================================\n"); free(dirBuff); return false; } if(ReadSectors(dirBuff, dirStartSector, dirSectorSize) == false) { printf("==================================================================\n"); printf(" BmFF::RenameRecordFile...ReadSectors error...src=%s\n", srcFileName.c_str()); printf("==================================================================\n"); free(dirBuff); close(mFd); return false; } data = dirBuff + 0x40; for(i = 0; i < nFiles; ++i) { char fn83[16]; char fnLong[128]; GetDirFileNameLong(data, fn83, fnLong); if(srcFileName.compare(0, srcFileName.length(), fnLong) == 0) { int writeStartSector = (0x40 + i * 0x60) / SECTOR_SIZE; int writeEndSector = (0x40 + i * 0x60 + 0x60) / SECTOR_SIZE; int writeSectors = writeEndSector - writeStartSector + 1; SetDirFileNameLong(data, fn83, trgFileName.c_str()); if(WriteSectors(dirBuff + writeEndSector * SECTOR_SIZE, dirStartSector + writeStartSector, writeSectors) != 0) { printf("==================================================================\n"); printf(" BmFF::RenameRecordFile...WriteSectors error...src=%s\n", srcFileName.c_str()); printf("==================================================================\n"); break; } ret = true; printf("==================================================================\n"); printf(" BmFF::RenameRecordFile OK...%s->%s\n", srcFileName.c_str(), trgFileName.c_str()); printf("==================================================================\n"); break; } data += 0x60; } free(dirBuff); close(mFd); return ret; } #endif void BmFF::ZeroBlocks(int startSector, int nSectors) { ssize_t written; char *buff; int i; buff = (char *)malloc(SECTOR_SIZE); memset(buff, 0, SECTOR_SIZE); loff_t to = ((((loff_t)startSector)) * SECTOR_SIZE); loff_t offset = lseek64(mFd, to, SEEK_SET); printf("SEEK:%I64d ->%I64d \n", offset, to); if(offset != to || offset < 0){ printf("==================================================================\n"); printf(" BmFF::ZeroBlocks() seek Failed offset:%ld!=%ld \n", offset, (startSector * SECTOR_SIZE)); printf("==================================================================\n"); free(buff); return; } for(i = 0; i < nSectors; ++i) { //lseek64(mFd, (loff_t)((startSector + i) * SECTOR_SIZE), SEEK_SET); written = write(mFd, buff, SECTOR_SIZE); // ,&mOV if(written != SECTOR_SIZE) { printf("==================================================================\n"); printf(" BmFF::ZeroBlocks() Failed...sector_num=%d (start:%d+num:%d)written:%d %lld \n", startSector + i,startSector,nSectors, written, offset); printf("==================================================================\n"); break; } } free(buff); } string BmFF::ReadFileName(int cluster) { unsigned int start_sector = mRootDirectoryStartSector + (cluster - 2) * SECTORS_PER_CLUSTER; char buff[SECTOR_SIZE]; bool ret; string fname = ""; ret = ReadSectors(buff, start_sector, 1); if(ret) { buff[36 + 56 - 1] = 0; fname = buff + 36; if(memcmp(buff + 28, "\0\0\0\100free", 8) != 0) fname = ""; else if (fname.size() != 22) fname = ""; else if(fname.find(".MP4") == string::npos) fname = ""; } return fname; }; void BmFF::WriteFileName(string fname, int cluster) { unsigned int start_sector = mRootDirectoryStartSector + (cluster - 2) * SECTORS_PER_CLUSTER; char buff[SECTOR_SIZE]; memset(buff, 0, SECTOR_SIZE); memcpy(buff + 28, "\0\0\0\100free", 8); memcpy(buff + 36, fname.c_str(), fname.size()); WriteSectors(buff, start_sector, 1); }; int BmFF::RecoverDirectories(void) { int ret = 0; off_t fatStartSector = (off_t)(FIRST_SECTOR + FAT_RESERVED_SECTORS); memset(mMemFat, 0, mSectorsPerFat * SECTOR_SIZE); mMemFat[0] = 0x0ffffff8; mMemFat[1] = 0xffffffff; mCurrentFatOffset = mRootDirectoryStartCluster; MakeMemDirectories(); if(!mMstarPark) if(mParkingNormalPercent > 0) ret = WriteSectors(mMemParkingDirectory, mParkingDirectoryStartSector, mParkingDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemNormalDirectory, mNormalDirectoryStartSector, mNormalDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemEventDirectory, mEventDirectoryStartSector, mEventDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) ret = WriteSectors(mMemManualDirectory, mManualDirectoryStartSector, mManualDirectoryClusters * SECTORS_PER_CLUSTER); if(ret == 0) { if(mParkingNormalPercent > 0) { if(mMstarPark) { ret = WriteSectors(mMemParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); } else { ret = WriteSectors(mMemParkingNormalDirectory, mParkingNormalDirectoryStartSector, mParkingNormalDirectoryClusters * SECTORS_PER_CLUSTER); ret = WriteSectors(mMemParkingEventDirectory, mParkingEventDirectoryStartSector, mParkingEventDirectoryClusters * SECTORS_PER_CLUSTER); } } } return ret; } #endif // #if (SUPPORT_FORMAT_FREE)