]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
1.0.13 release v1.0.13
authorlongpanda <admin@ventoy.net>
Sun, 14 Jun 2020 17:41:33 +0000 (01:41 +0800)
committerlongpanda <admin@ventoy.net>
Sun, 14 Jun 2020 17:41:42 +0000 (01:41 +0800)
55 files changed:
DOC/BuildVentoyFromSource.txt
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.inf
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c
GRUB2/MOD_SRC/grub-2.04/grub-core/fs/iso9660.c
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/file.c
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_json.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
GRUB2/MOD_SRC/grub-2.04/include/grub/file.h [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
GRUB2/MOD_SRC/grub-2.04/install.sh
IMG/cpio/ventoy/hook/clear/ventoy-hook.sh
IMG/cpio/ventoy/hook/gentoo/ventoy-hook.sh
IMG/cpio/ventoy/hook/kiosk/ventoy-disk.sh [new file with mode: 0644]
IMG/cpio/ventoy/hook/kiosk/ventoy-hook.sh [new file with mode: 0644]
IMG/cpio/ventoy/hook/mageia/ventoy-hook.sh
IMG/cpio/ventoy/hook/mageia/ventoy-inotifyd-hook.sh [new file with mode: 0644]
IMG/cpio/ventoy/hook/mageia/ventoy-inotifyd-start.sh [moved from IMG/cpio/ventoy/hook/mageia/udev_disk_hook.sh with 62% similarity]
IMG/cpio/ventoy/hook/rhel6/udev_disk_hook.sh
IMG/cpio/ventoy/hook/rhel6/ventoy-hook.sh
IMG/cpio/ventoy/hook/rhel7/ventoy-hook.sh
IMG/cpio/ventoy/hook/rhel7/ventoy-inotifyd-hook.sh
IMG/cpio/ventoy/hook/rhel7/ventoy-timeout.sh
IMG/cpio/ventoy/init
IMG/cpio/ventoy/ventoy.sh
INSTALL/EFI/BOOT/grubx64_real.efi
INSTALL/grub/debug.cfg [new file with mode: 0644]
INSTALL/grub/fonts/ascii.pf2
INSTALL/grub/fonts/unicode.pf2 [new file with mode: 0644]
INSTALL/grub/grub.cfg
INSTALL/grub/i386-pc/core.img
INSTALL/grub/localboot.cfg [new file with mode: 0644]
INSTALL/grub/power.cfg
INSTALL/grub/themes/ventoy/background.png
INSTALL/grub/themes/ventoy/theme.txt
INSTALL/grub/x86_64-efi/normal.mod
INSTALL/tool/ventoy_lib.sh
INSTALL/ventoy/ipxe.krn
INSTALL/ventoy/ventoy.cpio
INSTALL/ventoy/ventoy_x64.efi
INSTALL/ventoy/vtoyjump32.exe
INSTALL/ventoy/vtoyjump64.exe
IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c
IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h
vtoyjump/vtoyjump/vtoyjump.c

index 4c20700ef71a007c4bfe9ac3b1fc4a115bdd5958..191f95487c03324ee16647d20c6929d6d2dba871 100644 (file)
  INSTALL/EFI/BOOT/MokManager.efi --> EFI/BOOT/MokManager.efi  SHA-256: 3bf1f46cee0832355c7dd1dba880dea9bcaa78cc44375a1559d43bc9db18933b
 
 
-   
+5.11 INSTALL/tool/ash
+ https://busybox.net/downloads/binaries/1.31.0-i686-uclibc/   busybox_ASH
+ SHA-256: 2943f02f85fee0c9551aec47110a558a73f919c032b3c51e56d6f197b5ec4d7b  
    
index 3b83dd5a7106e295902edebdf3a48fe159fbecb1..c05e772f16f1f87d7235e951f5539cc1879336a4 100644 (file)
 #include <Protocol/SimpleFileSystem.h>
 #include <Ventoy.h>
 
-UINTN g_iso_buf_size = 0;
-BOOLEAN gMemdiskMode = FALSE;
 BOOLEAN gDebugPrint = FALSE;
-BOOLEAN gLoadIsoEfi = FALSE;
 ventoy_ram_disk g_ramdisk_param;
 ventoy_chain_head *g_chain;
 ventoy_img_chunk *g_chunk;
+UINT8 *g_os_param_reserved;
 UINT32 g_img_chunk_num;
 ventoy_override_chunk *g_override_chunk;
 UINT32 g_override_chunk_num;
 ventoy_virt_chunk *g_virt_chunk;
 UINT32 g_virt_chunk_num;
 vtoy_block_data gBlockData;
-ventoy_sector_flag *g_sector_flag = NULL;
-UINT32 g_sector_flag_num = 0;
 static grub_env_get_pf grub_env_get = NULL;
 
-EFI_FILE_OPEN g_original_fopen = NULL;
-EFI_FILE_CLOSE g_original_fclose = NULL;
-EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume = NULL;
-
 ventoy_grub_param_file_replace *g_file_replace_list = NULL;
 ventoy_efi_file_replace g_efi_file_replace;
 
 CHAR16 gFirstTryBootFile[256] = {0};
 
-CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
-
 /* Boot filename */
 UINTN gBootFileStartIndex = 1;
 CONST CHAR16 *gEfiBootFileName[] = 
@@ -76,9 +66,6 @@ CONST CHAR16 *gEfiBootFileName[] =
     L"\\efi\\boot\\bootx64.efi",
 };
 
-/* EFI block device vendor device path GUID */
-EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
-
 VOID EFIAPI VtoyDebug(IN CONST CHAR8  *Format, ...)
 {
     VA_LIST  Marker;
@@ -204,6 +191,12 @@ static void EFIAPI ventoy_dump_chain(ventoy_chain_head *chain)
     debug("os_param->vtoy_img_size=<%llu>",    chain->os_param.vtoy_img_size);
     debug("os_param->vtoy_img_location_addr=<0x%llx>", chain->os_param.vtoy_img_location_addr);
     debug("os_param->vtoy_img_location_len=<%u>",    chain->os_param.vtoy_img_location_len);
+    debug("os_param->vtoy_reserved=<%u %u %u %u>",    
+          g_os_param_reserved[0], 
+          g_os_param_reserved[1], 
+          g_os_param_reserved[2], 
+          g_os_param_reserved[3]
+          );
 
     ventoy_debug_pause();
     
@@ -224,312 +217,102 @@ static void EFIAPI ventoy_dump_chain(ventoy_chain_head *chain)
     ventoy_dump_virt_chunk(chain);
 }
 
-EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath)
+static int ventoy_update_image_location(ventoy_os_param *param)
 {
-    EFI_HANDLE Handle = NULL;
     EFI_STATUS Status = EFI_SUCCESS;
-    EFI_DEVICE_PATH_PROTOCOL *pLastNode = NULL;
-    EFI_DEVICE_PATH_PROTOCOL *pCurNode = NULL;
-    EFI_DEVICE_PATH_PROTOCOL *pTmpDevPath = NULL;
-    
-    pTmpDevPath = DuplicateDevicePath(pDevPath);
-    if (!pTmpDevPath)
-    {
-        return NULL;
-    }
+    UINT8 chksum = 0;
+    unsigned int i;
+    unsigned int length;
+    UINTN address = 0;
+    void *buffer = NULL;
+    ventoy_image_location *location = NULL;
+    ventoy_image_disk_region *region = NULL;
+    ventoy_img_chunk *chunk = g_chunk;
 
-    pCurNode = pTmpDevPath;
-    while (!IsDevicePathEnd(pCurNode))
-    {
-        pLastNode = pCurNode;
-        pCurNode = NextDevicePathNode(pCurNode);
-    }
-    if (pLastNode)
+    length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
+
+    Status = gBS->AllocatePool(EfiRuntimeServicesData, length + 4096 * 2, &buffer);
+    if (EFI_ERROR(Status) || NULL == buffer)
     {
-        CopyMem(pLastNode, pCurNode, sizeof(EFI_DEVICE_PATH_PROTOCOL));
+        debug("Failed to allocate runtime pool %r\n", Status);
+        return 1;
     }
 
-    pCurNode = pTmpDevPath;
-    Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &pCurNode, &Handle);
-    debug("Status:%r Parent Handle:%p DP:%s", Status, Handle, ConvertDevicePathToText(pTmpDevPath, FALSE, FALSE));
-
-    FreePool(pTmpDevPath);
-
-    return Handle;
-}
-
-EFI_STATUS EFIAPI ventoy_block_io_reset 
-(
-    IN EFI_BLOCK_IO_PROTOCOL          *This,
-    IN BOOLEAN                        ExtendedVerification
-) 
-{
-    (VOID)This;
-    (VOID)ExtendedVerification;
-       return EFI_SUCCESS;
-}
+    address = (UINTN)buffer;
 
-STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
-(
-    IN UINT64                 Sector,
-    IN UINTN                  Count,
-    OUT VOID                 *Buffer
-)
-{
-    EFI_STATUS Status = EFI_SUCCESS;
-    EFI_LBA MapLba = 0;
-    UINT32 i = 0;
-    UINTN secLeft = 0;
-    UINTN secRead = 0;
-    UINT64 ReadStart = 0;
-    UINT64 ReadEnd = 0;
-    UINT64 OverrideStart = 0;
-    UINT64 OverrideEnd= 0;
-    UINT8 *pCurBuf = (UINT8 *)Buffer;
-    ventoy_img_chunk *pchunk = g_chunk;
-    ventoy_override_chunk *pOverride = g_override_chunk;
-    EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
-
-    debug("read iso sector %lu  count %u", Sector, Count);
-
-    ReadStart = Sector * 2048;
-    ReadEnd = (Sector + Count) * 2048;
-
-    for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
+    if (address % 4096)
     {
-        if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
-        {
-            if (g_chain->disk_sector_size == 512)
-            {
-                MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
-            }
-            else
-            {
-                MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
-            }
-
-            secLeft = pchunk->img_end_sector + 1 - Sector;
-            secRead = (Count < secLeft) ? Count : secLeft;
-
-            Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
-                                     MapLba, secRead * 2048, pCurBuf);
-            if (EFI_ERROR(Status))
-            {
-                debug("Raw disk read block failed %r", Status);
-                return Status;
-            }
-
-            Count -= secRead;
-            Sector += secRead;
-            pCurBuf += secRead * 2048;
-        }
+        address += 4096 - (address % 4096);
     }
 
-    if (ReadStart > g_chain->real_img_size_in_bytes)
+    param->chksum = 0;
+    param->vtoy_img_location_addr = address;
+    param->vtoy_img_location_len = length;
+
+    /* update check sum */
+    for (i = 0; i < sizeof(ventoy_os_param); i++)
     {
-        return EFI_SUCCESS;
+        chksum += *((UINT8 *)param + i);
     }
+    param->chksum = (chksum == 0) ? 0 : (UINT8)(0x100 - chksum);
 
-    /* override data */
-    pCurBuf = (UINT8 *)Buffer;
-    for (i = 0; i < g_override_chunk_num; i++, pOverride++)
+    location = (ventoy_image_location *)(unsigned long)(param->vtoy_img_location_addr);
+    if (NULL == location)
     {
-        OverrideStart = pOverride->img_offset;
-        OverrideEnd = pOverride->img_offset + pOverride->override_size;
-    
-        if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
-        {
-            continue;
-        }
-
-        if (ReadStart <= OverrideStart)
-        {
-            if (ReadEnd <= OverrideEnd)
-            {
-                CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);  
-            }
-            else
-            {
-                CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
-            }
-        }
-        else
-        {
-            if (ReadEnd <= OverrideEnd)
-            {
-                CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart);     
-            }
-            else
-            {
-                CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
-            }
-        }
+        return 0;
     }
 
-    return EFI_SUCCESS;    
-}
-
-EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read 
-(
-    IN EFI_BLOCK_IO_PROTOCOL          *This,
-    IN UINT32                          MediaId,
-    IN EFI_LBA                         Lba,
-    IN UINTN                           BufferSize,
-    OUT VOID                          *Buffer
-) 
-{
-    //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
+    CopyMem(&location->guid, &param->guid, sizeof(ventoy_guid));
+    location->image_sector_size = 2048;
+    location->disk_sector_size  = g_chain->disk_sector_size;
+    location->region_count = g_img_chunk_num;
 
-    (VOID)This;
-    (VOID)MediaId;
+    region = location->regions;
 
-    CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
+    for (i = 0; i < g_img_chunk_num; i++)
+    {
+        region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
+        region->image_start_sector = chunk->img_start_sector;
+        region->disk_start_sector  = chunk->disk_start_sector;
+        region++;
+        chunk++;
+    }
 
-       return EFI_SUCCESS;
+    return 0;
 }
 
-EFI_STATUS EFIAPI ventoy_block_io_read 
-(
-    IN EFI_BLOCK_IO_PROTOCOL          *This,
-    IN UINT32                          MediaId,
-    IN EFI_LBA                         Lba,
-    IN UINTN                           BufferSize,
-    OUT VOID                          *Buffer
-) 
+EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath)
 {
-    UINT32 i = 0;
-    UINT32 j = 0;
-    UINT32 lbacount = 0;
-    UINT32 secNum = 0;
-    UINT64 offset = 0;
-    EFI_LBA curlba = 0;
-    EFI_LBA lastlba = 0;
-    UINT8 *lastbuffer;
-    ventoy_sector_flag *cur_flag;
-    ventoy_virt_chunk *node;
+    EFI_HANDLE Handle = NULL;
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_DEVICE_PATH_PROTOCOL *pLastNode = NULL;
+    EFI_DEVICE_PATH_PROTOCOL *pCurNode = NULL;
+    EFI_DEVICE_PATH_PROTOCOL *pTmpDevPath = NULL;
     
-    //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
-
-    secNum = BufferSize / 2048;
-    offset = Lba * 2048;
-
-    if (offset + BufferSize <= g_chain->real_img_size_in_bytes)
-    {
-        return ventoy_read_iso_sector(Lba, secNum, Buffer);
-    }
-
-    if (secNum > g_sector_flag_num)
-    {
-        cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
-        if (NULL == cur_flag)
-        {
-            return EFI_OUT_OF_RESOURCES;
-        }
-
-        FreePool(g_sector_flag);
-        g_sector_flag = cur_flag;
-        g_sector_flag_num = secNum;
-    }
-
-    for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
+    pTmpDevPath = DuplicateDevicePath(pDevPath);
+    if (!pTmpDevPath)
     {
-        cur_flag->flag = 0;
-        for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
-        {
-            if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
-            {
-                CopyMem((UINT8 *)Buffer + j * 2048, 
-                       (char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
-                       2048);
-                cur_flag->flag = 1;
-                break;
-            }
-            else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
-            {
-                cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
-                cur_flag->flag = 2;
-                break;
-            }
-        }
+        return NULL;
     }
 
-    for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
+    pCurNode = pTmpDevPath;
+    while (!IsDevicePathEnd(pCurNode))
     {
-        if (cur_flag->flag == 2)
-        {
-            if (lastlba == 0)
-            {
-                lastbuffer = (UINT8 *)Buffer + j * 2048;
-                lastlba = cur_flag->remap_lba;
-                lbacount = 1;
-            }
-            else if (lastlba + lbacount == cur_flag->remap_lba)
-            {
-                lbacount++;
-            }
-            else
-            {
-                ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
-                lastbuffer = (UINT8 *)Buffer + j * 2048;
-                lastlba = cur_flag->remap_lba;
-                lbacount = 1;
-            }
-        }
+        pLastNode = pCurNode;
+        pCurNode = NextDevicePathNode(pCurNode);
     }
-
-    if (lbacount > 0)
+    if (pLastNode)
     {
-        ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
+        CopyMem(pLastNode, pCurNode, sizeof(EFI_DEVICE_PATH_PROTOCOL));
     }
 
-       return EFI_SUCCESS;
-}
-
-EFI_STATUS EFIAPI ventoy_block_io_write 
-(
-    IN EFI_BLOCK_IO_PROTOCOL          *This,
-    IN UINT32                          MediaId,
-    IN EFI_LBA                         Lba,
-    IN UINTN                           BufferSize,
-    IN VOID                           *Buffer
-) 
-{
-    (VOID)This;
-    (VOID)MediaId;
-    (VOID)Lba;
-    (VOID)BufferSize;
-    (VOID)Buffer;
-       return EFI_WRITE_PROTECTED;
-}
-
-EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
-{
-       (VOID)This;
-       return EFI_SUCCESS;
-}
-
-
-EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
-{
-    UINTN NameLen = 0;
-    UINT8 TmpBuf[128] = {0};
-    VENDOR_DEVICE_PATH *venPath = NULL;
-
-    venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
-    NameLen = StrSize(VTOY_BLOCK_DEVICE_PATH_NAME);
-    venPath->Header.Type = HARDWARE_DEVICE_PATH;
-    venPath->Header.SubType = HW_VENDOR_DP;
-    venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
-    venPath->Header.Length[1] = 0;
-    CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
-    CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
-    
-    gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
-    gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
+    pCurNode = pTmpDevPath;
+    Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &pCurNode, &Handle);
+    debug("Status:%r Parent Handle:%p DP:%s", Status, Handle, ConvertDevicePathToText(pTmpDevPath, FALSE, FALSE));
 
-    debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
+    FreePool(pTmpDevPath);
 
-    return EFI_SUCCESS;
+    return Handle;
 }
 
 EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
@@ -545,7 +328,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
     return Status;
 }
 
-EFI_STATUS EFIAPI ventoy_del_ramdisk_param(VOID)
+EFI_STATUS EFIAPI ventoy_delete_ramdisk_param(VOID)
 {
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
@@ -559,7 +342,7 @@ EFI_STATUS EFIAPI ventoy_del_ramdisk_param(VOID)
 }
 
 
-EFI_STATUS EFIAPI ventoy_set_variable(VOID)
+EFI_STATUS EFIAPI ventoy_save_variable(VOID)
 {
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
@@ -585,56 +368,7 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
     return Status;
 }
 
-
-EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
-{   
-    EFI_STATUS Status = EFI_SUCCESS;
-    EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
-    
-    ventoy_fill_device_path();
-    
-    gBlockData.Media.BlockSize = 2048;
-    gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
-    gBlockData.Media.ReadOnly = TRUE;
-    gBlockData.Media.MediaPresent = 1;
-    gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
-
-       pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
-       pBlockIo->Media = &(gBlockData.Media);
-       pBlockIo->Reset = ventoy_block_io_reset;
-
-    if (gMemdiskMode)
-    {
-        pBlockIo->ReadBlocks = ventoy_block_io_ramdisk_read;
-    }
-    else
-    {
-       pBlockIo->ReadBlocks = ventoy_block_io_read;        
-    }
-    
-       pBlockIo->WriteBlocks = ventoy_block_io_write;
-       pBlockIo->FlushBlocks = ventoy_block_io_flush;
-
-    Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
-            &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
-            &gEfiDevicePathProtocolGuid, gBlockData.Path,
-            NULL);
-
-    debug("Install protocol %r", Status);
-
-    if (EFI_ERROR(Status))
-    {
-        return Status;
-    }
-
-    Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, 1);
-    debug("Connect controller %r", Status);
-
-    return EFI_SUCCESS;
-}
-
-
-EFI_STATUS EFIAPI ventoy_load_image
+STATIC EFI_STATUS EFIAPI ventoy_load_image
 (
     IN EFI_HANDLE ImageHandle,
     IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
@@ -745,156 +479,6 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
     }
 }
 
-STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle)
-{
-    UINTN i = 0;
-    UINTN Count = 0;
-    EFI_HANDLE Parent = NULL;
-    EFI_HANDLE *Handles = NULL;
-    EFI_STATUS Status = EFI_SUCCESS;
-    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
-    EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
-
-    Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 
-                                     NULL, &Count, &Handles);
-    if (EFI_ERROR(Status))
-    {
-        return Status;
-    }
-
-    debug("ventoy_find_iso_disk_fs fs count:%u", Count);
-
-    for (i = 0; i < Count; i++)
-    {
-        Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
-        if (EFI_ERROR(Status))
-        {
-            continue;
-        }
-
-        Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid, 
-                                   (VOID **)&pDevPath,
-                                   ImageHandle,
-                                   Handles[i],
-                                   EFI_OPEN_PROTOCOL_GET_PROTOCOL);
-        if (EFI_ERROR(Status))
-        {
-            debug("Failed to open device path protocol %r", Status);
-            continue;
-        }
-
-        debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
-        Parent = ventoy_get_parent_handle(pDevPath);
-
-        if (Parent == gBlockData.RawBlockIoHandle)
-        {
-            debug("Find ventoy disk fs");
-            gBlockData.DiskFsHandle = Handles[i];
-            gBlockData.pDiskFs = pFile;
-            gBlockData.pDiskFsDevPath = pDevPath;
-            break;
-        }
-    }
-
-    FreePool(Handles);
-
-    return EFI_SUCCESS;
-}
-
-STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
-{
-    EFI_HANDLE Image = NULL;
-    EFI_STATUS Status = EFI_SUCCESS;
-    CHAR16 LogVar[4] = L"5";
-            
-    Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath, 
-                               gIso9660EfiDriverPath, 
-                               sizeof(gIso9660EfiDriverPath), 
-                               &Image);
-    debug("load iso efi driver status:%r", Status);
-
-    if (gDebugPrint)
-    {
-        gRT->SetVariable(L"FS_LOGGING", &gShellVariableGuid, 
-                         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-                         sizeof(LogVar), LogVar);
-    }
-
-    gRT->SetVariable(L"FS_NAME_NOCASE", &gShellVariableGuid, 
-                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-                     sizeof(LogVar), LogVar);
-
-    gBlockData.IsoDriverImage = Image;
-    Status = gBS->StartImage(Image, NULL, NULL);
-    debug("Start iso efi driver status:%r", Status);
-
-    return EFI_SUCCESS;
-}
-
-static int ventoy_update_image_location(ventoy_os_param *param)
-{
-    EFI_STATUS Status = EFI_SUCCESS;
-    UINT8 chksum = 0;
-    unsigned int i;
-    unsigned int length;
-    UINTN address = 0;
-    void *buffer = NULL;
-    ventoy_image_location *location = NULL;
-    ventoy_image_disk_region *region = NULL;
-    ventoy_img_chunk *chunk = g_chunk;
-
-    length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
-
-    Status = gBS->AllocatePool(EfiRuntimeServicesData, length + 4096 * 2, &buffer);
-    if (EFI_ERROR(Status) || NULL == buffer)
-    {
-        debug("Failed to allocate runtime pool %r\n", Status);
-        return 1;
-    }
-
-    address = (UINTN)buffer;
-
-    if (address % 4096)
-    {
-        address += 4096 - (address % 4096);
-    }
-
-    param->chksum = 0;
-    param->vtoy_img_location_addr = address;
-    param->vtoy_img_location_len = length;
-
-    /* update check sum */
-    for (i = 0; i < sizeof(ventoy_os_param); i++)
-    {
-        chksum += *((UINT8 *)param + i);
-    }
-    param->chksum = (chksum == 0) ? 0 : (UINT8)(0x100 - chksum);
-
-    location = (ventoy_image_location *)(unsigned long)(param->vtoy_img_location_addr);
-    if (NULL == location)
-    {
-        return 0;
-    }
-
-    CopyMem(&location->guid, &param->guid, sizeof(ventoy_guid));
-    location->image_sector_size = 2048;
-    location->disk_sector_size  = g_chain->disk_sector_size;
-    location->region_count = g_img_chunk_num;
-
-    region = location->regions;
-
-    for (i = 0; i < g_img_chunk_num; i++)
-    {
-        region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
-        region->image_start_sector = chunk->img_start_sector;
-        region->disk_start_sector  = chunk->disk_start_sector;
-        region++;
-        chunk++;
-    }
-
-    return 0;
-}
-
 STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
 {   
     UINT32 i = 0;
@@ -923,11 +507,6 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         gDebugPrint = TRUE;
     }
 
