Commit c280baae authored by longpanda's avatar longpanda
Browse files

Add Ventoy Sparse Image Option

parent 425d6404
This diff is collapsed.
...@@ -72,6 +72,11 @@ typedef enum STR_ID ...@@ -72,6 +72,11 @@ typedef enum STR_ID
STR_WEB_TOKEN_MISMATCH, //37 STR_WEB_TOKEN_MISMATCH, //37
STR_WEB_SERVICE_BUSY, //38 STR_WEB_SERVICE_BUSY, //38
STR_MENU_VTSI_CREATE, //39
STR_VTSI_CREATE_TIP, //40
STR_VTSI_CREATE_SUCCESS, //41
STR_VTSI_CREATE_FAILED, //42
STR_ID_MAX STR_ID_MAX
}STR_ID; }STR_ID;
...@@ -83,7 +88,8 @@ extern BOOL g_SecureBoot; ...@@ -83,7 +88,8 @@ extern BOOL g_SecureBoot;
#define VTOY_MENU_PART_STYLE 0xA003 #define VTOY_MENU_PART_STYLE 0xA003
#define VTOY_MENU_PART_MBR 0xA004 #define VTOY_MENU_PART_MBR 0xA004
#define VTOY_MENU_PART_GPT 0xA005 #define VTOY_MENU_PART_GPT 0xA005
#define VTOY_MENU_ALL_DEV 0xA006 #define VTOY_MENU_ALL_DEV 0xA006
#define VTOY_MENU_VTSI 0xA007
typedef enum OPT_SUBMENU typedef enum OPT_SUBMENU
...@@ -93,6 +99,7 @@ typedef enum OPT_SUBMENU ...@@ -93,6 +99,7 @@ typedef enum OPT_SUBMENU
OPT_SUBMENU_PART_CFG, OPT_SUBMENU_PART_CFG,
OPT_SUBMENU_CLEAR, OPT_SUBMENU_CLEAR,
OPT_SUBMENU_ALL_DEV, OPT_SUBMENU_ALL_DEV,
OPT_SUBMENU_VTSI,
OPT_SUBMENU_MAX OPT_SUBMENU_MAX
}OPT_SUBMENU; }OPT_SUBMENU;
......
...@@ -1268,7 +1268,6 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) ...@@ -1268,7 +1268,6 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
{ {
MKFS_PARM Option; MKFS_PARM Option;
FRESULT Ret; FRESULT Ret;
FATFS fs;
Option.fmt = FM_EXFAT; Option.fmt = FM_EXFAT;
Option.n_fat = 1; Option.n_fat = 1;
...@@ -1289,28 +1288,10 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) ...@@ -1289,28 +1288,10 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
Log("Formatting Part1 exFAT ..."); Log("Formatting Part1 exFAT ...");
Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024); Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
if (FR_OK == Ret) if (FR_OK == Ret)
{ {
Log("Formatting Part1 exFAT success"); Log("Formatting Part1 exFAT success");
return 0;
Ret = f_mount(&fs, TEXT("0:"), 1);
Log("mount part %d", Ret);
if (FR_OK == Ret)
{
Ret = f_setlabel(TEXT("Ventoy"));
Log("f_setlabel %d", Ret);
Ret = f_mount(0, TEXT("0:"), 1);
Log("umount part %d", Ret);
return 0;
}
else
{
Log("mount exfat failed %d", Ret);
return 1;
}
} }
else else
{ {
...@@ -1556,6 +1537,225 @@ End: ...@@ -1556,6 +1537,225 @@ End:
return rc; return rc;
} }
int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
{
int i;
int rc = 1;
int Len = 0;
int dataLen = 0;
UINT size = 0;
UINT segnum = 0;
UINT32 chksum = 0;
UINT64 data_offset = 0;
UINT64 Part2StartSector = 0;
UINT64 Part1StartSector = 0;
UINT64 Part1SectorCount = 0;
UINT8 *pData = NULL;
UINT8 *pBkGptPartTbl = NULL;
BYTE *ImgBuf = NULL;
MBR_HEAD *pMBR = NULL;
VTSI_FOOTER *pImgFooter = NULL;
VTSI_SEGMENT *pSegment = NULL;
VTOY_GPT_INFO *pGptInfo = NULL;
VTOY_GPT_HDR *pBkGptHdr = NULL;
FILE *fp = NULL;
Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);
pData = (UINT8 *)malloc(size);
if (!pData)
{
Log("malloc image buffer failed %d.", size);
goto End;
}
pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));
pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
memset(pImgFooter, 0, sizeof(VTSI_FOOTER));
memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);
Log("Writing Boot Image ............................. ");
if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
{
Log("Failed to read stage1 img");
goto End;
}
unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);
SAFE_FREE(ImgBuf);
if (PartStyle)
{
pGptInfo = (VTOY_GPT_INFO *)pData;
memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;
memset(pBkGptPartTbl, 0, 33 * 512);
memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);
pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);
VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);
Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
Log("Write GPT Info OK ...");
}
else
{
pMBR = (MBR_HEAD *)pData;
VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle);
Part1StartSector = pMBR->PartTbl[0].StartSectorId;
Part1SectorCount = pMBR->PartTbl[0].SectorCount;
Part2StartSector = pMBR->PartTbl[1].StartSectorId;
Log("Write MBR OK ...");
}
Log("Writing EFI part Image ............................. ");
rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);
if (rc)
{
Log("Failed to read img file %p %u", ImgBuf, Len);
goto End;
}
PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);
memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);
if (dataLen == Len)
{
Log("decompress finished success");
g_part_img_buf[0] = pData + SIZE_1MB;
VentoyProcSecureBoot(g_SecureBoot);
}
else
{
Log("decompress finished failed");
goto End;
}
fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");
if (!fp)
{
Log("Failed to create Ventoy img file");
goto End;
}
Log("Writing stage1 data ............................. ");
fwrite(pData, 1, SIZE_1MB, fp);
pSegment[0].disk_start_sector = 0;
pSegment[0].sector_num = SIZE_1MB / 512;
pSegment[0].data_offset = data_offset;
data_offset += pSegment[0].sector_num * 512;
disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);
Log("Formatting part1 exFAT ...");
if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
{
Log("FormatPart1exFAT failed.");
disk_io_reset_imghook(&segnum, &data_offset);
goto End;
}
disk_io_reset_imghook(&segnum, &data_offset);
segnum++;
Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);
//write data
Log("Writing part2 data ............................. ");
fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);
pSegment[segnum].disk_start_sector = Part2StartSector;
pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;
pSegment[segnum].data_offset = data_offset;
data_offset += pSegment[segnum].sector_num * 512;
segnum++;
if (PartStyle)
{
Log("Writing backup gpt table ............................. ");
fwrite(pBkGptPartTbl, 1, 33 * 512, fp);
pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;
pSegment[segnum].sector_num = 33;
pSegment[segnum].data_offset = data_offset;
data_offset += pSegment[segnum].sector_num * 512;
segnum++;
}
Log("Writing segment metadata ............................. ");
for (i = 0; i < (int)segnum; i++)
{
Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,
pSegment[i].data_offset, pSegment[i].data_offset / 512);
}
dataLen = segnum * sizeof(VTSI_SEGMENT);
fwrite(pSegment, 1, dataLen, fp);
if (dataLen % 512)
{
//pData + SIZE_1MB - 8192 is a temp data buffer with zero
fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);
}
//Fill footer
pImgFooter->magic = VTSI_IMG_MAGIC;
pImgFooter->version = 1;
pImgFooter->disk_size = pPhyDrive->SizeInBytes;
memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);
pImgFooter->segment_num = segnum;
pImgFooter->segment_offset = data_offset;
for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)
{
chksum += *((UINT8 *)pSegment + i);
}
pImgFooter->segment_chksum = ~chksum;
for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)
{
chksum += *((UINT8 *)pImgFooter + i);
}
pImgFooter->foot_chksum = ~chksum;
Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum, data_offset);
Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);
fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);
fclose(fp);
Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));
rc = 0;
End:
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
Log("retcode:%d\n", rc);
SAFE_FREE(pData);
SAFE_FREE(ImgBuf);
return rc;
}
int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
{ {
int i; int i;
...@@ -1573,7 +1773,6 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) ...@@ -1573,7 +1773,6 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
UINT64 Part1SectorCount = 0; UINT64 Part1SectorCount = 0;
UINT64 Part2StartSector = 0; UINT64 Part2StartSector = 0;
Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>", Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
...@@ -1680,8 +1879,6 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) ...@@ -1680,8 +1879,6 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
goto End; goto End;
} }
PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
Log("Writing part2 FAT img ..."); Log("Writing part2 FAT img ...");
......
...@@ -28,6 +28,7 @@ DWORD g_PhyDriveCount = 0; ...@@ -28,6 +28,7 @@ DWORD g_PhyDriveCount = 0;
static int g_FilterRemovable = 0; static int g_FilterRemovable = 0;
int g_FilterUSB = 1; int g_FilterUSB = 1;
int g_ForceOperation = 1; int g_ForceOperation = 1;
int g_WriteImage = 0;
int ParseCmdLineOption(LPSTR lpCmdLine) int ParseCmdLineOption(LPSTR lpCmdLine)
{ {
......
...@@ -233,4 +233,61 @@ UINT32 VentoyCrc32(void *Buffer, UINT32 Length); ...@@ -233,4 +233,61 @@ UINT32 VentoyCrc32(void *Buffer, UINT32 Length);
#define SECURE_ICON_STRING _UICON(UNICODE_LOCK) #define SECURE_ICON_STRING _UICON(UNICODE_LOCK)
extern int g_WriteImage;
#define VTSI_IMG_MAGIC 0x0000594F544E4556ULL // "VENTOY\0\0"
#pragma pack(1)
/*
+---------------------------------
+ sector 0 ~ sector N-1
+ data area
+---------------------------------
+ sector N ~
+ segment[0]
+ segment[1]
+ segment[2]
+ ......
+ segment[M-1]
+ align data (aligned with 512)
+---------------------------------
+ footer
+---------------------------------
*
* All the integers are in little endian
* The sector size is fixed 512 for ventoy image file.
*
*/
#define VTSI_IMG_MAX_SEG 128
typedef struct {
UINT64 disk_start_sector;
UINT64 sector_num;
UINT64 data_offset;
}VTSI_SEGMENT;
typedef struct {
UINT64 magic;
UINT32 version;
UINT64 disk_size;
UINT32 disk_signature;
UINT32 foot_chksum;
UINT32 segment_num;
UINT32 segment_chksum;
UINT64 segment_offset;
UINT8 reserved[512 - 44];
}VTSI_FOOTER;
#pragma pack()
extern int __static_assert__[sizeof(VTSI_FOOTER) == 512 ? 1 : -1];
#define SAFE_FREE(ptr) if (ptr) { free(ptr); (ptr) = NULL; }
int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle);
void disk_io_set_imghook(FILE *fp, VTSI_SEGMENT *segment, int maxseg, UINT64 data_offset);
void disk_io_reset_imghook(int *psegnum, UINT64 *pDataOffset);
#endif #endif
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "ff.h" /* Obtains integer types */ #include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */ #include "diskio.h" /* Declarations of disk functions */
#include "../Ventoy2Disk.h"
/* Definitions of physical drive number for each drive */ /* Definitions of physical drive number for each drive */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */ #define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
...@@ -23,12 +25,41 @@ static UINT8 g_MbrSector[512]; ...@@ -23,12 +25,41 @@ static UINT8 g_MbrSector[512];
HANDLE g_hPhyDrive; HANDLE g_hPhyDrive;
UINT64 g_SectorCount; UINT64 g_SectorCount;
FILE *g_VentoyImgFp = NULL;
VTSI_SEGMENT *g_VentoySegment = NULL;
int g_VentoyMaxSeg = 0;
int g_VentoyCurSeg = -1;
UINT64 g_VentoyDataOffset = 0;
void disk_io_set_param(HANDLE Handle, UINT64 SectorCount) void disk_io_set_param(HANDLE Handle, UINT64 SectorCount)
{ {
g_hPhyDrive = Handle; g_hPhyDrive = Handle;
g_SectorCount = SectorCount; g_SectorCount = SectorCount;
} }
void disk_io_set_imghook(FILE *fp, VTSI_SEGMENT *segment, int maxseg, UINT64 data_offset)
{
g_VentoyImgFp = fp;
g_VentoySegment = segment;
g_VentoyMaxSeg = maxseg;
memset(segment, 0, maxseg * sizeof(VTSI_SEGMENT));
g_VentoyCurSeg = -1;
g_VentoyDataOffset = data_offset;
}
void disk_io_reset_imghook(int *psegnum, UINT64 *pDataOffset)
{
*psegnum = g_VentoyCurSeg + 1;
*pDataOffset = g_VentoyDataOffset;
g_VentoyImgFp = NULL;
g_VentoySegment = NULL;
g_VentoyMaxSeg = 0;
g_VentoyCurSeg = -1;
g_VentoyDataOffset = 0;
}
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Get Drive Status */ /* Get Drive Status */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
...@@ -126,6 +157,13 @@ DRESULT disk_read ( ...@@ -126,6 +157,13 @@ DRESULT disk_read (
BOOL bRet; BOOL bRet;
LARGE_INTEGER liCurrentPosition; LARGE_INTEGER liCurrentPosition;
//Log("xxx disk_read: sector:%ld count:%ld", (long)sector, (long)count);
if (g_VentoyImgFp)
{
return RES_OK;
}
liCurrentPosition.QuadPart = sector * 512; liCurrentPosition.QuadPart = sector * 512;
SetFilePointerEx(g_hPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); SetFilePointerEx(g_hPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
...@@ -162,6 +200,9 @@ DRESULT disk_write ( ...@@ -162,6 +200,9 @@ DRESULT disk_write (
DWORD dwSize; DWORD dwSize;
BOOL bRet; BOOL bRet;
LARGE_INTEGER liCurrentPosition; LARGE_INTEGER liCurrentPosition;
VTSI_SEGMENT *CurSeg = NULL;
Log("==== disk_write: sector:%ld count:%ld", (long)sector, (long)count);
// skip MBR // skip MBR
if (sector == 0) if (sector == 0)
...@@ -177,6 +218,31 @@ DRESULT disk_write ( ...@@ -177,6 +218,31 @@ DRESULT disk_write (
count--; count--;
} }
if (g_VentoyImgFp)
{
CurSeg = g_VentoySegment + g_VentoyCurSeg;
if (g_VentoyCurSeg >= 0 && CurSeg->sector_num > 0 && sector == CurSeg->disk_start_sector + CurSeg->sector_num)
{
CurSeg->sector_num += count; //merge
}
else
{
g_VentoyCurSeg++;
CurSeg++;
CurSeg->disk_start_sector = sector;
CurSeg->data_offset = g_VentoyDataOffset;
CurSeg->sector_num = count;
}
g_VentoyDataOffset += count * 512;
fwrite(buff, 1, count * 512, g_VentoyImgFp);
return RES_OK;
}
liCurrentPosition.QuadPart = sector * 512; liCurrentPosition.QuadPart = sector * 512;
SetFilePointerEx(g_hPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); SetFilePointerEx(g_hPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
......
...@@ -6067,6 +6067,11 @@ FRESULT f_mkfs ( ...@@ -6067,6 +6067,11 @@ FRESULT f_mkfs (
/* Initialize the root directory */ /* Initialize the root directory */
mem_set(buf, 0, sz_buf * ss); mem_set(buf, 0, sz_buf * ss);
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */ buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */
//default label: Ventoy (unicode)
buf[1] = 6; //label length
memcpy(buf + 2, L"Ventoy", 2 * buf[1]);
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment