]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
Add Linux native GUI program for Ventoy2Disk.
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / PhyDrive.c
index ec266eecd8caf17b1b16443c670e8d0a4fc30499..8d4e9bb44f2f379e9f5219644032542a050538f9 100644 (file)
@@ -230,19 +230,24 @@ BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2)
                         Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber,\r
                             prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);\r
 \r
-                        if (OnlyPart2 && prop_array[i].ullOffset == 2048*512)\r
+                        if (OnlyPart2)\r
                         {\r
-                            Log("Skip this partition...");\r
-                            continue;\r
+                            if (prop_array[i].ullOffset == 2048 * 512 || prop_array[i].ullSize != 32 * 1024 * 1024)\r
+                            {\r
+                                Log("Skip this partition...");\r
+                                continue;\r
+                            }\r
                         }\r
 \r
-\r
                         hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);\r
                         if (hr != S_OK) {\r
                             r = FALSE;\r
                             VDS_SET_ERROR(hr);\r
                             Log("Could not delete partitions: %u", LASTERR);\r
                         }\r
+                        else {\r
+                            Log("Delete this partitions success");\r
+                        }\r
                     }\r
                     r = TRUE;\r
                 }\r
@@ -289,7 +294,7 @@ out:
 }\r
 \r
 \r
-static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)\r
+static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)\r
 {\r
     size_t len;\r
     BOOL bRet;\r
@@ -304,7 +309,7 @@ static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameB
 \r
     PartOffset = 512ULL * StartSectorId;\r
 \r
-       Log("GetVentoyVolumeName PhyDrive %d SectorStart:%u PartOffset:%llu", PhyDrive, StartSectorId, (ULONGLONG)PartOffset);\r
+       Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive, (ULONGLONG)StartSectorId, (ULONGLONG)PartOffset);\r
 \r
     hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));\r
     if (hVolume == INVALID_HANDLE_VALUE)\r
@@ -798,10 +803,11 @@ static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
 }\r
 \r
 \r
-int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen)\r
+int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)\r
 {\r
     int rc = 0;\r
     HANDLE hDrive;\r
+    void *flfile;\r
 \r
     hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);\r
     if (hDrive == INVALID_HANDLE_VALUE)\r
@@ -831,6 +837,13 @@ int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSe
     if (rc == 0)\r
     {\r
         Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);\r
+\r
+        flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");\r
+        if (flfile)\r
+        {\r
+            *pSecureBoot = TRUE;\r
+            fl_fclose(flfile);\r
+        }\r
     }\r
 \r
     fl_shutdown();\r
@@ -962,6 +975,50 @@ int VentoyProcSecureBoot(BOOL SecureBoot)
                                free(filebuf);\r
                        }\r
                }\r