-    if (StrStr(pCmdLine, L"isoefi=on"))
-    {
-        gLoadIsoEfi = TRUE;
-    }
-
     pPos = StrStr(pCmdLine, L"FirstTry=@");
     if (pPos)
     {
@@ -998,6 +577,14 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
         g_virt_chunk_num = g_chain->virt_chunk_num;
 
+        g_os_param_reserved = (UINT8 *)(g_chain->os_param.vtoy_reserved);
+
+        /* Workaround for Windows & ISO9660 */
+        if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0)
+        {
+            g_fixup_iso9660_secover_enable = TRUE;
+        }
+
         for (i = 0; i < sizeof(ventoy_os_param); i++)
         {
             chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
@@ -1020,82 +607,28 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
     return EFI_SUCCESS;
 }
 
-EFI_STATUS EFIAPI ventoy_wrapper_file_open
-(
-    EFI_FILE_HANDLE This, 
-    EFI_FILE_HANDLE *New,
-    CHAR16 *Name, 
-    UINT64 Mode, 
-    UINT64 Attributes
-)
+EFI_STATUS EFIAPI ventoy_clean_env(VOID)
 {
-    UINT32 i = 0;
-    UINT32 j = 0;
-    UINT64 Sectors = 0;
-    EFI_STATUS Status = EFI_SUCCESS;
-    CHAR8 TmpName[256];
-    ventoy_virt_chunk *virt = NULL;
-
-    Status = g_original_fopen(This, New, Name, Mode, Attributes);
-    if (EFI_ERROR(Status))
-    {
-        return Status;
-    }
-
-    if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
-        g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
-    {
-        AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
-        for (j = 0; j < 4; j++)
-        {
-            if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
-            {
-                g_original_fclose(*New);
-                *New = &g_efi_file_replace.WrapperHandle;
-                ventoy_wrapper_file_procotol(*New);
-
-                virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
+    FreePool(g_sector_flag);
+    g_sector_flag_num = 0;
 
-                Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
-                
-                g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
-                g_efi_file_replace.FileSizeBytes = Sectors * 2048;
+    gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
 
-                if (gDebugPrint)
-                {
-                    debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
-                        g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
-                    sleep(3);
-                }
-                
-                return Status;
-            }
-        }
-    }
+    gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
+            &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
+            &gEfiDevicePathProtocolGuid, gBlockData.Path,
+            NULL);
 
-    return Status;
-}
+    ventoy_delete_variable();
 
-EFI_STATUS EFIAPI ventoy_wrapper_open_volume
-(
-    IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *This,
-    OUT EFI_FILE_PROTOCOL                 **Root
-)
-{
-    EFI_STATUS Status = EFI_SUCCESS;
-    
-    Status = g_original_open_volume(This, Root);
-    if (!EFI_ERROR(Status))
+    if (g_chain->os_param.vtoy_img_location_addr)
     {
-        g_original_fopen = (*Root)->Open;
-        g_original_fclose = (*Root)->Close;
-        (*Root)->Open = ventoy_wrapper_file_open;
+        FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
     }
 
-    return Status;
+    return EFI_SUCCESS;
 }
 
-
 EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
 {
     UINTN t = 0;
@@ -1179,7 +712,7 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
 
             if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC)
             {
-                g_original_open_volume = pFile->OpenVolume;
+                ventoy_wrapper_push_openvolume(pFile->OpenVolume);
                 pFile->OpenVolume = ventoy_wrapper_open_volume;
             }
             
@@ -1210,74 +743,6 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
     return EFI_SUCCESS;
 }
 
-EFI_STATUS EFIAPI ventoy_clean_env(VOID)
-{
-    FreePool(g_sector_flag);
-    g_sector_flag_num = 0;
-
-    if (gLoadIsoEfi && gBlockData.IsoDriverImage)
-    {
-        gBS->UnloadImage(gBlockData.IsoDriverImage);
-    }
-
-    gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
-
-    gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
-            &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
-            &gEfiDevicePathProtocolGuid, gBlockData.Path,
-            NULL);
-
-    ventoy_delete_variable();
-
-    if (g_chain->os_param.vtoy_img_location_addr)
-    {
-        FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
-    }
-
-    return EFI_SUCCESS;
-}
-
-EFI_STATUS EFIAPI ventoy_ramdisk_boot(IN EFI_HANDLE ImageHandle)
-{
-    EFI_STATUS Status = EFI_SUCCESS;
-    EFI_RAM_DISK_PROTOCOL *RamDisk = NULL;
-    EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
-
-    debug("RamDisk Boot ...");
-
-    Status = gBS->LocateProtocol(&gEfiRamDiskProtocolGuid, NULL, (VOID **)&RamDisk);
-    if (EFI_ERROR(Status))
-    {
-        debug("Failed to locate ramdisk protocol %r", Status);
-        return Status;
-    }
-    debug("Locate RamDisk Protocol %r ...", Status);
-
-    Status = RamDisk->Register((UINTN)g_chain, (UINT64)g_iso_buf_size, &gEfiVirtualCdGuid, NULL, &DevicePath);
-    if (EFI_ERROR(Status))
-    {
-        debug("Failed to register ramdisk %r", Status);
-        return Status;
-    }
-    
-    debug("Register RamDisk %r ...", Status);
-    debug("RamDisk DevicePath:<%s> ...", ConvertDevicePathToText(DevicePath, FALSE, FALSE));
-
-    ventoy_debug_pause();
-
-    gBlockData.Path = DevicePath;
-    gBlockData.DevicePathCompareLen = GetDevicePathSize(DevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
-
-    Status = ventoy_boot(ImageHandle);
-    if (EFI_NOT_FOUND == Status)
-    {
-        gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
-        gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC  L"!\r\n");
-        sleep(300);
-    }
-    
-    return EFI_SUCCESS;
-}
 
 EFI_STATUS EFIAPI VentoyEfiMain
 (
@@ -1309,26 +774,14 @@ EFI_STATUS EFIAPI VentoyEfiMain
         
         ventoy_install_blockio(ImageHandle, g_iso_buf_size);
         Status = ventoy_boot(ImageHandle);
-        if (EFI_NOT_FOUND == Status)
-        {
-            gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
-            gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC  L"!\r\n");
-            sleep(300);
-        }
-
-        ventoy_del_ramdisk_param();
+        
+        ventoy_delete_ramdisk_param();
     }
     else
     {
-        ventoy_set_variable();
+        ventoy_save_variable();
         ventoy_find_iso_disk(ImageHandle);
 
-        if (gLoadIsoEfi)
-        {
-            ventoy_find_iso_disk_fs(ImageHandle);
-            ventoy_load_isoefi_driver(ImageHandle);
-        }
-
         ventoy_debug_pause();
         
         ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
@@ -1336,32 +789,20 @@ EFI_STATUS EFIAPI VentoyEfiMain
         ventoy_debug_pause();
 
         Status = ventoy_boot(ImageHandle);
-        if (EFI_NOT_FOUND == Status)
-        {
-            if (!gLoadIsoEfi)
-            {
-                gLoadIsoEfi = TRUE;
-                ventoy_find_iso_disk_fs(ImageHandle);
-                ventoy_load_isoefi_driver(ImageHandle);
-
-                Status = ventoy_boot(ImageHandle);
-            }
-
-            if (EFI_NOT_FOUND == Status)
-            {
-                gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
-                gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC  L"!\r\n");
-                sleep(60);
-            }
-        }
 
         ventoy_clean_env();
     }
-    
+
+    if (EFI_NOT_FOUND == Status)
+    {
+        gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
+        gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC  L"!\r\n");
+        sleep(30);
+    }
+
     ventoy_clear_input();
     gST->ConOut->ClearScreen(gST->ConOut);
 
     return EFI_SUCCESS;
 }
 
-
index eb22e772e9fc20926d9e376ec98f9d76e56d4e37..48c68c8b21eca47d78a3296525462e7395bf500c 100644 (file)
@@ -199,10 +199,8 @@ typedef struct vtoy_block_data
     EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
     EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
 
-    EFI_HANDLE IsoDriverImage;
 }vtoy_block_data;
 
-#define ISO9660_EFI_DRIVER_PATH  L"\\ventoy\\iso9660_x64.efi"
 
 #define debug(expr, ...) if (gDebugPrint) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
 #define trace(expr, ...) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
@@ -254,6 +252,14 @@ typedef struct ventoy_ram_disk
     UINT64 DiskSize;
 }ventoy_ram_disk;
 
+typedef struct ventoy_iso9660_override
+{
+    UINT32 first_sector;
+    UINT32 first_sector_be;
+    UINT32 size;
+    UINT32 size_be;
+}ventoy_iso9660_override;
+
 #pragma pack()
 
 
@@ -282,7 +288,6 @@ typedef struct ventoy_system_wrapper
     bs->func = wrapper.New##func;\
 }
 
-extern ventoy_efi_file_replace g_efi_file_replace;
 extern BOOLEAN gDebugPrint;
 VOID EFIAPI VtoyDebug(IN CONST CHAR8  *Format, ...);
 EFI_STATUS EFIAPI ventoy_wrapper_system(VOID);
@@ -296,5 +301,30 @@ EFI_STATUS EFIAPI ventoy_block_io_read
     OUT VOID                          *Buffer
 );
 
+
+extern ventoy_chain_head *g_chain;
+extern ventoy_img_chunk *g_chunk;
+extern UINT32 g_img_chunk_num;
+extern ventoy_override_chunk *g_override_chunk;
+extern UINT32 g_override_chunk_num;
+extern ventoy_virt_chunk *g_virt_chunk;
+extern UINT32 g_virt_chunk_num;
+extern vtoy_block_data gBlockData;
+extern ventoy_efi_file_replace g_efi_file_replace;
+extern ventoy_sector_flag *g_sector_flag;
+extern UINT32 g_sector_flag_num;
+extern BOOLEAN gMemdiskMode;
+extern UINTN g_iso_buf_size;
+extern ventoy_grub_param_file_replace *g_file_replace_list;
+extern BOOLEAN g_fixup_iso9660_secover_enable;
+
+EFI_STATUS EFIAPI ventoy_wrapper_open_volume
+(
+    IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *This,
+    OUT EFI_FILE_PROTOCOL                 **Root
+);
+EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
+EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume);
+
 #endif
 
index 1db9b2182e417255e64dcb5b032d8c4df4d3514a..00a5e548fddd03199d2ff0b4ab5c9f73d24641e7 100644 (file)
@@ -29,6 +29,7 @@
   Ventoy.h
   Ventoy.c
   VentoyDebug.c
+  VentoyProtocol.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
new file mode 100644 (file)
index 0000000..624055d
--- /dev/null
@@ -0,0 +1,631 @@
+/******************************************************************************
+ * Ventoy.c
+ *
+ * Copyright (c) 2020, 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 <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Protocol/LoadedImage.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/RamDisk.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Ventoy.h>
+
+UINTN g_iso_buf_size = 0;
+BOOLEAN gMemdiskMode = FALSE;
+
+ventoy_sector_flag *g_sector_flag = NULL;
+UINT32 g_sector_flag_num = 0;
+
+EFI_FILE_OPEN g_original_fopen = NULL;
+EFI_FILE_CLOSE g_original_fclose = NULL;
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume = NULL;
+
+/* EFI block device vendor device path GUID */
+EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
+
+#define VENTOY_ISO9660_SECTOR_OVERFLOW  2097152
+
+BOOLEAN g_fixup_iso9660_secover_enable = FALSE;
+BOOLEAN g_fixup_iso9660_secover_start  = FALSE;
+UINT64  g_fixup_iso9660_secover_1st_secs = 0;
+UINT64  g_fixup_iso9660_secover_cur_secs = 0;
+UINT64  g_fixup_iso9660_secover_tot_secs = 0;
+
+EFI_STATUS EFIAPI ventoy_block_io_reset 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN BOOLEAN                        ExtendedVerification
+) 
+{
+    (VOID)This;
+    (VOID)ExtendedVerification;
+       return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
+(
+    IN UINT64                 Sector,
+    IN UINTN                  Count,
+    OUT VOID                 *Buffer
+)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_LBA MapLba = 0;
+    UINT32 i = 0;
+    UINTN secLeft = 0;
+    UINTN secRead = 0;
+    UINT64 ReadStart = 0;
+    UINT64 ReadEnd = 0;
+    UINT64 OverrideStart = 0;
+    UINT64 OverrideEnd= 0;
+    UINT8 *pCurBuf = (UINT8 *)Buffer;
+    ventoy_img_chunk *pchunk = g_chunk;
+    ventoy_override_chunk *pOverride = g_override_chunk;
+    EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
+    
+    debug("read iso sector %lu  count %u", Sector, Count);
+
+    ReadStart = Sector * 2048;
+    ReadEnd = (Sector + Count) * 2048;
+
+    for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
+    {
+        if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
+        {
+            if (g_chain->disk_sector_size == 512)
+            {
+                MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
+            }
+            else
+            {
+                MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
+            }
+
+            secLeft = pchunk->img_end_sector + 1 - Sector;
+            secRead = (Count < secLeft) ? Count : secLeft;
+
+            Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
+                                     MapLba, secRead * 2048, pCurBuf);
+            if (EFI_ERROR(Status))
+            {
+                debug("Raw disk read block failed %r", Status);
+                return Status;
+            }
+
+            Count -= secRead;
+            Sector += secRead;
+            pCurBuf += secRead * 2048;
+        }
+    }
+
+    if (ReadStart > g_chain->real_img_size_in_bytes)
+    {
+        return EFI_SUCCESS;
+    }
+
+    /* override data */
+    pCurBuf = (UINT8 *)Buffer;
+    for (i = 0; i < g_override_chunk_num; i++, pOverride++)
+    {
+        OverrideStart = pOverride->img_offset;
+        OverrideEnd = pOverride->img_offset + pOverride->override_size;
+    
+        if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
+        {
+            continue;
+        }
+
+        if (ReadStart <= OverrideStart)
+        {
+            if (ReadEnd <= OverrideEnd)
+            {
+                CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);  
+            }
+            else
+            {
+                CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
+            }
+        }
+        else
+        {
+            if (ReadEnd <= OverrideEnd)
+            {
+                CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart); 
+            }
+            else
+            {
+                CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
+            }
+        }
+
+        if (g_fixup_iso9660_secover_enable && (!g_fixup_iso9660_secover_start) && 
+            pOverride->override_size == sizeof(ventoy_iso9660_override))
+        {
+            ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)pOverride->override_data;
+            if (dirent->first_sector >= VENTOY_ISO9660_SECTOR_OVERFLOW)
+            {
+                g_fixup_iso9660_secover_start = TRUE;
+                g_fixup_iso9660_secover_cur_secs = 0;
+            }
+        }
+    }
+
+    return EFI_SUCCESS;    
+}
+
+EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN UINT32                          MediaId,
+    IN EFI_LBA                         Lba,
+    IN UINTN                           BufferSize,
+    OUT VOID                          *Buffer
+) 
+{
+    //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
+
+    (VOID)This;
+    (VOID)MediaId;
+
+    CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
+
+       return EFI_SUCCESS;
+}
+
+EFI_LBA EFIAPI ventoy_fixup_iso9660_sector(IN EFI_LBA Lba, UINT32 secNum)
+{
+    UINT32 i = 0;
+
+    if (g_fixup_iso9660_secover_cur_secs > 0)
+    {
+        Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
+        g_fixup_iso9660_secover_cur_secs += secNum;
+        if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
+        {
+            g_fixup_iso9660_secover_start = FALSE;
+            goto end;
+        }
+    }
+    else
+    {
+        ventoy_iso9660_override *dirent;
+        ventoy_override_chunk *pOverride;
+
+        for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
+        {
+            dirent = (ventoy_iso9660_override *)pOverride->override_data;
+            if (Lba == dirent->first_sector)
+            {
+                g_fixup_iso9660_secover_start = FALSE;
+                goto end;
+            }
+        }
+
+        if (g_fixup_iso9660_secover_start)
+        {
+            for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
+            {
+                dirent = (ventoy_iso9660_override *)pOverride->override_data;
+                if (Lba + VENTOY_ISO9660_SECTOR_OVERFLOW == dirent->first_sector)
+                {
+                    g_fixup_iso9660_secover_tot_secs = (dirent->size + 2047) / 2048;
+                    g_fixup_iso9660_secover_cur_secs = secNum;
+                    if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
+                    {
+                        g_fixup_iso9660_secover_start = FALSE;
+                    }
+                    Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
+                    goto end;
+                }
+            }
+        }
+    }
+
+end:
+    return Lba;
+}
+
+EFI_STATUS EFIAPI ventoy_block_io_read 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN UINT32                          MediaId,
+    IN EFI_LBA                         Lba,
+    IN UINTN                           BufferSize,
+    OUT VOID                          *Buffer
+) 
+{
+    UINT32 i = 0;
+    UINT32 j = 0;
+    UINT32 lbacount = 0;
+    UINT32 secNum = 0;
+    UINT64 offset = 0;
+    EFI_LBA curlba = 0;
+    EFI_LBA lastlba = 0;
+    UINT8 *lastbuffer;
+    ventoy_sector_flag *cur_flag;
+    ventoy_virt_chunk *node;
+    
+    //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
+
+    secNum = BufferSize / 2048;
+
+    /* Workaround for SSTR PE loader error */
+    if (g_fixup_iso9660_secover_start)
+    {
+        Lba = ventoy_fixup_iso9660_sector(Lba, secNum);
+    }
+
+    offset = Lba * 2048;
+
+    if (offset + BufferSize <= g_chain->real_img_size_in_bytes)
+    {
+        return ventoy_read_iso_sector(Lba, secNum, Buffer);
+    }
+
+    if (secNum > g_sector_flag_num)
+    {
+        cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
+        if (NULL == cur_flag)
+        {
+            return EFI_OUT_OF_RESOURCES;
+        }
+
+        FreePool(g_sector_flag);
+        g_sector_flag = cur_flag;
+        g_sector_flag_num = secNum;
+    }
+
+    for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
+    {
+        cur_flag->flag = 0;
+        for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
+        {
+            if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
+            {
+                CopyMem((UINT8 *)Buffer + j * 2048, 
+                       (char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
+                       2048);
+                cur_flag->flag = 1;
+                break;
+            }
+            else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
+            {
+                cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
+                cur_flag->flag = 2;
+                break;
+            }
+        }
+    }
+
+    for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
+    {
+        if (cur_flag->flag == 2)
+        {
+            if (lastlba == 0)
+            {
+                lastbuffer = (UINT8 *)Buffer + j * 2048;
+                lastlba = cur_flag->remap_lba;
+                lbacount = 1;
+            }
+            else if (lastlba + lbacount == cur_flag->remap_lba)
+            {
+                lbacount++;
+            }
+            else
+            {
+                ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
+                lastbuffer = (UINT8 *)Buffer + j * 2048;
+                lastlba = cur_flag->remap_lba;
+                lbacount = 1;
+            }
+        }
+    }
+
+    if (lbacount > 0)
+    {
+        ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
+    }
+
+       return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI ventoy_block_io_write 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN UINT32                          MediaId,
+    IN EFI_LBA                         Lba,
+    IN UINTN                           BufferSize,
+    IN VOID                           *Buffer
+) 
+{
+    (VOID)This;
+    (VOID)MediaId;
+    (VOID)Lba;
+    (VOID)BufferSize;
+    (VOID)Buffer;
+       return EFI_WRITE_PROTECTED;
+}
+
+EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+       (VOID)This;
+       return EFI_SUCCESS;
+}
+
+
+EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
+{
+    UINTN NameLen = 0;
+    UINT8 TmpBuf[128] = {0};
+    VENDOR_DEVICE_PATH *venPath = NULL;
+
+    venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
+    NameLen = StrSize(VTOY_BLOCK_DEVICE_PATH_NAME);
+    venPath->Header.Type = HARDWARE_DEVICE_PATH;
+    venPath->Header.SubType = HW_VENDOR_DP;
+    venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
+    venPath->Header.Length[1] = 0;
+    CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
+    CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
+    
+    gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
+    gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
+
+    debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
+{
+    UINTN i = 0;
+    UINTN Count = 0;
+    CHAR16 *DriverName = NULL;
+    EFI_HANDLE *Handles = NULL;
+    EFI_HANDLE DrvHandles[2] = { NULL };
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
+    EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
+
+    debug("ventoy_connect_driver <%s>...", DrvName);
+
+    Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid, 
+                                     NULL, &Count, &Handles);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+
+    for (i = 0; i < Count; i++)
+    {
+        Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
+        if (EFI_ERROR(Status))
+        {
+            continue;
+        }
+
+        Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
+        if (EFI_ERROR(Status) || NULL == DriverName)
+        {
+            continue;
+        }
+
+        if (StrStr(DriverName, DrvName))
+        {
+            debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
+            DrvHandles[0] = Handles[i];
+            break;
+        }
+    }
+
+    if (i < Count)
+    {
+        Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
+        debug("Connect partition driver:<%r>", Status);
+        goto end;
+    }
+
+    debug("%s NOT found, now try COMPONENT_NAME", DrvName);
+
+    Count = 0;
+    FreePool(Handles);
+    Handles = NULL;
+
+    Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid, 
+                                     NULL, &Count, &Handles);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+
+    for (i = 0; i < Count; i++)
+    {
+        Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
+        if (EFI_ERROR(Status))
+        {
+            continue;
+        }
+
+        Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
+        if (EFI_ERROR(Status))
+        {
+            continue;
+        }
+
+        if (StrStr(DriverName, DrvName))
+        {
+            debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
+            DrvHandles[0] = Handles[i];
+            break;
+        }
+    }
+
+    if (i < Count)
+    {
+        Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
+        debug("Connect partition driver:<%r>", Status);
+        goto end;
+    }
+
+    Status = EFI_NOT_FOUND;
+    
+end:
+    FreePool(Handles);
+    
+    return Status;
+}
+
+EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
+{   
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
+    
+    ventoy_fill_device_path();
+    
+    gBlockData.Media.BlockSize = 2048;
+    gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
+    gBlockData.Media.ReadOnly = TRUE;
+    gBlockData.Media.MediaPresent = 1;
+    gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
+
+       pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+       pBlockIo->Media = &(gBlockData.Media);
+       pBlockIo->Reset = ventoy_block_io_reset;
+    pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
+       pBlockIo->WriteBlocks = ventoy_block_io_write;
+       pBlockIo->FlushBlocks = ventoy_block_io_flush;
+
+    Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
+            &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
+            &gEfiDevicePathProtocolGuid, gBlockData.Path,
+            NULL);
+    debug("Install protocol %r %p", Status, gBlockData.Handle);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+    
+    Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
+    debug("Connect disk IO driver %r", Status);
+    ventoy_debug_pause();
+    
+    Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
+    debug("Connect partition driver %r", Status);
+    if (EFI_ERROR(Status))
+    {
+        Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, TRUE);
+        debug("Connect all controller %r", Status);
+    }
+
+    ventoy_debug_pause();
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI ventoy_wrapper_file_open
+(
+    EFI_FILE_HANDLE This, 
+    EFI_FILE_HANDLE *New,
+    CHAR16 *Name, 
+    UINT64 Mode, 
+    UINT64 Attributes
+)
+{
+    UINT32 i = 0;
+    UINT32 j = 0;
+    UINT64 Sectors = 0;
+    EFI_STATUS Status = EFI_SUCCESS;
+    CHAR8 TmpName[256];
+    ventoy_virt_chunk *virt = NULL;
+
+    Status = g_original_fopen(This, New, Name, Mode, Attributes);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+
+    if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
+        g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
+    {
+        AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
+        for (j = 0; j < 4; j++)
+        {
+            if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
+            {
+                g_original_fclose(*New);
+                *New = &g_efi_file_replace.WrapperHandle;
+                ventoy_wrapper_file_procotol(*New);
+
+                virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
+
+                Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
+                
+                g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
+                g_efi_file_replace.FileSizeBytes = Sectors * 2048;
+
+                if (gDebugPrint)
+                {
+                    debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
+                        g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
+                    sleep(3);
+                }
+                
+                return Status;
+            }
+        }
+    }
+
+    return Status;
+}
+
+EFI_STATUS EFIAPI ventoy_wrapper_open_volume
+(
+    IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *This,
+    OUT EFI_FILE_PROTOCOL                 **Root
+)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    
+    Status = g_original_open_volume(This, Root);
+    if (!EFI_ERROR(Status))
+    {
+        g_original_fopen = (*Root)->Open;
+        g_original_fclose = (*Root)->Close;
+        (*Root)->Open = ventoy_wrapper_file_open;
+    }
+
+    return Status;
+}
+
+EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume)
+{
+    g_original_open_volume = OpenVolume;
+    return EFI_SUCCESS;
+}
+
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c
new file mode 100644 (file)
index 0000000..6f1900d
--- /dev/null
@@ -0,0 +1,491 @@
+/* test.c -- The test command..  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB 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.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/fs.h>
+#include <grub/device.h>
+#include <grub/file.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static int g_test_case_insensitive = 0;
+
+/* A simple implementation for signed numbers. */
+static int
+grub_strtosl (char *arg, char **end, int base)
+{
+  if (arg[0] == '-')
+    return -grub_strtoul (arg + 1, end, base);
+  return grub_strtoul (arg, end, base);
+}
+
+/* Context for test_parse.  */
+struct test_parse_ctx
+{
+  int invert;
+  int or, and;
+  int file_exists;
+  struct grub_dirhook_info file_info;
+  char *filename;
+};
+
+/* Take care of discarding and inverting. */
+static void
+update_val (int val, struct test_parse_ctx *ctx)
+{
+  ctx->and = ctx->and && (ctx->invert ? ! val : val);
+  ctx->invert = 0;
+}
+
+/* A hook for iterating directories. */
+static int
+find_file (const char *cur_filename, const struct grub_dirhook_info *info,
+          void *data)
+{
+  int case_insensitive = 0;
+  struct test_parse_ctx *ctx = data;
+
+  if (g_test_case_insensitive || info->case_insensitive)
+    case_insensitive = 1;
+
+  if ((case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
+       : grub_strcmp (cur_filename, ctx->filename)) == 0)
+    {
+      ctx->file_info = *info;
+      ctx->file_exists = 1;
+      return 1;
+    }
+  return 0;
+}
+
+/* Check if file exists and fetch its information. */
+static void
+get_fileinfo (char *path, struct test_parse_ctx *ctx)
+{
+  char *pathname;
+  char *device_name;
+  grub_fs_t fs;
+  grub_device_t dev;
+
+  ctx->file_exists = 0;
+  device_name = grub_file_get_device_name (path);
+  dev = grub_device_open (device_name);
+  if (! dev)
+    {
+      grub_free (device_name);
+      return;
+    }
+
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    {
+      grub_free (device_name);
+      grub_device_close (dev);
+      return;
+    }
+
+  pathname = grub_strchr (path, ')');
+  if (! pathname)
+    pathname = path;
+  else
+    pathname++;
+
+  /* Remove trailing '/'. */
+  while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
+    pathname[grub_strlen (pathname) - 1] = 0;
+
+  /* Split into path and filename. */
+  ctx->filename = grub_strrchr (pathname, '/');
+  if (! ctx->filename)
+    {
+      path = grub_strdup ("/");
+      ctx->filename = pathname;
+    }
+  else
+    {
+      ctx->filename++;
+      path = grub_strdup (pathname);
+      path[ctx->filename - pathname] = 0;
+    }
+
+  /* It's the whole device. */
+  if (! *pathname)
+    {
+      ctx->file_exists = 1;
+      grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info));
+      /* Root is always a directory. */
+      ctx->file_info.dir = 1;
+
+      /* Fetch writing time. */
+      ctx->file_info.mtimeset = 0;
+      if (fs->fs_mtime)
+       {
+         if (! fs->fs_mtime (dev, &ctx->file_info.mtime))
+           ctx->file_info.mtimeset = 1;
+         grub_errno = GRUB_ERR_NONE;
+       }
+    }
+  else
+    (fs->fs_dir) (dev, path, find_file, ctx);
+
+  grub_device_close (dev);
+  grub_free (path);
+  grub_free (device_name);
+}
+
+/* Parse a test expression starting from *argn. */
+static int
+test_parse (char **args, int *argn, int argc)
+{
+  struct test_parse_ctx ctx = {
+    .and = 1,
+    .or = 0,
+    .invert = 0
+  };
+
+  /* Here we have the real parsing. */
+  while (*argn < argc)
+    {
+      /* First try 3 argument tests. */
+      if (*argn + 2 < argc)
+       {
+         /* String tests. */
+         if (grub_strcmp (args[*argn + 1], "=") == 0
+             || grub_strcmp (args[*argn + 1], "==") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "!=") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         /* GRUB extension: lexicographical sorting. */
+         if (grub_strcmp (args[*argn + 1], "<") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "<=") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], ">") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], ">=") == 0)
+           {
+             update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0,
+                         &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         /* Number tests. */
+         if (grub_strcmp (args[*argn + 1], "-eq") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                         == grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "-ge") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                         >= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "-gt") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                         > grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "-le") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                     <= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "-lt") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                         < grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn + 1], "-ne") == 0)
+           {
+             update_val (grub_strtosl (args[*argn], 0, 0)
+                         != grub_strtosl (args[*argn + 2], 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         /* GRUB extension: compare numbers skipping prefixes.
+            Useful for comparing versions. E.g. vmlinuz-2 -plt vmlinuz-11. */
+         if (grub_strcmp (args[*argn + 1], "-pgt") == 0
+             || grub_strcmp (args[*argn + 1], "-plt") == 0)
+           {
+             int i;
+             /* Skip common prefix. */
+             for (i = 0; args[*argn][i] == args[*argn + 2][i]
+                    && args[*argn][i]; i++);
+
+             /* Go the digits back. */
+             i--;
+             while (grub_isdigit (args[*argn][i]) && i > 0)
+               i--;
+             i++;
+
+             if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
+               update_val (grub_strtoul (args[*argn] + i, 0, 0)
+                           > grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
+             else
+               update_val (grub_strtoul (args[*argn] + i, 0, 0)
+                           < grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
+             (*argn) += 3;
+             continue;
+           }
+
+         /* -nt and -ot tests. GRUB extension: when doing -?t<bias> bias
+            will be added to the first mtime. */
+         if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0
+             || grub_memcmp (args[*argn + 1], "-ot", 3) == 0)
+           {
+             struct grub_dirhook_info file1;
+             int file1exists;
+             int bias = 0;
+
+             /* Fetch fileinfo. */
+             get_fileinfo (args[*argn], &ctx);
+             file1 = ctx.file_info;
+             file1exists = ctx.file_exists;
+             get_fileinfo (args[*argn + 2], &ctx);
+
+             if (args[*argn + 1][3])
+               bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
+
+             if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
+               update_val ((file1exists && ! ctx.file_exists)
+                           || (file1.mtimeset && ctx.file_info.mtimeset
+                               && file1.mtime + bias > ctx.file_info.mtime),
+                           &ctx);
+             else
+               update_val ((! file1exists && ctx.file_exists)
+                           || (file1.mtimeset && ctx.file_info.mtimeset
+                               && file1.mtime + bias < ctx.file_info.mtime),
+                           &ctx);
+             (*argn) += 3;
+             continue;
+           }
+       }
+
+      /* Two-argument tests. */
+      if (*argn + 1 < argc)
+       {
+         /* File tests. */
+         if (grub_strcmp (args[*argn], "-d") == 0)
+           {
+             get_fileinfo (args[*argn + 1], &ctx);
+             update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+      
+         if (grub_strcmp (args[*argn], "-D") == 0)
+           {
+             g_test_case_insensitive = 1;
+             get_fileinfo (args[*argn + 1], &ctx);
+          g_test_case_insensitive = 0;
+             update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn], "-e") == 0)
+           {
+             get_fileinfo (args[*argn + 1], &ctx);
+             update_val (ctx.file_exists, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+      
+         if (grub_strcmp (args[*argn], "-E") == 0)
+           {
+             g_test_case_insensitive = 1;
+             get_fileinfo (args[*argn + 1], &ctx);
+          g_test_case_insensitive = 0;
+             update_val (ctx.file_exists, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn], "-f") == 0)
+           {
+             get_fileinfo (args[*argn + 1], &ctx);
+             /* FIXME: check for other types. */
+             update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+         if (grub_strcmp (args[*argn], "-F") == 0)
+           {
+             g_test_case_insensitive = 1;
+             get_fileinfo (args[*argn + 1], &ctx);
+          g_test_case_insensitive = 0;
+             /* FIXME: check for other types. */
+             update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
+             (*argn) += 2;
+             continue;
+           }
+
+         if (grub_strcmp (args[*argn], "-s") == 0)
+           {
+             grub_file_t file;
+             file = grub_file_open (args[*argn + 1], GRUB_FILE_TYPE_GET_SIZE
+                                    | GRUB_FILE_TYPE_NO_DECOMPRESS);
+             update_val (file && (grub_file_size (file) != 0), &ctx);
+             if (file)
+               grub_file_close (file);
+             grub_errno = GRUB_ERR_NONE;
+             (*argn) += 2;
+             continue;
+           }
+
+         /* String tests. */
+         if (grub_strcmp (args[*argn], "-n") == 0)
+           {
+             update_val (args[*argn + 1][0], &ctx);
+
+             (*argn) += 2;
+             continue;
+           }
+         if (grub_strcmp (args[*argn], "-z") == 0)
+           {
+             update_val (! args[*argn + 1][0], &ctx);
+             (*argn) += 2;
+             continue;
+           }
+       }
+
+      /* Special modifiers. */
+
+      /* End of expression. return to parent. */
+      if (grub_strcmp (args[*argn], ")") == 0)
+       {
+         (*argn)++;
+         return ctx.or || ctx.and;
+       }
+      /* Recursively invoke if parenthesis. */
+      if (grub_strcmp (args[*argn], "(") == 0)
+       {
+         (*argn)++;
+         update_val (test_parse (args, argn, argc), &ctx);
+         continue;
+       }
+
+      if (grub_strcmp (args[*argn], "!") == 0)
+       {
+         ctx.invert = ! ctx.invert;
+         (*argn)++;
+         continue;
+       }
+      if (grub_strcmp (args[*argn], "-a") == 0)
+       {
+         (*argn)++;
+         continue;
+       }
+      if (grub_strcmp (args[*argn], "-o") == 0)
+       {
+         ctx.or = ctx.or || ctx.and;
+         ctx.and = 1;
+         (*argn)++;
+         continue;
+       }
+
+      /* No test found. Interpret if as just a string. */
+      update_val (args[*argn][0], &ctx);
+      (*argn)++;
+    }
+  return ctx.or || ctx.and;
+}
+
+static grub_err_t
+grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
+              int argc, char **args)
+{
+  int argn = 0;
+
+  if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
+    argc--;
+
+  return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
+    : grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
+}
+
+static grub_command_t cmd_1, cmd_2;
+\f
+GRUB_MOD_INIT(test)
+{
+  cmd_1 = grub_register_command ("[", grub_cmd_test,
+                                N_("EXPRESSION ]"), N_("Evaluate an expression."));
+  cmd_1->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
+  cmd_2 = grub_register_command ("test", grub_cmd_test,
+                                N_("EXPRESSION"), N_("Evaluate an expression."));
+  cmd_2->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
+}
+
+GRUB_MOD_FINI(test)
+{
+  grub_unregister_command (cmd_1);
+  grub_unregister_command (cmd_2);
+}
index 5901fac425c9c520c8bae0764d941c0e0137b84a..f5b6772e2f85d602977ecf9513e39c0ac0edf6d2 100644 (file)
@@ -117,6 +117,8 @@ struct grub_fshelp_find_file_iter_ctx
   enum grub_fshelp_filetype *foundtype;
 };
 
+int g_ventoy_case_insensitive = 0;
+
 /* Helper for grub_fshelp_find_file.  */
 static int
 find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
@@ -124,6 +126,11 @@ find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
 {
   struct grub_fshelp_find_file_iter_ctx *ctx = data;
 
+  if (g_ventoy_case_insensitive)
+  {
+      filetype |= GRUB_FSHELP_CASE_INSENSITIVE;
+  }
+
   if (filetype == GRUB_FSHELP_UNKNOWN ||
       ((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
        ? grub_strcasecmp (ctx->name, filename)
index f0e7dcfb0398817c0d9e6aac07afbcde21c00cb4..5785c6f3a0317d1d878a8c1c21c686a050254ff0 100644 (file)
@@ -32,6 +32,7 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+static int g_ventoy_no_joliet = 0;
 static grub_uint64_t g_ventoy_last_read_pos = 0;
 static grub_uint64_t g_ventoy_last_read_offset = 0;
 static grub_uint64_t g_ventoy_last_read_dirent_pos = 0;
@@ -480,8 +481,10 @@ grub_iso9660_mount (grub_disk_t disk)
                 (voldesc.escape[2] == 0x43) ||  /* UCS-2 Level 2.  */
                 (voldesc.escape[2] == 0x45)))  /* UCS-2 Level 3.  */
         {
-          copy_voldesc = 1;
-          data->joliet = 1;
+          if (0 == g_ventoy_no_joliet) {
+            copy_voldesc = 1;
+            data->joliet = 1;
+          }
         }
 
       if (copy_voldesc)
@@ -1108,6 +1111,11 @@ grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
   return err;
 }
 
+void grub_iso9660_set_nojoliet(int nojoliet)
+{
+    g_ventoy_no_joliet = nojoliet;
+}
+
 grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file)
 {
     (void)file;
index 9cb384251d1b720e3afabbb0949467b929c4040a..04d6ce76db085eaa1ca027621124589912f0b484 100644 (file)
@@ -27,7 +27,7 @@
 #include <grub/i18n.h>
 #include <grub/ventoy.h>
 
-#define        GRUB_CACHE_TIMEOUT      2
+#define        GRUB_CACHE_TIMEOUT      10
 
 /* The last time the disk was used.  */
 static grub_uint64_t grub_last_time = 0;
index b01bfad44bcb9b63c5771073316d55531f1290f1..b4d5238c9d5ea3d5c65ff48bca90cbae83079d48 100644 (file)
@@ -83,6 +83,29 @@ grub_file_t grub_memfile_open(const char *name)
     return file;
 }
 
+int ventoy_check_file_exist(const char * fmt, ...)
+{
+    va_list ap;
+    grub_file_t file;
+    char fullpath[256] = {0};
+
+    va_start (ap, fmt);
+    grub_vsnprintf(fullpath, 255, fmt, ap);
+    va_end (ap);
+
+    file = grub_file_open(fullpath, GRUB_FILE_TYPE_NONE);
+    if (!file)
+    {
+        grub_errno = 0;
+        return 0;
+    }
+    else
+    {
+        grub_file_close(file);
+        return 1;
+    }
+}
+
 grub_file_t
 grub_file_open (const char *name, enum grub_file_type type)
 {
index 43b2de984051ca8c296d3fb505e3ded6395074e4..2f22ecb56a53e1192beede96130cbb8b8af4572b 100644 (file)
@@ -260,6 +260,45 @@ reclaim_module_space (void)
 #endif
 }
 
+#ifndef GRUB_MACHINE_EFI
+static int ventoy_legacy_limit_workaround(void)
+{
+    grub_file_t file;
+    char *pos, *root;
+    char buf[128];
+
+    root = grub_strdup(grub_env_get("root"));
+    if (!root)
+    {
+        return 1;
+    }
+
+    pos = grub_strchr(root, ',');
+    if (pos) *pos = 0;
+
+    grub_snprintf(buf, sizeof(buf), "(%s,1)/ventoy/ventoy.disk.img.xz", root);
+    file = grub_file_open(buf, GRUB_FILE_TYPE_NONE);
+    if (file)
+    {
+        pos = grub_malloc(file->size);
+        if (pos)
+        {
+            grub_file_read(file, pos, file->size);
+            grub_snprintf(buf, sizeof(buf), "loopback ventoydisk mem:0x%lx:size:%lu", 
+                          (unsigned long)pos, (unsigned long)file->size);
+            
+            grub_parser_execute(buf);
+            grub_env_set("prefix", "(ventoydisk)/grub");
+        }
+
+        grub_file_close(file);
+    }
+
+    grub_free(root);      
+    return 0;
+}
+#endif
+
 /* The main routine.  */
 void __attribute__ ((noreturn))
 grub_main (void)
@@ -293,6 +332,12 @@ grub_main (void)
   grub_env_export ("root");
   grub_env_export ("prefix");
 
+#ifndef GRUB_MACHINE_EFI
+  if (0 == ventoy_check_file_exist("%s/grub.cfg", grub_env_get("prefix"))) {
+      ventoy_legacy_limit_workaround();
+  }
+#endif
+
   /* Reclaim space used for modules.  */
   reclaim_module_space ();
 
index 6c10f4ab22bcb01f5817c905c987cd7575c9c385..e416c6f322cca2dbefa1de9a046458b4225b2e48 100644 (file)
@@ -41,6 +41,7 @@ int g_ventoy_iso_uefi_drv = 0;
 int g_ventoy_last_entry = 0;
 int g_ventoy_suppress_esc = 0;
 int g_ventoy_menu_esc = 0;
+int g_ventoy_fn_mutex = 0;
 
 /* Time to delay after displaying an error message about a default/fallback
    entry failing to boot.  */
@@ -802,39 +803,53 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
              goto refresh;
 
         case GRUB_TERM_KEY_F2:
-            cmdstr = grub_env_get("VTOY_F2_CMD");
-            if (cmdstr)
-            {
-                menu_fini ();
-                grub_script_execute_sourcecode(cmdstr);
-                goto refresh;
+            if (0 == g_ventoy_fn_mutex) {
+                cmdstr = grub_env_get("VTOY_F2_CMD");
+                if (cmdstr)
+                {
+                    menu_fini ();
+                    g_ventoy_fn_mutex = 1;
+                    grub_script_execute_sourcecode(cmdstr);
+                    g_ventoy_fn_mutex = 0;
+                    goto refresh;
+                }
             }
             break;
         case GRUB_TERM_KEY_F3:
-            cmdstr = grub_env_get("VTOY_F3_CMD");
-            if (cmdstr)
-            {
-                menu_fini ();
-                grub_script_execute_sourcecode(cmdstr);
-                goto refresh;
+            if (0 == g_ventoy_fn_mutex) {
+                cmdstr = grub_env_get("VTOY_F3_CMD");
+                if (cmdstr)
+                {
+                    menu_fini ();
+                    grub_script_execute_sourcecode(cmdstr);
+                    goto refresh;
+                }
             }
             break;
         case GRUB_TERM_KEY_F4:
-            cmdstr = grub_env_get("VTOY_F4_CMD");
-            if (cmdstr)
-            {
-                menu_fini ();
-                grub_script_execute_sourcecode(cmdstr);
-                goto refresh;
+            if (0 == g_ventoy_fn_mutex) {
+                cmdstr = grub_env_get("VTOY_F4_CMD");
+                if (cmdstr)
+                {
+                    menu_fini ();
+                    g_ventoy_fn_mutex = 1;
+                    grub_script_execute_sourcecode(cmdstr);
+                    g_ventoy_fn_mutex = 0;
+                    goto refresh;
+                }
             }
             break;
         case GRUB_TERM_KEY_F5:
-            cmdstr = grub_env_get("VTOY_F5_CMD");
-            if (cmdstr)
-            {
-                menu_fini ();
-                grub_script_execute_sourcecode(cmdstr);
-                goto refresh;
+            if (0 == g_ventoy_fn_mutex) {
+                cmdstr = grub_env_get("VTOY_F5_CMD");
+                if (cmdstr)
+                {
+                    menu_fini ();
+                    g_ventoy_fn_mutex = 1;
+                    grub_script_execute_sourcecode(cmdstr);
+                    g_ventoy_fn_mutex = 0;
+                    goto refresh;
+                }
             }
             break;
         case GRUB_TERM_KEY_F6:
index 1ad4ebe8b2058d53e6078dc5d8242e5becac144e..93641ee393525c8777b750a271aeaf0470d5678c 100644 (file)
@@ -68,6 +68,7 @@ img_iterator_node *g_img_iterator_tail = NULL;
 
 grub_uint8_t g_ventoy_break_level = 0;
 grub_uint8_t g_ventoy_debug_level = 0;
+grub_uint8_t g_ventoy_chain_type = 0;
 grub_uint8_t *g_ventoy_cpio_buf = NULL;
 grub_uint32_t g_ventoy_cpio_size = 0;
 cpio_newc_header *g_ventoy_initrd_head = NULL;
@@ -433,6 +434,27 @@ static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int arg
     return rc;
 }
 
+static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    (void)ctxt;
+
+    if (argc != 1)
+    {
+        return 1;
+    }
+
+    if (args[0][0] == '1')
+    {
+        grub_iso9660_set_nojoliet(1);
+    }
+    else
+    {
+        grub_iso9660_set_nojoliet(0);
+    }
+
+    return 0;
+}
+
 static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int i;
@@ -853,6 +875,8 @@ static int ventoy_colect_img_files(const char *filename, const struct grub_dirho
             *((img_info **)(node->tail)) = img;
             g_ventoy_img_count++;
 
+            img->alias = ventoy_plugin_get_menu_alias(img->path);
+
             debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
         }
     }
@@ -1031,7 +1055,8 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
                       "  %s_%s \n" 
                       "}\n", 
                       grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT), 
-                      img->unsupport ? "[unsupported] " : "", img->name, img->id,
+                      img->unsupport ? "[unsupported] " : "", 
+                      img->alias ? img->alias : img->name, img->id,
                       (img->type == img_type_iso) ? "iso" : "wim",
                       img->unsupport ? "unsupport_menuentry" : "common_menuentry");
     }
