]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - EDK2/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
1.0.07 release
[Ventoy.git] / EDK2 / edk2-edk2-stable201911 / MdeModulePkg / Application / Ventoy / Ventoy.c
index d3c8216b67558b872810221d158f8e35a92cbef0..857e7415b7c535b0d4db5a7c274de6979baa2b82 100644 (file)
 #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;
 BOOLEAN gDebugPrint = FALSE;
 BOOLEAN gLoadIsoEfi = FALSE;
+ventoy_ram_disk g_ramdisk_param;
 ventoy_chain_head *g_chain;
 ventoy_img_chunk *g_chunk;
 UINT32 g_img_chunk_num;
@@ -49,15 +53,27 @@ 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[] = 
 {
+    L"@",
     EFI_REMOVABLE_MEDIA_FILE_NAME,
     L"\\EFI\\BOOT\\GRUBX64.EFI",
     L"\\EFI\\BOOT\\BOOTx64.EFI",
     L"\\EFI\\BOOT\\bootx64.efi",
+    L"\\efi\\boot\\bootx64.efi",
 };
 
 /* EFI block device vendor device path GUID */
@@ -353,6 +369,25 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
     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_STATUS EFIAPI ventoy_block_io_read 
 (
     IN EFI_BLOCK_IO_PROTOCOL          *This,
@@ -497,6 +532,33 @@ EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
     return EFI_SUCCESS;
 }
 
+EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_GUID VarGuid = VENTOY_GUID;
+    
+    Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  sizeof(g_ramdisk_param), &(g_ramdisk_param));
+    debug("set efi variable %r", Status);
+
+    return Status;
+}
+
+EFI_STATUS EFIAPI ventoy_del_ramdisk_param(VOID)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_GUID VarGuid = VENTOY_GUID;
+    
+    Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  0, NULL);
+    debug("delete efi variable %r", Status);
+
+    return Status;
+}
+
+
 EFI_STATUS EFIAPI ventoy_set_variable(VOID)
 {
     EFI_STATUS Status = EFI_SUCCESS;
@@ -524,7 +586,7 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
 }
 
 
-EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle)
+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);
@@ -532,7 +594,7 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle)
     ventoy_fill_device_path();
     
     gBlockData.Media.BlockSize = 2048;
-    gBlockData.Media.LastBlock = g_chain->virt_img_size_in_bytes / 2048 - 1;
+    gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
     gBlockData.Media.ReadOnly = TRUE;
     gBlockData.Media.MediaPresent = 1;
     gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
@@ -540,7 +602,16 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle)
        pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
        pBlockIo->Media = &(gBlockData.Media);
        pBlockIo->Reset = ventoy_block_io_reset;
-       pBlockIo->ReadBlocks = ventoy_block_io_read;
+
+    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;
 
@@ -827,6 +898,8 @@ static int ventoy_update_image_location(ventoy_os_param *param)
 STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
 {   
     UINT32 i = 0;
+    UINT32 old_cnt = 0;
+    UINTN size = 0;
     UINT8 chksum = 0;
     CHAR16 *pPos = NULL;
     CHAR16 *pCmdLine = NULL;
@@ -855,8 +928,33 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         gLoadIsoEfi = TRUE;
     }
 
+    pPos = StrStr(pCmdLine, L"FirstTry=@");
+    if (pPos)
+    {
+        pPos += StrLen(L"FirstTry=");
+        for (i = 0; i < ARRAY_SIZE(gFirstTryBootFile); i++, pPos++)
+        {
+            if (*pPos != L' ' && *pPos != L'\t' && *pPos)
+            {
+                gFirstTryBootFile[i] = (*pPos == '@') ? '\\' : *pPos;
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        gEfiBootFileName[0] = gFirstTryBootFile;
+        gBootFileStartIndex = 0;
+    }
+
     debug("cmdline:<%s>", pCmdLine);
 
+    if (gFirstTryBootFile[0])
+    {
+        debug("First Try:<%s>", gFirstTryBootFile);
+    }
+
     pPos = StrStr(pCmdLine, L"env_param=");
     if (!pPos)
     {
@@ -866,40 +964,141 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
     pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
     grub_env_get = pGrubParam->grub_env_get;
 
+    g_file_replace_list = &pGrubParam->file_replace;
+    old_cnt = g_file_replace_list->old_file_cnt;
+    debug("file replace: magic:0x%x virtid:%u name count:%u <%a> <%a> <%a> <%a>",
+        g_file_replace_list->magic,
+        g_file_replace_list->new_file_virtual_id,
+        old_cnt,
+        old_cnt > 0 ? g_file_replace_list->old_file_name[0] : "",
+        old_cnt > 1 ? g_file_replace_list->old_file_name[1] : "",
+        old_cnt > 2 ? g_file_replace_list->old_file_name[2] : "",
+        old_cnt > 3 ? g_file_replace_list->old_file_name[3] : ""
+        );
 
     pPos = StrStr(pCmdLine, L"mem:");
     g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
 
-    g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
-    g_img_chunk_num = g_chain->img_chunk_num;
-    g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
-    g_override_chunk_num = g_chain->override_chunk_num;
-    g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
-    g_virt_chunk_num = g_chain->virt_chunk_num;
+    pPos = StrStr(pPos, L"size:");
+    size = StrDecimalToUintn(pPos + 5);
 
-    for (i = 0; i < sizeof(ventoy_os_param); i++)
+    debug("memory addr:%p size:%lu", g_chain, size);
+
+    if (StrStr(pCmdLine, L"memdisk"))
     {
-        chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
+        g_iso_buf_size = size;
+        gMemdiskMode = TRUE;
     }
+    else
+    {
+        g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
+        g_img_chunk_num = g_chain->img_chunk_num;
+        g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
+        g_override_chunk_num = g_chain->override_chunk_num;
+        g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
+        g_virt_chunk_num = g_chain->virt_chunk_num;
+
+        for (i = 0; i < sizeof(ventoy_os_param); i++)
+        {
+            chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
+        }
 
-    if (gDebugPrint)
+        if (gDebugPrint)
+        {
+            debug("os param checksum: 0x%x %a", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
+        }
+
+        ventoy_update_image_location(&(g_chain->os_param));
+
+        if (gDebugPrint)
+        {
+            ventoy_dump_chain(g_chain);
+        }
+    }
+
+    FreePool(pCmdLine);
+    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))
     {
-        debug("os param checksum: 0x%x %a", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
+        return Status;
     }
 
-    ventoy_update_image_location(&(g_chain->os_param));
+    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;
+            }
+        }
+    }
 
-    if (gDebugPrint)
+    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))
     {
-        ventoy_dump_chain(g_chain);
+        g_original_fopen = (*Root)->Open;
+        g_original_fclose = (*Root)->Close;
+        (*Root)->Open = ventoy_wrapper_file_open;
     }
 
-    FreePool(pCmdLine);
-    return EFI_SUCCESS;
+    return Status;
 }
 
+
 EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
 {
+    UINTN t = 0;
     UINTN i = 0;
     UINTN j = 0;
     UINTN Find = 0;
@@ -910,77 +1109,99 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
     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))
+    for (t = 0; t < 3; t++)
     {
-        return Status;
-    }
-
-    debug("ventoy_boot fs count:%u", Count);
+        Count = 0;
+        Handles = NULL;
 
-    for (i = 0; i < Count; i++)
-    {
-        Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
+        Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 
+                                     NULL, &Count, &Handles);
         if (EFI_ERROR(Status))
         {
-            continue;
+            return Status;
         }
 
-        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("ventoy_boot fs count:%u", Count);
 
-        debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
-        if (CompareMem(gBlockData.Path, pDevPath, gBlockData.DevicePathCompareLen))
+        for (i = 0; i < Count; i++)
         {
-            debug("Not ventoy disk file system");
-            continue;
-        }
+            Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
+            if (EFI_ERROR(Status))
+            {
+                continue;
+            }
 
-        for (j = 0; j < ARRAY_SIZE(gEfiBootFileName); j++)
-        {
-            Status = ventoy_load_image(ImageHandle, pDevPath, gEfiBootFileName[j], 
-                                       StrSize(gEfiBootFileName[j]), &Image);
-            if (EFI_SUCCESS == Status)
+            debug("FS:%u Protocol:%p  OpenVolume:%p", i, pFile, pFile->OpenVolume);
+
+            Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid, 
+                                       (VOID **)&pDevPath,
+                                       ImageHandle,
+                                       Handles[i],
+                                       EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+            if (EFI_ERROR(Status))
             {
-                break;
+                debug("Failed to open device path protocol %r", Status);
+                continue;
             }
-            debug("Failed to load image %r <%s>", Status, gEfiBootFileName[j]);
-        }
 
-        if (j >= ARRAY_SIZE(gEfiBootFileName))
-        {
-            continue;
-        }
+            debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
+            if (CompareMem(gBlockData.Path, pDevPath, gBlockData.DevicePathCompareLen))
+            {
+                debug("Not ventoy disk file system");
+                continue;
+            }
 
-        Find++;
-        debug("Find boot file, now try to boot .....");
-        ventoy_debug_pause();
+            for (j = gBootFileStartIndex; j < ARRAY_SIZE(gEfiBootFileName); j++)
+            {
+                Status = ventoy_load_image(ImageHandle, pDevPath, gEfiBootFileName[j], 
+                                           StrSize(gEfiBootFileName[j]), &Image);
+                if (EFI_SUCCESS == Status)
+                {
+                    break;
+                }
+                debug("Failed to load image %r <%s>", Status, gEfiBootFileName[j]);
+            }
 
-        if (gDebugPrint)
-        {
-            gST->ConIn->Reset(gST->ConIn, FALSE);
+            if (j >= ARRAY_SIZE(gEfiBootFileName))
+            {
+                continue;
+            }
+
+            Find++;
+            debug("Find boot file, now try to boot .....");
+            ventoy_debug_pause();
+
+            if (gDebugPrint)
+            {
+                gST->ConIn->Reset(gST->ConIn, FALSE);
+                //ventoy_wrapper_system();
+            }
+
+            if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC)
+            {
+                g_original_open_volume = pFile->OpenVolume;
+                pFile->OpenVolume = ventoy_wrapper_open_volume;
+            }
+            
+            Status = gBS->StartImage(Image, NULL, NULL);
+            if (EFI_ERROR(Status))
+            {
+                debug("Failed to start image %r", Status);
+                sleep(3);
+                gBS->UnloadImage(Image);
+                break;
+            }
         }
-        
-        Status = gBS->StartImage(Image, NULL, NULL);
-        if (EFI_ERROR(Status))
+
+        FreePool(Handles);
+
+        if (Find == 0)
         {
-            debug("Failed to start image %r", Status);
-            gBS->UnloadImage(Image);
-            break;
+            debug("Fs not found, now wait and retry...");
+            sleep(2);
         }
     }
 
-    FreePool(Handles);
-
     if (Find == 0)
     {
         return EFI_NOT_FOUND;
@@ -1016,8 +1237,49 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID)
     return EFI_SUCCESS;
 }
 
-EFI_STATUS EFIAPI VentoyEfiMain
+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
 (
     IN EFI_HANDLE         ImageHandle,
     IN EFI_SYSTEM_TABLE  *SystemTable
@@ -1037,35 +1299,67 @@ EFI_STATUS EFIAPI VentoyEfiMain
     ventoy_clear_input();
 
     ventoy_parse_cmdline(ImageHandle);
-    ventoy_set_variable();
-    ventoy_find_iso_disk(ImageHandle);
 
-    if (gLoadIsoEfi)
+    if (gMemdiskMode)
     {
-        ventoy_find_iso_disk_fs(ImageHandle);
-        ventoy_load_isoefi_driver(ImageHandle);
+        g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
+        g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
+
+        ventoy_save_ramdisk_param();
+        
+        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();
     }
+    else
+    {
+        ventoy_set_variable();
+        ventoy_find_iso_disk(ImageHandle);
 
-    ventoy_debug_pause();
-    
-    ventoy_install_blockio(ImageHandle);
+        if (gLoadIsoEfi)
+        {
+            ventoy_find_iso_disk_fs(ImageHandle);
+            ventoy_load_isoefi_driver(ImageHandle);
+        }
 
-    ventoy_debug_pause();
+        ventoy_debug_pause();
+        
+        ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
 
-    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_debug_pause();
 
-    ventoy_clean_env();
+        Status = ventoy_boot(ImageHandle);
+        if (EFI_NOT_FOUND == Status)
+        {
+            if (!gLoadIsoEfi)
+            {
+                gLoadIsoEfi = TRUE;
+                ventoy_find_iso_disk_fs(ImageHandle);
+                ventoy_load_isoefi_driver(ImageHandle);
 
-    ventoy_clear_input();
-    gST->ConOut->ClearScreen(gST->ConOut);
+                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();
+    }
     
+    ventoy_clear_input();
+    gST->ConOut->ClearScreen(gST->ConOut);
 
     return EFI_SUCCESS;
 }