+\r
+        file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");\r
+        Log("Open ventoy efi file %p ", file);\r
+        if (file)\r
+        {\r
+            fl_fseek(file, 0, SEEK_END);\r
+            size = (int)fl_ftell(file);\r
+            fl_fseek(file, 0, SEEK_SET);\r
+\r
+            Log("ventoy efi file size %d ...", size);\r
+\r
+            filebuf = (char *)malloc(size);\r
+            if (filebuf)\r
+            {\r
+                fl_fread(filebuf, 1, size, file);\r
+            }\r
+\r
+            fl_fclose(file);\r
+\r
+            Log("Now delete all efi files ...");\r
+            fl_remove("/EFI/BOOT/BOOTIA32.EFI");\r
+            fl_remove("/EFI/BOOT/grubia32.efi");\r
+            fl_remove("/EFI/BOOT/grubia32_real.efi");\r
+            fl_remove("/EFI/BOOT/mmia32.efi");            \r
+\r
+            file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");\r
+            Log("Open bootia32 efi file %p ", file);\r
+            if (file)\r
+            {\r
+                if (filebuf)\r
+                {\r
+                    fl_fwrite(filebuf, 1, size, file);\r
+                }\r
+\r
+                fl_fflush(file);\r
+                fl_fclose(file);\r
+            }\r
+\r
+            if (filebuf)\r
+            {\r
+                free(filebuf);\r
+            }\r
+        }\r
+\r
        }\r
        else\r
        {\r
@@ -1216,7 +1273,6 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
 {\r
     MKFS_PARM Option;\r
     FRESULT Ret;\r
-    FATFS fs;\r
 \r
     Option.fmt = FM_EXFAT;\r
     Option.n_fat = 1;\r
@@ -1237,28 +1293,10 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
     Log("Formatting Part1 exFAT ...");\r
 \r
     Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);\r
-\r
     if (FR_OK == Ret)\r
     {\r
         Log("Formatting Part1 exFAT success");\r
-\r
-        Ret = f_mount(&fs, TEXT("0:"), 1);\r
-        Log("mount part %d", Ret);\r
-\r
-        if (FR_OK == Ret)\r
-        {\r
-            Ret = f_setlabel(TEXT("Ventoy"));\r
-            Log("f_setlabel %d", Ret);\r
-\r
-            Ret = f_mount(0, TEXT("0:"), 1);\r
-            Log("umount part %d", Ret);\r
-            return 0;\r
-        }\r
-        else\r
-        {\r
-            Log("mount exfat failed %d", Ret);\r
-            return 1;\r
-        }\r
+        return 0;\r
     }\r
     else\r
     {\r
@@ -1349,18 +1387,18 @@ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLett
         goto End;\r
     }\r
 \r
-    // clear first and last 1MB space\r
-    pTmpBuf = malloc(SIZE_1MB);\r
+    // clear first and last 2MB space\r
+    pTmpBuf = malloc(SIZE_2MB);\r
     if (!pTmpBuf)\r
     {\r
         Log("Failed to alloc memory.");\r
         rc = 1;\r
         goto End;\r
     }\r
-    memset(pTmpBuf, 0, SIZE_1MB);   \r
+    memset(pTmpBuf, 0, SIZE_2MB);\r
 \r
     SET_FILE_POS(512);\r
-    bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL);\r
+    bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);\r
     Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
     if (!bRet)\r
     {\r
@@ -1368,8 +1406,8 @@ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLett
         goto End;\r
     }\r
 \r
-    SET_FILE_POS(SIZE_1MB);\r
-    bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL);\r
+    SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);\r
+    bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);\r
     Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
     if (!bRet)\r
     {\r
@@ -1378,30 +1416,71 @@ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLett
     }\r
 \r
     SET_FILE_POS(0);\r
-    bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
-    Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
-    if (!bRet)\r
+\r
+    if (pPhyDrive->SizeInBytes > 2199023255552ULL)\r
     {\r
-        rc = 1;\r
-        goto End;\r
-    }\r
+        VTOY_GPT_INFO *pGptInfo;\r
+        VTOY_GPT_HDR BackupHead;\r
+        LARGE_INTEGER liCurrentPosition;\r
 \r
-    //clear boot code and partition table (reserved disk signature)\r
-    memset(MBR.BootCode, 0, 440);\r
-    memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));\r
+        pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;\r
 \r
-    VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);\r
+        VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
 \r
-    MBR.PartTbl[0].Active = 0x00; // bootable\r
-    MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512);\r
+        VentoyFillBackupGptHead(pGptInfo, &BackupHead);\r
+        if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
 \r
-    SET_FILE_POS(0);\r
-    bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);\r
-    Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
-    if (!bRet)\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);\r
+        if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        SET_FILE_POS(0);\r
+        if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        Log("Write GPT Info OK ...");\r
+    }\r
+    else\r
     {\r
-        rc = 1;\r
-        goto End;\r
+        bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
+        Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+        if (!bRet)\r
+        {\r
+            rc = 1;\r
+            goto End;\r
+        }\r
+\r
+        //clear boot code and partition table (reserved disk signature)\r
+        memset(MBR.BootCode, 0, 440);\r
+        memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));\r
+\r
+        VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);\r
+\r
+        MBR.PartTbl[0].Active = 0x00; // bootable\r
+        MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS\r
+\r
+        SET_FILE_POS(0);\r
+        bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);\r
+        Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+        if (!bRet)\r
+        {\r
+            rc = 1;\r
+            goto End;\r
+        }\r
     }\r
 \r
     Log("Clear Ventoy successfully finished");\r
