From 8632e565617ce5454729ebaae9eed17fe872513b Mon Sep 17 00:00:00 2001 From: longpanda Date: Wed, 20 Jan 2021 10:59:21 +0800 Subject: [PATCH] add vdiskchain module --- EDK2/build.sh | 59 +++ .../Application/VDiskChain/VDiskChain.c | 410 ++++++++++++++++++ .../Application/VDiskChain/VDiskChain.h | 97 +++++ .../Application/VDiskChain/VDiskChain.inf | 82 ++++ .../VDiskChain/VDiskChainProtocol.c | 264 +++++++++++ .../Application/VDiskChain/VDiskRawData.c | 1 + .../MdeModulePkg/MdeModulePkg.dsc | 1 + 7 files changed, 914 insertions(+) create mode 100644 EDK2/build.sh create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.h create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.inf create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskRawData.c diff --git a/EDK2/build.sh b/EDK2/build.sh new file mode 100644 index 00000000..63227643 --- /dev/null +++ b/EDK2/build.sh @@ -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 index 00000000..6c8a2ce5 --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c @@ -0,0 +1,410 @@ +/****************************************************************************** + * VDiskChain.c + * + * Copyright (c) 2021, longpanda + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..d4d21d00 --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * VDiskChain.h + * + * Copyright (c) 2021, longpanda + * + * 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 . + * + */ + +#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 index 00000000..2f8cfefe --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.inf @@ -0,0 +1,82 @@ +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VDiskChain + FILE_GUID = 5bce96e3-ba11-4440-833b-299cf5849193 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = VDiskChainEfiMain + + +[Sources] + VDiskChain.h + VDiskChain.c + VDiskRawData.c + VDiskChainProtocol.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + DebugLib + UefiDecompressLib + +[Guids] + gShellVariableGuid + gEfiVirtualCdGuid + gEfiFileInfoGuid + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiRamDiskProtocolGuid + gEfiAbsolutePointerProtocolGuid + gEfiAcpiTableProtocolGuid + gEfiBlockIo2ProtocolGuid + gEfiBusSpecificDriverOverrideProtocolGuid + gEfiComponentNameProtocolGuid + gEfiComponentName2ProtocolGuid + gEfiDriverBindingProtocolGuid + gEfiDiskIoProtocolGuid + gEfiDiskIo2ProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiHiiConfigAccessProtocolGuid + gEfiHiiFontProtocolGuid + gEfiLoadFileProtocolGuid + gEfiLoadFile2ProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiLoadedImageDevicePathProtocolGuid + gEfiPciIoProtocolGuid + gEfiSerialIoProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextInputExProtocolGuid + gEfiSimpleTextOutProtocolGuid + + + + + + 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 index 00000000..a6a6ad0b --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c @@ -0,0 +1,264 @@ +/****************************************************************************** + * VDiskChainProtocol.c + * + * Copyright (c) 2021, longpanda + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..190a1803 --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskRawData.c @@ -0,0 +1 @@ +123 diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc index f47ea6fb..c27b6d17 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc @@ -205,6 +205,7 @@ [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