@@ -1115,7 +1140,7 @@ static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char
     if (strdata && strdata[0] == '/')
     {
         len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
-        if (g_img_iterator_head.dir[len] != '/')
+        if (g_img_iterator_head.dir[len - 1] != '/')
         {
             g_img_iterator_head.dir[len++] = '/';
         }
@@ -1174,7 +1199,8 @@ static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char
                   "menuentry \"%s%s\" --id=\"VID_%d\" {\n"
                   "  %s_%s \n" 
                   "}\n", 
-                  cur->unsupport ? "[unsupported] " : "", cur->name, cur->id,
+                  cur->unsupport ? "[unsupported] " : "", 
+                  cur->alias ? cur->alias : cur->name, cur->id,
                   (cur->type == img_type_iso) ? "iso" : "wim",
                   cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
     }
@@ -1394,6 +1420,7 @@ int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
 void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
 {
     char *pos;
+    const char *fs = NULL;
     grub_uint32_t i;
     grub_uint8_t  chksum = 0;
     grub_disk_t   disk;
@@ -1419,6 +1446,14 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
 
     param->vtoy_reserved[0] = g_ventoy_break_level;
     param->vtoy_reserved[1] = g_ventoy_debug_level;
+    
+    param->vtoy_reserved[2] = g_ventoy_chain_type;
+
+    fs = ventoy_get_env("ventoy_fs_probe");
+    if (fs && grub_strcmp(fs, "udf") == 0)
+    {
+        param->vtoy_reserved[3] = 1;
+    }
 
     /* calculate checksum */
     for (i = 0; i < sizeof(ventoy_os_param); i++)
@@ -1567,6 +1602,8 @@ static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int ar
     (void)argc;
     (void)args;
 
+    debug("select auto installation %d\n", argc);
+
     if (argc < 1)
     {
         return 0;
@@ -1575,6 +1612,7 @@ static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int ar
     node = ventoy_plugin_find_install_template(args[0]);
     if (!node)
     {
+        debug("Install template not found for %s\n", args[0]);
         return 0;
     }
 
@@ -1622,6 +1660,8 @@ static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int arg
     (void)argc;
     (void)args;
 
+    debug("select persistece %d\n", argc);
+
     if (argc < 1)
     {
         return 0;
@@ -1630,6 +1670,7 @@ static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int arg
     node = ventoy_plugin_find_persistent(args[0]);
     if (!node)
     {
+        debug("Persistence image not found for %s\n", args[0]);
         return 0;
     }
 
@@ -1854,12 +1895,51 @@ static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, cha
     return 0;
 }
 
+static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    img_info *cur = g_ventoy_img_list;
+        
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    while (cur)
+    {
+        grub_printf("path:<%s>\n", cur->path);
+        grub_printf("name:<%s>\n\n", cur->name);
+        cur = cur->next;
+    }
+
+    return 0;
+}
+
 static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     (void)ctxt;
     (void)argc;
     (void)args;
 
+{
+    grub_file_t file;
+    char *buf;
+    char name[128];
+
+    file = grub_file_open("(hd0,1)/ventoy/ventoy.disk.img.xz", GRUB_FILE_TYPE_NONE);
+    if (file)
+    {
+        grub_printf("Open File OK (size:%llu)\n", (ulonglong)file->size);
+
+        buf = grub_malloc(file->size);
+        grub_file_read(file, buf, file->size);
+
+        grub_file_close(file);
+
+        grub_snprintf(name, sizeof(name), "mem:0x%llx:size:%llu", (ulonglong)(ulong)buf, (ulonglong)file->size);
+        grub_printf("<%s>\n", name);
+    }
+}
+
+
     ventoy_plugin_dump_auto_install();
 
     return 0;
@@ -1962,6 +2042,31 @@ static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc,
     return 0;
 }
 
+static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    grub_file_t file;
+
+    (void)ctxt;
+
+    if (argc != 1)
+    {
+        return 1;
+    }
+    
+    g_ventoy_case_insensitive = 1;
+    file = grub_file_open(args[0], VENTOY_FILE_TYPE);
+    g_ventoy_case_insensitive = 0;
+
+    grub_errno = 0;
+
+    if (file)
+    {
+        grub_file_close(file);
+        return 0;
+    }
+    return 1;
+}
+
 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int id = 0;
@@ -2109,6 +2214,8 @@ static int ventoy_env_init(void)
     grub_env_set("vtdebug_flag", "");
     grub_env_export("vtdebug_flag");
 
+
+
     g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
     g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
 