@@ -1438,7 +1517,7 @@ End:
         if (state != 1)\r
         {\r
             Log("need to mount ventoy part1...");\r
-            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))\r
+            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))\r
             {\r
                 DriveName[0] = MountDrive;\r
                 bRet = SetVolumeMountPointA(DriveName, DriveLetters);\r
@@ -1463,6 +1542,236 @@ End:
     return rc;\r
 }\r
 \r
+int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)\r
+{\r
+    int i;\r
+    int rc = 1;\r
+    int Len = 0;\r
+    int dataLen = 0;\r
+    UINT size = 0;\r
+    UINT segnum = 0;\r
+    UINT32 chksum = 0;\r
+    UINT64 data_offset = 0;\r
+    UINT64 Part2StartSector = 0;\r
+    UINT64 Part1StartSector = 0;\r
+    UINT64 Part1SectorCount = 0;\r
+    UINT8 *pData = NULL;    \r
+    UINT8 *pBkGptPartTbl = NULL;\r
+    BYTE *ImgBuf = NULL;\r
+    MBR_HEAD *pMBR = NULL;\r
+    VTSI_FOOTER *pImgFooter = NULL;\r
+    VTSI_SEGMENT *pSegment = NULL;\r
+    VTOY_GPT_INFO *pGptInfo = NULL;\r
+    VTOY_GPT_HDR *pBkGptHdr = NULL;\r
+    FILE *fp = NULL;\r
+\r
+    Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",\r
+        PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
+        GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
+    size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);\r
+\r
+    pData = (UINT8 *)malloc(size);\r
+    if (!pData)\r
+    {\r
+        Log("malloc image buffer failed %d.", size);\r
+        goto End;\r
+    }\r
+\r
+    pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));\r
+    pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));\r
+    memset(pImgFooter, 0, sizeof(VTSI_FOOTER));\r
+    memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));\r
+\r
+    PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);\r
+\r
+    Log("Writing Boot Image ............................. ");\r
+    if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))\r
+    {\r
+        Log("Failed to read stage1 img");\r
+        goto End;\r
+    }\r
+\r
+    unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);\r
+    SAFE_FREE(ImgBuf);\r
+\r
+    Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG, dataLen);\r
+\r
+    if (PartStyle)\r
+    {\r
+        pData[500] = 35;//update blocklist\r
+        memmove(pData + 34 * 512, pData, SIZE_1MB - 512 * 34);\r
+        memset(pData, 0, 34 * 512);\r
+\r
+        pGptInfo = (VTOY_GPT_INFO *)pData;\r
+        memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));\r
+        VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
+\r
+        pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;\r
+        memset(pBkGptPartTbl, 0, 33 * 512);\r
+\r
+        memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);\r
+        pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);\r
+        VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);\r
+\r
+        Part1StartSector = pGptInfo->PartTbl[0].StartLBA;\r
+        Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;\r
+        Part2StartSector = pGptInfo->PartTbl[1].StartLBA;\r
+\r
+        Log("Write GPT Info OK ...");\r
+    }\r
+    else\r
+    {\r
+        memmove(pData + 512, pData, SIZE_1MB - 512);\r
+        memset(pData, 0, 512);\r
+\r
+        pMBR = (MBR_HEAD *)pData;\r
+        VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle);\r
+        Part1StartSector = pMBR->PartTbl[0].StartSectorId;\r
+        Part1SectorCount = pMBR->PartTbl[0].SectorCount;\r
+        Part2StartSector = pMBR->PartTbl[1].StartSectorId;\r
+\r
+        Log("Write MBR OK ...");\r
+    }\r
+\r
+    Log("Writing EFI part Image ............................. ");\r
+    rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);\r
+    if (rc)\r
+    {\r
+        Log("Failed to read img file %p %u", ImgBuf, Len);\r
+        goto End;\r
+    }\r
+\r
+    PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);\r
+    memset(g_part_img_buf, 0, sizeof(g_part_img_buf));\r
+    unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);\r
+    if (dataLen == Len)\r
+    {\r
+        Log("decompress finished success");\r
+        g_part_img_buf[0] = pData + SIZE_1MB;\r
+\r
+        VentoyProcSecureBoot(g_SecureBoot);\r
+    }\r
+    else\r
+    {\r
+        Log("decompress finished failed");\r
+        goto End;\r
+    }\r
+\r
+    fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");\r
+    if (!fp)\r
+    {\r
+        Log("Failed to create Ventoy img file");\r
+        goto End;\r
+    }\r
+\r
+    Log("Writing stage1 data ............................. ");\r
+\r
+    fwrite(pData, 1, SIZE_1MB, fp);\r
+\r
+    pSegment[0].disk_start_sector = 0;\r
+    pSegment[0].sector_num = SIZE_1MB / 512;\r
+    pSegment[0].data_offset = data_offset;\r
+    data_offset += pSegment[0].sector_num * 512;\r
+\r
+    disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap\r
+    disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);\r
+\r
+    Log("Formatting part1 exFAT ...");\r
+    if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))\r
+    {\r
+        Log("FormatPart1exFAT failed.");\r
+        disk_io_reset_imghook(&segnum, &data_offset);\r
+        goto End;\r
+    }\r
+\r
+    disk_io_reset_imghook(&segnum, &data_offset);\r
+    segnum++;\r
+\r
+    Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);\r
+\r
+    //write data\r
+    Log("Writing part2 data ............................. ");\r
+    fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);\r
+    pSegment[segnum].disk_start_sector = Part2StartSector;\r
+    pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;\r
+    pSegment[segnum].data_offset = data_offset;\r
+    data_offset += pSegment[segnum].sector_num * 512;\r
+    segnum++;\r
+\r
+    if (PartStyle)\r
+    {\r
+        Log("Writing backup gpt table ............................. ");\r
+        fwrite(pBkGptPartTbl, 1, 33 * 512, fp);\r
+        pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;\r
+        pSegment[segnum].sector_num = 33;\r
+        pSegment[segnum].data_offset = data_offset;\r
+        data_offset += pSegment[segnum].sector_num * 512;\r
+        segnum++;\r
+    }\r
+\r
+    Log("Writing segment metadata ............................. ");\r
+\r
+    for (i = 0; i < (int)segnum; i++)\r
+    {\r
+        Log("SEG[%d]:  PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,\r
+            pSegment[i].data_offset, pSegment[i].data_offset / 512);\r
+    }\r
+\r
+    dataLen = segnum * sizeof(VTSI_SEGMENT);\r
+    fwrite(pSegment, 1, dataLen, fp);\r
+\r
+    if (dataLen % 512)\r
+    {\r
+        //pData + SIZE_1MB - 8192 is a temp data buffer with zero\r
+        fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);\r
+    }\r
+\r
+    //Fill footer\r
+    pImgFooter->magic = VTSI_IMG_MAGIC;\r
+    pImgFooter->version = 1;\r
+    pImgFooter->disk_size = pPhyDrive->SizeInBytes;\r
+    memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);\r
+    pImgFooter->segment_num = segnum;\r
+    pImgFooter->segment_offset = data_offset;\r
+\r
+    for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)\r
+    {\r
+        chksum += *((UINT8 *)pSegment + i);\r
+    }\r
+    pImgFooter->segment_chksum = ~chksum;\r
+\r
+    for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)\r
+    {\r
+        chksum += *((UINT8 *)pImgFooter + i);\r
+    }\r
+    pImgFooter->foot_chksum = ~chksum;\r
+\r
+    Log("Writing footer segnum(%u)  segoffset(%llu) ......................", segnum, data_offset);\r
+    Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);\r
+\r
+    fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);\r
+    fclose(fp);\r
+\r
+    Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));\r
+\r
+    rc = 0;\r
+\r
+End:\r
+\r
+    PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);\r
+\r
+    Log("retcode:%d\n", rc);\r
+\r
+    SAFE_FREE(pData);\r
+    SAFE_FREE(ImgBuf);\r
+    \r
+    return rc;\r
+}\r
+\r
+\r
 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)\r
 {\r
     int i;\r
@@ -1476,6 +1785,9 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
     CHAR DriveLetters[MAX_PATH] = { 0 };\r
     MBR_HEAD MBR;\r
     VTOY_GPT_INFO *pGptInfo = NULL;\r
+    UINT64 Part1StartSector = 0;\r
+    UINT64 Part1SectorCount = 0;\r
+    UINT64 Part2StartSector = 0;\r
 \r
     Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",\r
         PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
@@ -1489,10 +1801,19 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
 \r
     PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
 \r
-    VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);//also used to format 1st partition in GPT mode\r
     if (PartStyle)\r
     {\r
         VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
+        Part1StartSector = pGptInfo->PartTbl[0].StartLBA;\r
+        Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;\r
+        Part2StartSector = pGptInfo->PartTbl[1].StartLBA;\r
+    }\r
+    else\r
+    {\r
+        VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);\r
+        Part1StartSector = MBR.PartTbl[0].StartSectorId;\r
+        Part1SectorCount = MBR.PartTbl[0].SectorCount;\r
+        Part2StartSector = MBR.PartTbl[1].StartSectorId;\r
     }\r
 \r
     Log("Lock disk for clean ............................. ");\r
@@ -1556,7 +1877,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
     //Refresh Drive Layout\r
     DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
 \r
-    disk_io_set_param(hDrive, MBR.PartTbl[0].StartSectorId + MBR.PartTbl[0].SectorCount);\r
+    disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap\r
 \r
     PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);\r
 \r
@@ -1576,7 +1897,8 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
 \r
     PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);\r
     Log("Writing part2 FAT img ...");\r
-    if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId))\r
+    \r
+    if (0 != FormatPart2Fat(hDrive, Part2StartSector))\r
     {\r
         Log("FormatPart2Fat failed.");\r
         rc = 1;\r
@@ -1584,7 +1906,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
     }\r
 \r
     PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);\r
-    Log("Writting Boot Image ............................. ");\r
+    Log("Writing Boot Image ............................. ");\r
     if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)\r
     {\r
         Log("WriteGrubStage1ToPhyDrive failed.");\r
@@ -1593,7 +1915,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
     }\r
 \r
     PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);\r
-    Log("Writting Partition Table ........................ ");\r
+    Log("Writing Partition Table ........................ ");\r
     SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
 \r
     if (PartStyle)\r
@@ -1627,6 +1949,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
         }\r
 \r
         Log("Write GPT Info OK ...");\r
+        memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);\r
     }\r
     else\r
     {\r
@@ -1637,8 +1960,8 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
             goto End;\r
         }\r
         Log("Write MBR OK ...");\r
