]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
add vdiskchain module
authorlongpanda <admin@ventoy.net>
Wed, 20 Jan 2021 02:59:21 +0000 (10:59 +0800)
committerlongpanda <admin@ventoy.net>
Wed, 20 Jan 2021 02:59:21 +0000 (10:59 +0800)
EDK2/build.sh [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.h [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.inf [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskRawData.c [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc

diff --git a/EDK2/build.sh b/EDK2/build.sh
new file mode 100644 (file)
index 0000000..6322764
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+if [ -z "$1" ]; then
+    EDKARCH=X64
+    postfix=x64
+elif [ "$1" = "ia32" ]; then
+    EDKARCH=IA32
+    postfix=ia32
+    shift
+elif [ "$1" = "aa64" ]; then
+    EDKARCH=AARCH64
+    postfix=aa64
+    shift
+fi
+
+cd edk2-edk2-stable201911
+
+rm -rf ./Conf/.cache
+rm -f ./Conf/.AutoGenIdFile.txt
+
+VTEFI_PATH=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/Ventoy/Ventoy/OUTPUT/Ventoy.efi
+DST_PATH=../../INSTALL/ventoy/ventoy_${postfix}.efi
+
+VTEFI_PATH2=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VtoyUtil/VtoyUtil/OUTPUT/VtoyUtil.efi
+DST_PATH2=../../INSTALL/ventoy/vtoyutil_${postfix}.efi
+
+VTEFI_PATH3=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VDiskChain/VDiskChain/OUTPUT/VDiskChain.efi
+DST_PATH3=../../VDiskChain/Tool/vdiskchain_${postfix}.efi
+
+
+rm -f $VTEFI_PATH
+rm -f $DST_PATH
+rm -f $VTEFI_PATH2
+rm -f $DST_PATH2
+rm -f $VTEFI_PATH3
+rm -f $DST_PATH3
+
+source ./edksetup.sh
+
+if [ "$EDKARCH" = "AARCH64" ]; then    
+    PATH=$PATH:/opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin \
+    GCC48_AARCH64_PREFIX=aarch64-linux-gnu- \
+    build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
+else
+    build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
+fi
+
+if [ -e $VTEFI_PATH ] && [ -e $VTEFI_PATH2 ] && [ -e $VTEFI_PATH3 ]; then
+    echo -e '\n\n====================== SUCCESS ========================\n\n'    
+    cp -a $VTEFI_PATH $DST_PATH
+    cp -a $VTEFI_PATH2 $DST_PATH2
+    cp -a $VTEFI_PATH3 $DST_PATH3
+    cd ..
+else
+    echo -e '\n\n====================== FAILED ========================\n\n'
+    cd ..
+    exit 1
+fi
+
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c
new file mode 100644 (file)
index 0000000..6c8a2ce
--- /dev/null
@@ -0,0 +1,410 @@
+/******************************************************************************
+ * VDiskChain.c
+ *
+ * Copyright (c) 2021, longpanda <admin@ventoy.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <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 <Library/UefiDecompressLib.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 <VDiskChain.h>
+
+BOOLEAN gVDiskDebugPrint = FALSE;
+vdisk_block_data gVDiskBlockData;
+
+/* Boot filename */
+CONST CHAR16 *gEfiBootFileName[] = 
+{
+    L"@",
+    EFI_REMOVABLE_MEDIA_FILE_NAME,
+#if   defined (MDE_CPU_IA32)
+    L"\\EFI\\BOOT\\GRUBIA32.EFI",
+    L"\\EFI\\BOOT\\BOOTia32.EFI",
+    L"\\EFI\\BOOT\\bootia32.efi",
+    L"\\efi\\boot\\bootia32.efi",
+#elif defined (MDE_CPU_X64)
+    L"\\EFI\\BOOT\\GRUBX64.EFI",
+    L"\\EFI\\BOOT\\BOOTx64.EFI",
+    L"\\EFI\\BOOT\\bootx64.efi",
+    L"\\efi\\boot\\bootx64.efi",
+#elif defined (MDE_CPU_ARM)
+    L"\\EFI\\BOOT\\GRUBARM.EFI",
+    L"\\EFI\\BOOT\\BOOTarm.EFI",
+    L"\\EFI\\BOOT\\bootarm.efi",
+    L"\\efi\\boot\\bootarm.efi",
+#elif defined (MDE_CPU_AARCH64)
+    L"\\EFI\\BOOT\\GRUBAA64.EFI",
+    L"\\EFI\\BOOT\\BOOTaa64.EFI",
+    L"\\EFI\\BOOT\\bootaa64.efi",
+    L"\\efi\\boot\\bootaa64.efi",
+#endif
+    
+};
+
+UINT8 *g_disk_buf_addr = NULL;
+UINT64 g_disk_buf_size = 0;
+        
+VOID EFIAPI VDiskDebug(IN CONST CHAR8  *Format, ...)
+{
+    VA_LIST  Marker;
+    CHAR16   Buffer[512];
+
+    VA_START (Marker, Format);
+    UnicodeVSPrintAsciiFormat(Buffer, sizeof(Buffer), Format, Marker);
+    VA_END (Marker);
+    
+    gST->ConOut->OutputString(gST->ConOut, Buffer);
+}
+
+VOID EFIAPI vdisk_clear_input(VOID)
+{
+    EFI_INPUT_KEY Key;
+    
+    gST->ConIn->Reset(gST->ConIn, FALSE);
+    while (EFI_SUCCESS == gST->ConIn->ReadKeyStroke(gST->ConIn, &Key))
+    {
+        ;
+    }
+    gST->ConIn->Reset(gST->ConIn, FALSE);
+}
+
+STATIC EFI_STATUS EFIAPI vdisk_load_image
+(
+    IN EFI_HANDLE ImageHandle,
+    IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
+    IN CONST CHAR16 *FileName,
+    IN UINTN FileNameLen,
+    OUT EFI_HANDLE *Image
+)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    CHAR16 TmpBuf[256] = {0};
+    FILEPATH_DEVICE_PATH *pFilePath = NULL;
+    EFI_DEVICE_PATH_PROTOCOL *pImgPath = NULL;
+
+    pFilePath = (FILEPATH_DEVICE_PATH *)TmpBuf;
+    pFilePath->Header.Type = MEDIA_DEVICE_PATH;
+    pFilePath->Header.SubType = MEDIA_FILEPATH_DP;
+    pFilePath->Header.Length[0] = FileNameLen + sizeof(EFI_DEVICE_PATH_PROTOCOL);
+    pFilePath->Header.Length[1] = 0;
+    CopyMem(pFilePath->PathName, FileName, FileNameLen);
+    
+    pImgPath = AppendDevicePathNode(pDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)pFilePath);
+    if (!pImgPath)
+    {
+        return EFI_NOT_FOUND;
+    }
+    
+    Status = gBS->LoadImage(FALSE, ImageHandle, pImgPath, NULL, 0, Image);
+    
+    debug("Load Image File %r DP: <%s>", Status, ConvertDevicePathToText(pImgPath, FALSE, FALSE));
+
+    FreePool(pImgPath);
+    
+    return Status;
+}
+
+STATIC EFI_STATUS EFIAPI vdisk_decompress_vdisk(IN EFI_LOADED_IMAGE_PROTOCOL *pImageInfo)
+{
+    UINT32 Size;
+    UINT32 DestinationSize;
+    UINT32 ScratchSize;
+    UINT8 *buf;
+    VOID  *ScratchBuf;
+    EFI_STATUS Status = EFI_SUCCESS;
+
+    (VOID)pImageInfo;
+
+    vdisk_get_vdisk_raw(&buf, &Size);
+    UefiDecompressGetInfo(buf + VDISK_MAGIC_LEN, Size - VDISK_MAGIC_LEN, &DestinationSize, &ScratchSize);
+    debug("vdisk: size:%u realsize:%u", Size, DestinationSize);
+
+    g_disk_buf_size = DestinationSize;
+    g_disk_buf_addr = AllocatePool(DestinationSize);
+    ScratchBuf = AllocatePool(ScratchSize);
+    
+    Status = UefiDecompress(buf + VDISK_MAGIC_LEN, g_disk_buf_addr, ScratchBuf);
+    FreePool(ScratchBuf);
+
+    debug("Status:%r %p %u", Status, g_disk_buf_addr, (UINT32)g_disk_buf_size);
+    
+    return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS vdisk_patch_vdisk_path(CHAR16 *pos)
+{
+    UINTN i;
+    UINTN j;
+    CHAR16 *end;
+    CHAR8 *buf = (char *)g_disk_buf_addr;
+    
+    if (*pos == L'\"')
+    {
+        pos++;
+    }
+
+    end = StrStr(pos, L".vtoy");
+    end += 5;//string length
+    
+    for (i = 0; i < g_disk_buf_size; i++)
+    {
+        if (*(UINT32 *)(buf + i) == 0x59595959)
+        {
+            for (j = 0; j < 300; j++)
+            {
+                if (buf[i + j] != 'Y')
+                {
+                    break;
+                }
+            }
+
+            if (j >= 300)
+            {
+                break; 
+            }
+        }
+    }
+
+    if (i >= g_disk_buf_size)
+    {
+        debug("No need to fill vdisk path");
+        return 0;
+    }
+
+    debug("Fill vdisk path at %d", i);        
+
+    while (pos != end)
+    {
+        buf[i++] = (CHAR8)(*pos++);
+    }
+
+    buf[i++] = '\"';
+    
+    while (buf[i] == 'Y' || buf[i] == '\"')
+    {
+        buf[i] = ' ';
+        i++;
+    }   
+
+    return 0;    
+}
+
+STATIC EFI_STATUS EFIAPI vdisk_parse_cmdline(IN EFI_HANDLE ImageHandle)
+{   
+    CHAR16 *Pos = NULL;
+    CHAR16 *pCmdLine = NULL;
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
+
+    Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
+    if (EFI_ERROR(Status))
+    {
+        VDiskDebug("Failed to handle load image protocol %r\n", Status);
+        return Status;
+    }
+
+    pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
+    SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
+    CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
+
+    if (StrStr(pCmdLine, L"debug"))
+    {
+        gVDiskDebugPrint = TRUE;
+    }
+    
+    debug("cmdline:<%s>", pCmdLine);
+    vdisk_debug_pause();
+
+    Pos = StrStr(pCmdLine, L"vdisk=");
+    if (NULL == Pos || NULL == StrStr(pCmdLine, L".vtoy"))
+    {
+        VDiskDebug("vdisk parameter not found!\n");
+        return EFI_NOT_FOUND;
+    }
+
+    vdisk_decompress_vdisk(pImageInfo);
+
+    vdisk_patch_vdisk_path(Pos + 6);
+
+    FreePool(pCmdLine);
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI vdisk_boot(IN EFI_HANDLE ImageHandle)
+{
+    UINTN t = 0;
+    UINTN i = 0;
+    UINTN j = 0;
+    UINTN Find = 0;
+    UINTN Count = 0;
+    EFI_HANDLE Image = NULL;
+    EFI_HANDLE *Handles = NULL;
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
+    EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
+
+    for (t = 0; t < 3; t++)
+    {
+        Count = 0;
+        Handles = NULL;
+
+        Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 
+                                     NULL, &Count, &Handles);
+        if (EFI_ERROR(Status))
+        {
+            return Status;
+        }
+
+        debug("vdisk_boot fs count:%u", Count);
+
+        for (i = 0; i < Count; i++)
+        {
+            Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
+            if (EFI_ERROR(Status))
+            {
+                continue;
+            }
+
+            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))
+            {
+                debug("Failed to open device path protocol %r", Status);
+                continue;
+            }
+
+            debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
+            if (CompareMem(gVDiskBlockData.Path, pDevPath, gVDiskBlockData.DevicePathCompareLen))
+            {
+                debug("Not ventoy disk file system");
+                continue;
+            }
+
+            for (j = 1; j < ARRAY_SIZE(gEfiBootFileName); j++)
+            {
+                Status = vdisk_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 (j >= ARRAY_SIZE(gEfiBootFileName))
+            {
+                continue;
+            }
+
+            Find++;
+            debug("Find boot file, now try to boot .....");
+            vdisk_debug_pause();
+
+            if (gVDiskDebugPrint)
+            {
+                gST->ConIn->Reset(gST->ConIn, FALSE);
+            }
+
+            /* can't add debug print here */
+            //ventoy_wrapper_system();
+            Status = gBS->StartImage(Image, NULL, NULL);
+            if (EFI_ERROR(Status))
+            {
+                debug("Failed to start image %r", Status);
+                sleep(3);
+                gBS->UnloadImage(Image);
+                break;
+            }
+        }
+
+        FreePool(Handles);
+
+        if (Find == 0)
+        {
+            debug("Fs not found, now wait and retry...");
+            sleep(2);
+        }
+    }
+
+    if (Find == 0)
+    {
+        return EFI_NOT_FOUND;
+    }
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI VDiskChainEfiMain
+(
+    IN EFI_HANDLE         ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+
+    gST->ConOut->ClearScreen(gST->ConOut);
+    vdisk_clear_input();
+
+    Status = vdisk_parse_cmdline(ImageHandle);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+
+    vdisk_install_blockio(ImageHandle, g_disk_buf_size);
+    vdisk_debug_pause();
+
+    Status = vdisk_boot(ImageHandle);
+    
+    gBS->DisconnectController(gVDiskBlockData.Handle, NULL, NULL);
+    gBS->UninstallMultipleProtocolInterfaces(gVDiskBlockData.Handle,
+            &gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
+            &gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
+            NULL);
+
+    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);
+    }
+    
+    vdisk_clear_input();
+    gST->ConOut->ClearScreen(gST->ConOut);
+
+    return EFI_SUCCESS;
+}
+
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.h b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.h
new file mode 100644 (file)
index 0000000..d4d21d0
--- /dev/null
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * VDiskChain.h
+ *
+ * Copyright (c) 2021, longpanda <admin@ventoy.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef __VENTOY_H__
+#define __VENTOY_H__
+
+#define VDISK_MAGIC_LEN  32
+
+#define VDISK_BLOCK_DEVICE_PATH_GUID                                   \
+       { 0x6ed2134e, 0xc2ea, 0x4943, { 0x99, 0x54, 0xa7, 0x76, 0xe5, 0x9c, 0x12, 0xc3 }}
+
+#define VDISK_BLOCK_DEVICE_PATH_NAME  L"vdisk"
+
+#if   defined (MDE_CPU_IA32)
+  #define VENTOY_UEFI_DESC   L"IA32 UEFI"
+#elif defined (MDE_CPU_X64)
+  #define VENTOY_UEFI_DESC   L"X64 UEFI"
+#elif defined (MDE_CPU_EBC)
+#elif defined (MDE_CPU_ARM)
+  #define VENTOY_UEFI_DESC   L"ARM UEFI"
+#elif defined (MDE_CPU_AARCH64)
+  #define VENTOY_UEFI_DESC   L"ARM64 UEFI"
+#else
+  #error Unknown Processor Type
+#endif
+
+typedef struct vdisk_block_data 
+{
+       EFI_HANDLE Handle;
+       EFI_BLOCK_IO_MEDIA Media;       /* Media descriptor */
+       EFI_BLOCK_IO_PROTOCOL BlockIo;  /* Block I/O protocol */
+
+    UINTN DevicePathCompareLen;
+       EFI_DEVICE_PATH_PROTOCOL *Path; /* Device path protocol */
+
+    EFI_HANDLE RawBlockIoHandle;
+    EFI_BLOCK_IO_PROTOCOL *pRawBlockIo;
+    EFI_DEVICE_PATH_PROTOCOL *pDiskDevPath;
+
+    /* ventoy disk part2 ESP */
+    EFI_HANDLE DiskFsHandle;
+    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
+    EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
+
+    EFI_HANDLE IsoDriverImage;
+}vdisk_block_data;
+
+
+#define debug(expr, ...) if (gVDiskDebugPrint) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
+#define trace(expr, ...) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
+#define sleep(sec) gBS->Stall(1000000 * (sec))
+
+#define vdisk_debug_pause() \
+if (gVDiskDebugPrint) \
+{ \
+    UINTN __Index = 0; \
+    gST->ConOut->OutputString(gST->ConOut, L"[VDISK] ###### Press Enter to continue... ######\r\n");\
+    gST->ConIn->Reset(gST->ConIn, FALSE); \
+    gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
+}
+
+extern BOOLEAN gVDiskDebugPrint;
+VOID EFIAPI VDiskDebug(IN CONST CHAR8  *Format, ...);
+EFI_STATUS EFIAPI vdisk_block_io_read 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN UINT32                          MediaId,
+    IN EFI_LBA                         Lba,
+    IN UINTN                           BufferSize,
+    OUT VOID                          *Buffer
+);
+
+extern UINT8 *g_disk_buf_addr;
+extern UINT64 g_disk_buf_size;
+extern vdisk_block_data gVDiskBlockData;
+EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
+int vdisk_get_vdisk_raw(UINT8 **buf, UINT32 *size);
+
+#endif
+
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.inf b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.inf
new file mode 100644 (file)
index 0000000..2f8cfef
--- /dev/null
@@ -0,0 +1,82 @@
+#************************************************************************************\r
+# Copyright (c) 2020, longpanda <admin@ventoy.net>\r
+# \r
+# This program is free software; you can redistribute it and/or\r
+# modify it under the terms of the GNU General Public License as\r
+# published by the Free Software Foundation; either version 3 of the\r
+# License, or (at your option) any later version.\r
+# \r
+# This program is distributed in the hope that it will be useful, but\r
+# WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+# General Public License for more details.\r
+# \r
+# You should have received a copy of the GNU General Public License\r
+# along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+# \r
+#************************************************************************************\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = VDiskChain\r
+  FILE_GUID                      = 5bce96e3-ba11-4440-833b-299cf5849193\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = VDiskChainEfiMain\r
+\r
+\r
+[Sources]\r
+  VDiskChain.h\r
+  VDiskChain.c\r
+  VDiskRawData.c\r
+  VDiskChainProtocol.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiApplicationEntryPoint\r
+  UefiLib\r
+  DebugLib\r
+  UefiDecompressLib\r
+\r
+[Guids]\r
+  gShellVariableGuid\r
+  gEfiVirtualCdGuid\r
+  gEfiFileInfoGuid\r
+  \r
+[Protocols]\r
+  gEfiLoadedImageProtocolGuid\r
+  gEfiBlockIoProtocolGuid\r
+  gEfiDevicePathProtocolGuid\r
+  gEfiSimpleFileSystemProtocolGuid\r
+  gEfiRamDiskProtocolGuid\r
+  gEfiAbsolutePointerProtocolGuid\r
+  gEfiAcpiTableProtocolGuid\r
+  gEfiBlockIo2ProtocolGuid\r
+  gEfiBusSpecificDriverOverrideProtocolGuid\r
+  gEfiComponentNameProtocolGuid\r
+  gEfiComponentName2ProtocolGuid\r
+  gEfiDriverBindingProtocolGuid\r
+  gEfiDiskIoProtocolGuid\r
+  gEfiDiskIo2ProtocolGuid\r
+  gEfiGraphicsOutputProtocolGuid\r
+  gEfiHiiConfigAccessProtocolGuid\r
+  gEfiHiiFontProtocolGuid\r
+  gEfiLoadFileProtocolGuid\r
+  gEfiLoadFile2ProtocolGuid\r
+  gEfiLoadedImageProtocolGuid\r
+  gEfiLoadedImageDevicePathProtocolGuid\r
+  gEfiPciIoProtocolGuid\r
+  gEfiSerialIoProtocolGuid\r
+  gEfiSimpleTextInProtocolGuid\r
+  gEfiSimpleTextInputExProtocolGuid\r
+  gEfiSimpleTextOutProtocolGuid\r
+  \r
+  \r
+  \r
+  \r
+  \r
+  \r
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c
new file mode 100644 (file)
index 0000000..a6a6ad0
--- /dev/null
@@ -0,0 +1,264 @@
+/******************************************************************************
+ * VDiskChainProtocol.c
+ *
+ * Copyright (c) 2021, longpanda <admin@ventoy.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <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 <VDiskChain.h>
+
+/* EFI block device vendor device path GUID */
+EFI_GUID gVDiskBlockDevicePathGuid = VDISK_BLOCK_DEVICE_PATH_GUID;
+
+EFI_STATUS EFIAPI vdisk_block_io_reset 
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN BOOLEAN                        ExtendedVerification
+) 
+{
+    (VOID)This;
+    (VOID)ExtendedVerification;
+       return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI vdisk_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+       (VOID)This;
+       return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI vdisk_block_io_read
+(
+    IN EFI_BLOCK_IO_PROTOCOL          *This,
+    IN UINT32                          MediaId,
+    IN EFI_LBA                         Lba,
+    IN UINTN                           BufferSize,
+    OUT VOID                          *Buffer
+)
+{
+    (VOID)This;
+    (VOID)MediaId;
+
+    debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
+    CopyMem(Buffer, g_disk_buf_addr + (Lba * 512), BufferSize);
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI vdisk_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)Buffer;
+
+    debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
+    return EFI_WRITE_PROTECTED;
+}
+
+EFI_STATUS EFIAPI vdisk_fill_device_path(VOID)
+{
+    UINTN NameLen = 0;
+    UINT8 TmpBuf[128] = {0};
+    VENDOR_DEVICE_PATH *venPath = NULL;
+
+    venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
+    NameLen = StrSize(VDISK_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, &gVDiskBlockDevicePathGuid, sizeof(EFI_GUID));
+    CopyMem(venPath + 1, VDISK_BLOCK_DEVICE_PATH_NAME, NameLen);
+    
+    gVDiskBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
+    gVDiskBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
+
+    debug("gVDiskBlockData.Path=<%s>\n", ConvertDevicePathToText(gVDiskBlockData.Path, FALSE, FALSE));
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI vdisk_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("vdisk_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("vdisk_connect_driver:<%s> <%r>", DrvName, 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("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
+        goto end;
+    }
+
+    Status = EFI_NOT_FOUND;
+    
+end:
+    FreePool(Handles);
+    
+    return Status;
+}
+
+EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
+{   
+    EFI_STATUS Status = EFI_SUCCESS;
+    EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gVDiskBlockData.BlockIo);
+    
+    vdisk_fill_device_path();
+
+    debug("install block io protocol %p", ImageHandle);
+    vdisk_debug_pause();
+
+    gVDiskBlockData.Media.BlockSize = 512;
+    gVDiskBlockData.Media.LastBlock = ImgSize / 512 - 1;
+    gVDiskBlockData.Media.ReadOnly = TRUE;
+    gVDiskBlockData.Media.MediaPresent = 1;
+    gVDiskBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
+
+       pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+       pBlockIo->Media = &(gVDiskBlockData.Media);
+       pBlockIo->Reset = vdisk_block_io_reset;
+    pBlockIo->ReadBlocks = vdisk_block_io_read;
+       pBlockIo->WriteBlocks = vdisk_block_io_write;
+       pBlockIo->FlushBlocks = vdisk_block_io_flush;
+
+    Status = gBS->InstallMultipleProtocolInterfaces(&gVDiskBlockData.Handle,
+            &gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
+            &gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
+            NULL);
+    debug("Install protocol %r %p", Status, gVDiskBlockData.Handle);
+    if (EFI_ERROR(Status))
+    {
+        return Status;
+    }
+
+    Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Disk I/O Driver");
+    debug("Connect disk IO driver %r", Status);
+
+    Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Partition Driver");
+    debug("Connect partition driver %r", Status);
+    if (EFI_ERROR(Status))
+    {
+        Status = gBS->ConnectController(gVDiskBlockData.Handle, NULL, NULL, TRUE);
+        debug("Connect all controller %r", Status);
+    }
+
+    vdisk_debug_pause();
+
+    return EFI_SUCCESS;
+}
+
diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskRawData.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskRawData.c
new file mode 100644 (file)
index 0000000..190a180
--- /dev/null
@@ -0,0 +1 @@
+123
index f47ea6fbe5eb2bbd06b3ed3a97d029b891dc3333..c27b6d17b98d5bf33047cedb342652c83b24c556 100644 (file)
 [Components]
   MdeModulePkg/Application/Ventoy/Ventoy.inf
   MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
 [Components]
   MdeModulePkg/Application/Ventoy/Ventoy.inf
   MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
+  MdeModulePkg/Application/VDiskChain/VDiskChain.inf
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf
   MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
   MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf
   MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
   MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf