Commit b0568922 authored by longpanda's avatar longpanda
Browse files

1.0.60 release

parent 69b6bb8f
/******************************************************************************
* partresize.c ---- ventoy part resize util
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fat_filelib.h>
#include "vtoycli.h"
static int g_disk_fd = 0;
static UINT64 g_disk_offset = 0;
static GUID g_ZeroGuid = {0};
static GUID g_WindowsDataPartGuid = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
static int vtoy_disk_read(uint32 sector, uint8 *buffer, uint32 sector_count)
{
UINT64 offset = sector * 512ULL;
lseek(g_disk_fd, g_disk_offset + offset, SEEK_SET);
read(g_disk_fd, buffer, sector_count * 512);
return 1;
}
static int vtoy_disk_write(uint32 sector, uint8 *buffer, uint32 sector_count)
{
UINT64 offset = sector * 512ULL;
lseek(g_disk_fd, g_disk_offset + offset, SEEK_SET);
write(g_disk_fd, buffer, sector_count * 512);
return 1;
}
static int gpt_check(const char *disk)
{
int fd = -1;
int rc = 1;
VTOY_GPT_INFO *pGPT = NULL;
fd = open(disk, O_RDONLY);
if (fd < 0)
{
printf("Failed to open %s\n", disk);
goto out;
}
pGPT = malloc(sizeof(VTOY_GPT_INFO));
if (NULL == pGPT)
{
goto out;
}
memset(pGPT, 0, sizeof(VTOY_GPT_INFO));
read(fd, pGPT, sizeof(VTOY_GPT_INFO));
if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
{
rc = 0;
}
out:
check_close(fd);
check_free(pGPT);
return rc;
}
static int part_check(const char *disk)
{
int i;
int fd = -1;
int rc = 0;
int Index = 0;
int Count = 0;
int PartStyle = 0;
UINT64 Part1Start;
UINT64 Part1End;
UINT64 NextPartStart;
UINT64 DiskSizeInBytes;
VTOY_GPT_INFO *pGPT = NULL;
DiskSizeInBytes = get_disk_size_in_byte(disk);
if (DiskSizeInBytes == 0)
{
printf("Failed to get disk size of %s\n", disk);
goto out;
}
fd = open(disk, O_RDONLY);
if (fd < 0)
{
printf("Failed to open %s\n", disk);
goto out;
}
pGPT = malloc(sizeof(VTOY_GPT_INFO));
if (NULL == pGPT)
{
goto out;
}
memset(pGPT, 0, sizeof(VTOY_GPT_INFO));
read(fd, pGPT, sizeof(VTOY_GPT_INFO));
if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
{
PartStyle = 1;
}
else
{
PartStyle = 0;
}
if (PartStyle == 0)
{
PART_TABLE *PartTbl = pGPT->MBR.PartTbl;
for (Count = 0, i = 0; i < 4; i++)
{
if (PartTbl[i].SectorCount > 0)
{
printf("MBR Part%d SectorStart:%u SectorCount:%u\n", i + 1, PartTbl[i].StartSectorId, PartTbl[i].SectorCount);
Count++;
}
}
//We must have a free partition table for VTOYEFI partition
if (Count >= 4)
{
printf("###[FAIL] 4 MBR partition tables are all used.\n");
goto out;
}
if (PartTbl[0].SectorCount > 0)
{
Part1Start = PartTbl[0].StartSectorId;
Part1End = PartTbl[0].SectorCount + Part1Start;
}
else
{
printf("###[FAIL] MBR Partition 1 is invalid\n");
goto out;
}
Index = -1;
NextPartStart = DiskSizeInBytes / 512ULL;
for (i = 1; i < 4; i++)
{
if (PartTbl[i].SectorCount > 0 && NextPartStart > PartTbl[i].StartSectorId)
{
Index = i;
NextPartStart = PartTbl[i].StartSectorId;
}
}
NextPartStart *= 512ULL;
printf("DiskSize:%llu NextPartStart:%llu(LBA:%llu) Index:%d\n",
DiskSizeInBytes, NextPartStart, NextPartStart / 512ULL, Index);
}
else
{
VTOY_GPT_PART_TBL *PartTbl = pGPT->PartTbl;
for (Count = 0, i = 0; i < 128; i++)
{
if (memcmp(&(PartTbl[i].PartGuid), &g_ZeroGuid, sizeof(GUID)))
{
printf("GPT Part%d StartLBA:%llu LastLBA:%llu\n", i + 1, PartTbl[i].StartLBA, PartTbl[i].LastLBA);
Count++;
}
}
if (Count >= 128)
{
printf("###[FAIL] 128 GPT partition tables are all used.\n");
goto out;
}
if (memcmp(&(PartTbl[0].PartGuid), &g_ZeroGuid, sizeof(GUID)))
{
Part1Start = PartTbl[0].StartLBA;
Part1End = PartTbl[0].LastLBA + 1;
}
else
{
printf("###[FAIL] GPT Partition 1 is invalid\n");
goto out;
}
Index = -1;
NextPartStart = (pGPT->Head.PartAreaEndLBA + 1);
for (i = 1; i < 128; i++)
{
if (memcmp(&(PartTbl[i].PartGuid), &g_ZeroGuid, sizeof(GUID)) && NextPartStart > PartTbl[i].StartLBA)
{
Index = i;
NextPartStart = PartTbl[i].StartLBA;
}
}
NextPartStart *= 512ULL;
printf("DiskSize:%llu NextPartStart:%llu(LBA:%llu) Index:%d\n",
DiskSizeInBytes, NextPartStart, NextPartStart / 512ULL, Index);
}
printf("Valid partition table (%s): Valid partition count:%d\n", (PartStyle == 0) ? "MBR" : "GPT", Count);
//Partition 1 MUST start at 1MB
Part1Start *= 512ULL;
Part1End *= 512ULL;
printf("Partition 1 start at: %llu %lluKB, end:%llu, NextPartStart:%llu\n",
Part1Start, Part1Start / 1024, Part1End, NextPartStart);
if (Part1Start != SIZE_1MB)
{
printf("###[FAIL] Partition 1 is not start at 1MB\n");
goto out;
}
//If we have free space after partition 1
if (NextPartStart - Part1End >= VENTOY_EFI_PART_SIZE)
{
printf("Free space after partition 1 (%llu) is enough for VTOYEFI part\n", NextPartStart - Part1End);
rc = 1;
}
else if (NextPartStart == Part1End)
{
printf("There is no free space after partition 1\n");
rc = 2;
}
else
{
printf("The free space after partition 1 is not enough\n");
rc = 2;
}
out:
check_close(fd);
check_free(pGPT);
return rc;
}
static int secureboot_proc(char *disk, UINT64 part2start)
{
int rc = 0;
int size;
int fd = -1;
char *filebuf = NULL;
void *file = NULL;
fd = open(disk, O_RDWR);
if (fd < 0)
{
printf("Failed to open %s\n", disk);
return 1;
}
g_disk_fd = fd;
g_disk_offset = part2start * 512ULL;
fl_init();
if (0 == fl_attach_media(vtoy_disk_read, vtoy_disk_write))
{
file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
printf("Open ventoy efi file %p\n", file);
if (file)
{
fl_fseek(file, 0, SEEK_END);
size = (int)fl_ftell(file);
fl_fseek(file, 0, SEEK_SET);
printf("ventoy x64 efi file size %d ...\n", size);
filebuf = (char *)malloc(size);
if (filebuf)
{
fl_fread(filebuf, 1, size, file);
}
fl_fclose(file);
fl_remove("/EFI/BOOT/BOOTX64.EFI");
fl_remove("/EFI/BOOT/grubx64.efi");
fl_remove("/EFI/BOOT/grubx64_real.efi");
fl_remove("/EFI/BOOT/MokManager.efi");
fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
printf("Open bootx64 efi file %p\n", file);
if (file)
{
if (filebuf)
{
fl_fwrite(filebuf, 1, size, file);
}
fl_fflush(file);
fl_fclose(file);
}
if (filebuf)
{
free(filebuf);
}
}
file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
printf("Open ventoy ia32 efi file %p\n", file);
if (file)
{
fl_fseek(file, 0, SEEK_END);
size = (int)fl_ftell(file);
fl_fseek(file, 0, SEEK_SET);
printf("ventoy efi file size %d ...\n", size);
filebuf = (char *)malloc(size);
if (filebuf)
{
fl_fread(filebuf, 1, size, file);
}
fl_fclose(file);
fl_remove("/EFI/BOOT/BOOTIA32.EFI");
fl_remove("/EFI/BOOT/grubia32.efi");
fl_remove("/EFI/BOOT/grubia32_real.efi");
fl_remove("/EFI/BOOT/mmia32.efi");
file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
printf("Open bootia32 efi file %p\n", file);
if (file)
{
if (filebuf)
{
fl_fwrite(filebuf, 1, size, file);
}
fl_fflush(file);
fl_fclose(file);
}
if (filebuf)
{
free(filebuf);
}
}
}
else
{
rc = 1;
}
fl_shutdown();
fsync(fd);
return rc;
}
static int VentoyFillMBRLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table)
{
UINT8 Head;
UINT8 Sector;
UINT8 nSector = 63;
UINT8 nHead = 8;
UINT32 Cylinder;
UINT32 EndSectorId;
while (nHead != 0 && (DiskSizeInBytes / 512 / nSector / nHead) > 1024)
{
nHead = (UINT8)nHead * 2;
}
if (nHead == 0)
{
nHead = 255;
}
Cylinder = StartSectorId / nSector / nHead;
Head = StartSectorId / nSector % nHead;
Sector = StartSectorId % nSector + 1;
Table->StartHead = Head;
Table->StartSector = Sector;
Table->StartCylinder = Cylinder;
EndSectorId = StartSectorId + SectorCount - 1;
Cylinder = EndSectorId / nSector / nHead;
Head = EndSectorId / nSector % nHead;
Sector = EndSectorId % nSector + 1;
Table->EndHead = Head;
Table->EndSector = Sector;
Table->EndCylinder = Cylinder;
Table->StartSectorId = StartSectorId;
Table->SectorCount = SectorCount;
return 0;
}
static int WriteDataToPhyDisk(int fd, UINT64 offset, void *buffer, int len)
{
ssize_t wrlen;
off_t newseek;
newseek = lseek(fd, offset, SEEK_SET);
if (newseek != offset)
{
printf("Failed to lseek %llu %lld %d\n", offset, (long long)newseek, errno);
return 0;
}
wrlen = write(fd, buffer, len);
if ((int)wrlen != len)
{
printf("Failed to write %d %d %d\n", len, (int)wrlen, errno);
return 0;
}
return 1;
}
static int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead)
{
UINT64 LBA;
UINT64 BackupLBA;
memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR));
LBA = pHead->EfiStartLBA;
BackupLBA = pHead->EfiBackupLBA;
pHead->EfiStartLBA = BackupLBA;
pHead->EfiBackupLBA = LBA;
pHead->PartTblStartLBA = BackupLBA + 1 - 33;
pHead->Crc = 0;
pHead->Crc = VtoyCrc32(pHead, pHead->Length);
return 0;
}
static int update_part_table(char *disk, UINT64 part2start)
{
int i;
int j;
int fd = -1;
int rc = 1;
int PartStyle = 0;
ssize_t len = 0;
UINT64 DiskSizeInBytes;
VTOY_GPT_INFO *pGPT = NULL;
VTOY_GPT_HDR *pBack = NULL;
DiskSizeInBytes = get_disk_size_in_byte(disk);
if (DiskSizeInBytes == 0)
{
printf("Failed to get disk size of %s\n", disk);
goto out;
}
fd = open(disk, O_RDWR);
if (fd < 0)
{
printf("Failed to open %s\n", disk);
goto out;
}
pGPT = malloc(sizeof(VTOY_GPT_INFO) + sizeof(VTOY_GPT_HDR));
if (NULL == pGPT)
{
goto out;
}
memset(pGPT, 0, sizeof(VTOY_GPT_INFO) + sizeof(VTOY_GPT_HDR));
pBack = (VTOY_GPT_HDR *)(pGPT + 1);
len = read(fd, pGPT, sizeof(VTOY_GPT_INFO));
if (len != (ssize_t)sizeof(VTOY_GPT_INFO))
{
printf("Failed to read partition table %d err:%d\n", (int)len, errno);
goto out;
}
if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
{
PartStyle = 1;
}
else
{
PartStyle = 0;
}
if (PartStyle == 0)
{
PART_TABLE *PartTbl = pGPT->MBR.PartTbl;
for (i = 1; i < 4; i++)
{
if (PartTbl[i].SectorCount == 0)
{
break;
}
}
if (i >= 4)
{
printf("###[FAIL] Can not find a free MBR partition table.\n");
goto out;
}
for (j = i - 1; j > 0; j--)
{
printf("Move MBR partition table %d --> %d\n", j + 1, j + 2);
memcpy(PartTbl + (j + 1), PartTbl + j, sizeof(PART_TABLE));
}
memset(PartTbl + 1, 0, sizeof(PART_TABLE));
VentoyFillMBRLocation(DiskSizeInBytes, (UINT32)part2start, VENTOY_EFI_PART_SIZE / 512, PartTbl + 1);
PartTbl[1].Active = 0x00;
PartTbl[1].FsFlag = 0xEF; // EFI System Partition
PartTbl[0].Active = 0x80; // bootable
PartTbl[0].SectorCount = (UINT32)part2start - 2048;
if (!WriteDataToPhyDisk(fd, 0, &(pGPT->MBR), 512))
{
printf("MBR write MBR failed\n");
goto out;
}
fsync(fd);
printf("MBR update partition table success.\n");
rc = 0;
}
else
{
VTOY_GPT_PART_TBL *PartTbl = pGPT->PartTbl;
for (i = 1; i < 128; i++)
{
if (memcmp(&(PartTbl[i].PartGuid), &g_ZeroGuid, sizeof(GUID)) == 0)
{
break;
}
}
if (i >= 128)
{
printf("###[FAIL] Can not find a free GPT partition table.\n");
goto out;
}
for (j = i - 1; j > 0; j--)
{
printf("Move GPT partition table %d --> %d\n", j + 1, j + 2);
memcpy(PartTbl + (j + 1), PartTbl + j, sizeof(VTOY_GPT_PART_TBL));
}
// to fix windows issue
memset(PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL));
memcpy(&(PartTbl[1].PartType), &g_WindowsDataPartGuid, sizeof(GUID));
ventoy_gen_preudo_uuid(&(PartTbl[1].PartGuid));
PartTbl[0].LastLBA = part2start - 1;
PartTbl[1].StartLBA = PartTbl[0].LastLBA + 1;
PartTbl[1].LastLBA = PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;
PartTbl[1].Attr = 0xC000000000000001ULL;
PartTbl[1].Name[0] = 'V';
PartTbl[1].Name[1] = 'T';
PartTbl[1].Name[2] = 'O';
PartTbl[1].Name[3] = 'Y';
PartTbl[1].Name[4] = 'E';
PartTbl[1].Name[5] = 'F';
PartTbl[1].Name[6] = 'I';
PartTbl[1].Name[7] = 0;
//Update CRC
pGPT->Head.PartTblCrc = VtoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));
pGPT->Head.Crc = 0;
pGPT->Head.Crc = VtoyCrc32(&(pGPT->Head), pGPT->Head.Length);
printf("pGPT->Head.EfiStartLBA=%llu\n", pGPT->Head.EfiStartLBA);
printf("pGPT->Head.EfiBackupLBA=%llu\n", pGPT->Head.EfiBackupLBA);
VentoyFillBackupGptHead(pGPT, pBack);
if (!WriteDataToPhyDisk(fd, pGPT->Head.EfiBackupLBA * 512, pBack, 512))
{
printf("GPT write backup head failed\n");
goto out;
}
if (!WriteDataToPhyDisk(fd, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32))
{
printf("GPT write backup partition table failed\n");
goto out;
}
if (!WriteDataToPhyDisk(fd, 0, pGPT, 512 * 34))
{
printf("GPT write MBR & Main partition table failed\n");
goto out;
}
fsync(fd);
printf("GPT update partition table success.\n");
rc = 0;
}
out:
check_close(fd);
check_free(pGPT);
return rc;
}
int partresize_main(int argc, char **argv)
{
UINT64 sector;
if (argc != 3 && argc != 4)
{
printf("usage: partresize -c/-f /dev/sdb\n");
return 1;
}
if (strcmp(argv[1], "-c") == 0)
{
return part_check(argv[2]);
}
else if (strcmp(argv[1], "-s") == 0)
{
sector = strtoull(argv[3], NULL, 10);
return secureboot_proc(argv[2], sector);
}
else if (strcmp(argv[1], "-p") == 0)
{
sector = strtoull(argv[3], NULL, 10);
return update_part_table(argv[2], sector);
}
else if (strcmp(argv[1], "-t") == 0)
{
return gpt_check(argv[2]);
}
else
{
return 1;
}
}
/******************************************************************************
* vtoycli.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include "vtoycli.h"
void ventoy_gen_preudo_uuid(void *uuid)
{
int i;
int fd;
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
{
srand(time(NULL));
for (i = 0; i < 8; i++)
{
*((uint16_t *)uuid + i) = (uint16_t)(rand() & 0xFFFF);
}
}
else
{
read(fd, uuid, 16);
close(fd);
}
}
UINT64 get_disk_size_in_byte(const char *disk)
{
int fd;
int rc;
const char *pos = disk;
unsigned long long size = 0;
char diskpath[256] = {0};
char sizebuf[64] = {0};
if (strncmp(disk, "/dev/", 5) == 0)
{
pos = disk + 5;
}
// Try 1: get size from sysfs
snprintf(diskpath, sizeof(diskpath) - 1, "/sys/block/%s/size", pos);
if (access(diskpath, F_OK) >= 0)
{
fd = open(diskpath, O_RDONLY);
if (fd >= 0)
{
read(fd, sizebuf, sizeof(sizebuf));
size = strtoull(sizebuf, NULL, 10);
close(fd);
return (size * 512);
}
}
else
{
printf("%s not exist \n", diskpath);
}
printf("disk %s size %llu bytes\n", disk, (unsigned long long)size);
return size;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
return 1;
}
else if (strcmp(argv[1], "fat") == 0)
{
return vtoyfat_main(argc - 1, argv + 1);
}
else if (strcmp(argv[1], "gpt") == 0)
{
return vtoygpt_main(argc - 1, argv + 1);
}
else if (strcmp(argv[1], "partresize") == 0)
{
return partresize_main(argc - 1, argv + 1);
}
else
{
return 1;
}
}
/******************************************************************************
* vtoycli.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VTOYCLI_H__
#define __VTOYCLI_H__
#define VENTOY_EFI_PART_ATTR 0xC000000000000001ULL
#define SIZE_1MB (1024 * 1024)
#define VENTOY_EFI_PART_SIZE (32 * SIZE_1MB)
#define check_free(p) if (p) free(p)
#define check_close(fd) if (fd >= 0) close(fd)
#define VOID void
#define CHAR char
#define UINT64 unsigned long long
#define UINT32 unsigned int
#define UINT16 unsigned short
#define CHAR16 unsigned short
#define UINT8 unsigned char
UINT32 VtoyCrc32(VOID *Buffer, UINT32 Length);
#define COMPILE_ASSERT(expr) extern char __compile_assert[(expr) ? 1 : -1]
#pragma pack(1)
typedef struct PART_TABLE
{
UINT8 Active;
UINT8 StartHead;
UINT16 StartSector : 6;
UINT16 StartCylinder : 10;
UINT8 FsFlag;
UINT8 EndHead;
UINT16 EndSector : 6;
UINT16 EndCylinder : 10;
UINT32 StartSectorId;
UINT32 SectorCount;
}PART_TABLE;
typedef struct MBR_HEAD
{
UINT8 BootCode[446];
PART_TABLE PartTbl[4];
UINT8 Byte55;
UINT8 ByteAA;
}MBR_HEAD;
typedef struct GUID
{
UINT32 data1;
UINT16 data2;
UINT16 data3;
UINT8 data4[8];
}GUID;
typedef struct VTOY_GPT_HDR
{
CHAR Signature[8]; /* EFI PART */
UINT8 Version[4];
UINT32 Length;
UINT32 Crc;
UINT8 Reserved1[4];
UINT64 EfiStartLBA;
UINT64 EfiBackupLBA;
UINT64 PartAreaStartLBA;
UINT64 PartAreaEndLBA;
GUID DiskGuid;
UINT64 PartTblStartLBA;
UINT32 PartTblTotNum;
UINT32 PartTblEntryLen;
UINT32 PartTblCrc;
UINT8 Reserved2[420];
}VTOY_GPT_HDR;
COMPILE_ASSERT(sizeof(VTOY_GPT_HDR) == 512);
typedef struct VTOY_GPT_PART_TBL
{
GUID PartType;
GUID PartGuid;
UINT64 StartLBA;
UINT64 LastLBA;
UINT64 Attr;
CHAR16 Name[36];
}VTOY_GPT_PART_TBL;
COMPILE_ASSERT(sizeof(VTOY_GPT_PART_TBL) == 128);
typedef struct VTOY_GPT_INFO
{
MBR_HEAD MBR;
VTOY_GPT_HDR Head;
VTOY_GPT_PART_TBL PartTbl[128];
}VTOY_GPT_INFO;
typedef struct VTOY_BK_GPT_INFO
{
VTOY_GPT_PART_TBL PartTbl[128];
VTOY_GPT_HDR Head;
}VTOY_BK_GPT_INFO;
COMPILE_ASSERT(sizeof(VTOY_GPT_INFO) == 512 * 34);
COMPILE_ASSERT(sizeof(VTOY_BK_GPT_INFO) == 512 * 33);
#pragma pack()
UINT32 VtoyCrc32(VOID *Buffer, UINT32 Length);
int vtoygpt_main(int argc, char **argv);
int vtoyfat_main(int argc, char **argv);
int partresize_main(int argc, char **argv);
void ventoy_gen_preudo_uuid(void *uuid);
UINT64 get_disk_size_in_byte(const char *disk);
#endif /* __VTOYCLI_H__ */
/******************************************************************************
* vtoyfat.c ---- Parse fat file system
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fat_filelib.h>
static int g_disk_fd = 0;
static int vtoy_disk_read(uint32 sector, uint8 *buffer, uint32 sector_count)
{
lseek(g_disk_fd, sector * 512, SEEK_SET);
read(g_disk_fd, buffer, sector_count * 512);
return 1;
}
static int check_secure_boot(void)
{
void *flfile = NULL;
flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
if (flfile)
{
fl_fclose(flfile);
return 0;
}
return 1;
}
static int get_ventoy_version(void)
{
int rc = 1;
int size = 0;
char *buf = NULL;
char *pos = NULL;
char *end = NULL;
void *flfile = NULL;
flfile = fl_fopen("/grub/grub.cfg", "rb");
if (flfile)
{
fl_fseek(flfile, 0, SEEK_END);
size = (int)fl_ftell(flfile);
fl_fseek(flfile, 0, SEEK_SET);
buf = malloc(size + 1);
if (buf)
{
fl_fread(buf, 1, size, flfile);
buf[size] = 0;
pos = strstr(buf, "VENTOY_VERSION=");
if (pos)
{
pos += strlen("VENTOY_VERSION=");
if (*pos == '"')
{
pos++;
}
end = pos;
while (*end != 0 && *end != '"' && *end != '\r' && *end != '\n')
{
end++;
}
*end = 0;
printf("%s\n", pos);
rc = 0;
}
free(buf);
}
fl_fclose(flfile);
}
return rc;
}
int vtoyfat_main(int argc, char **argv)
{
int op = 0;
int rc = 1;
char *disk;
if (argc != 2 && argc != 3)
{
printf("Usage: vtoyfat /dev/sdbs \n");
printf("Usage: vtoyfat -s /dev/sdbs \n");
return 1;
}
if (argv[1][0] == '-' && argv[1][1] == 'T')
{
return 0;
}
disk = argv[1];
if (argv[1][0] == '-' && argv[1][1] == 's')
{
op = 1;
disk = argv[2];
}
g_disk_fd = open(disk, O_RDONLY);
if (g_disk_fd < 0)
{
printf("Failed to open %s\n", disk);
return 1;
}
fl_init();
if (0 == fl_attach_media(vtoy_disk_read, NULL))
{
if (op == 0)
{
rc = get_ventoy_version();
}
else
{
rc = check_secure_boot();
}
}
fl_shutdown();
close(g_disk_fd);
return rc;
}
/******************************************************************************
* vtoygpt.c ---- ventoy gpt util
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include "vtoycli.h"
void DumpGuid(const char *prefix, GUID *guid)
{
printf("%s: %08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
prefix,
guid->data1, guid->data2, guid->data3,
guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3],
guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]
);
}
void DumpHead(VTOY_GPT_HDR *pHead)
{
UINT32 CrcRead;
UINT32 CrcCalc;
printf("Signature:<%s>\n", pHead->Signature);
printf("Version:<%02x %02x %02x %02x>\n", pHead->Version[0], pHead->Version[1], pHead->Version[2], pHead->Version[3]);
printf("Length:%u\n", pHead->Length);
printf("Crc:0x%08x\n", pHead->Crc);
printf("EfiStartLBA:%lu\n", pHead->EfiStartLBA);
printf("EfiBackupLBA:%lu\n", pHead->EfiBackupLBA);
printf("PartAreaStartLBA:%lu\n", pHead->PartAreaStartLBA);
printf("PartAreaEndLBA:%lu\n", pHead->PartAreaEndLBA);
DumpGuid("DiskGuid", &pHead->DiskGuid);
printf("PartTblStartLBA:%lu\n", pHead->PartTblStartLBA);
printf("PartTblTotNum:%u\n", pHead->PartTblTotNum);
printf("PartTblEntryLen:%u\n", pHead->PartTblEntryLen);
printf("PartTblCrc:0x%08x\n", pHead->PartTblCrc);
CrcRead = pHead->Crc;
pHead->Crc = 0;
CrcCalc = VtoyCrc32(pHead, pHead->Length);
if (CrcCalc != CrcRead)
{
printf("Head CRC Check Failed\n");
}
else
{
printf("Head CRC Check SUCCESS [%x] [%x]\n", CrcCalc, CrcRead);
}
CrcRead = pHead->PartTblCrc;
CrcCalc = VtoyCrc32(pHead + 1, pHead->PartTblEntryLen * pHead->PartTblTotNum);
if (CrcCalc != CrcRead)
{
printf("Part Table CRC Check Failed\n");
}
else
{
printf("Part Table CRC Check SUCCESS [%x] [%x]\n", CrcCalc, CrcRead);
}
}
void DumpPartTable(VTOY_GPT_PART_TBL *Tbl)
{
int i;
DumpGuid("PartType", &Tbl->PartType);
DumpGuid("PartGuid", &Tbl->PartGuid);
printf("StartLBA:%lu\n", Tbl->StartLBA);
printf("LastLBA:%lu\n", Tbl->LastLBA);
printf("Attr:0x%lx\n", Tbl->Attr);
printf("Name:");
for (i = 0; i < 36 && Tbl->Name[i]; i++)
{
printf("%c", (CHAR)(Tbl->Name[i]));
}
printf("\n");
}
void DumpMBR(MBR_HEAD *pMBR)
{
int i;
for (i = 0; i < 4; i++)
{
printf("=========== Partition Table %d ============\n", i + 1);
printf("PartTbl.Active = 0x%x\n", pMBR->PartTbl[i].Active);
printf("PartTbl.FsFlag = 0x%x\n", pMBR->PartTbl[i].FsFlag);
printf("PartTbl.StartSectorId = %u\n", pMBR->PartTbl[i].StartSectorId);
printf("PartTbl.SectorCount = %u\n", pMBR->PartTbl[i].SectorCount);
printf("PartTbl.StartHead = %u\n", pMBR->PartTbl[i].StartHead);
printf("PartTbl.StartSector = %u\n", pMBR->PartTbl[i].StartSector);
printf("PartTbl.StartCylinder = %u\n", pMBR->PartTbl[i].StartCylinder);
printf("PartTbl.EndHead = %u\n", pMBR->PartTbl[i].EndHead);
printf("PartTbl.EndSector = %u\n", pMBR->PartTbl[i].EndSector);
printf("PartTbl.EndCylinder = %u\n", pMBR->PartTbl[i].EndCylinder);
}
}
int DumpGptInfo(VTOY_GPT_INFO *pGptInfo)
{
int i;
DumpMBR(&pGptInfo->MBR);
DumpHead(&pGptInfo->Head);
for (i = 0; i < 128; i++)
{
if (pGptInfo->PartTbl[i].StartLBA == 0)
{
break;
}
printf("=====Part %d=====\n", i);
DumpPartTable(pGptInfo->PartTbl + i);
}
return 0;
}
int vtoygpt_main(int argc, char **argv)
{
int i;
int fd;
UINT64 DiskSize;
CHAR16 *Name = NULL;
VTOY_GPT_INFO *pMainGptInfo = NULL;
VTOY_BK_GPT_INFO *pBackGptInfo = NULL;
if (argc != 3)
{
printf("usage: vtoygpt -f /dev/sdb\n");
return 1;
}
fd = open(argv[2], O_RDWR);
if (fd < 0)
{
printf("Failed to open %s\n", argv[2]);
return 1;
}
pMainGptInfo = malloc(sizeof(VTOY_GPT_INFO));
pBackGptInfo = malloc(sizeof(VTOY_BK_GPT_INFO));
if (NULL == pMainGptInfo || NULL == pBackGptInfo)
{
close(fd);
return 1;
}
read(fd, pMainGptInfo, sizeof(VTOY_GPT_INFO));
if (argv[1][0] == '-' && argv[1][1] == 'd')
{
DumpGptInfo(pMainGptInfo);
}
else
{
DiskSize = lseek(fd, 0, SEEK_END);
lseek(fd, DiskSize - 33 * 512, SEEK_SET);
read(fd, pBackGptInfo, sizeof(VTOY_BK_GPT_INFO));
Name = pMainGptInfo->PartTbl[1].Name;
if (Name[0] == 'V' && Name[1] == 'T' && Name[2] == 'O' && Name[3] == 'Y')
{
pMainGptInfo->PartTbl[1].Attr = VENTOY_EFI_PART_ATTR;
pMainGptInfo->Head.PartTblCrc = VtoyCrc32(pMainGptInfo->PartTbl, sizeof(pMainGptInfo->PartTbl));
pMainGptInfo->Head.Crc = 0;
pMainGptInfo->Head.Crc = VtoyCrc32(&pMainGptInfo->Head, pMainGptInfo->Head.Length);
pBackGptInfo->PartTbl[1].Attr = VENTOY_EFI_PART_ATTR;
pBackGptInfo->Head.PartTblCrc = VtoyCrc32(pBackGptInfo->PartTbl, sizeof(pBackGptInfo->PartTbl));
pBackGptInfo->Head.Crc = 0;
pBackGptInfo->Head.Crc = VtoyCrc32(&pBackGptInfo->Head, pBackGptInfo->Head.Length);
lseek(fd, 512, SEEK_SET);
write(fd, (UINT8 *)pMainGptInfo + 512, sizeof(VTOY_GPT_INFO) - 512);
lseek(fd, DiskSize - 33 * 512, SEEK_SET);
write(fd, pBackGptInfo, sizeof(VTOY_BK_GPT_INFO));
fsync(fd);
}
}
free(pMainGptInfo);
free(pBackGptInfo);
close(fd);
return 0;
}
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