+        memcpy(&(pPhyDrive->MBR), &MBR, 512);\r
     }\r
-    \r
 \r
     //Refresh Drive Layout\r
     DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
@@ -1675,7 +1998,8 @@ End:
         if (state != 1)\r
         {\r
             Log("need to mount ventoy part1...");\r
-            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))\r
+            \r
+            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))\r
             {\r
                 DriveName[0] = MountDrive;\r
                 bRet = SetVolumeMountPointA(DriveName, DriveLetters);\r
@@ -1719,6 +2043,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
     MBR_HEAD BootImg;\r
     MBR_HEAD MBR;\r
     VTOY_GPT_INFO *pGptInfo = NULL;\r
+    UINT8 ReservedData[4096];\r
 \r
     Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",\r
         pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
@@ -1771,6 +2096,10 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
         Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);\r
     }\r
 \r
+    //Read Reserved Data\r
+    SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);\r
+    ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);\r
+\r
     GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
 \r
     if (DriveLetters[0] == 0)\r
@@ -1814,7 +2143,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
 \r
     Log("Lock volume for update .......................... ");\r
     hVolume = INVALID_HANDLE_VALUE;\r
-       Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, (UINT32)StartSector, DriveLetters, sizeof(DriveLetters), TRUE);\r
+       Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);\r
     if (ERROR_SUCCESS == Status)\r
     {\r
         Log("Now lock and dismount volume <%s>", DriveLetters);\r
@@ -1895,6 +2224,11 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
         goto End;\r
     }\r
 \r
+    //write reserved data\r
+    SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);    \r
+    bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);\r
+    Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);\r
+\r
     // Boot Image\r
     VentoyGetLocalBootImg(&BootImg);\r
 \r