]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - EDK2/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
1.0.04 release
[Ventoy.git] / EDK2 / edk2-edk2-stable201911 / MdeModulePkg / Application / Ventoy / Ventoy.c
index d3c8216b67558b872810221d158f8e35a92cbef0..dc73764d9fe8663c6bd6e2ce524b385637ede2ac 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;
@@ -353,6 +357,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 +520,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 +574,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 +582,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 +590,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 +886,7 @@ static int ventoy_update_image_location(ventoy_os_param *param)
 STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
 {   
     UINT32 i = 0;
+    UINTN size = 0;
     UINT8 chksum = 0;
     CHAR16 *pPos = NULL;
     CHAR16 *pCmdLine = NULL;
@@ -866,32 +926,44 @@ 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;
 
-
     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++)
-    {
-        chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
-    }
+    debug("memory addr:%p size:%lu", g_chain, size);
 
-    if (gDebugPrint)
+    if (StrStr(pCmdLine, L"memdisk"))
     {
-        debug("os param checksum: 0x%x %a", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
+        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);
+        }
 
-    ventoy_update_image_location(&(g_chain->os_param));
+        if (gDebugPrint)
+        {
+            debug("os param checksum: 0x%x %a", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
+        }
 
-    if (gDebugPrint)
-    {
-        ventoy_dump_chain(g_chain);
+        ventoy_update_image_location(&(g_chain->os_param));
+
+        if (gDebugPrint)
+        {
+            ventoy_dump_chain(g_chain);
+        }
     }
 
     FreePool(pCmdLine);
@@ -974,6 +1046,7 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
         if (EFI_ERROR(Status))
         {
             debug("Failed to start image %r", Status);
+            sleep(3);
             gBS->UnloadImage(Image);
             break;
         }
@@ -1016,8 +1089,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,36 +1151,56 @@ 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)
+        {
+            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_clean_env();
+    }
+    
     ventoy_clear_input();
     gST->ConOut->ClearScreen(gST->ConOut);
 
-    
-
     return EFI_SUCCESS;
 }