@@ -2146,11 +2253,13 @@ static cmd_para ventoy_cmds[] =
     { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
     { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
     { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
+    { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
     { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
     { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
     { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
     { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
 
+    { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
     { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
     { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
     { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem, 0, NULL, "", "", NULL },
@@ -2164,18 +2273,25 @@ static cmd_para ventoy_cmds[] =
     { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
     { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
     { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
+    { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
 
     { "vt_windows_reset",      ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
-    { "vt_windows_locate_wim", ventoy_cmd_wimdows_locate_wim, 0, NULL, "", "", NULL },
     { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
+    { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
+    { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
+    { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
+    { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
     { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
 
     { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
     { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata, 0, NULL, "", "", NULL },
     { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
+    { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
 
     
     { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
+    { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
+
 };
 
 
index da6e6889474cafc1385b180e6577d70128c06709..c621b1f858720cd2dbbe7251e835e82241e1cd25 100644 (file)
@@ -132,6 +132,9 @@ typedef struct img_info
 {
     char path[512];
     char name[256];
+
+    const char *alias;
+    
     int id;
     int type;
     grub_uint64_t size;
@@ -363,6 +366,19 @@ typedef struct wim_tail
     grub_uint32_t new_lookup_align_len;
 }wim_tail;
 
+typedef struct wim_patch
+{
+    int pathlen;
+    char path[256];
+
+    wim_hash old_hash;
+    wim_tail wim_data;
+    wim_lookup_entry *replace_look;
+
+    int valid;
+
+    struct wim_patch *next;
+}wim_patch;
 
 
 typedef enum _JSON_TYPE
@@ -412,11 +428,13 @@ typedef struct _JSON_PARSE
 }
 
 typedef int (*ventoy_plugin_entry_pf)(VTOY_JSON *json, const char *isodisk);
+typedef int (*ventoy_plugin_check_pf)(VTOY_JSON *json, const char *isodisk);
 
 typedef struct plugin_entry
 {
     const char *key;
     ventoy_plugin_entry_pf entryfunc;
+    ventoy_plugin_check_pf checkfunc;
 }plugin_entry;
 
 
@@ -440,9 +458,9 @@ int ventoy_is_file_exist(const char *fmt, ...);
 int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
-grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
 
 VTOY_JSON *vtoy_json_find_item
 (
@@ -596,12 +614,23 @@ typedef struct persistence_config
     struct persistence_config *next;
 }persistence_config;
 
+typedef struct menu_alias
+{
+    int pathlen;
+    char isopath[256];
+    char alias[256];
+
+    struct menu_alias *next;
+}menu_alias;
+
 extern int g_ventoy_menu_esc;
 extern int g_ventoy_suppress_esc;
 extern int g_ventoy_last_entry;
 extern int g_ventoy_memdisk_mode;
 extern int g_ventoy_iso_raw;
 extern int g_ventoy_iso_uefi_drv;
+extern int g_ventoy_case_insensitive;
+extern grub_uint8_t g_ventoy_chain_type;
 
 int ventoy_cmp_img(img_info *img1, img_info *img2);
 void ventoy_swap_img(img_info *img1, img_info *img2);
@@ -611,9 +640,15 @@ persistence_config * ventoy_plugin_find_persistent(const char *isopath);
 void ventoy_plugin_dump_auto_install(void);
 int ventoy_fill_windows_rtdata(void *buf, char *isopath);
 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list);
+const char * ventoy_plugin_get_menu_alias(const char *isopath);
 int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
 int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
 void ventoy_plugin_dump_persistence(void);
+grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
 
 #endif /* __VENTOY_DEF_H__ */
 
index 8a4e8b1081f9592a4d25722849029802a370ead4..b9e4a743490d78548fa4fd509f2c81245cebea6d 100644 (file)
@@ -42,6 +42,11 @@ static void json_debug(const char *fmt, ...)
 {
     va_list args;
 
+    if (g_ventoy_debug == 0)
+    {
+        return;
+    }
+
     va_start (args, fmt);
     grub_vprintf (fmt, args);
     va_end (args);
index 1e795c3cdf9bd464cb6ed3200669bd354b5e28a3..ddd7499aa97725effc15fea86c8c1e8f79d7d4ca 100644 (file)
@@ -841,6 +841,50 @@ static grub_err_t ventoy_linux_locate_initrd(int filt, int *filtcnt)
 }
 
 
+grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int index = 0;
+    char buf[32];
+    initrd_info *node = NULL;
+    
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    if (argc != 1)
+    {
+        return 1;
+    }
+
+    if (g_initrd_img_count == 1)
+    {
+        ventoy_set_env(args[0], "0");
+        VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+    }
+
+    for (node = g_initrd_img_list; node; node = node->next)
+    {
+        if (node->size <= 0)
+        {
+            continue;
+        }
+    
+        if (grub_strstr(node->name, "ucode") || grub_strstr(node->name, "-firmware"))
+        {
+            index++;
+            continue;
+        }
+
+        grub_snprintf(buf, sizeof(buf), "%d", index);
+        ventoy_set_env(args[0], buf);
+        break;
+    }
+
+    debug("main initrd index:%d\n", index);
+
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
 grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int sizefilt = 0;
@@ -1100,6 +1144,7 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
     grub_memset(chain, 0, sizeof(ventoy_chain_head));
 
     /* part 1: os parameter */
+    g_ventoy_chain_type = 0;
     ventoy_fill_os_param(file, &(chain->os_param));
 
     /* part 2: chain head */
index 4aad58d81adbad7a8ef76c9ec6bedf3ffa475612..1948d0af4c4a859899bf443aafaa3d64fcc07798 100644 (file)
@@ -41,6 +41,46 @@ GRUB_MOD_LICENSE ("GPLv3+");
 static char g_iso_disk_name[128];
 static install_template *g_install_template_head = NULL;
 static persistence_config *g_persistence_head = NULL;
+static menu_alias *g_menu_alias_head = NULL;
+
+static int ventoy_plugin_control_check(VTOY_JSON *json, const char *isodisk)
+{
+    int rc = 0;
+    VTOY_JSON *pNode = NULL;
+    VTOY_JSON *pChild = NULL;
+
+    (void)isodisk;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        grub_printf("Not array type %d\n", json->enDataType);
+        return 1;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        if (pNode->enDataType == JSON_TYPE_OBJECT)
+        {
+            pChild = pNode->pstChild;
+            if (pChild->enDataType == JSON_TYPE_STRING)
+            {
+                grub_printf("%s: %s\n", pChild->pcName, pChild->unData.pcStrVal);
+            }
+            else
+            {
+                grub_printf("%s is NOT string type\n", pChild->pcName);
+                rc = 1;
+            }
+        }
+        else
+        {
+            grub_printf("%s is not an object\n", pNode->pcName);
+            rc = 1;
+        }
+    }
+
+    return rc;
+}
 
 static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
 {
@@ -70,6 +110,64 @@ static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
     return 0;
 }
 
+static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
+{
+    int exist = 0;
+    const char *value;
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "file");
+    if (value)
+    {
+        grub_printf("file: %s\n", value);
+        if (value[0] == '/')
+        {
+            exist = ventoy_is_file_exist("%s%s", isodisk, value);
+        }
+        else
+        {
+            exist = ventoy_is_file_exist("%s/ventoy/%s", isodisk, value);
+        }
+        
+        if (exist == 0)
+        {
+            grub_printf("Theme file %s does NOT exist\n", value);
+            return 1;
+        }
+    }
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
+    if (value)
+    {
+        grub_printf("gfxmode: %s\n", value);
+    }
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
+    if (value)
+    {
+        grub_printf("display_mode: %s\n", value);
+    }
+
+    value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
+    if (value)
+    {
+        grub_printf("ventoy_left: %s\n", value);
+    }
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
+    if (value)
+    {
+        grub_printf("ventoy_top: %s\n", value);
+    }
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
+    if (value)
+    {
+        grub_printf("ventoy_color: %s\n", value);
+    }
+
+    return 0;
+}
+
 static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
 {
     const char *value;
@@ -104,6 +202,13 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
         grub_env_set("vtoy_gfxmode", value);
     }
     
+    value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
+    if (value)
+    {
+        debug("display_mode %s\n", value);
+        grub_env_set("vtoy_display_mode", value);
+    }
+
     value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
     if (value)
     {
@@ -125,6 +230,92 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
     return 0;
 }
 
+static int ventoy_plugin_check_path(const char *path, const char *file)
+{
+    if (file[0] != '/')
+    {
+        grub_printf("%s is NOT begin with '/' \n", file);
+        return 1;
+    }
+
+    if (grub_strchr(file, '\\'))
+    {
+        grub_printf("%s contains invalid '\\' \n", file);
+        return 1;
+    }
+    
+    if (grub_strstr(file, "//"))
+    {
+        grub_printf("%s contains invalid double slash\n", file);
+        return 1;
+    }
+
+    if (grub_strstr(file, "../"))
+    {
+        grub_printf("%s contains invalid '../' \n", file);
+        return 1;
+    }
+
+    if (!ventoy_is_file_exist("%s%s", path, file))
+    {
+        grub_printf("%s%s does NOT exist\n", path, file);
+        return 1;
+    }
+
+    return 0;
+}
+
+static int ventoy_plugin_check_fullpath
+(
+    VTOY_JSON *json, 
+    const char *isodisk, 
+    const char *key
+)
+{
+    int rc = 0;
+    int ret = 0;
+    VTOY_JSON *node = json;
+    VTOY_JSON *child = NULL;
+    
+    while (node)
+    {
+        if (0 == grub_strcmp(key, node->pcName))
+        {
+            break;
+        }
+        node = node->pstNext;
+    }
+
+    if (!node)
+    {
+        return 1;
+    }
+
+    if (JSON_TYPE_STRING == node->enDataType)
+    {
+        ret = ventoy_plugin_check_path(isodisk, node->unData.pcStrVal);
+        grub_printf("%s: %s [%s]\n", key, node->unData.pcStrVal, ret ? "FAIL" : "OK");
+    }
+    else if (JSON_TYPE_ARRAY == node->enDataType)
+    {
+        for (child = node->pstChild; child; child = child->pstNext)
+        {
+            if (JSON_TYPE_STRING != child->enDataType)
+            {
+                grub_printf("Non string json type\n");
+            }
+            else
+            {
+                rc = ventoy_plugin_check_path(isodisk, child->unData.pcStrVal);
+                grub_printf("%s: %s [%s]\n", key, child->unData.pcStrVal, rc ? "FAIL" : "OK");
+                ret += rc;
+            }
+        }
+    }
+
+    return ret;
+}
+
 static int ventoy_plugin_parse_fullpath
 (
     VTOY_JSON *json, 
@@ -209,6 +400,46 @@ static int ventoy_plugin_parse_fullpath
     return rc;
 }
 
+static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk)
+{
+    const char *iso = NULL;
+    VTOY_JSON *pNode = NULL;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        grub_printf("Not array type %d\n", json->enDataType);
+        return 1;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        if (pNode->enDataType != JSON_TYPE_OBJECT)
+        {
+            grub_printf("NOT object type\n");
+        }
+    
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        if (iso)
+        {
+            if (0 == ventoy_plugin_check_path(isodisk, iso))
+            {
+                grub_printf("image: %s [OK]\n", iso);
+                ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template");
+            }
+            else
+            {
+                grub_printf("image: %s [FAIL]\n", iso);
+            }
+        }
+        else
+        {
+            grub_printf("image not found\n");
+        }
+    }
+
+    return 0;
+}
+
 static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk)
 {
     int pathnum = 0;
@@ -264,6 +495,45 @@ static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk
     return 0;
 }
 
+static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk)
+{
+    const char *iso = NULL;
+    VTOY_JSON *pNode = NULL;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        grub_printf("Not array type %d\n", json->enDataType);
+        return 1;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        if (pNode->enDataType != JSON_TYPE_OBJECT)
+        {
+            grub_printf("NOT object type\n");
+        }
+    
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        if (iso)
+        {
+            if (0 == ventoy_plugin_check_path(isodisk, iso))
+            {
+                grub_printf("image: %s [OK]\n", iso);
+                ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend");
+            } 
+            else
+            {
+                grub_printf("image: %s [FAIL]\n", iso);
+            }
+        }
+        else
+        {
+            grub_printf("image not found\n");
+        }
+    }
+
+    return 0;
+}
 
 static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
 {
@@ -322,13 +592,93 @@ static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
     return 0;
 }
 
+static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk)
+{
+    const char *iso = NULL;
+    const char *alias = NULL;
+    VTOY_JSON *pNode = NULL;
+
+    (void)isodisk;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        grub_printf("Not array %d\n", json->enDataType);
+        return 1;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
+        if (iso && iso[0] == '/' && alias)
+        {
+            grub_printf("image: <%s>\n", iso);
+            grub_printf("alias: <%s>\n\n", alias);
+        }
+    }
+
+    return 0;
+}
+
+static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
+{
+    const char *iso = NULL;
+    const char *alias = NULL;
+    VTOY_JSON *pNode = NULL;
+    menu_alias *node = NULL;
+    menu_alias *next = NULL;
+
+    (void)isodisk;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        debug("Not array %d\n", json->enDataType);
+        return 0;
+    }
+
+    if (g_menu_alias_head)
+    {
+        for (node = g_menu_alias_head; node; node = next)
+        {
+            next = node->next;
+            grub_free(node);
+        }
+
+        g_menu_alias_head = NULL;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
+        if (iso && iso[0] == '/' && alias)
+        {
+            node = grub_zalloc(sizeof(menu_alias));
+            if (node)
+            {
+                node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
+                grub_snprintf(node->alias, sizeof(node->alias), "%s", alias);
+
+                if (g_menu_alias_head)
+                {
+                    node->next = g_menu_alias_head;
+                }
+                
+                g_menu_alias_head = node;
+            }
+        }
+    }
+
+    return 0;
+}
 
 static plugin_entry g_plugin_entries[] = 
 {
-    { "control", ventoy_plugin_control_entry },
-    { "theme", ventoy_plugin_theme_entry },
-    { "auto_install", ventoy_plugin_auto_install_entry },
-    { "persistence", ventoy_plugin_persistence_entry },
+    { "control", ventoy_plugin_control_entry, ventoy_plugin_control_check },
+    { "theme", ventoy_plugin_theme_entry, ventoy_plugin_theme_check },
+    { "auto_install", ventoy_plugin_auto_install_entry, ventoy_plugin_auto_install_check },
+    { "persistence", ventoy_plugin_persistence_entry, ventoy_plugin_persistence_check },
+    { "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check },
 };
 
 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
@@ -566,3 +916,100 @@ end:
     return rc;
 }
 
+const char * ventoy_plugin_get_menu_alias(const char *isopath)
+{
+    menu_alias *node = NULL;
+    int len = (int)grub_strlen(isopath);
+    
+    for (node = g_menu_alias_head; node; node = node->next)
+    {
+        if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
+        {
+            return node->alias;
+        }
+    }
+
+    return NULL;
+}
+
+grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int i = 0;
+    int ret = 0;
+    char *buf = NULL;
+    grub_file_t file;
+    VTOY_JSON *node = NULL;
+    VTOY_JSON *json = NULL;
+    
+    (void)ctxt;
+
+    if (argc != 3)
+    {
+        return 0;
+    }
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
+    if (!file)
+    {
+        grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
+        goto end;
+    }
+
+    buf = grub_malloc(file->size + 1);
+    if (!buf)
+    {
+        grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
+        goto end;
+    }
+    
+    buf[file->size] = 0;
+    grub_file_read(file, buf, file->size);
+
+    json = vtoy_json_create();
+    if (!json)
+    {
+        grub_printf("Failed to create json\n");
+        goto end;
+    }
+
+    ret = vtoy_json_parse(json, buf);
+    if (ret)
+    {
+        grub_printf("Syntax error detected in ventoy.json, please check it.\n");
+        goto end;
+    }
+
+    for (node = json->pstChild; node; node = node->pstNext)
+    {
+        if (grub_strcmp(node->pcName, args[1]) == 0)
+        {
+            break;
+        }
+    }
+
+    if (!node)
+    {
+        grub_printf("%s is NOT found in ventoy.json\n", args[1]);
+        goto end;
+    }
+
+    for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
+    {
+        if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
+        {
+            if (g_plugin_entries[i].checkfunc)
+            {
+                ret = g_plugin_entries[i].checkfunc(node, args[2]);                
+            }
+            break;
+        }
+    }
+    
+end:
+    check_free(file, grub_file_close);
+    check_free(json, vtoy_json_destroy);
+    grub_check_free(buf);
+
+    return 0;
+}
+
index 6ca05632b38e0089bfb796b65689892d09d4f189..438b6985f4b6f8a2f77000d23b2326d3f6c4db54 100644 (file)
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-wim_hash g_old_hash;
-wim_tail g_wim_data;
+static int g_iso_fs_type = 0;
+static int g_wim_total_patch_count = 0;
+static int g_wim_valid_patch_count = 0;
+static wim_patch *g_wim_patch_head = NULL;
 
-static wim_lookup_entry *g_replace_look = NULL;
+grub_uint8_t g_temp_buf[512];
 
 grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf );
 
+static wim_patch *ventoy_find_wim_patch(const char *path)
+{
+    int len = (int)grub_strlen(path);
+    wim_patch *node = g_wim_patch_head;
+
+    while (node)
+    {
+        if (len == node->pathlen && 0 == grub_strcmp(path, node->path))
+        {
+            return node;
+        }
+        node = node->next;
+    }
+
+    return NULL;
+}
+
+static int ventoy_collect_wim_patch(const char *bcdfile)
+{
+    int i, j, k;
+    int rc = 1;
+    grub_uint64_t magic;
+    grub_file_t file = NULL;
+    char *buf = NULL;
+    wim_patch *node = NULL;
+    char c;
+    grub_uint8_t byte;
+    char valid;
+    char path[256];
+
+    g_ventoy_case_insensitive = 1;
+    file = grub_file_open(bcdfile, VENTOY_FILE_TYPE);
+    g_ventoy_case_insensitive = 0;
+    if (!file)
+    {
+        debug("Failed to open file %s\n", bcdfile);
+        grub_errno = 0;
+        goto end;
+    }
+
+    buf = grub_malloc(file->size + 8);
+    if (!buf)
+    {
+        goto end;
+    }
+
+    grub_file_read(file, buf, file->size);
+
+    for (i = 0; i < (int)file->size - 8; i++)
+    {        
+        if (buf[i + 8] != 0)
+        {
+            continue;
+        }
+        
+        magic = *(grub_uint64_t *)(buf + i);
+        
+        /* .wim .WIM .Wim */
+        if ((magic == 0x006D00690077002EULL) ||
+            (magic == 0x004D00490057002EULL) ||
+            (magic == 0x006D00690057002EULL))
+        {
+            for (j = i; j > 0; j-= 2)
+            {
+                if (*(grub_uint16_t *)(buf + j) == 0)
+                {
+                    break;
+                }
+            }
+
+            if (j > 0)
+            {
+                byte = (grub_uint8_t)(*(grub_uint16_t *)(buf + j + 2));
+                if (byte != '/' && byte != '\\')
+                {
+                    continue;
+                }
+                
+                valid = 1;
+                for (k = 0, j += 2; k < (int)sizeof(path) - 1 && j < i + 8; j += 2)
+                {
+                    byte = (grub_uint8_t)(*(grub_uint16_t *)(buf + j));
+                    c = (char)byte;
+                    if (byte > '~' || byte < ' ') /* not printable */
+                    {
+                        valid = 0;
+                        break;
+                    }
+                    else if (c == '\\')
+                    {
+                        c = '/';
+                    }
+                    
+                    path[k++] = c;
+                }
+                path[k++] = 0;
+
+                debug("@@@@ Find wim flag:<%s>\n", path);
+
+                if (0 == valid)
+                {
+                    debug("Invalid wim file %d\n", k);
+                }
+                else if (NULL == ventoy_find_wim_patch(path))
+                {
+                    node = grub_zalloc(sizeof(wim_patch));
+                    if (node)
+                    {
+                        node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", path);
+
+                        debug("add patch <%s>\n", path);
+                        
+                        if (g_wim_patch_head)
+                        {
+                            node->next = g_wim_patch_head;
+                        }
+                        g_wim_patch_head = node;
+
+                        g_wim_total_patch_count++;
+                    }
+                }
+                else
+                {
+                    debug("wim <%s> already exist\n", path);
+                }
+            }
+        }
+    }
+
+end:
+    check_free(file, grub_file_close);
+    grub_check_free(buf);
+    return rc;
+}
+
+grub_err_t ventoy_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    char buf[32];
+    
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    if (argc == 1)
+    {
+        grub_snprintf(buf, sizeof(buf), "%d", g_wim_total_patch_count);
+        ventoy_set_env(args[0], buf);
+    }
+    
+    return 0;
+}
+
+grub_err_t ventoy_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    wim_patch *node = NULL;
+    
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    if (argc != 2)
+    {
+        return 1;
+    }
+
+    debug("ventoy_cmd_collect_wim_patch %s %s\n", args[0], args[1]);
+
+    if (grub_strcmp(args[0], "bcd") == 0)
+    {
+        ventoy_collect_wim_patch(args[1]);
+        return 0;
+    }
+
+    if (NULL == ventoy_find_wim_patch(args[1]))
+    {
+        node = grub_zalloc(sizeof(wim_patch));
+        if (node)
+        {
+            node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", args[1]);
+
+            debug("add patch <%s>\n", args[1]);
+            
+            if (g_wim_patch_head)
+            {
+                node->next = g_wim_patch_head;
+            }
+            g_wim_patch_head = node;
+
+            g_wim_total_patch_count++;
+        }
+    }
+
+    return 0;
+}
+
+
+grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int i = 0;
+    wim_patch *node = NULL;
+
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    for (node = g_wim_patch_head; node; node = node->next)
+    {
+        grub_printf("%d %s [%s]\n", i++, node->path, node->valid ? "SUCCESS" : "FAIL");
+    }
+
+    return 0;
+}
+
+
 static int wim_name_cmp(const char *search, grub_uint16_t *name, grub_uint16_t namelen)
 {
     char c1 = vtoy_to_upper(*search);
@@ -96,16 +312,24 @@ static int ventoy_is_pe64(grub_uint8_t *buffer)
 
 grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args)
 {
+    wim_patch *next = NULL;
+    wim_patch *node = g_wim_patch_head;
+
     (void)ctxt;
     (void)argc;
     (void)args;
-    
-    check_free(g_wim_data.jump_bin_data, grub_free);
-    check_free(g_wim_data.new_meta_data, grub_free);
-    check_free(g_wim_data.new_lookup_data, grub_free);
 
-    grub_memset(&g_wim_data, 0, sizeof(g_wim_data));
+    while (node)
+    {
+        next = node->next;
+        grub_free(node);
+        node = next;
+    }
 
+    g_wim_patch_head = NULL;
+    g_wim_total_patch_count = 0;
+    g_wim_valid_patch_count = 0;
+    
     return 0;
 }
 
@@ -159,7 +383,7 @@ end:
     return 0;
 }
 
-static int ventoy_get_override_info(grub_file_t file)
+static int ventoy_get_override_info(grub_file_t file, wim_tail *wim_data)
 {
     grub_uint32_t start_block;
     grub_uint64_t file_offset;
@@ -169,7 +393,7 @@ static int ventoy_get_override_info(grub_file_t file)
     
     if (grub_strcmp(file->fs->name, "iso9660") == 0)
     {
-        g_wim_data.iso_type = 0;
+        g_iso_fs_type = wim_data->iso_type = 0;
         override_len = sizeof(ventoy_iso9660_override);
         override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
 
@@ -181,7 +405,7 @@ static int ventoy_get_override_info(grub_file_t file)
     }
     else
     {
-        g_wim_data.iso_type = 1;    
+        g_iso_fs_type = wim_data->iso_type = 1;    
         override_len = sizeof(ventoy_udf_override);
         override_offset = grub_udf_get_last_file_attr_offset(file, &start_block, &fe_entry_size_offset);
         
@@ -191,11 +415,11 @@ static int ventoy_get_override_info(grub_file_t file)
             (ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset, start_block);
     }
 
-    g_wim_data.file_offset = file_offset;
-    g_wim_data.udf_start_block = start_block;
-    g_wim_data.fe_entry_size_offset = fe_entry_size_offset;
-    g_wim_data.override_offset = override_offset;
-    g_wim_data.override_len = override_len;
+    wim_data->file_offset = file_offset;
+    wim_data->udf_start_block = start_block;
+    wim_data->fe_entry_size_offset = fe_entry_size_offset;
+    wim_data->override_offset = override_offset;
+    wim_data->override_len = override_len;
 
     return 0;
 }
@@ -336,7 +560,7 @@ static wim_directory_entry * search_replace_wim_dirent(void *meta_data, wim_dire
 {
     wim_directory_entry *wim_dirent = NULL;
     const char *winpeshl_path[] = { "Windows", "System32", "winpeshl.exe", NULL };
-    const char *pecmd_path[] = { "Windows", "System32", "PECMD.exe", NULL };
+    //const char *pecmd_path[] = { "Windows", "System32", "PECMD.exe", NULL };
 
     wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path);
     if (wim_dirent)
@@ -344,11 +568,13 @@ static wim_directory_entry * search_replace_wim_dirent(void *meta_data, wim_dire
         return wim_dirent;
     }
     
+    #if 0
     wim_dirent = search_full_wim_dirent(meta_data, dir, pecmd_path);
     if (wim_dirent)
     {
         return wim_dirent;
     }
+    #endif
 
     return NULL;
 }
@@ -394,7 +620,7 @@ static wim_lookup_entry * ventoy_find_meta_entry(wim_header *header, wim_lookup_
     return NULL;
 }
 
-static int ventoy_update_all_hash(void *meta_data, wim_directory_entry *dir)
+static int ventoy_update_all_hash(wim_patch *patch, void *meta_data, wim_directory_entry *dir)
 {
     if ((meta_data == NULL) || (dir == NULL))
     {
@@ -408,15 +634,15 @@ static int ventoy_update_all_hash(void *meta_data, wim_directory_entry *dir)
 
     do
     {
-        if (dir->subdir == 0 && grub_memcmp(dir->hash.sha1, g_old_hash.sha1, sizeof(wim_hash)) == 0)
+        if (dir->subdir == 0 && grub_memcmp(dir->hash.sha1, patch->old_hash.sha1, sizeof(wim_hash)) == 0)
         {
             debug("find target file, name_len:%u upadte hash\n", dir->name_len);
-            grub_memcpy(dir->hash.sha1, &(g_wim_data.bin_hash), sizeof(wim_hash));
+            grub_memcpy(dir->hash.sha1, &(patch->wim_data.bin_hash), sizeof(wim_hash));
         }
         
         if (dir->subdir)
         {
-            ventoy_update_all_hash(meta_data, (wim_directory_entry *)((char *)meta_data + dir->subdir));
+            ventoy_update_all_hash(patch, meta_data, (wim_directory_entry *)((char *)meta_data + dir->subdir));
         }
     
         dir = (wim_directory_entry *)((char *)dir + dir->len);
@@ -425,7 +651,7 @@ static int ventoy_update_all_hash(void *meta_data, wim_directory_entry *dir)
     return 0;
 }
 
-static int ventoy_cat_exe_file_data(grub_uint32_t exe_len, grub_uint8_t *exe_data)
+static int ventoy_cat_exe_file_data(wim_tail *wim_data, grub_uint32_t exe_len, grub_uint8_t *exe_data)
 {
     int pe64 = 0;
     char file[256];
@@ -439,19 +665,19 @@ static int ventoy_cat_exe_file_data(grub_uint32_t exe_len, grub_uint8_t *exe_dat
     ventoy_load_jump_exe(file, &jump_data, &jump_len, NULL);
     jump_align = ventoy_align(jump_len, 16);
     
-    g_wim_data.jump_exe_len = jump_len;
-    g_wim_data.bin_raw_len = jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exe_len;
-    g_wim_data.bin_align_len = ventoy_align(g_wim_data.bin_raw_len, 2048);
+    wim_data->jump_exe_len = jump_len;
+    wim_data->bin_raw_len = jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exe_len;
+    wim_data->bin_align_len = ventoy_align(wim_data->bin_raw_len, 2048);
     
-    g_wim_data.jump_bin_data = grub_malloc(g_wim_data.bin_align_len);
-    if (g_wim_data.jump_bin_data)
+    wim_data->jump_bin_data = grub_malloc(wim_data->bin_align_len);
+    if (wim_data->jump_bin_data)
     {
-        grub_memcpy(g_wim_data.jump_bin_data, jump_data, jump_len);
-        grub_memcpy(g_wim_data.jump_bin_data + jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data), exe_data, exe_len);
+        grub_memcpy(wim_data->jump_bin_data, jump_data, jump_len);
+        grub_memcpy(wim_data->jump_bin_data + jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data), exe_data, exe_len);
     }
 
     debug("jump_exe_len:%u bin_raw_len:%u bin_align_len:%u\n", 
-        g_wim_data.jump_exe_len, g_wim_data.bin_raw_len, g_wim_data.bin_align_len);
+        wim_data->jump_exe_len, wim_data->bin_raw_len, wim_data->bin_align_len);
     
     return 0;
 }
@@ -490,49 +716,63 @@ static int ventoy_update_before_chain(ventoy_os_param *param, char *isopath)
     wim_lookup_entry *meta_look = NULL;
     wim_security_header *security = NULL;
     wim_directory_entry *rootdir = NULL;
-    wim_header *head = &(g_wim_data.wim_header);    
-    wim_lookup_entry *lookup = (wim_lookup_entry *)g_wim_data.new_lookup_data;
+    wim_header *head = NULL;
+    wim_lookup_entry *lookup = NULL;
+    wim_patch *node = NULL;
+    wim_tail *wim_data = NULL;
 
-    jump_align = ventoy_align(g_wim_data.jump_exe_len, 16);
-    if (g_wim_data.jump_bin_data)
+    for (node = g_wim_patch_head; node; node = node->next)
     {
-        grub_memcpy(g_wim_data.jump_bin_data + jump_align, param, sizeof(ventoy_os_param));        
-        ventoy_fill_windows_rtdata(g_wim_data.jump_bin_data + jump_align + sizeof(ventoy_os_param), isopath);
-    }
+        if (0 == node->valid)
+        {
+            continue;
+        }
 
-    grub_crypto_hash(GRUB_MD_SHA1, g_wim_data.bin_hash.sha1, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
+        wim_data = &node->wim_data;
+        head = &wim_data->wim_header;
+        lookup = (wim_lookup_entry *)wim_data->new_lookup_data;
 
-    security = (wim_security_header *)g_wim_data.new_meta_data;
-    rootdir = (wim_directory_entry *)(g_wim_data.new_meta_data + ((security->len + 7) & 0xFFFFFFF8U));
+        jump_align = ventoy_align(wim_data->jump_exe_len, 16);
+        if (wim_data->jump_bin_data)
+        {
+            grub_memcpy(wim_data->jump_bin_data + jump_align, param, sizeof(ventoy_os_param));        
+            ventoy_fill_windows_rtdata(wim_data->jump_bin_data + jump_align + sizeof(ventoy_os_param), isopath);
+        }
 
-    /* update all winpeshl.exe dirent entry's hash */
-    ventoy_update_all_hash(g_wim_data.new_meta_data, rootdir);
+        grub_crypto_hash(GRUB_MD_SHA1, wim_data->bin_hash.sha1, wim_data->jump_bin_data, wim_data->bin_raw_len);
 
-    /* update winpeshl.exe lookup entry data (hash/offset/length) */
-    if (g_replace_look)
-    {
-        debug("update replace lookup entry_id:%ld\n", ((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry));
-        g_replace_look->resource.raw_size = g_wim_data.bin_raw_len;
-        g_replace_look->resource.size_in_wim = g_wim_data.bin_raw_len;
-        g_replace_look->resource.flags = 0;
-        g_replace_look->resource.offset = g_wim_data.wim_align_size;
+        security = (wim_security_header *)wim_data->new_meta_data;
+        rootdir = (wim_directory_entry *)(wim_data->new_meta_data + ((security->len + 7) & 0xFFFFFFF8U));
 
-        grub_memcpy(g_replace_look->hash.sha1, g_wim_data.bin_hash.sha1, sizeof(wim_hash));
-    }
+        /* update all winpeshl.exe dirent entry's hash */
+        ventoy_update_all_hash(node, wim_data->new_meta_data, rootdir);
 
-    /* update metadata's hash */
-    meta_look = ventoy_find_meta_entry(head, lookup);
-    if (meta_look)
-    {
-        debug("find meta lookup entry_id:%ld\n", ((long)meta_look - (long)lookup) / sizeof(wim_lookup_entry));
-        grub_memcpy(&meta_look->resource, &head->metadata, sizeof(wim_resource_header));
-        grub_crypto_hash(GRUB_MD_SHA1, meta_look->hash.sha1, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
+        /* update winpeshl.exe lookup entry data (hash/offset/length) */
+        if (node->replace_look)
+        {
+            debug("update replace lookup entry_id:%ld\n", ((long)node->replace_look - (long)lookup) / sizeof(wim_lookup_entry));
+            node->replace_look->resource.raw_size = wim_data->bin_raw_len;
+            node->replace_look->resource.size_in_wim = wim_data->bin_raw_len;
+            node->replace_look->resource.flags = 0;
+            node->replace_look->resource.offset = wim_data->wim_align_size;
+
+            grub_memcpy(node->replace_look->hash.sha1, wim_data->bin_hash.sha1, sizeof(wim_hash));
+        }
+
+        /* update metadata's hash */
+        meta_look = ventoy_find_meta_entry(head, lookup);
+        if (meta_look)
+        {
+            debug("find meta lookup entry_id:%ld\n", ((long)meta_look - (long)lookup) / sizeof(wim_lookup_entry));
+            grub_memcpy(&meta_look->resource, &head->metadata, sizeof(wim_resource_header));
+            grub_crypto_hash(GRUB_MD_SHA1, meta_look->hash.sha1, wim_data->new_meta_data, wim_data->new_meta_len);
+        }
     }
 
     return 0;
 }
 
-grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args)
+static int ventoy_wimdows_locate_wim(const char *disk, wim_patch *patch)
 {
     int rc;
     grub_file_t file;
@@ -543,20 +783,22 @@ grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, c
     wim_security_header *security = NULL;
     wim_directory_entry *rootdir = NULL;
     wim_directory_entry *search = NULL;
-    wim_header *head = &(g_wim_data.wim_header);    
+    wim_header *head = &(patch->wim_data.wim_header);    
+    wim_tail *wim_data = &patch->wim_data;
     
-    (void)ctxt;
-    (void)argc;
+    debug("windows locate wim start %s\n", patch->path);
 
-    debug("windows locate wim start %s\n", args[0]);
+    g_ventoy_case_insensitive = 1;
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", disk, patch->path);
+    g_ventoy_case_insensitive = 0;
     
-    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
     if (!file)
     {
-        return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]); 
+        debug("File %s%s NOT exist\n", disk, patch->path);
+        return 1;
     }
 
-    ventoy_get_override_info(file);
+    ventoy_get_override_info(file, &patch->wim_data);
 
     grub_file_seek(file, 0);
     grub_file_read(file, head, sizeof(wim_header));
@@ -596,8 +838,8 @@ grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, c
     }
     
     debug("find replace file at %p\n", search);
-
-    grub_memcpy(&g_old_hash, search->hash.sha1, sizeof(wim_hash));
+    
+    grub_memcpy(&patch->old_hash, search->hash.sha1, sizeof(wim_hash));
 
     debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size);
     lookup = grub_malloc(head->lookup.raw_size);
@@ -605,16 +847,16 @@ grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, c
     grub_file_read(file, lookup, head->lookup.raw_size);
 
     /* find and extact winpeshl.exe */
-    g_replace_look = ventoy_find_look_entry(head, lookup, &g_old_hash);
-    if (g_replace_look)
+    patch->replace_look = ventoy_find_look_entry(head, lookup, &patch->old_hash);
+    if (patch->replace_look)
     {
-        exe_len = (grub_uint32_t)g_replace_look->resource.raw_size;
+        exe_len = (grub_uint32_t)patch->replace_look->resource.raw_size;
         debug("find replace lookup entry_id:%ld raw_size:%u\n", 
-            ((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
+            ((long)patch->replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
 
-        if (0 == ventoy_read_resource(file, &(g_replace_look->resource), (void **)&(exe_data)))
+        if (0 == ventoy_read_resource(file, &(patch->replace_look->resource), (void **)&(exe_data)))
         {
-            ventoy_cat_exe_file_data(exe_len, exe_data);
+            ventoy_cat_exe_file_data(wim_data, exe_len, exe_data);
             grub_free(exe_data);
         }
         else
@@ -624,106 +866,236 @@ grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, c
     }
     else
     {
-        debug("failed to find lookup entry for replace file 0x%02x 0x%02x\n", g_old_hash.sha1[0], g_old_hash.sha1[1]);
+        debug("failed to find lookup entry for replace file 0x%02x 0x%02x\n", 
+               patch->old_hash.sha1[0],  patch->old_hash.sha1[1]);
     }
 
-    g_wim_data.wim_raw_size = (grub_uint32_t)file->size;
-    g_wim_data.wim_align_size = ventoy_align(g_wim_data.wim_raw_size, 2048);
+    wim_data->wim_raw_size = (grub_uint32_t)file->size;
+    wim_data->wim_align_size = ventoy_align(wim_data->wim_raw_size, 2048);
     
-    check_free(g_wim_data.new_meta_data, grub_free);
-    g_wim_data.new_meta_data = decompress_data;
-    g_wim_data.new_meta_len = head->metadata.raw_size;
-    g_wim_data.new_meta_align_len = ventoy_align(g_wim_data.new_meta_len, 2048);
+    grub_check_free(wim_data->new_meta_data);
+    wim_data->new_meta_data = decompress_data;
+    wim_data->new_meta_len = head->metadata.raw_size;
+    wim_data->new_meta_align_len = ventoy_align(wim_data->new_meta_len, 2048);
     
-    check_free(g_wim_data.new_lookup_data, grub_free);
-    g_wim_data.new_lookup_data = (grub_uint8_t *)lookup;
-    g_wim_data.new_lookup_len = (grub_uint32_t)head->lookup.raw_size;
-    g_wim_data.new_lookup_align_len = ventoy_align(g_wim_data.new_lookup_len, 2048);
+    grub_check_free(wim_data->new_lookup_data);
+    wim_data->new_lookup_data = (grub_uint8_t *)lookup;
+    wim_data->new_lookup_len = (grub_uint32_t)head->lookup.raw_size;
+    wim_data->new_lookup_align_len = ventoy_align(wim_data->new_lookup_len, 2048);
 
     head->metadata.flags = RESHDR_FLAG_METADATA;
-    head->metadata.offset = g_wim_data.wim_align_size + g_wim_data.bin_align_len;
-    head->metadata.size_in_wim = g_wim_data.new_meta_len;
-    head->metadata.raw_size = g_wim_data.new_meta_len;
+    head->metadata.offset = wim_data->wim_align_size + wim_data->bin_align_len;
+    head->metadata.size_in_wim = wim_data->new_meta_len;
+    head->metadata.raw_size = wim_data->new_meta_len;
 
     head->lookup.flags = 0;
-    head->lookup.offset = head->metadata.offset + g_wim_data.new_meta_align_len;
-    head->lookup.size_in_wim = g_wim_data.new_lookup_len;
-    head->lookup.raw_size = g_wim_data.new_lookup_len;
+    head->lookup.offset = head->metadata.offset + wim_data->new_meta_align_len;
+    head->lookup.size_in_wim = wim_data->new_lookup_len;
+    head->lookup.raw_size = wim_data->new_lookup_len;
 
     grub_file_close(file);
 
     debug("%s", "windows locate wim finish\n");
-    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+    return 0;
+}
+
+grub_err_t ventoy_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    wim_patch *node = g_wim_patch_head;
+
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    while (node)
+    {
+        if (0 == ventoy_wimdows_locate_wim(args[0], node))
+        {
+            node->valid = 1;
+            g_wim_valid_patch_count++;
+        }
+
+        node = node->next;
+    }
+
+    return 0;
 }
 
 static grub_uint32_t ventoy_get_override_chunk_num(void)
 {
-    /* 1: block count in Partition Descriptor */
-    /* 2: file_size in file_entry or extend_file_entry */
-    /* 3: data_size and position in extend data short ad */
-    /* 4: new wim file header */
-    return 4;
+    if (g_iso_fs_type == 0)
+    {
+        /* ISO9660: */
+        /* per wim */
+        /* 1: file_size and file_offset */
+        /* 2: new wim file header */
+        return g_wim_valid_patch_count * 2;
+    }
+    else
+    {
+        /* UDF: */
+        /* global: */
+        /* 1: block count in Partition Descriptor */
+
+        /* per wim */
+        /* 1: file_size in file_entry or extend_file_entry */
+        /* 2: data_size and position in extend data short ad */
+        /* 3: new wim file header */
+        return g_wim_valid_patch_count * 3 + 1;        
+    }
 }
 
-static void ventoy_windows_fill_override_data(    grub_uint64_t isosize, void *override)
+static void ventoy_windows_fill_override_data_iso9660(    grub_uint64_t isosize, void *override)
 {
-    grub_uint32_t data32;
-    grub_uint64_t data64;
     grub_uint64_t sector;
     grub_uint32_t new_wim_size;
     ventoy_override_chunk *cur;
+    wim_patch *node = NULL;
+    wim_tail *wim_data = NULL;
+    ventoy_iso9660_override *dirent = NULL;
 
     sector = (isosize + 2047) / 2048;
 
     cur = (ventoy_override_chunk *)override;
 
-    new_wim_size = g_wim_data.wim_align_size + g_wim_data.bin_align_len + 
-        g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;
+    debug("ventoy_windows_fill_override_data_iso9660 %lu\n", (ulong)isosize);
 
-    if (g_wim_data.iso_type == 0)
+    for (node = g_wim_patch_head; node; node = node->next)
     {
-        ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)g_wim_data.override_data;
+        wim_data = &node->wim_data;
+        if (0 == node->valid)
+        {
+            continue;
+        }
+        
+        new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + 
+                wim_data->new_meta_align_len + wim_data->new_lookup_align_len;
+
+        dirent = (ventoy_iso9660_override *)wim_data->override_data;
 
         dirent->first_sector    = (grub_uint32_t)sector;
         dirent->size            = new_wim_size;
         dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
         dirent->size_be         = grub_swap_bytes32(dirent->size);
+
+        sector += (new_wim_size / 2048);
+
+        /* override 1: position and length in dirent */
+        cur->img_offset = wim_data->override_offset;
+        cur->override_size = wim_data->override_len;
+        grub_memcpy(cur->override_data, wim_data->override_data, cur->override_size);
+        cur++;
+
+        /* override 2: new wim file header */
+        cur->img_offset = wim_data->file_offset;
+        cur->override_size = sizeof(wim_header);
+        grub_memcpy(cur->override_data, &(wim_data->wim_header), cur->override_size);
+        cur++;
     }
-    else
+
+    return;
+}
+
+static void ventoy_windows_fill_override_data_udf(    grub_uint64_t isosize, void *override)
+{
+    grub_uint32_t data32;
+    grub_uint64_t data64;
+    grub_uint64_t sector;
+    grub_uint32_t new_wim_size;
+    grub_uint64_t total_wim_size = 0;
+    grub_uint32_t udf_start_block = 0;
+    ventoy_override_chunk *cur;
+    wim_patch *node = NULL;
+    wim_tail *wim_data = NULL;
+    ventoy_udf_override *udf = NULL;
+
+    sector = (isosize + 2047) / 2048;
+
+    cur = (ventoy_override_chunk *)override;
+
+    debug("ventoy_windows_fill_override_data_udf %lu\n", (ulong)isosize);
+
+    for (node = g_wim_patch_head; node; node = node->next)
     {
-        ventoy_udf_override *udf = (ventoy_udf_override *)g_wim_data.override_data;
-        udf->length   = new_wim_size;
-        udf->position = (grub_uint32_t)sector - g_wim_data.udf_start_block;
+        wim_data = &node->wim_data;
+        if (node->valid)
+        {
+            if (udf_start_block == 0)
+            {
+                udf_start_block = wim_data->udf_start_block;
+            }
+            new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + 
+                wim_data->new_meta_align_len + wim_data->new_lookup_align_len;
+            total_wim_size += new_wim_size;
+        }
     }
 
     //override 1: sector number in pd data 
     cur->img_offset = grub_udf_get_last_pd_size_offset();
     cur->override_size = 4;
-    data32 = sector - g_wim_data.udf_start_block + (new_wim_size / 2048);
+    data32 = sector - udf_start_block + (total_wim_size / 2048);
     grub_memcpy(cur->override_data, &(data32), 4);
 
-    //override 2: filesize in file_entry
-    cur++;
-    cur->img_offset = g_wim_data.fe_entry_size_offset;
-    cur->override_size = 8;
-    data64 = new_wim_size;
-    grub_memcpy(cur->override_data, &(data64), 8);
-
-    /* override 3: position and length in extend data */
-    cur++;
-    cur->img_offset = g_wim_data.override_offset;
-    cur->override_size = g_wim_data.override_len;
-    grub_memcpy(cur->override_data, g_wim_data.override_data, cur->override_size);
-
-    /* override 4: new wim file header */
-    cur++;
-    cur->img_offset = g_wim_data.file_offset;
-    cur->override_size = sizeof(wim_header);
-    grub_memcpy(cur->override_data, &(g_wim_data.wim_header), cur->override_size);
+    for (node = g_wim_patch_head; node; node = node->next)
+    {
+        wim_data = &node->wim_data;
+        if (0 == node->valid)
+        {
+            continue;
+        }
+        
+        new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + 
+                wim_data->new_meta_align_len + wim_data->new_lookup_align_len;
+
+        //override 2: filesize in file_entry
+        cur++;
+        cur->img_offset = wim_data->fe_entry_size_offset;
+        cur->override_size = 8;
+        data64 = new_wim_size;
+        grub_memcpy(cur->override_data, &(data64), 8);
+
+        udf = (ventoy_udf_override *)wim_data->override_data;
+        udf->length   = new_wim_size;
+        udf->position = (grub_uint32_t)sector - udf_start_block;
+
+        sector += (new_wim_size / 2048);
+
+        /* override 3: position and length in extend data */
+        cur++;
+        cur->img_offset = wim_data->override_offset;
+        cur->override_size = wim_data->override_len;
+        grub_memcpy(cur->override_data, wim_data->override_data, cur->override_size);
+
+        /* override 4: new wim file header */
+        cur++;
+        cur->img_offset = wim_data->file_offset;
+        cur->override_size = sizeof(wim_header);
+        grub_memcpy(cur->override_data, &(wim_data->wim_header), cur->override_size);
+    }
 
     return;
 }
 
+static grub_uint32_t ventoy_windows_get_virt_data_size(void)
+{
+    grub_uint32_t size = 0;
+    wim_tail *wim_data = NULL;
+    wim_patch *node = g_wim_patch_head;
+    
+    while (node)
+    {
+        if (node->valid)
+        {
+            wim_data = &node->wim_data;
+            size += sizeof(ventoy_virt_chunk) + wim_data->bin_align_len + 
+                    wim_data->new_meta_align_len + wim_data->new_lookup_align_len;
+        }
+        node = node->next;
+    }
+    
+    return size;
+}
+
 static void ventoy_windows_fill_virt_data(    grub_uint64_t isosize, ventoy_chain_head *chain)
 {
     grub_uint64_t sector;
@@ -732,37 +1104,53 @@ static void ventoy_windows_fill_virt_data(    grub_uint64_t isosize, ventoy_chai
     grub_uint32_t mem_secs;
     char *override = NULL;
     ventoy_virt_chunk *cur = NULL;
+    wim_tail *wim_data = NULL;
+    wim_patch *node = NULL;    
 
     sector = (isosize + 2047) / 2048;
-    offset = sizeof(ventoy_virt_chunk);
-    
-    wim_secs = g_wim_data.wim_align_size / 2048;
-    mem_secs = (g_wim_data.bin_align_len + g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len) / 2048;
+    offset = sizeof(ventoy_virt_chunk) * g_wim_valid_patch_count;
 
     override = (char *)chain + chain->virt_chunk_offset;
     cur = (ventoy_virt_chunk *)override;
 
-    cur->remap_sector_start = sector;
-    cur->remap_sector_end   = cur->remap_sector_start + wim_secs;
-    cur->org_sector_start   = (grub_uint32_t)(g_wim_data.file_offset / 2048);
-    
-    cur->mem_sector_start   = cur->remap_sector_end;
-    cur->mem_sector_end     = cur->mem_sector_start + mem_secs;
-    cur->mem_sector_offset  = offset;
+    for (node = g_wim_patch_head; node; node = node->next)
+    {
+        if (0 == node->valid)
+        {
+            continue;
+        }
 
-    grub_memcpy(override + offset, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
-    offset += g_wim_data.bin_align_len;
+        wim_data = &node->wim_data;
 
-    grub_memcpy(override + offset, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
-    offset += g_wim_data.new_meta_align_len;
-    
-    grub_memcpy(override + offset, g_wim_data.new_lookup_data, g_wim_data.new_lookup_len);
-    offset += g_wim_data.new_lookup_align_len;
+        wim_secs = wim_data->wim_align_size / 2048;
+        mem_secs = (wim_data->bin_align_len + wim_data->new_meta_align_len + wim_data->new_lookup_align_len) / 2048;
+
+        cur->remap_sector_start = sector;
+        cur->remap_sector_end   = cur->remap_sector_start + wim_secs;
+        cur->org_sector_start   = (grub_uint32_t)(wim_data->file_offset / 2048);
+        
+        cur->mem_sector_start   = cur->remap_sector_end;
+        cur->mem_sector_end     = cur->mem_sector_start + mem_secs;
+        cur->mem_sector_offset  = offset;
+
+        sector += wim_secs + mem_secs;
+        cur++;
+
+        grub_memcpy(override + offset, wim_data->jump_bin_data, wim_data->bin_raw_len);
+        offset += wim_data->bin_align_len;
+
+        grub_memcpy(override + offset, wim_data->new_meta_data, wim_data->new_meta_len);
+        offset += wim_data->new_meta_align_len;
+        
+        grub_memcpy(override + offset, wim_data->new_lookup_data, wim_data->new_lookup_len);
+        offset += wim_data->new_lookup_align_len;
+
+        chain->virt_img_size_in_bytes += wim_data->wim_align_size + 
+                                         wim_data->bin_align_len + 
+                                         wim_data->new_meta_align_len + 
+                                         wim_data->new_lookup_align_len;
+    }
 
-    chain->virt_img_size_in_bytes += g_wim_data.wim_align_size + 
-                                     g_wim_data.bin_align_len + 
-                                     g_wim_data.new_meta_align_len + 
-                                     g_wim_data.new_lookup_align_len;
     return;
 }
 
@@ -828,7 +1216,7 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c
         return 1;
     }
 
-    if (0 == ventoy_compatible && g_wim_data.new_meta_data == NULL)
+    if (0 == ventoy_compatible && g_wim_valid_patch_count == 0)
     {
         unknown_image = 1;
         debug("Warning: %s was not recognized by Ventoy\n", args[0]);
@@ -871,8 +1259,7 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c
     else
     {
         override_size = ventoy_get_override_chunk_num() * sizeof(ventoy_override_chunk);
-        virt_chunk_size = sizeof(ventoy_virt_chunk) + g_wim_data.bin_align_len + 
-            g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;;
+        virt_chunk_size = ventoy_windows_get_virt_data_size();
         size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
     }
 
@@ -903,9 +1290,10 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c
     grub_memset(chain, 0, sizeof(ventoy_chain_head));
 
     /* part 1: os parameter */
+    g_ventoy_chain_type = 1;
     ventoy_fill_os_param(file, &(chain->os_param));
 
-    if (g_wim_data.jump_bin_data && g_wim_data.new_meta_data)
+    if (0 == unknown_image)
     {
         ventoy_update_before_chain(&(chain->os_param), args[0]);
     }
@@ -934,7 +1322,7 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c
         return 0;
     }
 
-    if (g_wim_data.new_meta_data == NULL)
+    if (0 == g_wim_valid_patch_count)
     {
         return 0;
     }
@@ -942,11 +1330,19 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c
     /* part 4: override chunk */
     chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
     chain->override_chunk_num = ventoy_get_override_chunk_num();
-    ventoy_windows_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
+
+    if (g_iso_fs_type == 0)
+    {
+        ventoy_windows_fill_override_data_iso9660(isosize, (char *)chain + chain->override_chunk_offset);
+    }
+    else
+    {
+        ventoy_windows_fill_override_data_udf(isosize, (char *)chain + chain->override_chunk_offset);        
+    }
 
     /* part 5: virt chunk */
     chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
-    chain->virt_chunk_num = 1;
+    chain->virt_chunk_num = g_wim_valid_patch_count;
     ventoy_windows_fill_virt_data(isosize, chain);
 
     if (ventoy_is_efi_os() == 0)
@@ -1099,6 +1495,7 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char
     grub_memset(chain, 0, sizeof(ventoy_chain_head));
 
     /* part 1: os parameter */
+    g_ventoy_chain_type = 0;
     ventoy_fill_os_param(file, &(chain->os_param));
 
     /* part 2: chain head */
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/file.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/file.h
new file mode 100644 (file)
index 0000000..6c4203c
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB 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.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_FILE_HEADER
+#define GRUB_FILE_HEADER       1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/device.h>
+#include <grub/fs.h>
+#include <grub/disk.h>
+
+enum grub_file_type
+  {
+    GRUB_FILE_TYPE_NONE = 0,
+    /* GRUB module to be loaded.  */
+    GRUB_FILE_TYPE_GRUB_MODULE,
+    /* Loopback file to be represented as disk.  */
+    GRUB_FILE_TYPE_LOOPBACK,
+    /* Linux kernel to be loaded.  */
+    GRUB_FILE_TYPE_LINUX_KERNEL,
+    /* Linux initrd.  */
+    GRUB_FILE_TYPE_LINUX_INITRD,
+
+    /* Multiboot kernel.  */
+    GRUB_FILE_TYPE_MULTIBOOT_KERNEL,
+    /* Multiboot module.  */
+    GRUB_FILE_TYPE_MULTIBOOT_MODULE,
+
+    /* Xen hypervisor - used on ARM only. */
+    GRUB_FILE_TYPE_XEN_HYPERVISOR,
+    /* Xen module - used on ARM only. */
+    GRUB_FILE_TYPE_XEN_MODULE,
+
+    GRUB_FILE_TYPE_BSD_KERNEL,
+    GRUB_FILE_TYPE_FREEBSD_ENV,
+    GRUB_FILE_TYPE_FREEBSD_MODULE,
+    GRUB_FILE_TYPE_FREEBSD_MODULE_ELF,
+    GRUB_FILE_TYPE_NETBSD_MODULE,
+    GRUB_FILE_TYPE_OPENBSD_RAMDISK,
+
+    GRUB_FILE_TYPE_XNU_INFO_PLIST,
+    GRUB_FILE_TYPE_XNU_MKEXT,
+    GRUB_FILE_TYPE_XNU_KEXT,
+    GRUB_FILE_TYPE_XNU_KERNEL,
+    GRUB_FILE_TYPE_XNU_RAMDISK,
+    GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE,
+    GRUB_FILE_XNU_DEVPROP,
+
+    GRUB_FILE_TYPE_PLAN9_KERNEL,
+
+    GRUB_FILE_TYPE_NTLDR,
+    GRUB_FILE_TYPE_TRUECRYPT,
+    GRUB_FILE_TYPE_FREEDOS,
+    GRUB_FILE_TYPE_PXECHAINLOADER,
+    GRUB_FILE_TYPE_PCCHAINLOADER,
+
+    GRUB_FILE_TYPE_COREBOOT_CHAINLOADER,
+
+    GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE,
+
+    /* File holding signature.  */
+    GRUB_FILE_TYPE_SIGNATURE,
+    /* File holding public key to verify signature once.  */
+    GRUB_FILE_TYPE_PUBLIC_KEY,
+    /* File holding public key to add to trused keys.  */
+    GRUB_FILE_TYPE_PUBLIC_KEY_TRUST,
+    /* File of which we intend to print a blocklist to the user.  */
+    GRUB_FILE_TYPE_PRINT_BLOCKLIST,
+    /* File we intend to use for test loading or testing speed.  */
+    GRUB_FILE_TYPE_TESTLOAD,
+    /* File we open only to get its size. E.g. in ls output.  */
+    GRUB_FILE_TYPE_GET_SIZE,
+    /* Font file.  */
+    GRUB_FILE_TYPE_FONT,
+    /* File holding encryption key for encrypted ZFS.  */
+    GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
+    /* File we open n grub-fstest.  */
+    GRUB_FILE_TYPE_FSTEST,
+    /* File we open n grub-mount.  */
+    GRUB_FILE_TYPE_MOUNT,
+    /* File which we attempt to identify the type of.  */
+    GRUB_FILE_TYPE_FILE_ID,
+    /* File holding ACPI table.  */
+    GRUB_FILE_TYPE_ACPI_TABLE,
+    /* File holding Device Tree.  */
+    GRUB_FILE_TYPE_DEVICE_TREE_IMAGE,
+    /* File we intend show to user.  */
+    GRUB_FILE_TYPE_CAT,
+    GRUB_FILE_TYPE_HEXCAT,
+    /* One of pair of files we intend to compare.  */
+    GRUB_FILE_TYPE_CMP,
+    /* List of hashes for hashsum.  */
+    GRUB_FILE_TYPE_HASHLIST,
+    /* File hashed by hashsum.  */
+    GRUB_FILE_TYPE_TO_HASH,
+    /* Keyboard layout.  */
+    GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
+    /* Picture file.  */
+    GRUB_FILE_TYPE_PIXMAP,
+    /* *.lst shipped by GRUB.  */
+    GRUB_FILE_TYPE_GRUB_MODULE_LIST,
+    /* config file.  */
+    GRUB_FILE_TYPE_CONFIG,
+    GRUB_FILE_TYPE_THEME,
+    GRUB_FILE_TYPE_GETTEXT_CATALOG,
+    GRUB_FILE_TYPE_FS_SEARCH,
+    GRUB_FILE_TYPE_AUDIO,
+    GRUB_FILE_TYPE_VBE_DUMP,
+
+    GRUB_FILE_TYPE_LOADENV,
+    GRUB_FILE_TYPE_SAVEENV,
+
+    GRUB_FILE_TYPE_VERIFY_SIGNATURE,
+
+    GRUB_FILE_TYPE_MASK = 0xffff,
+
+    /* --skip-sig is specified.  */
+    GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
+    GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
+  };
+
+/* File description.  */
+struct grub_file
+{
+  /* File name.  */
+  char *name;
+
+  /* The underlying device.  */
+  grub_device_t device;
+
+  /* The underlying filesystem.  */
+  grub_fs_t fs;
+
+  /* The current offset.  */
+  grub_off_t offset;
+  grub_off_t progress_offset;
+
+  /* Progress info. */
+  grub_uint64_t last_progress_time;
+  grub_off_t last_progress_offset;
+  grub_uint64_t estimated_speed;
+
+  /* The file size.  */
+  grub_off_t size;
+
+  /* If file is not easily seekable. Should be set by underlying layer.  */
+  int not_easily_seekable;
+
+  /* Filesystem-specific data.  */
+  void *data;
+
+  /* This is called when a sector is read. Used only for a disk device.  */
+  grub_disk_read_hook_t read_hook;
+
+  /* Caller-specific data passed to the read hook.  */
+  void *read_hook_data;
+};
+typedef struct grub_file *grub_file_t;
+
+extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
+
+/* Filters with lower ID are executed first.  */
+typedef enum grub_file_filter_id
+  {
+    GRUB_FILE_FILTER_VERIFY,
+    GRUB_FILE_FILTER_GZIO,
+    GRUB_FILE_FILTER_XZIO,
+    GRUB_FILE_FILTER_LZOPIO,
+    GRUB_FILE_FILTER_MAX,
+    GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
+    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
+  } grub_file_filter_id_t;
+
+typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
+
+extern grub_file_filter_t EXPORT_VAR(grub_file_filters)[GRUB_FILE_FILTER_MAX];
+
+static inline void
+grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
+{
+  grub_file_filters[id] = filter;
+}
+
+static inline void
+grub_file_filter_unregister (grub_file_filter_id_t id)
+{
+  grub_file_filters[id] = 0;
+}
+
+/* Get a device name from NAME.  */
+char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
+
+int EXPORT_FUNC(ventoy_check_file_exist) (const char * fmt, ...);
+grub_file_t EXPORT_FUNC(grub_file_open) (const char *name, enum grub_file_type type);
+grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
+                                         grub_size_t len);
+grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
+grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
+
+/* Return value of grub_file_size() in case file size is unknown. */
+#define GRUB_FILE_SIZE_UNKNOWN  0xffffffffffffffffULL
+
+static inline grub_off_t
+grub_file_size (const grub_file_t file)
+{
+  return file->size;
+}
+
+static inline grub_off_t
+grub_file_tell (const grub_file_t file)
+{
+  return file->offset;
+}
+
+static inline int
+grub_file_seekable (const grub_file_t file)
+{
+  return !file->not_easily_seekable;
+}
+
+grub_file_t
+grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
+                      grub_off_t start, grub_off_t size);
+void
+grub_file_offset_close (grub_file_t file);
+
+#endif /* ! GRUB_FILE_HEADER */
index 799bfb4ef935d638e97ca927a04a25039c393940..6c320725dfdc31060aaec4300220efe83d84ba80 100644 (file)
@@ -109,6 +109,8 @@ typedef struct ventoy_os_param
      *
      * vtoy_reserved[0]: vtoy_break_level
      * vtoy_reserved[1]: vtoy_debug_level
+     * vtoy_reserved[2]: vtoy_chain_type     0:Linux    1:Windows
+     * vtoy_reserved[3]: vtoy_iso_format     0:iso9660  1:udf
      *
      */
     grub_uint8_t   vtoy_reserved[32];    // Internal use by ventoy
@@ -227,6 +229,7 @@ typedef struct ventoy_grub_param
 
 int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
 int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
+void grub_iso9660_set_nojoliet(int nojoliet);
 grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file);
 grub_uint64_t grub_iso9660_get_last_file_dirent_pos(grub_file_t file);
 grub_uint64_t grub_udf_get_file_offset(grub_file_t file);
index 45a28f0dca6a62745b1856dbb5de3e54fd408a7a..930330839c5327e841cb512d31772877aa67cdc1 100644 (file)
@@ -12,10 +12,10 @@ make install
 PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/
 
 net_modules_legacy="net tftp http"
-all_modules_legacy="date drivemap blocklist lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal  linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_msdos fat exfat ntfs loopback gzio normal  udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
+all_modules_legacy="date drivemap blocklist ntldr search at_keyboard usb_keyboard  gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal  linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_msdos fat exfat ntfs loopback gzio normal  udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
 
 net_modules_uefi="efinet net tftp http"
-all_modules_uefi="blocklist ventoy test ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain  priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
+all_modules_uefi="blocklist ventoy test search at_keyboard usb_keyboard  gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain  priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
 
 
 if [ "$1" = "uefi" ]; then
index a73b70276eacaa19d2815efc9a0ec485fb73e46f..d29eddfcd847a4beb98e4107ad7325c68d4b7a9b 100644 (file)
 
 . $VTOY_PATH/hook/ventoy-os-lib.sh
 
-$SED "/find_and_mount_installer *$/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/clear/disk-hook.sh" -i  /init
+if $GREP -q find_and_mount_installer /init; then
+    echo "find_and_mount_installer" >> $VTLOG
+    $SED "/find_and_mount_installer *$/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/clear/disk-hook.sh" -i  /init
+else
+    echo "find_installer" >> $VTLOG
+    $SED "/\$.*find_installer/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/clear/disk-hook.sh" -i  /init
+fi
index ce5dbe5ed21f7af5e6da7c9c7556eb77809fa1c1..e4d90ee7f7c2fbda55aeed8168e21f1a0300b1b0 100644 (file)
 
 . $VTOY_PATH/hook/ventoy-os-lib.sh
 
-if [ -d /etc/udev/rules.d ] || [ -d /lib/udev/rules.d ]; then    
+if $GREP -q kaspersky /proc/version; then
+    $SED "/sysresccd_stage1_normal[^(]*$/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/gentoo/disk_hook.sh"  -i /init
+elif [ -d /etc/udev/rules.d ] || [ -d /lib/udev/rules.d ]; then    
     ventoy_systemd_udevd_work_around
     ventoy_add_udev_rule "$VTOY_PATH/hook/default/udev_disk_hook.sh %k noreplace"
 else
-    if $GREP -q kaspersky /proc/version; then
-        $SED "/sysresccd_stage1_normal[^(]*$/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/gentoo/disk_hook.sh"  -i /init
-    else
-        $SED "/mdev *-s/a\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/gentoo/disk_hook.sh"  -i /init
-    fi
+    $SED "/mdev *-s/a\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/gentoo/disk_hook.sh"  -i /init    
 fi
diff --git a/IMG/cpio/ventoy/hook/kiosk/ventoy-disk.sh b/IMG/cpio/ventoy/hook/kiosk/ventoy-disk.sh
new file mode 100644 (file)
index 0000000..2c93427
--- /dev/null
@@ -0,0 +1,70 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, 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/>.
+# 
+#************************************************************************************
+
+. /ventoy/hook/ventoy-hook-lib.sh
+
+VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
+
+ventoy_os_install_dmsetup_by_unsquashfs() {
+    vtlog "ventoy_os_install_dmsetup_by_unsquashfs $*"
+    
+    vtKerVer=$(uname -r)
+    vtKoPo=$(ventoy_get_module_postfix)
+    vtlog "vtKerVer=$vtKerVer vtKoPo=$vtKoPo"
+
+    vtoydm -i -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/iso_file_list
+
+    vtline=$(grep '[-][-] .*kernel.xzm '  $VTOY_PATH/iso_file_list)    
+    sector=$(echo $vtline | awk '{print $(NF-1)}')
+    length=$(echo $vtline | awk '{print $NF}')
+    
+    vtlog "vtline=$vtline  sector=$sector  length=$length"
+    
+    vtoydm -e -f $VTOY_PATH/ventoy_image_map -d $1 -s $sector -l $length -o $VTOY_PATH/kernel.xzm
+    mkdir -p $VTOY_PATH/sqfs  
+    mount $VTOY_PATH/kernel.xzm  $VTOY_PATH/sqfs
+
+    dmModPath="/lib/modules/$vtKerVer/kernel/drivers/md/dm-mod.$vtKoPo"    
+    
+    if [ -e $VTOY_PATH/sqfs${dmModPath} ]; then
+        vtlog "success $VTOY_PATH/sqfs${dmModPath}"
+        insmod $VTOY_PATH/sqfs${dmModPath}
+    else
+        vterr "failed $VTOY_PATH/sqfs${dmModPath}"
+        false
+    fi
+    
+    umount $VTOY_PATH/sqfs
+    rm -f $VTOY_PATH/kernel.xzm
+}
+
+wait_for_usb_disk_ready
+
+vtdiskname=$(get_ventoy_disk_name)
+if [ "$vtdiskname" = "unknown" ]; then
+    vtlog "ventoy disk not found"
+    PATH=$VTPATH_OLD
+    exit 0
+fi
+
+ventoy_os_install_dmsetup_by_unsquashfs $vtdiskname
+
+ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
+
+PATH=$VTPATH_OLD
diff --git a/IMG/cpio/ventoy/hook/kiosk/ventoy-hook.sh b/IMG/cpio/ventoy/hook/kiosk/ventoy-hook.sh
new file mode 100644 (file)
index 0000000..31e5b96
--- /dev/null
@@ -0,0 +1,22 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, 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/>.
+# 
+#************************************************************************************
+
+. $VTOY_PATH/hook/ventoy-os-lib.sh
+
+$SED '/^ *search [^(]*$/i\    /ventoy/busybox/sh  /ventoy/hook/kiosk/ventoy-disk.sh'  -i /init
index 5edc8f2bdd85ae6e96ef07166a313c7d0f502c29..05c6c412e2409ddb9163c1b732e708af56569b19 100644 (file)
@@ -1,7 +1,29 @@
 #!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, 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/>.
+# 
+#************************************************************************************
 
 . $VTOY_PATH/hook/ventoy-os-lib.sh
 
-ventoy_systemd_udevd_work_around
+#ventoy_systemd_udevd_work_around
+#ventoy_add_udev_rule "$VTOY_PATH/hook/mageia/udev_disk_hook.sh %k noreplace"
+
+ventoy_set_inotify_script  mageia/ventoy-inotifyd-hook.sh
+$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/mageia/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/99-ventoy-inotifyd-start.sh
+
+
 
-ventoy_add_udev_rule "$VTOY_PATH/hook/mageia/udev_disk_hook.sh %k noreplace"
diff --git a/IMG/cpio/ventoy/hook/mageia/ventoy-inotifyd-hook.sh b/IMG/cpio/ventoy/hook/mageia/ventoy-inotifyd-hook.sh
new file mode 100644 (file)
index 0000000..bc604ff
--- /dev/null
@@ -0,0 +1,69 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, 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/>.
+# 
+#************************************************************************************
+
+. /ventoy/hook/ventoy-hook-lib.sh
+
+if is_ventoy_hook_finished; then
+    exit 0
+fi
+
+vtlog "##### INOTIFYD: $2/$3 is created ..."
+
+VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
+
+if is_inotify_ventoy_part $3; then
+
+    vtlog "find ventoy partition ..."
+    $BUSYBOX_PATH/sh $VTOY_PATH/hook/default/udev_disk_hook.sh $3 noreplace
+    
+    blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')  
+    vtDM=$(ventoy_find_dm_id ${blkdev_num})   
+    vtLABEL=$($BUSYBOX_PATH/blkid /dev/$vtDM | $AWK '{print $2}' | $SED 's/.*"\(.*\)".*/\1/')
+    
+    vtlog "blkdev_num=$blkdev_num  vtDM=$vtDM  label $vtLABEL ..."
+   
+    if [ -n "$vtLABEL" ]; then
+        $BUSYBOX_PATH/mkdir -p /dev/disk/by-label/
+        ln -s /dev/$vtDM /dev/disk/by-label/$vtLABEL
+    fi
+    
+    #
+    # cheatcode for mageia
+    #
+    # From mageia/soft/drakx/mdk-stage1 source code, we see that the stage1 binary will search 
+    # /tmp/syslog file to determin whether there is a DAC960 cdrom in the system.
+    # So we insert some string to /tmp/syslog file to cheat the stage1 program.
+    #
+    $BUSYBOX_PATH/mkdir -p /dev/rd
+    ventoy_copy_device_mapper "/dev/rd/ventoy"
+    echo 'ventoy cheatcode /dev/rd/ventoy:  model' >> /tmp/syslog
+
+    if [ -e /sbin/mgalive-root ]; then
+        vtlog "set mgalive-root ..."
+            
+        $BUSYBOX_PATH/cp -a $BUSYBOX_PATH/blkid /sbin/blkid
+        $BUSYBOX_PATH/mkdir -p /dev/mapper
+        ln -s /dev/$vtDM  /dev/mapper/ventoy     
+        /sbin/mgalive-root /dev/dm-0    
+    fi
+    
+    set_ventoy_hook_finish
+fi
+
+PATH=$VTPATH_OLD
similarity index 62%
rename from IMG/cpio/ventoy/hook/mageia/udev_disk_hook.sh
rename to IMG/cpio/ventoy/hook/mageia/ventoy-inotifyd-start.sh
index b685c71d100e52f39f629d7f0a44eb8b03fd67ec..6be8155510e922a76a7c82f2e2a1583520271fec 100644 (file)
 
 . /ventoy/hook/ventoy-hook-lib.sh
 
-if is_ventoy_hook_finished || not_ventoy_disk "${1:0:-1}"; then
-    exit 0
-fi
-
-ventoy_udev_disk_common_hook $*
+vtHook=$($CAT $VTOY_PATH/inotifyd-hook-script.txt)
 
-#
-# cheatcode for mageia
-#
-# From mageia/soft/drakx/mdk-stage1 source code, we see that the stage1 binary will search 
-# /tmp/syslog file to determin whether there is a DAC960 cdrom in the system.
-# So we insert some string to /tmp/syslog file to cheat the stage1 program.
-#
-$BUSYBOX_PATH/mkdir -p /dev/rd
-ventoy_copy_device_mapper "/dev/rd/ventoy"
-echo 'ventoy cheatcode /dev/rd/ventoy:  model' >> /tmp/syslog
-
-# OK finish
-set_ventoy_hook_finish
+vtdisk=$(get_ventoy_disk_name)
+if [ "$vtdisk" = "unknown" ]; then
+    vtlog "... start inotifyd listen $vtHook ..."
+    $BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $vtHook  /dev:n  2>&-  & 
+else
+    vtlog "... $vtdisk already exist ..."
+    $BUSYBOX_PATH/sh $vtHook n /dev "${vtdisk#/dev/}2"
+fi
index 388c92cf2bbf3add432c283b6d0caf38d27633c2..d84f0bc8b6ad53520b50486c6f1510a7b59a0345 100644 (file)
@@ -64,7 +64,7 @@ fi
 
 
 #some distro add there repo file to /etc/anaconda.repos.d/ which will cause error during installation
-$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $VTOY_PATH/hook/rhel6/anaconda-repo-listen.sh /etc/anaconda.repos.d:n &  
+#$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $VTOY_PATH/hook/rhel6/anaconda-repo-listen.sh /etc/anaconda.repos.d:n &  
 
 ventoy_udev_disk_common_hook $* "noreplace"
 
index e66dbc5a21a1bca925d0abd66d6a7830587243c4..beb41e13d9c89ad702e7b30450728b45f09c8e71 100644 (file)
@@ -22,6 +22,5 @@
 $BUSYBOX_PATH/mkdir -p /etc/anaconda.repos.d  /mnt/ventoy
 ventoy_print_yum_repo "ventoy" "file:///mnt/ventoy" > /etc/anaconda.repos.d/ventoy.repo
 
-
 ventoy_add_udev_rule "$VTOY_PATH/hook/rhel6/udev_disk_hook.sh %k"
 ventoy_add_kernel_udev_rule "loop7" "$VTOY_PATH/hook/rhel6/udev_disk_hook.sh %k"
index 431d58a4a41e075c201e9050e2036a7952929b0d..1bb6a6b18071028549078a248bd07deb4e4eed1d 100644 (file)
@@ -31,7 +31,13 @@ else
             VTKS="inst.ks=hd:/dev/dm-0:$vtRawKs"
             break
         fi
-    done    
+        
+        if echo $vtParam | $GREP -q '^ks=.*:/'; then
+            vtRawKs=$(echo $vtParam | $AWK -F: '{print $NF}')
+            VTKS="ks=hd:/dev/dm-0:$vtRawKs"
+            break
+        fi
+    done
 fi
 
 echo "VTKS=$VTKS" >> $VTLOG
@@ -44,8 +50,15 @@ fi
 
 ventoy_set_inotify_script  rhel7/ventoy-inotifyd-hook.sh
 
-$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/rhel7/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/01-ventoy-inotifyd-start.sh
-$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/rhel7/ventoy-timeout.sh /lib/dracut/hooks/initqueue/timeout/01-ventoy-timeout.sh
+#Fedora
+if $BUSYBOX_PATH/which dmsquash-live-root > /dev/null; then
+    vtPriority=99
+else
+    vtPriority=01
+fi
+
+$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/rhel7/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/${vtPriority}-ventoy-inotifyd-start.sh
+$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/rhel7/ventoy-timeout.sh /lib/dracut/hooks/initqueue/timeout/${vtPriority}-ventoy-timeout.sh
 
 # suppress write protected mount warning
 if [ -e /usr/sbin/anaconda-diskroot ]; then
index d79bb2df30a3b0730c402a284f5ec836e81e715d..a565098bfe8a8a3a78a28fc280356bd2383365e8 100644 (file)
@@ -28,6 +28,16 @@ vtlog "##### INOTIFYD: $2/$3 is created ..."
 VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
 
 if is_inotify_ventoy_part $3; then
+
+    vtGenRulFile='/etc/udev/rules.d/99-live-squash.rules'
+    if [ -e $vtGenRulFile ] && $GREP -q dmsquash $vtGenRulFile; then
+        vtScript=$($GREP -m1 'RUN.=' $vtGenRulFile | $AWK -F'RUN.=' '{print $2}' | $SED 's/"\(.*\)".*/\1/')
+        vtlog "vtScript=$vtScript"
+        $vtScript
+    else
+        vtlog "$vtGenRulFile not exist..."
+    fi
+
     vtlog "find ventoy partition ..."
     $BUSYBOX_PATH/sh $VTOY_PATH/hook/default/udev_disk_hook.sh $3 noreplace
     
@@ -41,9 +51,10 @@ if is_inotify_ventoy_part $3; then
         ventoy_swap_device /dev/dm-0 /dev/$vtDM
     fi
     
-    vtlog "set anaconda-diskroot ..."
-    /sbin/anaconda-diskroot /dev/dm-0    
-    #/sbin/initqueue --settled --onetime --name anaconda-diskroot anaconda-diskroot  /dev/dm-0
+    if [ -e /sbin/anaconda-diskroot ]; then
+        vtlog "set anaconda-diskroot ..."
+        /sbin/anaconda-diskroot /dev/dm-0    
+    fi
     
     set_ventoy_hook_finish
 fi
index a5db322c2e1082ad8f8d1262609a6e17762cb311..87ece3be9728223014c5e79d03aae1f747de84c0 100644 (file)
@@ -26,8 +26,9 @@ VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
 blkdev_num=$(dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')  
 vtDM=$(ventoy_find_dm_id ${blkdev_num})
 
-vtlog "diskroot $vtDM ..."
-/sbin/anaconda-diskroot /dev/dm-0    
-#/sbin/initqueue --settled --onetime --name anaconda-diskroot anaconda-diskroot  /dev/$vtDM
+if [ -e /sbin/anaconda-diskroot ]; then
+    vtlog "set anaconda-diskroot ..."
+    /sbin/anaconda-diskroot /dev/dm-0    
+fi
 
 PATH=$VTPATH_OLD
index c2b7b507a39b1c631efc24b265b48b7667632a05..61659fc38aab8d2c2b80a8b0a63d5ec325e5414c 100644 (file)
@@ -51,7 +51,17 @@ fi
 #                                                                  #
 ####################################################################
 cd /
-rm -rf /init /linuxrc /sbin /dev/  /root
+rm -rf /init /linuxrc /dev/  /root
+
+vtSbinFileNum=$(ls -1 /sbin | wc -l)
+if [ $vtSbinFileNum -eq 1 ]; then
+    echo "remove whole sbin directory" >> $VTLOG
+    rm -rf /sbin
+else
+    echo "remove only sbin/init file" >> $VTLOG
+    ls -l /sbin >> $VTLOG
+    rm -f /sbin/init
+fi
 
 ventoy_is_initrd_ramdisk() {
     #As I known, PCLinuxOS use ramdisk
index edab7e8c80d0e3d725c6ddd3ae40876c48097170..84f54923c914e1e4af7e45a64f50138155867f9d 100644 (file)
@@ -87,6 +87,10 @@ ventoy_get_os_type() {
     elif $EGREP -q 'archlinux|ARCH' /proc/version; then
         echo 'arch'; return
     
+    # kiosk
+    elif $EGREP -q 'kiosk' /proc/version; then
+        echo 'kiosk'; return
+    
     # gentoo
     elif $EGREP -q '[Gg]entoo' /proc/version; then
         echo 'gentoo'; return
@@ -215,7 +219,6 @@ if [ "$VTOY_BREAK_LEVEL" = "03" ] || [ "$VTOY_BREAK_LEVEL" = "13" ]; then
 fi
 
 
-
 ####################################################################
 #                                                                  #
 # Step 4 : Hand over to real init                                  #
index e6ba9bb6da0370018c44637c13b2fefa0f48eebf..292c37ac2c40948575dcbcb366746e75737d5658 100644 (file)
Binary files a/INSTALL/EFI/BOOT/grubx64_real.efi and b/INSTALL/EFI/BOOT/grubx64_real.efi differ
diff --git a/INSTALL/grub/debug.cfg b/INSTALL/grub/debug.cfg
new file mode 100644 (file)
index 0000000..9e74ac7
--- /dev/null
@@ -0,0 +1,57 @@
+submenu 'Check plugin json configuration (ventoy.json)' {
+    menuentry 'Check global control plugin configuration' {
+        set pager=1
+        vt_check_plugin_json $iso_path control $iso_path
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
+    menuentry 'Check theme plugin configuration' {
+        set pager=1
+        vt_check_plugin_json $iso_path theme $iso_path
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
+    menuentry 'Check auto install plugin configuration' {
+        set pager=1
+        vt_check_plugin_json $iso_path auto_install $iso_path
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
+    menuentry 'Check persistence plugin configuration' {
+        set pager=1
+        vt_check_plugin_json $iso_path persistence $iso_path
+        
+        echo -e "\n############### dump persistence ###############"
+        vt_dump_persistence
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
+    menuentry 'Check menu alias plugin configuration' {
+        set pager=1
+        vt_check_plugin_json $iso_path menu_alias $iso_path
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
+    menuentry 'Return to previous menu [Esc]' VTOY_RET {
+        echo 'Return ...'
+    }
+}
+
+menuentry 'Return to previous menu [Esc]' VTOY_RET {
+    echo 'Return ...'
+}
index 1eb3edcffa6a30b1431c09c443ad1da33af8a06b..d81ac8b959a11e8d145c5a6d7540548f6ed2f6d0 100644 (file)
Binary files a/INSTALL/grub/fonts/ascii.pf2 and b/INSTALL/grub/fonts/ascii.pf2 differ
diff --git a/INSTALL/grub/fonts/unicode.pf2 b/INSTALL/grub/fonts/unicode.pf2
new file mode 100644 (file)
index 0000000..b340859
Binary files /dev/null and b/INSTALL/grub/fonts/unicode.pf2 differ
index b1ef9b0a5e46d30cc417a75443d4d7a909ab1eca..e7627f651155f55a37eee481058fdd3a8d3b5a96 100644 (file)
 # 
 #************************************************************************************
 
+function ventoy_pause {
+    if [ -n "${vtdebug_flag}" ]; then
+        echo "press Enter to continue ......"
+        read vtTmpPause
+    fi
+}
+
+function ventoy_debug_pause {
+    if [ -n "${vtdebug_flag}" ]; then
+        echo "press Enter to continue ......"
+        read vtTmpPause
+    fi
+}
+
+
 function ventoy_power {
-    configfile ($root)/grub/power.cfg
+    configfile $prefix/power.cfg
+}
+
+function ventoy_diagnosis {    
+    configfile $prefix/debug.cfg
+}
+
+function ventoy_localboot {    
+    configfile $prefix/localboot.cfg
 }
 
 function get_os_type {
-    set vtoy_os=Linux    
-    for file in "efi/microsoft" "sources/boot.wim" "boot/bcd" "bootmgr.efi" "boot/etfsboot.com" "BOOT/etfsboot.com"; do
-        if [ -e $1/$file ]; then
+    set vtoy_os=Linux
+    
+    for file in "efi/microsoft/boot/bcd" "sources/boot.wim" "boot/bcd" "bootmgr.efi" "boot/etfsboot.com" ; do        
+        if vt_file_exist_nocase (loop)/$file; then        
             set vtoy_os=Windows
             break
         fi
     done
-    
+
     if [ -n "${vtdebug_flag}" ]; then
         echo ISO is $vtoy_os
     fi
 }
 
-function vt_check_pe {
-    unset VT_PE_SUPPORT
-
+function vt_check_compatible_pe {
+    #Check for PE without external tools
     if [ -f $1/HBCD_PE.ini ]; then
-        set ventoy_compatible=YES
-        set VT_PE_SUPPORT=YES
-    elif [ -f $1/easyu.flg ]; then
-        set VT_PE_SUPPORT=YES
-    elif [ -f $1/USM.ICO ]; then
-        set VT_PE_SUPPORT=YES
-    elif [ -d $1/USM_TOOL ]; then
-        set VT_PE_SUPPORT=YES
+        set ventoy_compatible=YES        
     fi
 }
 
 function locate_initrd {
     vt_linux_locate_initrd 
 
-    if [ -n "${vtdebug_flag}" ]; then
+    if [ -n "${vtdebug_flag}" ]; then        
         vt_linux_dump_initrd
-        sleep 5
+        ventoy_debug_pause
     fi
 }
 
-function find_wim_file {
-    unset ventoy_wim_file
+function locate_wim {
+    vt_windows_locate_wim_patch (loop)
     
-    for file in "sources/boot.wim" "sources/BOOT.WIM" "Sources/Win10PEx64.WIM" "boot/BOOT.WIM" \
-                "winpe_x64.wim" "boot/10pex64.wim" "BOOT/USM1PE6L.WIM" "BOOT/USM1PE6F.WIM"; do
-        if [ -e $1/$file ]; then
-            set ventoy_wim_file=$1/$file
-            break
-        fi
-    done
+    if [ -n "${vtdebug_flag}" ]; then
+        echo '###############################################'
+        vt_dump_wim_patch
+        echo '###############################################'
+        ventoy_debug_pause
+    fi
 }
 
+function distro_specify_wim_patch {
+    if [ -d (loop)/h3pe ]; then
+        vt_windows_collect_wim_patch wim /BOOT/H3_10PE.WIM
+        vt_windows_collect_wim_patch wim /BOOT/H3_7PE.WIM
+        vt_windows_collect_wim_patch wim /BOOT/H3_8PE.WIM
+        vt_windows_collect_wim_patch wim /BOOT/H3_81PE.WIM
+    fi
+}
+
+function distro_specify_wim_patch_phase2 {
+    if [ -f (loop)/boot/boot.wim ]; then
+        vt_windows_collect_wim_patch wim /boot/boot.wim
+    fi
+}
+
+
 function distro_specify_initrd_file {
     if [ -e (loop)/boot/all.rdz ]; then
         vt_linux_specify_initrd_file /boot/all.rdz
@@ -127,32 +158,50 @@ function distro_specify_initrd_file_phase2 {
 
 function uefi_windows_menu_func {
     vt_windows_reset
-    
-    if [ "$ventoy_compatible" = "NO" ]; then        
-        find_wim_file (loop)
-        if [ -n "$ventoy_wim_file" ]; then
-            vt_windows_locate_wim $ventoy_wim_file
+
+    if [ "$ventoy_compatible" = "NO" ]; then   
+        
+        if [ "$ventoy_fs_probe" = "iso9660" ]; then
+            loopback -d loop
+            vt_iso9660_nojoliet 1            
+            loopback loop $1$2
         fi
-    fi
-    
-    vt_windows_chain_data ${1}${chosen_path}
+        
+        for file in "efi/microsoft/boot/bcd"; do
+            vt_windows_collect_wim_patch bcd (loop)/$file                
+        done
 
-    if [ -n "${vtdebug_flag}" ]; then
-        sleep 5
+        vt_windows_count_wim_patch vt_wim_cnt
+        if [ $vt_wim_cnt -eq 0 ]; then
+            distro_specify_wim_patch_phase2
+        fi
+        
+        ventoy_debug_pause        
+        locate_wim
     fi
 
+    vt_windows_chain_data ${1}${chosen_path}    
+    ventoy_debug_pause
+    
     if [ -n "$vtoy_chain_mem_addr" ]; then
         terminal_output  console       
         chainloader ${vtoy_path}/ventoy_x64.efi  env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
         boot
     else
         echo "chain empty failed"
-        sleep 5
+        ventoy_pause
     fi
 }
 
 function uefi_linux_menu_func {
     if [ "$ventoy_compatible" = "NO" ]; then    
+        
+        if [ "$ventoy_fs_probe" = "udf" ]; then
+            loopback -d loop            
+            set ventoy_fs_probe=iso9660
+            loopback loop $1$2
+        fi
+        
         vt_load_cpio  ${vtoy_path}/ventoy.cpio   $2 $1
 
         vt_linux_clear_initrd
@@ -166,20 +215,14 @@ function uefi_linux_menu_func {
                 fi
             done
         fi
-        
+
         # special process for special distros
         if [ -d (loop)/loader/entries ]; then
-            set LoadIsoEfiDriver=on
             vt_linux_parse_initrd_grub  dir  (loop)/loader/entries/
         elif [ -d (loop)/boot/grub ]; then
             vt_linux_parse_initrd_grub  dir  (loop)/boot/grub/
         fi
         
-        if [ -e (loop)/syslinux/alt0/full.cz ]; then
-            set LoadIsoEfiDriver=on
-            set FirstTryBootFile='@EFI@BOOT@grubx64.efi'
-        fi
-        
         distro_specify_initrd_file
         
         vt_linux_initrd_count vtcount
@@ -194,6 +237,24 @@ function uefi_linux_menu_func {
         fi
         
         locate_initrd
+        
+        if [ -d (loop)/loader/entries ]; then
+            vt_linux_get_main_initrd_index vtindex
+            
+            if [ -d (loop)/arch ]; then
+                if [ -f (loop)/arch/boot/x86_64/archiso.img ]; then
+                    vt_add_replace_file $vtindex "EFI\\archiso\\archiso.img"
+                elif [ -f (loop)/boot/initramfs_x86_64.img ]; then
+                    vt_add_replace_file $vtindex "boot\\initramfs_x86_64.img"
+                fi
+            elif [ -f (loop)/EFI/BOOT/initrd.gz ]; then
+                vt_add_replace_file $vtindex "EFI\\BOOT\\initrd.gz"
+            fi
+        elif [ -e (loop)/syslinux/alt0/full.cz ]; then
+            vt_add_replace_file 0 "EFI\\BOOT\\full.cz"            
+            set FirstTryBootFile='@EFI@BOOT@grubx64.efi'
+        fi
+        
     fi
     
     vt_linux_chain_data ${1}${chosen_path}
@@ -204,7 +265,7 @@ function uefi_linux_menu_func {
         boot
     else
         echo "chain empty failed"
-        sleep 5
+        ventoy_pause
     fi
 }
 
@@ -232,6 +293,7 @@ function uefi_iso_menu_func {
         set ventoy_fs_probe=udf
     else
         set ventoy_fs_probe=iso9660
+        vt_iso9660_nojoliet 0
     fi
 
     loopback loop ${1}${chosen_path}
@@ -257,13 +319,7 @@ function uefi_iso_menu_func {
     vt_img_sector ${1}${chosen_path}
     
     if [ "$vtoy_os" = "Windows" ]; then
-        vt_check_pe (loop)        
-        if [ "$VT_PE_SUPPORT" != "YES" ]; then
-            if [ "$ventoy_fs_probe" = "iso9660" ]; then        
-                set ventoy_compatible=YES
-            fi
-        fi
-    
+        vt_check_compatible_pe (loop)        
         uefi_windows_menu_func  $1 ${chosen_path}
     else
         uefi_linux_menu_func  $1 ${chosen_path}
@@ -287,32 +343,50 @@ function uefi_iso_memdisk {
 function legacy_windows_menu_func {
     vt_windows_reset
     
-    if [ "$ventoy_compatible" = "NO" ]; then                
-        find_wim_file (loop)
-        if [ -n "$ventoy_wim_file" ]; then
-            vt_windows_locate_wim $ventoy_wim_file
-        elif [ -n "${vtdebug_flag}" ]; then
-            echo No wim file found
+    if [ "$ventoy_compatible" = "NO" ]; then   
+        
+        if [ "$ventoy_fs_probe" = "iso9660" ]; then
+            loopback -d loop
+            vt_iso9660_nojoliet 1
+            loopback loop $1$2
         fi
+        
+        for file in "boot/bcd" "/efi/microsoft/boot/bcd" "SSTR/BCD"; do
+            vt_windows_collect_wim_patch bcd (loop)/$file                
+        done
+        
+        distro_specify_wim_patch
+
+        vt_windows_count_wim_patch vt_wim_cnt
+        if [ $vt_wim_cnt -eq 0 ]; then
+            distro_specify_wim_patch_phase2
+        fi
+        
+        ventoy_debug_pause        
+        locate_wim
     fi
-       
-    vt_windows_chain_data ${1}${chosen_path}
-    
-    if [ -n "${vtdebug_flag}" ]; then
-        sleep 5
-    fi
+
+    vt_windows_chain_data ${1}${chosen_path}    
+    ventoy_debug_pause    
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
         linux16   $vtoy_path/ipxe.krn ${vtdebug_flag} ibft mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
         boot
     else
         echo "chain empty failed"
-        sleep 5
+        ventoy_pause
     fi
 }
 
 function legacy_linux_menu_func {
     if [ "$ventoy_compatible" = "NO" ]; then
+
+        if [ "$ventoy_fs_probe" = "udf" ]; then
+            loopback -d loop
+            set ventoy_fs_probe=iso9660
+            loopback loop $1$2
+        fi
+    
         vt_load_cpio  $vtoy_path/ventoy.cpio  $2 $1
 
         vt_linux_clear_initrd
@@ -352,18 +426,15 @@ function legacy_linux_menu_func {
         locate_initrd
     fi
     
-    vt_linux_chain_data ${1}${chosen_path}
-    
-    if [ -n "${vtdebug_flag}" ]; then
-        sleep 5
-    fi
+    vt_linux_chain_data ${1}${chosen_path}    
+    ventoy_debug_pause
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
         linux16   $vtoy_path/ipxe.krn ${vtdebug_flag}  mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
         boot
     else
         echo "chain empty failed"
-        sleep 5
+        ventoy_pause
     fi
 }
 
@@ -381,12 +452,12 @@ function legacy_iso_menu_func {
         set ventoy_fs_probe=udf
     else
         set ventoy_fs_probe=iso9660
-    fi   
-
-    loopback loop ${1}${chosen_path}
+        vt_iso9660_nojoliet 0
+    fi
     
+    loopback loop ${1}${chosen_path}
     get_os_type (loop)
-    
+
     if [ -n "$vtcompat" ]; then
         set ventoy_compatible=YES
         unset vtcompat
@@ -399,13 +470,7 @@ function legacy_iso_menu_func {
     vt_img_sector ${1}${chosen_path}
 
     if [ "$vtoy_os" = "Windows" ]; then
-        vt_check_pe (loop)        
-        if [ "$VT_PE_SUPPORT" != "YES" ]; then
-            if [ "$ventoy_fs_probe" = "iso9660" ]; then        
-                set ventoy_compatible=YES
-            fi
-        fi
-        
+        vt_check_compatible_pe (loop)        
         legacy_windows_menu_func  $1 ${chosen_path}
     else
         legacy_linux_menu_func  $1 ${chosen_path}
@@ -446,10 +511,9 @@ function iso_unsupport_menuentry {
 
 function wim_common_menuentry {
     vt_chosen_img_path chosen_path
-    vt_wim_chain_data ${iso_path}${chosen_path}    
-    if [ -n "${vtdebug_flag}" ]; then
-        sleep 5
-    fi
+    vt_wim_chain_data ${iso_path}${chosen_path}
+    
+    ventoy_debug_pause    
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
         if [ "$grub_platform" = "pc" ]; then
@@ -461,7 +525,7 @@ function wim_common_menuentry {
         boot
     else
         echo "chain empty failed"
-        sleep 5
+        ventoy_pause
     fi
 }
 
@@ -479,7 +543,7 @@ function wim_unsupport_menuentry {
 #############################################################
 #############################################################
 
-set VENTOY_VERSION="1.0.12"
+set VENTOY_VERSION="1.0.13"
 
 # Default menu display mode, you can change it as you want.
 #    0: List mode   
@@ -490,10 +554,12 @@ set VTOY_DEFAULT_MENU_MODE=0
 unset timeout
 
 set VTOY_MEM_DISK_STR="[Memdisk]"
-set VTOY_ISO_RAW_STR="ISO RAW"
+set VTOY_ISO_RAW_STR="Compatible Mode"
 set VTOY_ISO_UEFI_DRV_STR="UEFI FS"
 
 set VTOY_F2_CMD="ventoy_power"
+set VTOY_F4_CMD="ventoy_localboot"
+set VTOY_F5_CMD="ventoy_diagnosis"
 
 if [ "$grub_platform" = "pc" ]; then
     set VTOY_TEXT_MENU_VER="Ventoy $VENTOY_VERSION BIOS  www.ventoy.net"
@@ -504,7 +570,7 @@ fi
 vt_device $root  vtoy_dev
 
 if [ "$vtoy_dev" = "tftp" ]; then
-    set vtoy_path=($root)    
+    set vtoy_path=($root)
     for vtid in 0 1 2 3; do
         if [ -d (hd$vtid,2)/ventoy ]; then
             set iso_path=(hd$vtid,1)
@@ -512,13 +578,19 @@ if [ "$vtoy_dev" = "tftp" ]; then
             break
         fi
     done
+    loadfont ascii
 else
-    set vtoy_path=($root)/ventoy    
+    if [ "$prefix" = "(ventoydisk)/grub" ]; then
+        set vtoy_path=(ventoydisk)/ventoy
+    else
+        set vtoy_path=($root)/ventoy
+    fi
+
     set iso_path=($vtoy_dev,1)
     set vtoy_efi_part=($vtoy_dev,2)
+    loadfont unicode
 fi
 
-loadfont ascii
 
 #Load Plugin
 if [ -f $iso_path/ventoy/ventoy.json ]; then
@@ -534,10 +606,10 @@ fi
 
 if [ $VTOY_DEFAULT_MENU_MODE -eq 0 ]; then
     set VTOY_F3_CMD="vt_dynamic_menu 1 1"
-    set VTOY_HOTKEY_TIP="F1:Memdisk  F2:Power  F3:TreeView"
+    set VTOY_HOTKEY_TIP="F1:Memdisk  F2:Power  F3:TreeView  F4:Localboot  F5:Debug"
 else
     set VTOY_F3_CMD="vt_dynamic_menu 1 0"
-    set VTOY_HOTKEY_TIP="F1:Memdisk  F2:Power  F3:ListView"
+    set VTOY_HOTKEY_TIP="F1:Memdisk  F2:Power  F3:ListView  F4:Localboot  F5:Debug"
 fi
 
 
@@ -553,7 +625,13 @@ else
     set theme=$prefix/themes/ventoy/theme.txt
 fi
 
-terminal_output  gfxterm
+if [ "$vtoy_display_mode" = "CLI" ]; then
+    terminal_output  console
+else
+    terminal_output  gfxterm
+fi
+
+#vtdebug on
 
 #colect all image files (iso files)
 set ventoy_img_count=0
index 424bb76acd228fd2093e971a2cbc0b638ddd6fbe..4406727906ab6ce10aeaa348b5dda8029c0e936c 100644 (file)
Binary files a/INSTALL/grub/i386-pc/core.img and b/INSTALL/grub/i386-pc/core.img differ
diff --git a/INSTALL/grub/localboot.cfg b/INSTALL/grub/localboot.cfg
new file mode 100644 (file)
index 0000000..e9893e4
--- /dev/null
@@ -0,0 +1,57 @@
+
+if [ "$grub_platform" = "pc" ]; then
+    menuentry 'Search and boot Windows' {    
+        if search -n -s -f /bootmgr; then
+            ntldr /bootmgr
+        elif search -n -s -f /ntldr; then
+            ntldr /ntldr
+        else
+            echo "Windows NOT found ..."
+        fi        
+    }
+    
+    menuentry 'Boot the 1st local disk' {
+        set root=(hd0,1)
+        chainloader +1
+        boot
+    }
+    
+    menuentry 'Boot the 2nd local disk' {
+        set root=(hd1,1)
+        chainloader +1
+        boot
+    }
+    
+    menuentry 'Boot the 3rd local disk' {
+        set root=(hd2,1)
+        chainloader +1
+        boot
+    }
+    
+else
+
+    menuentry 'Search and boot Windows' {    
+        if search -n -s -f /EFI/Microsoft/Boot/bootmgfw.efi; then
+            terminal_output  console
+            chainloader /EFI/Microsoft/Boot/bootmgfw.efi
+            boot
+        else
+            echo "Windows NOT found ..."
+        fi        
+    }
+    
+    menuentry 'Search and boot BOOTX64.EFI' {    
+        if search -n -s -f /efi/boot/bootx64.efi; then
+            terminal_output  console
+            chainloader /efi/boot/bootx64.efi
+            boot
+        else
+            echo "BOOTX64.EFI NOT found ..."
+        fi        
+    }
+
+fi
+
+menuentry 'Return to menu [Esc]' VTOY_RET {
+    echo 'Return ...'
+}
index daecd66657388c4cbfd32734c1470e5c12cbca55..a07f278d7a563b760177df5847b16c24b010449b 100644 (file)
@@ -7,7 +7,7 @@ menuentry Reboot {
 menuentry Halt {
     echo -e '\n\nSystem is halting ... \n'
     sleep 1
-    reboot
+    halt
 }
 
 menuentry 'Return to menu [Esc]' VTOY_RET {
index 10098dd3ffe4f24b6671d9156a97fde61647b788..b0190fc67e4f9046f608f497a5831be832506dc6 100644 (file)
Binary files a/INSTALL/grub/themes/ventoy/background.png and b/INSTALL/grub/themes/ventoy/background.png differ
index a73017b744e09ceb6a43b0208d7d0f17289ee2db..ecb2e62b1c1c88bdfdc502cc48ace3d7e5c8f988 100644 (file)
@@ -1,9 +1,7 @@
 
 desktop-image: "background.png"
 title-text: " "
-title-font: "ascii"
 title-color: "#ffffff"
-message-font: "ascii"
 message-color: "#f2f2f2"
 
 terminal-box: "terminal_box_*.png"
@@ -16,14 +14,12 @@ terminal-box: "terminal_box_*.png"
 
   menu_pixmap_style = "menu_*.png"
 
-  item_font = "ascii"  
   item_color = "#ffffff"  
   item_height = 30
   
   item_spacing = 1
   item_padding = 1
 
-  selected_item_font = "ascii"
   selected_item_color= "#f2f2f2"
   selected_item_pixmap_style = "select_*.png"
 
@@ -67,8 +63,8 @@ terminal-box: "terminal_box_*.png"
 
 
 + hbox{ 
-    left = 90%
-    top = 30 
+    left = 30%
+    top = 95%-50
     width = 10%
     height = 25
     + label {text = "@VTOY_ISO_RAW@" color = "red" align = "left"} 
index 19e42a995ea8e3f20a4b13c5c3f42f5ce0598a5c..0f6b368a4a72551b553e59537ff8cf1856e36810 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/normal.mod and b/INSTALL/grub/x86_64-efi/normal.mod differ
index 80dea30add52c36a2b871138665adc9f36a2add4..a9fc9a8898514f6fa77468a69647816fc3885bb3 100644 (file)
@@ -278,7 +278,7 @@ EOF
 
     echo "create efi fat fs $PART2 ..."
     for i in 0 1 2 3 4 5 6 7 8 9; do
-        if mkfs.vfat -F 16 -n EFI $PART2; then
+        if mkfs.vfat -F 16 -n VTOYEFI $PART2; then
             echo 'success'
             break
         else
index 5b13a0e12593d86b83c8ab509f23b431c8c3115a..766971d43476a673cd14a1da9f1ccc28cec452d4 100644 (file)
Binary files a/INSTALL/ventoy/ipxe.krn and b/INSTALL/ventoy/ipxe.krn differ
index a45afff76da90f9a863af03baf93037ccd8ac9ac..74886bb53d2f6ee851b324114e0a356441a56279 100644 (file)
Binary files a/INSTALL/ventoy/ventoy.cpio and b/INSTALL/ventoy/ventoy.cpio differ
index 8f94a70df5516c0c2cd595d094dcc75d1717f26c..c59a5d74a4fa75ce6fa6f84bfc3a399e7b8ac24f 100644 (file)
Binary files a/INSTALL/ventoy/ventoy_x64.efi and b/INSTALL/ventoy/ventoy_x64.efi differ
index 047610626347ac566f020cf0ae4cb666c5bdca52..cc54475c65c15c7390cb01729917d3f27620483b 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump32.exe and b/INSTALL/ventoy/vtoyjump32.exe differ
index 698d816efff06e855385e8819501dcc73689e5da..9273282ea8ee510211cab9026628b81fbdce9892 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump64.exe and b/INSTALL/ventoy/vtoyjump64.exe differ
index f113b36343b774c42fa8cbb570ca30fbe1bd1120..d3ccb2b43d0d96e009d736b35b4a9700f63fd957 100644 (file)
@@ -33,6 +33,8 @@ ventoy_img_chunk *g_chunk;
 uint32_t g_img_chunk_num;
 ventoy_img_chunk *g_cur_chunk;
 uint32_t g_disk_sector_size;
+uint8_t *g_os_param_reserved;
+
 
 ventoy_override_chunk *g_override_chunk;
 uint32_t g_override_chunk_num;
@@ -42,6 +44,14 @@ uint32_t g_virt_chunk_num;
 
 ventoy_sector_flag g_sector_flag[128];
 
+#define VENTOY_ISO9660_SECTOR_OVERFLOW  2097152
+
+int     g_fixup_iso9660_secover_enable = 0;
+int     g_fixup_iso9660_secover_start  = 0;
+uint64  g_fixup_iso9660_secover_1st_secs = 0;
+uint64  g_fixup_iso9660_secover_cur_secs = 0;
+uint64  g_fixup_iso9660_secover_tot_secs = 0;
+
 static struct int13_disk_address __bss16 ( ventoy_address );
 #define ventoy_address __use_data16 ( ventoy_address )
 
@@ -195,6 +205,17 @@ static int ventoy_vdisk_read_real(uint64_t lba, unsigned int count, unsigned lon
                 memcpy((char *)databuffer, override_data + start - override_start, override_end - start);
             }
         }
+
+        if (g_fixup_iso9660_secover_enable && (!g_fixup_iso9660_secover_start) && 
+            g_override_chunk[i].override_size == sizeof(ventoy_iso9660_override))
+        {
+            ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)override_data;
+            if (dirent->first_sector >= VENTOY_ISO9660_SECTOR_OVERFLOW)
+            {
+                g_fixup_iso9660_secover_start = 1;
+                g_fixup_iso9660_secover_cur_secs = 0;
+            }
+        }
     }
 
 end:
@@ -202,6 +223,59 @@ end:
     return 0;
 }
 
+uint64_t ventoy_fixup_iso9660_sector(uint64_t Lba, uint32_t secNum)
+{
+    uint32_t i = 0;
+
+    if (g_fixup_iso9660_secover_cur_secs > 0)
+    {
+        Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
+        g_fixup_iso9660_secover_cur_secs += secNum;
+        if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
+        {
+            g_fixup_iso9660_secover_start = 0;
+            goto end;
+        }
+    }
+    else
+    {
+        ventoy_iso9660_override *dirent;
+        ventoy_override_chunk *pOverride;
+
+        for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
+        {
+            dirent = (ventoy_iso9660_override *)pOverride->override_data;
+            if (Lba == dirent->first_sector)
+            {
+                g_fixup_iso9660_secover_start = 0;
+                goto end;
+            }
+        }
+
+        if (g_fixup_iso9660_secover_start)
+        {
+            for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
+            {
+                dirent = (ventoy_iso9660_override *)pOverride->override_data;
+                if (Lba + VENTOY_ISO9660_SECTOR_OVERFLOW == dirent->first_sector)
+                {
+                    g_fixup_iso9660_secover_tot_secs = (dirent->size + 2047) / 2048;
+                    g_fixup_iso9660_secover_cur_secs = secNum;
+                    if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
+                    {
+                        g_fixup_iso9660_secover_start = 0;
+                    }
+                    Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
+                    goto end;
+                }
+            }
+        }
+    }
+
+end:
+    return Lba;
+}
+
 int ventoy_vdisk_read(struct san_device *sandev, uint64_t lba, unsigned int count, unsigned long buffer)
 {
     uint32_t i, j;
@@ -223,6 +297,12 @@ int ventoy_vdisk_read(struct san_device *sandev, uint64_t lba, unsigned int coun
 
     ix86 = (struct i386_all_regs *)sandev->x86_regptr;
 
+    /* Workaround for SSTR PE loader error */
+    if (g_fixup_iso9660_secover_start)
+    {
+        lba = ventoy_fixup_iso9660_sector(lba, count);
+    }
+
     readend = (lba + count) * 2048;
     if (readend <= g_chain->real_img_size_in_bytes)
     {
@@ -384,6 +464,8 @@ static void ventoy_dump_chain(ventoy_chain_head *chain)
     printf("os_param->vtoy_img_size=<%llu>\n",    chain->os_param.vtoy_img_size);
     printf("os_param->vtoy_reserve[0]=<%u>\n",    vtoy_reserve[0]);
     printf("os_param->vtoy_reserve[1]=<%u>\n",    vtoy_reserve[1]);
+    printf("os_param->vtoy_reserve[2]=<%u>\n",    vtoy_reserve[2]);
+    printf("os_param->vtoy_reserve[3]=<%u>\n",    vtoy_reserve[3]);
     printf("os_param->vtoy_img_location_addr=<0x%llx>\n", chain->os_param.vtoy_img_location_addr);
     printf("os_param->vtoy_img_location_len=<%u>\n",   chain->os_param.vtoy_img_location_len);
     ventoy_debug_pause();
@@ -489,6 +571,14 @@ int ventoy_boot_vdisk(void *data)
     g_disk_sector_size = g_chain->disk_sector_size;
     g_cur_chunk = g_chunk;
 
+    g_os_param_reserved = (uint8_t *)(g_chain->os_param.vtoy_reserved);
+
+    /* Workaround for Windows & ISO9660 */
+    if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0)
+    {
+        g_fixup_iso9660_secover_enable = 1;
+    }
+
     g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
     g_override_chunk_num = g_chain->override_chunk_num;
 
index 81be2d757b507909d25a9e033e059530c5f19d7b..27b4dcaf3adcfe5f77717f41d34d46766df150de 100644 (file)
@@ -80,6 +80,14 @@ typedef struct ventoy_os_param
     grub_uint8_t   reserved[31];
 }ventoy_os_param;
 
+typedef struct ventoy_iso9660_override
+{
+    uint32_t first_sector;
+    uint32_t first_sector_be;
+    uint32_t size;
+    uint32_t size_be;
+}ventoy_iso9660_override;
+
 #pragma pack()
 
 // compile assert to check that size of ventoy_os_param must be 512
index ffc31210eadedf25a192fb498554a42c6f48a1c2..0ee4ae461054fd9243338143bdd8f553859c65cc 100644 (file)
@@ -492,13 +492,13 @@ static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
 
 static CHAR GetMountLogicalDrive(void)
 {
-       CHAR Letter = 'Z';
+       CHAR Letter = 'Y';
        DWORD Drives;
-       DWORD Mask = 0x2000000;
+       DWORD Mask = 0x1000000;
 
        Drives = GetLogicalDrives();
     Log("Drives=0x%x", Drives);
-
+    
        while (Mask)
        {
                if ((Drives & Mask) == 0)
@@ -724,7 +724,7 @@ static int ProcessUnattendedInstallation(const char *script)
     {
         Letter = 'X';
     }
-
+    
     sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
     Log("Copy file <%s> --> <%s>", script, CurDir);
     CopyFile(script, CurDir, FALSE);