Initial commit from Ventoy@7cbdc5c

This commit is contained in:
2026-08-23 00:38:40 -04:00
commit e9a7a16826
2848 changed files with 439164 additions and 0 deletions
+59
View File
@@ -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
[ -d ../../VDiskChain ] && rm -f $DST_PATH3
unset WORKSPACE
source ./edksetup.sh
if [ "$EDKARCH" = "AARCH64" ]; then
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
[ -d ../../VDiskChain ] && cp -a $VTEFI_PATH3 $DST_PATH3
cd ..
else
echo -e '\n\n====================== FAILED ========================\n\n'
cd ..
exit 1
fi
+113
View File
@@ -0,0 +1,113 @@
#!/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/VtoyShim/VtoyShim/OUTPUT/VtoyShim.efi
DST_PATH=../../INSTALL/EFI/BOOT/fb${postfix}.efi
rm -f $VTEFI_PATH
rm -f $DST_PATH
unset WORKSPACE
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 -m MdeModulePkg/Application/VtoyShim/VtoyShim.inf
else
build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48 -m MdeModulePkg/Application/VtoyShim/VtoyShim.inf
fi
if [ -e $VTEFI_PATH ]; then
objdump -h "$VTEFI_PATH"
echo ""
objcopy \
--add-section .sbat="MdeModulePkg/Application/VtoyShim/sbat.csv" \
--set-section-flags .sbat=alloc,load,readonly,data \
"$VTEFI_PATH" "$DST_PATH"
#find the right sbat section VMA
tmpfile=$(mktemp)
cnt1=$(objdump -h "$DST_PATH" | grep -P '^\s*[0-9][0-9]* \.' | wc -l)
cnt2=$(objdump -h "$DST_PATH" | grep -P 'ALLOC' | wc -l)
if [ $cnt1 -ne $cnt2 ]; then
echo "Section count mismatch $cnt1 $cnt2"
objdump -h "$DST_PATH"
exit 1
fi
objdump -h "$DST_PATH" | grep -P '^\s*[0-9][0-9]* \.' > $tmpfile
sbat_size=$(stat -c '%s' MdeModulePkg/Application/VtoyShim/sbat.csv)
sbat_size_hex=$(printf '0x%08x' $sbat_size)
lmax='0000000000000000'
lsize='0000000000000000'
while read line; do
echo $line
lbase=$(echo $line | awk '{print $4}')
if expr "$lmax" \< "$lbase" > /dev/null; then
lmax=$lbase
lsize=$(echo $line | awk '{print $3}')
fi
echo "max=$lmax size=$lsize"
done < $tmpfile
rm -f $tmpfile
lvma=$((0x${lsize}+0x${lmax}))
lvma_align=`printf '0x%08x' $(( (lvma + 4095) / 4096 * 4096 ))`
echo "sbat section lvma_align=$lvma_align"
objcopy --adjust-section-vma .sbat=$lvma_align "$DST_PATH"
img_base=$(objdump -p "$DST_PATH" | grep ImageBase | awk '{print $2}')
size_img=0x$(objdump -p "$DST_PATH" | grep SizeOfImage | awk '{print $2}')
sbat_end=`printf '0x%08x' $(($lvma_align+$sbat_size_hex))`
if [ "$img_base" != "0000000000000000" ]; then
echo "#### ImageBase is not 0 $img_base"
exit 1
fi
echo "size_img=$size_img sbat_size=$sbat_size_hex sbat_range $lvma_align - $sbat_end"
if expr "$size_img" \< "$sbat_end" > /dev/null; then
echo "SizeOfImage $size_img less than sbat section addr $sbat_end"
exit 1
else
echo "SizeOfImage $size_img >= $sbat_end is OK"
fi
objdump -h "$DST_PATH"
echo -e '\n\n====================== SUCCESS ========================\n\n'
cd ..
else
echo -e '\n\n====================== FAILED ========================\n\n'
cd ..
exit 1
fi
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
rm -rf edk2-edk2-stable201911
unzip edk2-edk2-stable201911.zip > /dev/null
/bin/cp -a ./edk2_mod/edk2-edk2-stable201911 ./
cd edk2-edk2-stable201911
make -j 4 -C BaseTools/
cd ..
echo '======== build EDK2 for i386-efi ==============='
sh ./build.sh ia32 || exit 1
echo '======== build EDK2 for arm64-efi ==============='
sh ./build.sh aa64 || exit 1
echo '======== build EDK2 for x86_64-efi ==============='
sh ./build.sh || exit 1
echo '======== build EDK2 for x86_64-efi ==============='
sh ./build_shim.sh || exit 1
@@ -0,0 +1,472 @@
/******************************************************************************
* VDiskChain.c
*
* Copyright (c) 2021, longpanda <[email protected]>
*
* 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;
STATIC EFI_GET_VARIABLE g_org_get_variable = NULL;
STATIC EFI_EXIT_BOOT_SERVICES g_org_exit_boot_service = NULL;
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;
}
EFI_STATUS EFIAPI vdisk_get_variable_wrapper
(
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes, OPTIONAL
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
)
{
EFI_STATUS Status = EFI_SUCCESS;
Status = g_org_get_variable(VariableName, VendorGuid, Attributes, DataSize, Data);
if (StrCmp(VariableName, L"SecureBoot") == 0)
{
if ((*DataSize == 1) && Data)
{
*(UINT8 *)Data = 0;
}
}
return Status;
}
EFI_STATUS EFIAPI vdisk_exit_boot_service_wrapper
(
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
)
{
if (g_org_get_variable)
{
gRT->GetVariable = g_org_get_variable;
g_org_get_variable = NULL;
}
return g_org_exit_boot_service(ImageHandle, MapKey);
}
STATIC EFI_STATUS EFIAPI vdisk_disable_secure_boot(IN EFI_HANDLE ImageHandle)
{
/* step1: wrapper security protocol. */
/* Do we still need it since we have been loaded ? */
/* step2: fake SecureBoot variable */
g_org_exit_boot_service = gBS->ExitBootServices;
gBS->ExitBootServices = vdisk_exit_boot_service_wrapper;
g_org_get_variable = gRT->GetVariable;
gRT->GetVariable = vdisk_get_variable_wrapper;
return EFI_SUCCESS;
}
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);
if (StrStr(pCmdLine, L"secureboot=off"))
{
vdisk_disable_secure_boot(ImageHandle);
}
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;
}
@@ -0,0 +1,97 @@
/******************************************************************************
* VDiskChain.h
*
* Copyright (c) 2021, longpanda <[email protected]>
*
* 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
@@ -0,0 +1,82 @@
#************************************************************************************
# Copyright (c) 2020, longpanda <[email protected]>
#
# 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/>.
#
#************************************************************************************
[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
@@ -0,0 +1,264 @@
/******************************************************************************
* VDiskChainProtocol.c
*
* Copyright (c) 2021, longpanda <[email protected]>
*
* 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;
}
@@ -0,0 +1,2 @@
#include <Uefi.h>
int vdisk_get_vdisk_raw(UINT8 **buf, UINT32 *size) { *buf = NULL; *size = 0; return 0; }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,437 @@
/******************************************************************************
* Ventoy.h
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 COMPILE_ASSERT(expr) extern char __compile_assert[(expr) ? 1 : -1]
#define VTOY_SHIM_POLICY_GUID {0x90a29d14, 0x3968, 0x48fe, { 0x85, 0x81, 0x6b, 0x7f, 0x7d, 0xc4, 0x70, 0x55 }};
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
typedef enum ventoy_chain_type
{
ventoy_chain_linux = 0, /* 0: linux */
ventoy_chain_windows, /* 1: windows */
ventoy_chain_wim, /* 2: wim */
ventoy_chain_max
}ventoy_chain_type;
#pragma pack(1)
typedef struct ventoy_guid
{
UINT32 data1;
UINT16 data2;
UINT16 data3;
UINT8 data4[8];
}ventoy_guid;
typedef struct ventoy_image_disk_region
{
UINT32 image_sector_count; /* image sectors contained in this region */
UINT32 image_start_sector; /* image sector start */
UINT64 disk_start_sector; /* disk sector start */
}ventoy_image_disk_region;
typedef struct ventoy_image_location
{
ventoy_guid guid;
/* image sector size, currently this value is always 2048 */
UINT32 image_sector_size;
/* disk sector size, normally the value is 512 */
UINT32 disk_sector_size;
UINT32 region_count;
/*
* disk region data
* If the image file has more than one fragments in disk,
* there will be more than one region data here.
*
*/
ventoy_image_disk_region regions[1];
/* ventoy_image_disk_region regions[2~region_count-1] */
}ventoy_image_location;
typedef struct ventoy_os_param
{
ventoy_guid guid; // VENTOY_GUID
UINT8 chksum; // checksum
UINT8 vtoy_disk_guid[16];
UINT64 vtoy_disk_size; // disk size in bytes
UINT16 vtoy_disk_part_id; // begin with 1
UINT16 vtoy_disk_part_type; // 0:exfat 1:ntfs other: reserved
char vtoy_img_path[384]; // It seems to be enough, utf-8 format
UINT64 vtoy_img_size; // image file size in bytes
/*
* Ventoy will write a copy of ventoy_image_location data into runtime memory
* this is the physically address and length of that memory.
* Address 0 means no such data exist.
* Address will be aligned by 4KB.
*
*/
UINT64 vtoy_img_location_addr;
UINT32 vtoy_img_location_len;
UINT64 vtoy_reserved[4]; // Internal use by ventoy
UINT8 vtoy_disk_signature[4];
UINT8 reserved[27];
}ventoy_os_param;
#pragma pack()
// compile assert to check that size of ventoy_os_param must be 512
COMPILE_ASSERT(sizeof(ventoy_os_param) == 512);
#pragma pack(4)
typedef struct ventoy_chain_head
{
ventoy_os_param os_param;
UINT32 disk_drive;
UINT32 drive_map;
UINT32 disk_sector_size;
UINT64 real_img_size_in_bytes;
UINT64 virt_img_size_in_bytes;
UINT32 boot_catalog;
UINT8 boot_catalog_sector[2048];
UINT32 img_chunk_offset;
UINT32 img_chunk_num;
UINT32 override_chunk_offset;
UINT32 override_chunk_num;
UINT32 virt_chunk_offset;
UINT32 virt_chunk_num;
}ventoy_chain_head;
typedef struct ventoy_img_chunk
{
UINT32 img_start_sector; //2KB
UINT32 img_end_sector;
UINT64 disk_start_sector; // in disk_sector_size
UINT64 disk_end_sector;
}ventoy_img_chunk;
typedef struct ventoy_override_chunk
{
UINT64 img_offset;
UINT32 override_size;
UINT8 override_data[512];
}ventoy_override_chunk;
typedef struct ventoy_virt_chunk
{
UINT32 mem_sector_start;
UINT32 mem_sector_end;
UINT32 mem_sector_offset;
UINT32 remap_sector_start;
UINT32 remap_sector_end;
UINT32 org_sector_start;
}ventoy_virt_chunk;
#pragma pack()
#define VTOY_BLOCK_DEVICE_PATH_GUID \
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
#if defined (MDE_CPU_IA32)
#define VENTOY_UEFI_DESC L"IA32 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_ia32.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_ia32.efi"
#elif defined (MDE_CPU_X64)
#define VENTOY_UEFI_DESC L"X64 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_x64.efi"
#elif defined (MDE_CPU_EBC)
#elif defined (MDE_CPU_ARM)
#define VENTOY_UEFI_DESC L"ARM UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_arm.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_arm.efi"
#elif defined (MDE_CPU_AARCH64)
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_aa64.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_aa64.efi"
#else
#error Unknown Processor Type
#endif
#define VENTOY_DEVICE_WARN 1
#define VTOY_WARNING L"!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
typedef struct ventoy_sector_flag
{
UINT8 flag; // 0:init 1:mem 2:remap
UINT64 remap_lba;
}ventoy_sector_flag;
typedef struct vtoy_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;
}vtoy_block_data;
#define debug(expr, ...) if (gDebugPrint) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
#define trace(expr, ...) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
#define sleep(sec) gBS->Stall(1000000 * (sec))
#define ventoy_debug_pause() \
if (gDebugPrint) \
{ \
UINTN __Index = 0; \
gST->ConOut->OutputString(gST->ConOut, L"[VTOY] ###### Press Enter to continue... ######\r\n");\
gST->ConIn->Reset(gST->ConIn, FALSE); \
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
}
typedef int (*grub_env_set_pf)(const char *name, const char *val);
typedef const char * (*grub_env_get_pf)(const char *name);
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
#pragma pack(1)
#define VTOY_MAX_CONF_REPLACE 2
#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF
#define GRUB_IMG_REPLACE_MAGIC 0x1259BEEF
typedef struct ventoy_efi_file_replace
{
UINT64 BlockIoSectorStart;
UINT64 CurPos;
UINT64 FileSizeBytes;
EFI_FILE_PROTOCOL WrapperHandle;
}ventoy_efi_file_replace;
typedef struct ventoy_grub_param_file_replace
{
UINT32 magic;
char old_file_name[4][256];
UINT32 old_file_cnt;
UINT32 new_file_virtual_id;
}ventoy_grub_param_file_replace;
typedef struct ventoy_grub_param
{
grub_env_get_pf grub_env_get;
grub_env_set_pf grub_env_set;
ventoy_grub_param_file_replace file_replace;
ventoy_grub_param_file_replace img_replace[VTOY_MAX_CONF_REPLACE];
grub_env_printf_pf grub_env_printf;
}ventoy_grub_param;
typedef struct ventoy_ram_disk
{
UINT64 PhyAddr;
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;
typedef struct PART_TABLE
{
UINT8 Active; // 0x00 0x80
UINT8 StartHead;
UINT16 StartSector : 6;
UINT16 StartCylinder : 10;
UINT8 FsFlag;
UINT8 EndHead;
UINT16 EndSector : 6;
UINT16 EndCylinder : 10;
UINT32 StartSectorId;
UINT32 SectorCount;
}PART_TABLE;
typedef struct MBR_HEAD
{
UINT8 BootCode[446];
PART_TABLE PartTbl[4];
UINT8 Byte55;
UINT8 ByteAA;
}MBR_HEAD;
#pragma pack()
typedef struct well_known_guid
{
EFI_GUID *guid;
const char *name;
}well_known_guid;
typedef struct ventoy_system_wrapper
{
EFI_LOCATE_PROTOCOL NewLocateProtocol;
EFI_LOCATE_PROTOCOL OriLocateProtocol;
EFI_HANDLE_PROTOCOL NewHandleProtocol;
EFI_HANDLE_PROTOCOL OriHandleProtocol;
EFI_OPEN_PROTOCOL NewOpenProtocol;
EFI_OPEN_PROTOCOL OriOpenProtocol;
EFI_LOCATE_HANDLE_BUFFER NewLocateHandleBuffer;
EFI_LOCATE_HANDLE_BUFFER OriLocateHandleBuffer;
EFI_PROTOCOLS_PER_HANDLE NewProtocolsPerHandle;
EFI_PROTOCOLS_PER_HANDLE OriProtocolsPerHandle;
EFI_LOCATE_HANDLE NewLocateHandle;
EFI_LOCATE_HANDLE OriLocateHandle;
EFI_LOCATE_DEVICE_PATH NewLocateDevicePath;
EFI_LOCATE_DEVICE_PATH OriLocateDevicePath;
} ventoy_system_wrapper;
#define MAX_DRIVER_BIND_WRAPPER 64
typedef struct DriverBindWrapper
{
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
EFI_DRIVER_BINDING_SUPPORTED pfOldSupport;
}DRIVER_BIND_WRAPPER;
#define ventoy_wrapper(bs, wrapper, func, newfunc) \
{\
wrapper.Ori##func = bs->func;\
wrapper.New##func = newfunc;\
bs->func = wrapper.New##func;\
}
#define VENTOY_GET_COMPONENT_NAME(Protocol, DriverName) \
{\
DriverName = NULL;\
Status = Protocol->GetDriverName(Protocol, "en", &DriverName);\
if (EFI_ERROR(Status) || NULL == DriverName) \
{\
DriverName = NULL;\
Status = Protocol->GetDriverName(Protocol, "eng", &DriverName);\
if (EFI_ERROR(Status) || NULL == DriverName) \
{\
continue;\
}\
}\
}
extern BOOLEAN gDebugPrint;
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...);
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID);
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
);
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_efi_file_replace g_img_file_replace[VTOY_MAX_CONF_REPLACE];
extern ventoy_sector_flag *g_sector_flag;
extern UINT32 g_sector_flag_num;
extern BOOLEAN gMemdiskMode;
extern BOOLEAN gSector512Mode;
extern UINTN g_iso_buf_size;
extern UINT8 *g_iso_data_buf;
extern ventoy_grub_param_file_replace *g_file_replace_list;
extern ventoy_grub_param_file_replace *g_img_replace_list;
extern BOOLEAN g_fixup_iso9660_secover_enable;
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;
extern BOOLEAN g_fix_windows_1st_cdrom_issue;
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);
EFI_STATUS ventoy_hook_keyboard_start(VOID);
EFI_STATUS ventoy_hook_keyboard_stop(VOID);
BOOLEAN ventoy_is_cdrom_dp_exist(VOID);
EFI_STATUS ventoy_hook_1st_cdrom_start(VOID);
EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID);
EFI_STATUS ventoy_disable_ex_filesystem(VOID);
EFI_STATUS ventoy_enable_ex_filesystem(VOID);
EFI_STATUS ventoy_lock_res(UINT8 LockType);
EFI_STATUS ventoy_unlock_res(VOID);
#endif
@@ -0,0 +1,86 @@
#************************************************************************************
# Copyright (c) 2020, longpanda <[email protected]>
#
# 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/>.
#
#************************************************************************************
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Ventoy
FILE_GUID = 1c3a0915-09dc-49c2-873d-0aaaa7733299
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VentoyEfiMain
[BuildOptions]
# Force standard GNU ld to pack and align ELF segments to 4KB page boundaries
GCC:*_*_*_DLINK_FLAGS = -Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000
[Sources]
Ventoy.h
Ventoy.c
VentoyDebug.c
VentoyProtocol.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
DebugLib
[Guids]
gEfiGlobalVariableGuid
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
@@ -0,0 +1,229 @@
/******************************************************************************
* Ventoy.c
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 <Protocol/DriverBinding.h>
#include <Ventoy.h>
#define PROCOTOL_SLEEP_MSECONDS 0
#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS)
STATIC ventoy_system_wrapper g_system_wrapper;
static struct well_known_guid g_efi_well_known_guids[] =
{
{ &gEfiAbsolutePointerProtocolGuid, "AbsolutePointer" },
{ &gEfiAcpiTableProtocolGuid, "AcpiTable" },
{ &gEfiBlockIoProtocolGuid, "BlockIo" },
{ &gEfiBlockIo2ProtocolGuid, "BlockIo2" },
{ &gEfiBusSpecificDriverOverrideProtocolGuid, "BusSpecificDriverOverride" },
{ &gEfiComponentNameProtocolGuid, "ComponentName" },
{ &gEfiComponentName2ProtocolGuid, "ComponentName2" },
{ &gEfiDevicePathProtocolGuid, "DevicePath" },
{ &gEfiDriverBindingProtocolGuid, "DriverBinding" },
{ &gEfiDiskIoProtocolGuid, "DiskIo" },
{ &gEfiDiskIo2ProtocolGuid, "DiskIo2" },
{ &gEfiGraphicsOutputProtocolGuid, "GraphicsOutput" },
{ &gEfiHiiConfigAccessProtocolGuid, "HiiConfigAccess" },
{ &gEfiHiiFontProtocolGuid, "HiiFont" },
{ &gEfiLoadFileProtocolGuid, "LoadFile" },
{ &gEfiLoadFile2ProtocolGuid, "LoadFile2" },
{ &gEfiLoadedImageProtocolGuid, "LoadedImage" },
{ &gEfiLoadedImageDevicePathProtocolGuid, "LoadedImageDevicePath"},
{ &gEfiPciIoProtocolGuid, "PciIo" },
{ &gEfiSerialIoProtocolGuid, "SerialIo" },
{ &gEfiSimpleFileSystemProtocolGuid, "SimpleFileSystem" },
{ &gEfiSimpleTextInProtocolGuid, "SimpleTextInput" },
{ &gEfiSimpleTextInputExProtocolGuid, "SimpleTextInputEx" },
{ &gEfiSimpleTextOutProtocolGuid, "SimpleTextOutput" },
};
STATIC CHAR8 gEfiGuidName[128];
static const char * ventoy_get_guid_name(EFI_GUID *guid)
{
UINTN i;
for (i = 0; i < ARRAY_SIZE(g_efi_well_known_guids); i++)
{
if (CompareGuid(g_efi_well_known_guids[i].guid, guid))
{
return g_efi_well_known_guids[i].name;
}
}
AsciiSPrint(gEfiGuidName, sizeof(gEfiGuidName), "%g", guid);
return gEfiGuidName;
}
STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
)
{
EFI_STATUS Status = EFI_SUCCESS;
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
Status = g_system_wrapper.OriHandleProtocol(Handle, Protocol, Interface);
if (CompareGuid(Protocol, &gEfiSimpleFileSystemProtocolGuid))
{
EFI_FILE_PROTOCOL *FileProtocol = NULL;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = *((EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **)(Interface));
pFile->OpenVolume(pFile, &FileProtocol);
trace("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
pFile, pFile->OpenVolume, FileProtocol, FileProtocol->Open);
sleep(3);
}
return Status;
}
STATIC EFI_STATUS EFIAPI ventoy_open_protocol
(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface, OPTIONAL
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
)
{
debug("ventoy_open_protocol:<%p> %a", Handle, ventoy_get_guid_name(Protocol)); debug_sleep();
return g_system_wrapper.OriOpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes);
}
STATIC EFI_STATUS EFIAPI ventoy_locate_protocol
(
IN EFI_GUID *Protocol,
IN VOID *Registration, OPTIONAL
OUT VOID **Interface
)
{
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
return g_system_wrapper.OriLocateProtocol(Protocol, Registration, Interface);
}
STATIC EFI_STATUS EFIAPI ventoy_locate_handle_buffer
(
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol, OPTIONAL
IN VOID *SearchKey, OPTIONAL
IN OUT UINTN *NoHandles,
OUT EFI_HANDLE **Buffer
)
{
debug("ventoy_locate_handle_buffer:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
return g_system_wrapper.OriLocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer);
}
STATIC EFI_STATUS EFIAPI ventoy_protocol_per_handle
(
IN EFI_HANDLE Handle,
OUT EFI_GUID ***ProtocolBuffer,
OUT UINTN *ProtocolBufferCount
)
{
debug("ventoy_protocol_per_handle:%p", Handle); debug_sleep();
return g_system_wrapper.OriProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount);
}
EFI_STATUS EFIAPI ventoy_locate_handle
(
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol, OPTIONAL
IN VOID *SearchKey, OPTIONAL
IN OUT UINTN *BufferSize,
OUT EFI_HANDLE *Buffer
)
{
UINTN i;
EFI_HANDLE Handle;
EFI_STATUS Status = EFI_SUCCESS;
debug("ventoy_locate_handle: %d %a %p", SearchType, ventoy_get_guid_name(Protocol), SearchKey);
Status = g_system_wrapper.OriLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
debug("ventoy_locate_handle: %r Handle Count:%u", Status, *BufferSize/sizeof(EFI_HANDLE));
if (EFI_SUCCESS == Status)
{
for (i = 0; i < *BufferSize / sizeof(EFI_HANDLE); i++)
{
if (Buffer[i] == gBlockData.Handle)
{
Handle = Buffer[0];
Buffer[0] = Buffer[i];
Buffer[i] = Handle;
debug("####### Handle at %u", i);
break;
}
}
}
debug_sleep();
return Status;
}
STATIC EFI_STATUS EFIAPI ventoy_locate_device_path
(
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
OUT EFI_HANDLE *Device
)
{
debug("ventoy_locate_device_path:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
return g_system_wrapper.OriLocateDevicePath(Protocol, DevicePath, Device);
}
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID)
{
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
ventoy_wrapper(gBS, g_system_wrapper, LocateHandleBuffer, ventoy_locate_handle_buffer);
ventoy_wrapper(gBS, g_system_wrapper, ProtocolsPerHandle, ventoy_protocol_per_handle);
ventoy_wrapper(gBS, g_system_wrapper, LocateHandle, ventoy_locate_handle);
ventoy_wrapper(gBS, g_system_wrapper, LocateDevicePath, ventoy_locate_device_path);
return EFI_SUCCESS;
}
@@ -0,0 +1,665 @@
/******************************************************************************
* VtoyShim.c
*
* Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
*/
#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/PeCoffLib.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 <Protocol/DevicePathToText.h>
#include <Protocol/DevicePathFromText.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/Security.h>
#include <Protocol/Security2.h>
#include <IndustryStandard/PeImage.h>
#include <VtoyShim.h>
#define CUR_SBAT_VER 1
STATIC UINT8 gVtoyGrubSha256Hash[32] __attribute__((aligned(32))) = {
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26
};
STATIC BOOLEAN gGrubLaunched = FALSE;
STATIC EFI_GUID gShimLockGUID = SHIM_LOCK_GUID;
STATIC EFI_SECURITY_FILE_AUTHENTICATION_STATE gSysSecFileAuth = NULL;
STATIC EFI_SECURITY2_FILE_AUTHENTICATION gSysSec2FileAuth = NULL;
STATIC BOOLEAN gVtoyByPassSB = FALSE; /* must be FALSE by default for revoke */
STATIC VTOY_SHIM gVtoyShimProtocol;
STATIC EFI_HANDLE gVtoyShimProtHandle;
STATIC SHIM_LOCK gShimLock;
STATIC EFI_EXIT_BOOT_SERVICES gSysExitBootServices = NULL;
STATIC EFI_GET_VARIABLE gSysGetVariable = NULL;
STATIC VOID EFIAPI HookSystemService(VOID);
STATIC VOID EFIAPI UnHookSystemService(VOID);
STATIC VOID EFIAPI VtoyLog(CONST CHAR16 *Format, ...)
{
VA_LIST Marker;
CHAR16 Buffer[512];
UINTN BufLen = 0;
Buffer[0] = 0;
VA_START(Marker, Format);
BufLen = UnicodeVSPrint(Buffer, sizeof(Buffer), Format, Marker);
VA_END(Marker);
if (gST->ConOut && gST->ConOut->OutputString)
{
gST->ConOut->OutputString(gST->ConOut, Buffer);
}
}
STATIC VOID EFIAPI DumpDevicePath(const EFI_DEVICE_PATH_PROTOCOL *DevicePath)
{
CHAR16 *DPStr = NULL;
if (DevicePath)
{
DPStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
}
if (DPStr)
{
vLog(L"%s", DPStr);
FreePool(DPStr);
}
else
{
vLog(L"NULL");
}
}
STATIC VOID EFIAPI ShowSBWarning(const EFI_DEVICE_PATH_PROTOCOL *DevicePath)
{
vLog(L"\r\n=======================================================");
vLog(L"=======================================================\r\n");
DumpDevicePath(DevicePath);
vLog(L"\r\n####### Ventoy Security Boot Violation ##########\r\n");
vLog(L"=======================================================");
vLog(L"=======================================================");
VtoySleep(5);
}
STATIC VOID * EFIAPI FindShimFuncAddr(UINT64 FuncOffset)
{
EFI_STATUS Status;
SHIM_IMAGE_LOADER *ImgLoader = NULL;
EFI_GUID ShimImgLoaderGuid = SHIM_IMAGE_LOADER_GUID;
Status = gBS->LocateProtocol(&ShimImgLoaderGuid, NULL, (VOID **)&ImgLoader);
if (EFI_ERROR(Status) || !ImgLoader || !ImgLoader->LoadImage)
{
vLog(L"Failed to locate shim image loader protocol %lx %p", Status, ImgLoader);
return NULL;
}
if (NM_SHIM_LOAD_IMAGE_OFFSET > FuncOffset)
{
return (UINT8 *)ImgLoader->LoadImage - (NM_SHIM_LOAD_IMAGE_OFFSET - FuncOffset);
}
else
{
return (UINT8 *)ImgLoader->LoadImage + (FuncOffset - NM_SHIM_LOAD_IMAGE_OFFSET);
}
}
EFI_STATUS EFIAPI LaunchRealGrub(EFI_HANDLE ImageHandle, CONST CHAR16 *FileName)
{
EFI_STATUS Status;
UINTN BufferSize = 0;
CHAR16 *DevDpStr = NULL;
CHAR16 *NewDpStr = NULL;
EFI_HANDLE ChildHandle = NULL;
EFI_LOADED_IMAGE_PROTOCOL *Li = NULL;
EFI_DEVICE_PATH_PROTOCOL *DeviceDP = NULL;
EFI_DEVICE_PATH_PROTOCOL *TargetDp = NULL;
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID**)&Li);
if (EFI_ERROR(Status))
{
vLog(L"Failed to locate loaded image protocol %lx", Status);
return Status;
}
DeviceDP = DevicePathFromHandle(Li->DeviceHandle);
if (!DeviceDP || !IsDevicePathValid(DeviceDP, 0))
{
vLog(L"Failed to get device path of device handle %p", Li->DeviceHandle);
Status = EFI_NOT_FOUND;
goto END;
}
DevDpStr = ConvertDevicePathToText(DeviceDP, FALSE, TRUE);
if (!DevDpStr)
{
vLog(L"Failed to convert device path to text");
Status = EFI_OUT_OF_RESOURCES;
goto END;
}
BufferSize = (StrLen(DevDpStr) + 64) * sizeof(CHAR16);
NewDpStr = (CHAR16 *)AllocatePool(BufferSize);
if (!NewDpStr)
{
vLog(L"Failed to alloc new device path string buffer size:%lu", BufferSize);
Status = EFI_OUT_OF_RESOURCES;
goto END;
}
UnicodeSPrint(NewDpStr, BufferSize, L"%s/EFI/BOOT/%s", DevDpStr, FileName);
TargetDp = ConvertTextToDevicePath(NewDpStr);
if (!TargetDp)
{
vLog(L"Failed to convert new text <%s> to device path", NewDpStr);
Status = EFI_NOT_FOUND;
goto END;
}
Status = gBS->LoadImage(FALSE, ImageHandle, TargetDp, NULL, 0, &ChildHandle);
if (EFI_ERROR(Status))
{
vLog(L"Failed to LoadImage %lx", Status);
goto END;
}
Status = gBS->StartImage(ChildHandle, NULL, NULL);
if (EFI_ERROR(Status))
{
vLog(L"Failed to StartImage %lx", Status);
gBS->UnloadImage(ChildHandle);
goto END;
}
END:
CheckFreePool(DevDpStr);
CheckFreePool(NewDpStr);
CheckFreePool(TargetDp);
return Status;
}
STATIC EFI_STATUS EFIAPI CheckVtoyGrub
(
VOID *FileBuffer,
UINTN FileSize
)
{
UINT8 Sha256Hash[64];
if (!FileBuffer || FileSize < sizeof(EFI_IMAGE_DOS_HEADER))
{
vErr(L"Invalid FileBuffer:%p or size:%ld", FileBuffer, FileSize);
return EFI_SECURITY_VIOLATION;
}
ZeroMem(Sha256Hash, sizeof(Sha256Hash));
calc_sha256(FileBuffer, (UINT64)FileSize, Sha256Hash);
if (CompareMem(Sha256Hash, gVtoyGrubSha256Hash, 32) != 0)
{
vErr(L"Ventoy hash check failed.");
gRT->ResetSystem(EfiResetWarm, EFI_SECURITY_VIOLATION, 0, NULL);
return EFI_SECURITY_VIOLATION;
}
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI SecurityPolicyAuth
(
const EFI_SECURITY_ARCH_PROTOCOL *This,
UINT32 AuthenticationStatus,
const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
)
{
/*
* Some old UEFI firmware (without Security2 protocol) will hang when run OpenVolume.
* So finally I decide not to support such UEFI firmware.
* It means that for UEFI firmware before 2.5 (about 2015) Ventoy only supports Bypass policy.
*
*/
(VOID)This;
(VOID)AuthenticationStatus;
(VOID)DevicePathConst;
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI Security2PolicyAuth
(
const EFI_SECURITY2_ARCH_PROTOCOL *This,
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
VOID *FileBuffer,
UINTN FileSize,
BOOLEAN BootPolicy
)
{
EFI_STATUS Status;
/* Just return OK if the user choose to bypass SB */
if (gVtoyByPassSB)
{
return EFI_SUCCESS;
}
if (!gGrubLaunched)
{
return CheckVtoyGrub(FileBuffer, FileSize);
}
/*
* Step 1:
* Use original UEFI firmware auth API.
* If it's OK, it may be signed with Microsoft UEFI CA. (e.g. bootmgr/shim/...)
*/
if (gSysSec2FileAuth)
{
Status = gSysSec2FileAuth(This, DevicePath, FileBuffer, FileSize, BootPolicy);
if (!EFI_ERROR(Status))
{
return EFI_SUCCESS;
}
}
/*
* Step 2:
* Use shim verify API.
* If it's OK, it may be signed with a MOK key. (e.g. Ventoy EFI files)
*/
if (gShimLock.Verify)
{
if (FileBuffer && FileSize > 0 && FileSize < 0xFFFFFFFFUL)
{
Status = gShimLock.Verify(FileBuffer, (UINT32)FileSize);
if (!EFI_ERROR(Status))
{
return EFI_SUCCESS;
}
}
}
ShowSBWarning(DevicePath);
return EFI_SECURITY_VIOLATION;
}
STATIC EFI_STATUS EFIAPI HookSecurityPolicy(VOID)
{
EFI_STATUS Status;
EFI_STATUS Status2;
EFI_SECURITY_ARCH_PROTOCOL *Security = NULL;
EFI_SECURITY2_ARCH_PROTOCOL *Security2 = NULL;
Status = gBS->LocateProtocol(&gEfiSecurityArchProtocolGuid, NULL, (VOID **)&Security);
Status2 = gBS->LocateProtocol(&gEfiSecurity2ArchProtocolGuid, NULL, (VOID **)&Security2);
if (EFI_ERROR(Status) && EFI_ERROR(Status2))
{
vLog(L"Failed to locate security or security2 protocol. %lx %lx %p %p",
Status, Status2, Security, Security2);
return EFI_NOT_FOUND;
}
if (Security2)
{
gSysSec2FileAuth = Security2->FileAuthentication;
Security2->FileAuthentication = Security2PolicyAuth;
}
if (Security)
{
gSysSecFileAuth = Security->FileAuthenticationState;
Security->FileAuthenticationState = SecurityPolicyAuth;
}
return EFI_SUCCESS;
}
STATIC VOID EFIAPI UnHookSecurityPolicy(VOID)
{
EFI_STATUS Status;
EFI_STATUS Status2;
EFI_SECURITY_ARCH_PROTOCOL *Security = NULL;
EFI_SECURITY2_ARCH_PROTOCOL *Security2 = NULL;
if (!gSysSec2FileAuth && !gSysSecFileAuth)
{
return;
}
Status = gBS->LocateProtocol(&gEfiSecurityArchProtocolGuid, NULL, (VOID **)&Security);
Status2 = gBS->LocateProtocol(&gEfiSecurity2ArchProtocolGuid, NULL, (VOID **)&Security2);
if (EFI_ERROR(Status) && EFI_ERROR(Status2))
{
vLog(L"Failed to locate security or security2 protocol. %lx %lx %p %p",
Status, Status2, Security, Security2);
return;
}
if (Security2 && gSysSec2FileAuth && Security2->FileAuthentication == Security2PolicyAuth)
{
Security2->FileAuthentication = gSysSec2FileAuth;
gSysSec2FileAuth = NULL;
}
if (Security && gSysSecFileAuth && Security->FileAuthenticationState == SecurityPolicyAuth)
{
Security->FileAuthenticationState = gSysSecFileAuth;
gSysSecFileAuth = NULL;
}
}
STATIC VOID EFIAPI VtoyByPassSB(VOID)
{
gVtoyByPassSB = TRUE;
}
STATIC VOID EFIAPI VtoyCheckSB(VOID)
{
gVtoyByPassSB = FALSE;
}
STATIC VOID EFIAPI VtoyLaunched(VOID)
{
gGrubLaunched = TRUE;
}
STATIC VOID EFIAPI UnInstallVtoyShimProtocol(VOID)
{
EFI_GUID Guid = VTOY_SHIM_POLICY_GUID;
if (gVtoyShimProtHandle)
{
gBS->UninstallProtocolInterface(gVtoyShimProtHandle, &Guid, &gVtoyShimProtocol);
gVtoyShimProtHandle = NULL;
}
}
STATIC EFI_STATUS EFIAPI InstallVtoyShimProtocol(VOID)
{
EFI_STATUS Status;
EFI_GUID Guid = VTOY_SHIM_POLICY_GUID;
VTOY_SHIM *Prot = NULL;
gVtoyShimProtocol.ByPassSB = VtoyByPassSB;
gVtoyShimProtocol.CheckSB = VtoyCheckSB;
gVtoyShimProtocol.Launched = VtoyLaunched;
Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&Prot);
if (!EFI_ERROR(Status))
{
vLog(L"Ventoy shim already loaded, cannot be nested.");
return EFI_ALREADY_STARTED;
}
Status = gBS->InstallProtocolInterface(&gVtoyShimProtHandle, &Guid,
EFI_NATIVE_INTERFACE, &gVtoyShimProtocol);
if (EFI_ERROR(Status))
{
vLog(L"Failed to install protocol %lx", Status);
}
return Status;
}
STATIC BOOLEAN EFIAPI IsSecureBootEnabled(VOID)
{
UINT8 SecureBoot = 0;
UINTN DataSize;
EFI_STATUS Status;
DataSize = sizeof(SecureBoot);
Status = gST->RuntimeServices->GetVariable(L"SecureBoot", &gEfiGlobalVariableGuid, NULL,
&DataSize, &SecureBoot);
if (EFI_ERROR(Status))
{
return FALSE;
}
return SecureBoot ? TRUE : FALSE;
}
STATIC BOOLEAN EFIAPI IsSetupMode(VOID)
{
UINT8 SetupMode = 0;
UINTN DataSize;
EFI_STATUS Status;
DataSize = sizeof(SetupMode);
Status = gST->RuntimeServices->GetVariable(L"SetupMode", &gEfiGlobalVariableGuid, NULL,
&DataSize, &SetupMode);
if (EFI_ERROR(Status))
{
return FALSE;
}
return SetupMode ? TRUE : FALSE;
}
STATIC EFI_STATUS EFIAPI ShimEfiMain
(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
SHIM_LOCK *ShimLock = NULL;
shim_void_func_pf Func1 = NULL;
shim_void_func_pf Func2 = NULL;
/* We must be launched by shim */
Status = gBS->LocateProtocol(&gShimLockGUID, NULL, (VOID**)&ShimLock);
if (EFI_ERROR(Status) || !ShimLock)
{
vErr(L"Failed to locate SHIM LOCK Protocol %lx", Status);
return Status;
}
/* Backup shim Lock because we will remove it later */
gShimLock.Verify = ShimLock->Verify;
gShimLock.Hash = ShimLock->Hash;
gShimLock.Context = ShimLock->Context;
Status = InstallVtoyShimProtocol();
if (EFI_ERROR(Status))
{
vErr(L"Failed to install ventoy shim protocol");
return Status;
}
/*
* IMPORTANT: All recent shim implementations hook the UEFI Boot Services
* (e.g. LoadImage, StartImage) to enforce signature verification.
*
* We must restore the original system service pointers here. If we fail to do this,
* we will be unable to launch Ventoy-signed EFI binaries or any other unsigned
* EFI applications later, even when the user has explicitly opted to disable
* all Secure Boot validation checks.
*
* To the best of my knowledge, there is no official way to remove these hooks.
* This is a tricky hack that relies on shim's internal implementation details.
* It may break in future versions of shim, and a better approach may exist.
*
*/
Func1 = FindShimFuncAddr(NM_UNHOOK_SYSTEM_SERVICES_OFFSET);
Func2 = FindShimFuncAddr(NM_UNINSTALL_SHIM_PROTOCOLS_OFFSET);
if (!Func1 || !Func2)
{
vErr(L"Can not find shim func %p %p", Func1, Func2);
Status = EFI_NOT_FOUND;
goto END;
}
Func1(); /* call shim unhook_system_services() */
Func2(); /* call shim uninstall_shim_protocols() */
HookSystemService();
/* Hook the system security policy */
Status = HookSecurityPolicy();
if (EFI_ERROR(Status))
{
vErr(L"Failed to hook system security policy");
goto END;
}
/* Finally launch Ventoy grub */
Status = LaunchRealGrub(ImageHandle, REAL_GRUB_FILE);
if (EFI_ERROR(Status))
{
vErr(L"Failed to finally launch real grub %s", REAL_GRUB_FILE);
goto END;
}
END:
/* UnHook system security policy */
UnHookSecurityPolicy();
UnInstallVtoyShimProtocol();
UnHookSystemService();
return Status;
}
EFI_STATUS EFIAPI VtoyGetVariable
(
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes, OPTIONAL
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
)
{
BOOLEAN bChk = FALSE;
EFI_STATUS Status;
if (gVtoyByPassSB && VariableName && VendorGuid && DataSize && Data && (*DataSize) > 0)
{
bChk = TRUE;
}
Status = gSysGetVariable(VariableName, VendorGuid, Attributes, DataSize, Data);
if (bChk && (!EFI_ERROR(Status)))
{
if (CompareMem(&gShimLockGUID, VendorGuid, 16) == 0 &&
StrCmp(VariableName, L"MokSBState") == 0)
{
*(UINT8 *)Data = 1;
}
}
return Status;
}
STATIC VOID EFIAPI UnHookSystemService(VOID)
{
if (gSysExitBootServices)
{
gBS->ExitBootServices = gSysExitBootServices;
gSysExitBootServices = NULL;
}
if (gSysGetVariable)
{
gST->RuntimeServices->GetVariable = gSysGetVariable;
gSysGetVariable = NULL;
}
}
STATIC EFI_STATUS EFIAPI VtoyExitBootServices
(
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
)
{
EFI_EXIT_BOOT_SERVICES SysExitBS;
/* UnHookSystemService will set gSysExitBootServices NULL */
SysExitBS = gSysExitBootServices;
UnHookSecurityPolicy();
UnInstallVtoyShimProtocol();
UnHookSystemService();
return SysExitBS(ImageHandle, MapKey);
}
STATIC VOID EFIAPI HookSystemService(VOID)
{
gSysExitBootServices = gBS->ExitBootServices;
gBS->ExitBootServices = VtoyExitBootServices;
gSysGetVariable = gST->RuntimeServices->GetVariable;
gST->RuntimeServices->GetVariable = VtoyGetVariable;
}
EFI_STATUS EFIAPI VtoyShimEfiMain
(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
BOOLEAN IsSetup = FALSE;
BOOLEAN IsSecureBoot = FALSE;
EFI_STATUS Status;
IsSetup = IsSetupMode();
IsSecureBoot = IsSecureBootEnabled();
if (!IsSecureBoot || IsSetup)
{
/* If secure boot is not enabled or in SetupMode, nothing needed, just launch Ventoy grub */
Status = LaunchRealGrub(ImageHandle, REAL_GRUB_FILE);
if (EFI_ERROR(Status))
{
vErr(L"Failed to launch %s", REAL_GRUB_FILE);
}
}
else
{
Status = ShimEfiMain(ImageHandle, SystemTable);
}
return Status;
}
@@ -0,0 +1,116 @@
/******************************************************************************
* VtoyShim.h
*
* Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
*/
#ifndef __VTOYSHIM_H__
#define __VTOYSHIM_H__
#if defined (MDE_CPU_IA32)
#define REAL_GRUB_FILE L"grubia32_real.efi"
#elif defined (MDE_CPU_X64)
#define REAL_GRUB_FILE L"grubx64_real.efi"
#elif defined (MDE_CPU_AARCH64)
#define REAL_GRUB_FILE L"grubaa64_real.efi"
#else
#error "Not supported now"
#endif
/* The following definations are copied from shim source code */
#define SHIM_LOCK_GUID {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } };
typedef
EFI_STATUS
(*EFI_SHIM_LOCK_VERIFY) (
IN VOID *buffer,
IN UINT32 size
);
typedef
EFI_STATUS
(*EFI_SHIM_LOCK_HASH) (
IN char *data,
IN int datasize,
PE_COFF_LOADER_IMAGE_CONTEXT *context,
UINT8 *sha256hash,
UINT8 *sha1hash
);
typedef
EFI_STATUS
(*EFI_SHIM_LOCK_CONTEXT) (
IN VOID *data,
IN unsigned int datasize,
PE_COFF_LOADER_IMAGE_CONTEXT *context
);
typedef struct _SHIM_LOCK {
EFI_SHIM_LOCK_VERIFY Verify;
EFI_SHIM_LOCK_HASH Hash;
EFI_SHIM_LOCK_CONTEXT Context;
} SHIM_LOCK;
#define SHIM_IMAGE_LOADER_GUID {0x1f492041, 0xfadb, 0x4e59, {0x9e, 0x57, 0x7c, 0xaf, 0xe7, 0x3a, 0x55, 0xab } }
typedef struct _SHIM_IMAGE_LOADER {
EFI_IMAGE_LOAD LoadImage;
EFI_IMAGE_START StartImage;
EFI_EXIT Exit;
EFI_IMAGE_UNLOAD UnloadImage;
} SHIM_IMAGE_LOADER;
typedef VOID (*shim_void_func_pf)(VOID);
/*
* The two offset here are extract from the shim file which used in Ventoy.
* nm BOOTX64.EFI | grep shim_load_image
* nm BOOTX64.EFI | grep unhook_system_services
* nm BOOTX64.EFI | grep uninstall_shim_protocols
*
* It means that they must be updated every time Ventoy update the shim file.
*
*/
#define NM_SHIM_LOAD_IMAGE_OFFSET 0x2dc12
#define NM_UNHOOK_SYSTEM_SERVICES_OFFSET 0x2e278
#define NM_UNINSTALL_SHIM_PROTOCOLS_OFFSET 0x26264
#define VtoySleep(sec) gBS->Stall(1000000 * (sec))
#define vLog(fmt, ...) VtoyLog(fmt "\r\n", ##__VA_ARGS__)
#define vErr(fmt, ...) VtoyLog(fmt "\r\n", ##__VA_ARGS__); VtoySleep(5)
#define vDbg(fmt, ...) VtoyLog(fmt "\r\n", ##__VA_ARGS__); VtoySleep(2)
#define CheckFreePool(p) \
do { \
if (p) { \
FreePool(p); \
(p) = NULL; \
}\
} while (0)
#define VTOY_SHIM_POLICY_GUID {0x90a29d14, 0x3968, 0x48fe, { 0x85, 0x81, 0x6b, 0x7f, 0x7d, 0xc4, 0x70, 0x55 }};
typedef VOID (EFIAPI *VTOY_BYPASS_SB)(VOID);
typedef VOID (EFIAPI *VTOY_CHECK_SB)(VOID);
typedef VOID (EFIAPI *VTOY_LAUNCHED)(VOID);
typedef struct _VTOY_SHIM{
VTOY_BYPASS_SB ByPassSB;
VTOY_BYPASS_SB CheckSB;
VTOY_LAUNCHED Launched;
} VTOY_SHIM;
void calc_sha256(const void *data, UINT64 len, void *output);
#endif
@@ -0,0 +1,84 @@
#************************************************************************************
# Copyright (c) 2026, longpanda <[email protected]>
#
# 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/>.
#
#************************************************************************************
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = VtoyShim
FILE_GUID = 6d7c7406-b32c-461f-8454-ddaa5243d93d
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VtoyShimEfiMain
[BuildOptions]
# Force standard GNU ld to pack and align ELF segments to 4KB page boundaries
GCC:*_*_*_DLINK_FLAGS = -Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000
[Sources]
VtoyShim.h
VtoyShim.c
sha256.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
DevicePathLib
DebugLib
[Guids]
gEfiGlobalVariableGuid
gShellVariableGuid
gEfiVirtualCdGuid
gEfiFileInfoGuid
[Protocols]
gEfiSecurityArchProtocolGuid
gEfiSecurity2ArchProtocolGuid
gEfiLoadedImageProtocolGuid
gEfiBlockIoProtocolGuid
gEfiDevicePathProtocolGuid
gEfiDevicePathToTextProtocolGuid
gEfiDevicePathFromTextProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiRamDiskProtocolGuid
gEfiAbsolutePointerProtocolGuid
gEfiAcpiTableProtocolGuid
gEfiBlockIo2ProtocolGuid
gEfiBusSpecificDriverOverrideProtocolGuid
gEfiComponentNameProtocolGuid
gEfiComponentName2ProtocolGuid
gEfiDriverBindingProtocolGuid
gEfiDiskIoProtocolGuid
gEfiDiskIo2ProtocolGuid
gEfiGraphicsOutputProtocolGuid
gEfiHiiConfigAccessProtocolGuid
gEfiHiiFontProtocolGuid
gEfiLoadFileProtocolGuid
gEfiLoadFile2ProtocolGuid
gEfiLoadedImageProtocolGuid
gEfiLoadedImageDevicePathProtocolGuid
gEfiPciIoProtocolGuid
gEfiSerialIoProtocolGuid
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextInputExProtocolGuid
gEfiSimpleTextOutProtocolGuid
@@ -0,0 +1,2 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
ventoy-shim,1,Ventoy,ventoy-shim,1.0,https://www.ventoy.net/
1 sbat 1 SBAT Version sbat 1 https://github.com/rhboot/shim/blob/main/SBAT.md
2 ventoy-shim 1 Ventoy ventoy-shim 1.0 https://www.ventoy.net/
@@ -0,0 +1,170 @@
/******************************************************************************
* VtoyShim.c
*
* Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
*/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
static const UINT32 sha256_initial_h[8]
= { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
static const UINT32 sha256_round_k[64]
= { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
static void sha256_endian_reverse64(UINT64 input, UINT8 *output) {
output[7] = (input >> 0) & 0xff;
output[6] = (input >> 8) & 0xff;
output[5] = (input >> 16) & 0xff;
output[4] = (input >> 24) & 0xff;
output[3] = (input >> 32) & 0xff;
output[2] = (input >> 40) & 0xff;
output[1] = (input >> 48) & 0xff;
output[0] = (input >> 56) & 0xff;
}
static UINT32 sha256_endian_read32(UINT8 *input) {
UINT32 output = 0;
output |= (input[0] << 24);
output |= (input[1] << 16);
output |= (input[2] << 8);
output |= (input[3] << 0);
return output;
}
static void sha256_endian_reverse32(UINT32 input, UINT8 *output) {
output[3] = (input >> 0) & 0xff;
output[2] = (input >> 8) & 0xff;
output[1] = (input >> 16) & 0xff;
output[0] = (input >> 24) & 0xff;
}
static UINT32 sha256_ror(UINT32 input, UINT32 by) {
return (input >> by) | (((input & ((1 << by) - 1))) << (32 - by));
}
void calc_sha256(const void *data, UINT64 len, void *output)
{
int i = 0;
int j = 0;
UINT8 padding[80];
UINT64 current = (len + 1) % 64;
// want to be == 56 % 64.
UINT64 needed = (64 + 56 - current) % 64;
UINT64 extra = needed + 9;
UINT64 total = len + extra;
UINT32 v[8];
UINT64 cursor = 0;
for(i = 1; i < 80; i++)
{
padding[i] = 0;
}
padding[0] = 0x80;
sha256_endian_reverse64(len * 8, padding + total - len - 8);
for(i = 0; i < 8; i++)
{
v[i] = sha256_initial_h[i];
}
for(cursor = 0; cursor * 64 < total; cursor++)
{
UINT32 t[8];
UINT32 w[64];
for(i = 0; i < 8; i++)
{
t[i] = v[i];
}
if(cursor * 64 + 64 <= len)
{
for(j = 0; j < 16; j++)
{
w[j] = sha256_endian_read32((UINT8 *)data + cursor * 64 + j * 4);
}
}
else
{
if(cursor * 64 < len)
{
UINT64 size = len - cursor * 64;
if(size > 0)
{
CopyMem(w, (UINT8 *)data + cursor * 64, size);
}
CopyMem((UINT8 *)w + size, padding, 64 - size);
}
else
{
UINT64 off = (cursor * 64 - len) % 64;
CopyMem((UINT8 *)w, padding + off, 64);
}
for(j = 0; j < 16; j++)
{
w[j] = sha256_endian_read32((UINT8 *)&w[j]);
}
}
for(j = 16; j < 64; j++)
{
UINT32 s1 = sha256_ror(w[j - 2], 17) ^ sha256_ror(w[j - 2], 19) ^ (w[j - 2] >> 10);
UINT32 s0 = sha256_ror(w[j - 15], 7) ^ sha256_ror(w[j - 15], 18) ^ (w[j - 15] >> 3);
w[j] = s1 + w[j - 7] + s0 + w[j - 16];
}
for(j = 0; j < 64; j++)
{
UINT32 ch = (t[4] & t[5]) ^ (~t[4] & t[6]);
UINT32 maj = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
UINT32 S0 = sha256_ror(t[0], 2) ^ sha256_ror(t[0], 13) ^ sha256_ror(t[0], 22);
UINT32 S1 = sha256_ror(t[4], 6) ^ sha256_ror(t[4], 11) ^ sha256_ror(t[4], 25);
UINT32 t1 = t[7] + S1 + ch + sha256_round_k[j] + w[j];
UINT32 t2 = S0 + maj;
t[7] = t[6];
t[6] = t[5];
t[5] = t[4];
t[4] = t[3] + t1;
t[3] = t[2];
t[2] = t[1];
t[1] = t[0];
t[0] = t1 + t2;
}
for(i = 0; i < 8; i++)
{
v[i] += t[i];
}
}
for(i = 0; i < 8; i++)
{
sha256_endian_reverse32(v[i], (UINT8 *)output + i * 4);
}
}
@@ -0,0 +1,179 @@
/******************************************************************************
* Memhole.c
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 <VtoyUtil.h>
STATIC BOOLEAN IsMemContiguous
(
IN CONST EFI_MEMORY_DESCRIPTOR *Prev,
IN CONST EFI_MEMORY_DESCRIPTOR *Curr,
IN CONST EFI_MEMORY_DESCRIPTOR *Next
)
{
UINTN Addr1 = 0;
UINTN Addr2 = 0;
if (Prev == NULL || Curr == NULL || Next == NULL)
{
return FALSE;
}
if (Prev->Type == EfiBootServicesData &&
Curr->Type == EfiConventionalMemory &&
Next->Type == EfiBootServicesData)
{
Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages);
Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages);
if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart)
{
return TRUE;
}
}
return FALSE;
}
STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc
(
OUT UINTN *pSize,
OUT UINTN *pItemSize,
OUT UINTN *pDescCount
)
{
UINTN Size = 0;
UINTN MapKey = 0;
UINTN ItemSize = 0;
UINTN DescCount = 0;
UINT32 Version = 0;
EFI_STATUS Status = EFI_SUCCESS;
EFI_MEMORY_DESCRIPTOR *pDesc = NULL;
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
if (EFI_BUFFER_TOO_SMALL != Status)
{
debug("GetMemoryMap: %r", Status);
return NULL;
}
Size += SIZE_1KB;
pDesc = AllocatePool(Size);
if (!pDesc)
{
debug("AllocatePool: %lu failed", Size);
return NULL;
}
ZeroMem(pDesc, Size);
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
if (EFI_ERROR(Status))
{
debug("GetMemoryMap: %r", Status);
FreePool(pDesc);
return NULL;
}
Curr = pDesc;
while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size))
{
DescCount++;
Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
}
*pSize = Size;
*pItemSize = ItemSize;
*pDescCount = DescCount;
debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount);
return pDesc;
}
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
{
UINTN Size = 0;
UINTN ItemSize = 0;
UINTN DescCount = 0;
UINTN TotalMem = 0;
EFI_STATUS Status = EFI_SUCCESS;
EFI_PHYSICAL_ADDRESS AllocAddr = 0;
EFI_MEMORY_DESCRIPTOR *pDescs = NULL;
EFI_MEMORY_DESCRIPTOR *Prev = NULL;
EFI_MEMORY_DESCRIPTOR *Next = NULL;
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
(VOID)ImageHandle;
(VOID)CmdLine;
pDescs = GetMemDesc(&Size, &ItemSize, &DescCount);
if (!pDescs)
{
return EFI_NOT_FOUND;
}
if (DescCount < 500)
{
FreePool(pDescs);
Printf("There is no need to fixup (%lu)\n", DescCount);
return EFI_SUCCESS;
}
Curr = pDescs;
while ((UINT8 *)Curr < (UINT8 *)pDescs + Size)
{
Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
if (IsMemContiguous(Prev, Curr, Next))
{
AllocAddr = Curr->PhysicalStart;
Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr);
if (EFI_SUCCESS == Status)
{
TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages);
}
}
Prev = Curr;
Curr = Next;
}
Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem);
return EFI_SUCCESS;
}
@@ -0,0 +1,140 @@
/******************************************************************************
* VtoyDrv.c
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 <VtoyUtil.h>
STATIC UINTN g_EfiDriverNameCnt = 0;
STATIC CHAR16 *g_EfiDriverNameList[1024] = { NULL };
STATIC EFI_STATUS AddEfiDriverName(IN CHAR16 *DriverName)
{
UINTN i = 0;
if (g_EfiDriverNameCnt >= 1024)
{
return EFI_OUT_OF_RESOURCES;
}
for (i = 0; i < g_EfiDriverNameCnt; i++)
{
if (g_EfiDriverNameList[i] && StrCmp(g_EfiDriverNameList[i], DriverName) == 0)
{
break;
}
}
if (i >= g_EfiDriverNameCnt)
{
g_EfiDriverNameList[g_EfiDriverNameCnt] = DriverName;
g_EfiDriverNameCnt++;
}
return EFI_SUCCESS;
}
EFI_STATUS ShowEfiDrivers(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
{
UINTN i = 0;
UINTN Count = 0;
CHAR16 *DriverName = NULL;
EFI_HANDLE *Handles = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
(VOID)ImageHandle;
(VOID)CmdLine;
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;
}
DriverName = NULL;
Status = VtoyGetComponentName(2, Name2Protocol, &DriverName);
if ((!EFI_ERROR(Status)) && (DriverName))
{
AddEfiDriverName(DriverName);
}
}
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;
}
DriverName = NULL;
Status = VtoyGetComponentName(1, Name2Protocol, &DriverName);
if ((!EFI_ERROR(Status)) && (DriverName))
{
AddEfiDriverName(DriverName);
}
}
FreePool(Handles);
for (i = 0; i < g_EfiDriverNameCnt; i++)
{
Printf("%2d %s\n", i, g_EfiDriverNameList[i]);
}
return EFI_SUCCESS;
}
@@ -0,0 +1,178 @@
/******************************************************************************
* VtoyUtil.c
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 <VtoyUtil.h>
BOOLEAN gVtoyDebugPrint = FALSE;
STATIC CONST CHAR16 *gCurFeature= NULL;
STATIC CHAR16 *gCmdLine = NULL;
STATIC grub_env_printf_pf g_env_printf = NULL;
STATIC VtoyUtilFeature gFeatureList[] =
{
{ L"fix_windows_mmap", FixWindowsMemhole },
{ L"show_efi_drivers", ShowEfiDrivers },
};
EFI_STATUS VtoyGetComponentName(IN UINTN Ver, IN VOID *Protocol, OUT CHAR16 **DriverName)
{
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 *DrvName = NULL;
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
if (1 == Ver)
{
NameProtocol = (EFI_COMPONENT_NAME_PROTOCOL *)Protocol;
Status = NameProtocol->GetDriverName(Protocol, "en", &DrvName);
if (EFI_ERROR(Status) || NULL == DrvName)
{
Status = NameProtocol->GetDriverName(Protocol, "eng", &DrvName);
}
}
else
{
Name2Protocol = (EFI_COMPONENT_NAME2_PROTOCOL *)Protocol;
Status = Name2Protocol->GetDriverName(Protocol, "en", &DrvName);
if (EFI_ERROR(Status) || NULL == DrvName)
{
Status = Name2Protocol->GetDriverName(Protocol, "eng", &DrvName);
}
}
*DriverName = DrvName;
return Status;
}
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...)
{
VA_LIST Marker;
CHAR8 Buffer[512];
VA_START (Marker, Format);
AsciiVSPrint(Buffer, sizeof(Buffer), Format, Marker);
VA_END (Marker);
if (g_env_printf)
{
g_env_printf("%s", Buffer);
}
}
STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
{
CHAR16 *pPos = NULL;
CHAR16 *pCmdLine = NULL;
EFI_STATUS Status = EFI_SUCCESS;
ventoy_grub_param *pGrubParam = NULL;
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
if (EFI_ERROR(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"vtoyefitest"))
{
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
gST->ConOut->OutputString(gST->ConOut, L"\r\n######### VTOY #########");
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
return EFI_SUCCESS;
}
if (StrStr(pCmdLine, L"debug"))
{
gVtoyDebugPrint = TRUE;
}
pPos = StrStr(pCmdLine, L"env_param=");
if (!pPos)
{
return EFI_INVALID_PARAMETER;
}
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
g_env_printf = pGrubParam->grub_env_printf;
pPos = StrStr(pCmdLine, L"feature=");
if (!pPos)
{
return EFI_INVALID_PARAMETER;
}
gCurFeature = pPos + StrLen(L"feature=");
gCmdLine = pCmdLine;
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI VtoyUtilEfiMain
(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINTN i;
UINTN Len;
ParseCmdline(ImageHandle);
for (i = 0; gCurFeature && i < ARRAY_SIZE(gFeatureList); i++)
{
Len = StrLen(gFeatureList[i].Cmd);
if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0)
{
debug("Find main proc <%s>", gFeatureList[i].Cmd);
gFeatureList[i].MainProc(ImageHandle, gCurFeature + Len);
break;
}
}
if (gCmdLine)
{
FreePool(gCmdLine);
gCmdLine = NULL;
}
return EFI_SUCCESS;
}
@@ -0,0 +1,70 @@
/******************************************************************************
* VtoyUtil.h
*
* Copyright (c) 2020, longpanda <[email protected]>
*
* 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 __VTOYUTIL_H__
#define __VTOYUTIL_H__
#define VTOY_SHIM_POLICY_GUID {0x90a29d14, 0x3968, 0x48fe, { 0x85, 0x81, 0x6b, 0x7f, 0x7d, 0xc4, 0x70, 0x55 }};
#pragma pack(1)
typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
typedef int (*grub_env_set_pf)(const char *name, const char *val);
typedef const char * (*grub_env_get_pf)(const char *name);
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
#define VTOY_MAX_CONF_REPLACE 2
typedef struct ventoy_grub_param_file_replace
{
UINT32 magic;
char old_file_name[4][256];
UINT32 old_file_cnt;
UINT32 new_file_virtual_id;
}ventoy_grub_param_file_replace;
typedef struct ventoy_grub_param
{
grub_env_get_pf grub_env_get;
grub_env_set_pf grub_env_set;
ventoy_grub_param_file_replace file_replace;
ventoy_grub_param_file_replace img_replace[VTOY_MAX_CONF_REPLACE];
grub_env_printf_pf grub_env_printf;
}ventoy_grub_param;
#pragma pack()
typedef struct VtoyUtilFeature
{
CONST CHAR16 *Cmd;
VTOY_UTIL_PROC_PF MainProc;
}VtoyUtilFeature;
extern BOOLEAN gVtoyDebugPrint;
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...);
#define debug(expr, ...) if (gVtoyDebugPrint) VtoyUtilDebug("[VTOY] "expr"\n", ##__VA_ARGS__)
#define Printf VtoyUtilDebug
EFI_STATUS VtoyGetComponentName(IN UINTN Ver, IN VOID *Protocol, OUT CHAR16 **DriverName);
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
EFI_STATUS ShowEfiDrivers(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
#endif
@@ -0,0 +1,84 @@
#************************************************************************************
# Copyright (c) 2020, longpanda <[email protected]>
#
# 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/>.
#
#************************************************************************************
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = VtoyUtil
FILE_GUID = a43466a0-68c6-469d-ba4b-678bbe90bc47
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VtoyUtilEfiMain
[BuildOptions]
# Force standard GNU ld to pack and align ELF segments to 4KB page boundaries
GCC:*_*_*_DLINK_FLAGS = -Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000
[Sources]
VtoyUtil.h
VtoyUtil.c
VtoyDrv.c
Memhole.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
DebugLib
[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
@@ -0,0 +1,499 @@
## @file
# EFI/PI Reference Module Package for All Architectures
#
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
PLATFORM_NAME = MdeModule
PLATFORM_GUID = 587CE499-6CBE-43cd-94E2-186218569478
PLATFORM_VERSION = 0.98
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/MdeModule
SUPPORTED_ARCHITECTURES = IA32|X64|EBC|ARM|AARCH64
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
#
# Entry point
#
PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
#
# Basic
#
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
#
# UEFI & PI
#
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
#
# Generic Modules
#
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
#
# Misc
#
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
PciHostBridgeLib|MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
[LibraryClasses.EBC.PEIM]
IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
[LibraryClasses.common.PEI_CORE]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
[LibraryClasses.common.PEIM]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
[LibraryClasses.common.DXE_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
[LibraryClasses.common.SMM_CORE]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
[LibraryClasses.common.DXE_SMM_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
[LibraryClasses.common.UEFI_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
[LibraryClasses.common.MM_STANDALONE]
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
MemoryAllocationLib|MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
#
# It is not possible to prevent ARM compiler calls to generic intrinsic functions.
# This library provides the instrinsic functions generated by a given compiler.
# [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
#
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
#
# Since software stack checking may be heuristically enabled by the compiler
# include BaseStackCheckLib unconditionally.
#
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
[LibraryClasses.EBC]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
[PcdsFeatureFlag]
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText|FALSE
[PcdsFixedAtBuild]
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
[PcdsDynamicExDefault]
gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
[Components]
MdeModulePkg/Application/Ventoy/Ventoy.inf
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
MdeModulePkg/Application/VtoyShim/VtoyShim.inf
MdeModulePkg/Application/VDiskChain/VDiskChain.inf
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
MdeModulePkg/Logo/Logo.inf
MdeModulePkg/Logo/LogoDxe.inf
MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
MdeModulePkg/Bus/Pci/IdeBusPei/IdeBusPei.inf
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
MdeModulePkg/Core/Pei/PeiMain.inf
MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf
MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf
MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf
MdeModulePkg/Library/DxePrintLibPrint2Protocol/DxePrintLibPrint2Protocol.inf
MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf
MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
MdeModulePkg/Library/ResetUtilityLib/ResetUtilityLib.inf
MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.inf
MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
MdeModulePkg/Library/PeiDebugPrintHobLib/PeiDebugPrintHobLib.inf
MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
MdeModulePkg/Library/PeiDebugLibDebugPpi/PeiDebugLibDebugPpi.inf
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf
MdeModulePkg/Library/BaseIpmiLibNull/BaseIpmiLibNull.inf
MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiProtocol.inf
MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIpmiProtocol.inf
MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
MdeModulePkg/Library/DisplayUpdateProgressLibText/DisplayUpdateProgressLibText.inf
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
MdeModulePkg/Application/UiApp/UiApp.inf{
<LibraryClasses>
NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
}
MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
MdeModulePkg/Universal/DebugPortDxe/DebugPortDxe.inf
MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
MdeModulePkg/Universal/Metronome/Metronome.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf {
<LibraryClasses>
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
}
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf {
<LibraryClasses>
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
}
MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf
MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
MdeModulePkg/Universal/PCD/Pei/Pcd.inf
MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
MdeModulePkg/Application/VariableInfo/VariableInfo.inf
MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSampleDxe.inf
MdeModulePkg/Universal/LegacyRegion2Dxe/LegacyRegion2Dxe.inf
MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf {
<LibraryClasses>
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
}
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
MdeModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
}
MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
}
MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf {
<LibraryClasses>
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
}
MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
MdeModulePkg/Universal/DebugServicePei/DebugServicePei.inf
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
[Components.IA32, Components.X64, Components.AARCH64]
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
MdeModulePkg/Universal/EbcDxe/EbcDebuggerConfig.inf
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
MdeModulePkg/Core/Dxe/DxeMain.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
}
!if $(TOOL_CHAIN_TAG) != "XCODE5"
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
!endif
[Components.IA32, Components.X64]
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
[Components.X64]
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
File diff suppressed because it is too large Load Diff
+794
View File
@@ -0,0 +1,794 @@
/* file.c - SimpleFileIo Interface */
/*
* Copyright © 2014-2017 Pete Batard <[email protected]>
* Based on iPXE's efi_driver.c and efi_file.c:
* Copyright © 2011,2013 Michael Brown <[email protected]>.
*
* 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 "driver.h"
/**
* Get EFI file name (for debugging)
*
* @v file EFI file
* @ret Name Name
*/
static const CHAR16 *
FileName(EFI_GRUB_FILE *File)
{
EFI_STATUS Status;
static CHAR16 Path[MAX_PATH];
Status = Utf8ToUtf16NoAlloc(File->path, Path, sizeof(Path));
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not convert filename to UTF16");
return NULL;
}
return Path;
}
/* Simple hook to populate the timestamp and directory flag when opening a file */
static INT32
InfoHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *Info, VOID *Data)
{
EFI_GRUB_FILE *File = (EFI_GRUB_FILE *) Data;
/* Look for a specific file */
if (strcmpa(name, File->basename) != 0)
return 0;
File->IsDir = (BOOLEAN) (Info->Dir);
if (Info->MtimeSet)
File->Mtime = Info->Mtime;
return 0;
}
/**
* Open file
*
* @v This File handle
* @ret new New file handle
* @v Name File name
* @v Mode File mode
* @v Attributes File attributes (for newly-created files)
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New,
CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
{
EFI_STATUS Status;
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
EFI_GRUB_FILE *NewFile;
// TODO: Use dynamic buffers?
char path[MAX_PATH], clean_path[MAX_PATH], *dirname;
INTN i, len;
BOOLEAN AbsolutePath = (*Name == L'\\');
PrintInfo(L"Open(" PERCENT_P L"%s, \"%s\")\n", (UINTN) This,
IS_ROOT(File)?L" <ROOT>":L"", Name);
/* Fail unless opening read-only */
if (Mode != EFI_FILE_MODE_READ) {
PrintWarning(L"File '%s' can only be opened in read-only mode\n", Name);
return EFI_WRITE_PROTECTED;
}
/* Additional failures */
if ((StrCmp(Name, L"..") == 0) && IS_ROOT(File)) {
PrintInfo(L"Trying to open <ROOT>'s parent\n");
return EFI_NOT_FOUND;
}
/* See if we're trying to reopen current (which the EFI Shell insists on doing) */
if ((*Name == 0) || (StrCmp(Name, L".") == 0)) {
PrintInfo(L" Reopening %s\n", IS_ROOT(File)?L"<ROOT>":FileName(File));
File->RefCount++;
*New = This;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
/* If we have an absolute path, don't bother completing with the parent */
if (AbsolutePath) {
len = 0;
} else {
strcpya(path, File->path);
len = strlena(path);
/* Add delimiter if needed */
if ((len == 0) || (path[len-1] != '/'))
path[len++] = '/';
}
/* Copy the rest of the path (converted to UTF-8) */
Status = Utf16ToUtf8NoAlloc(Name, &path[len], sizeof(path) - len);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not convert path to UTF-8");
return Status;
}
/* Convert the delimiters */
for (i = strlena(path) - 1 ; i >= len; i--) {
if (path[i] == '\\')
path[i] = '/';
}
/* We only want to handle with absolute paths */
clean_path[0] = '/';
/* Find out if we're dealing with root by removing the junk */
CopyPathRelative(&clean_path[1], path, MAX_PATH - 1);
if (clean_path[1] == 0) {
/* We're dealing with the root */
PrintInfo(L" Reopening <ROOT>\n");
*New = &File->FileSystem->RootFile->EfiFile;
/* Must make sure that DirIndex is reset too (NB: no concurrent access!) */
File->FileSystem->RootFile->DirIndex = 0;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
// TODO: eventually we should seek for already opened files and increase RefCount
/* Allocate and initialise an instance of a file */
Status = GrubCreateFile(&NewFile, File->FileSystem);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not instantiate file");
return Status;
}
NewFile->path = AllocatePool(strlena(clean_path)+1);
if (NewFile->path == NULL) {
GrubDestroyFile(NewFile);
PrintError(L"Could not instantiate path\n");
return EFI_OUT_OF_RESOURCES;
}
strcpya(NewFile->path, clean_path);
/* Isolate the basename and dirname */
for (i = strlena(clean_path) - 1; i >= 0; i--) {
if (clean_path[i] == '/') {
clean_path[i] = 0;
break;
}
}
dirname = (i <= 0) ? "/" : clean_path;
NewFile->basename = &NewFile->path[i+1];
/* Find if we're working with a directory and fill the grub timestamp */
Status = GrubDir(NewFile, dirname, InfoHook, (VOID *) NewFile);
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_FOUND)
PrintStatusError(Status, L"Could not get file attributes for '%s'", Name);
FreePool(NewFile->path);
GrubDestroyFile(NewFile);
return Status;
}
/* Finally we can call on GRUB open() if it's a regular file */
if (!NewFile->IsDir) {
Status = GrubOpen(NewFile);
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_FOUND)
PrintStatusError(Status, L"Could not open file '%s'", Name);
FreePool(NewFile->path);
GrubDestroyFile(NewFile);
return Status;
}
}
NewFile->RefCount++;
*New = &NewFile->EfiFile;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileOpenEx(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name,
UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
{
return FileOpen(This, New, Name, Mode, Attributes);
}
/**
* Close file
*
* @v This File handle
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileClose(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Close(" PERCENT_P L"|'%s') %s\n", (UINTN) This, FileName(File),
IS_ROOT(File)?L"<ROOT>":L"");
/* Nothing to do it this is the root */
if (IS_ROOT(File))
return EFI_SUCCESS;
if (--File->RefCount == 0) {
/* Close the file if it's a regular one */
if (!File->IsDir)
GrubClose(File);
/* NB: basename points into File->path and does not need to be freed */
if (File->path != NULL)
FreePool(File->path);
GrubDestroyFile(File);
}
return EFI_SUCCESS;
}
/**
* Close and delete file
*
* @v This File handle
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileDelete(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintError(L"Cannot delete '%s'\n", FileName(File));
/* Close file */
FileClose(This);
/* Warn of failure to delete */
return EFI_WARN_DELETE_FAILURE;
}
/* GRUB uses a callback for each directory entry, whereas EFI uses repeated
* firmware generated calls to FileReadDir() to get the info for each entry,
* so we have to reconcile the twos. For now, we'll re-issue a call to GRUB
* dir(), and run through all the entries (to find the one we
* are interested in) multiple times. Maybe later we'll try to optimize this
* by building a one-off chained list of entries that we can parse...
*/
static INT32
DirHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *DirInfo, VOID *Data)
{
EFI_STATUS Status;
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
INT64 *Index = (INT64 *) &Info->FileSize;
CHAR8 *filename = (CHAR8 *) (UINTN) Info->PhysicalSize;
EFI_TIME Time = { 1970, 01, 01, 00, 00, 00, 0, 0, 0, 0, 0};
// Eliminate '.' or '..'
if ((name[0] == '.') && ((name[1] == 0) || ((name[1] == '.') && (name[2] == 0))))
return 0;
/* Ignore any entry that doesn't match our index */
if ((*Index)-- != 0)
return 0;
strcpya(filename, name);
Status = Utf8ToUtf16NoAlloc(filename, Info->FileName, (INTN)(Info->Size - sizeof(EFI_FILE_INFO)));
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert directory entry to UTF-8");
return (INT32) Status;
}
/* The Info struct size already accounts for the extra NUL */
Info->Size = sizeof(*Info) + StrLen(Info->FileName) * sizeof(CHAR16);
// Oh, and of course GRUB uses a 32 bit signed mtime value (seriously, wtf guys?!?)
if (DirInfo->MtimeSet)
GrubTimeToEfiTime(DirInfo->Mtime, &Time);
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
Info->Attribute = EFI_FILE_READ_ONLY;
if (DirInfo->Dir)
Info->Attribute |= EFI_FILE_DIRECTORY;
return 0;
}
/**
* Read directory entry
*
* @v file EFI file
* @v Len Length to read
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS
FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data)
{
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
EFI_STATUS Status;
/* We temporarily repurpose the FileSize as a *signed* entry index */
INT64 *Index = (INT64 *) &Info->FileSize;
/* And PhysicalSize as a pointer to our filename */
CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize;
CHAR8 path[MAX_PATH];
EFI_GRUB_FILE *TmpFile = NULL;
INTN len;
/* Unless we can fit our maximum size, forget it */
if (*Len < sizeof(EFI_FILE_INFO)) {
*Len = MINIMUM_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
/* Populate our Info template */
ZeroMem(Data, *Len);
Info->Size = *Len;
*Index = File->DirIndex;
strcpya(path, File->path);
len = strlena(path);
if (path[len-1] != '/')
path[len++] = '/';
*basename = &path[len];
/* Invoke GRUB's directory listing */
Status = GrubDir(File, File->path, DirHook, Data);
if (*Index >= 0) {
/* No more entries */
*Len = 0;
return EFI_SUCCESS;
}
if (EFI_ERROR(Status)) {
if (Status == EFI_BUFFER_TOO_SMALL) {
*Len = MINIMUM_INFO_LENGTH;
} else {
PrintStatusError(Status, L"Directory listing failed");
}
return Status;
}
/* Our Index/FileSize must be reset */
Info->FileSize = 0;
Info->PhysicalSize = 0;
/* For regular files, we still need to fill the size */
if (!(Info->Attribute & EFI_FILE_DIRECTORY)) {
/* Open the file and read its size */
Status = GrubCreateFile(&TmpFile, File->FileSystem);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Unable to create temporary file");
return Status;
}
TmpFile->path = path;
Status = GrubOpen(TmpFile);
if (EFI_ERROR(Status)) {
// TODO: EFI_NO_MAPPING is returned for links...
PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName);
/* Non fatal error */
} else {
Info->FileSize = GrubGetFileSize(TmpFile);
Info->PhysicalSize = GrubGetFileSize(TmpFile);
GrubClose(TmpFile);
}
GrubDestroyFile(TmpFile);
}
*Len = (UINTN) Info->Size;
/* Advance to the next entry */
File->DirIndex++;
// PrintInfo(L" Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName,
// (Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L"");
return EFI_SUCCESS;
}
/**
* Read from file
*
* @v This File handle
* @v Len Length to read
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileRead(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Read(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File),
*Len, File->IsDir?L"<DIR>":L"");
/* If this is a directory, then fetch the directory entries */
if (File->IsDir)
return FileReadDir(File, Len, Data);
return GrubRead(File, Data, Len);
}
/* Ex version */
static EFI_STATUS EFIAPI
FileReadEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
{
return FileRead(This, &(Token->BufferSize), Token->Buffer);
}
/**
* Write to file
*
* @v This File handle
* @v Len Length to write
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileWrite(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintError(L"Cannot write to '%s'\n", FileName(File));
return EFI_WRITE_PROTECTED;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileWriteEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
{
return FileWrite(This, &(Token->BufferSize), Token->Buffer);
}
/**
* Set file position
*
* @v This File handle
* @v Position New file position
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
UINT64 FileSize;
PrintInfo(L"SetPosition(" PERCENT_P L"|'%s', %lld) %s\n", (UINTN) This,
FileName(File), Position, (File->IsDir)?L"<DIR>":L"");
/* If this is a directory, reset the Index to the start */
if (File->IsDir) {
if (Position != 0)
return EFI_INVALID_PARAMETER;
File->DirIndex = 0;
return EFI_SUCCESS;
}
/* Fail if we attempt to seek past the end of the file (since
* we do not support writes).
*/
FileSize = GrubGetFileSize(File);
if (Position > FileSize) {
PrintError(L"'%s': Cannot seek to #%llx of %llx\n",
FileName(File), Position, FileSize);
return EFI_UNSUPPORTED;
}
/* Set position */
GrubSetFileOffset(File, Position);
PrintDebug(L"'%s': Position set to %llx\n",
FileName(File), Position);
return EFI_SUCCESS;
}
/**
* Get file position
*
* @v This File handle
* @ret Position New file position
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileGetPosition(EFI_FILE_HANDLE This, UINT64 *Position)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"GetPosition(" PERCENT_P L"|'%s', %lld)\n", (UINTN) This, FileName(File));
if (File->IsDir)
*Position = File->DirIndex;
else
*Position = GrubGetFileOffset(File);
return EFI_SUCCESS;
}
/**
* Get file information
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
{
EFI_STATUS Status;
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data;
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *VLInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Data;
EFI_TIME Time;
CHAR8* label;
UINTN tmpLen;
PrintInfo(L"GetInfo(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This,
FileName(File), *Len, File->IsDir?L"<DIR>":L"");
/* Determine information to return */
if (CompareMem(Type, &gEfiFileInfoGuid, sizeof(*Type)) == 0) {
/* Fill file information */
PrintExtra(L"Get regular file information\n");
if (*Len < sizeof(EFI_FILE_INFO)) {
*Len = MINIMUM_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
ZeroMem(Data, sizeof(EFI_FILE_INFO));
Info->Attribute = EFI_FILE_READ_ONLY;
GrubTimeToEfiTime(File->Mtime, &Time);
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
if (File->IsDir) {
Info->Attribute |= EFI_FILE_DIRECTORY;
} else {
Info->FileSize = GrubGetFileSize(File);
Info->PhysicalSize = GrubGetFileSize(File);
}
tmpLen = (UINTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1);
Status = Utf8ToUtf16NoAllocUpdateLen(File->basename, Info->FileName, &tmpLen);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL) {
PrintStatusError(Status, L"Could not convert basename to UTF-16");
} else {
*Len = MINIMUM_INFO_LENGTH;
}
return Status;
}
/* The Info struct size already accounts for the extra NUL */
Info->Size = sizeof(EFI_FILE_INFO) + tmpLen;
*Len = (INTN)Info->Size;
return EFI_SUCCESS;
} else if (CompareMem(Type, &gEfiFileSystemInfoGuid, sizeof(*Type)) == 0) {
/* Get file system information */
PrintExtra(L"Get file system information\n");
if (*Len < sizeof(EFI_FILE_SYSTEM_INFO)) {
*Len = MINIMUM_FS_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
ZeroMem(Data, sizeof(EFI_FILE_INFO));
FSInfo->Size = *Len;
FSInfo->ReadOnly = 1;
/* NB: This should really be cluster size, but we don't have access to that */
if (File->FileSystem->BlockIo2 != NULL) {
FSInfo->BlockSize = File->FileSystem->BlockIo2->Media->BlockSize;
} else {
FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize;
}
if (FSInfo->BlockSize == 0) {
PrintWarning(L"Corrected Media BlockSize\n");
FSInfo->BlockSize = 512;
}
if (File->FileSystem->BlockIo2 != NULL) {
FSInfo->VolumeSize = (File->FileSystem->BlockIo2->Media->LastBlock + 1) *
FSInfo->BlockSize;
} else {
FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) *
FSInfo->BlockSize;
}
/* No idea if we can easily get this for GRUB, and the device is RO anyway */
FSInfo->FreeSpace = 0;
Status = GrubLabel(File, &label);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not read disk label");
FSInfo->VolumeLabel[0] = 0;
*Len = sizeof(EFI_FILE_SYSTEM_INFO);
} else {
tmpLen = (INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO) - 1);
Status = Utf8ToUtf16NoAllocUpdateLen(label, FSInfo->VolumeLabel, &tmpLen);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL) {
PrintStatusError(Status, L"Could not convert label to UTF-16");
} else {
*Len = MINIMUM_FS_INFO_LENGTH;
}
return Status;
}
FSInfo->Size = sizeof(EFI_FILE_SYSTEM_INFO) - 1 + tmpLen;
*Len = (INTN)FSInfo->Size;
}
return EFI_SUCCESS;
} else if (CompareMem(Type, &gEfiFileSystemVolumeLabelInfoIdGuid, sizeof(*Type)) == 0) {
/* Get the volume label */
Status = GrubLabel(File, &label);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not read disk label");
}
else {
Status = Utf8ToUtf16NoAllocUpdateLen(label, VLInfo->VolumeLabel, Len);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert label to UTF-16");
return Status;
}
}
return EFI_SUCCESS;
} else {
Print(L"'%s': Cannot get information of type ", FileName(File));
PrintGuid(Type);
Print(L"\n");
return EFI_UNSUPPORTED;
}
}
/**
* Set file information
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileSetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
Print(L"Cannot set information of type ");
PrintGuid(Type);
Print(L" for file '%s'\n", FileName(File));
return EFI_WRITE_PROTECTED;
}
/**
* Flush file modified data
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileFlush(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Flush(" PERCENT_P L"|'%s')\n", (UINTN) This, FileName(File));
return EFI_SUCCESS;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileFlushEx(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
{
return FileFlush(This);
}
/**
* Open root directory
*
* @v This EFI simple file system
* @ret Root File handle for the root directory
* @ret Status EFI status code
*/
EFI_STATUS EFIAPI
FileOpenVolume(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, EFI_FILE_HANDLE *Root)
{
EFI_FS *FSInstance = _CR(This, EFI_FS, FileIoInterface);
PrintInfo(L"OpenVolume\n");
*Root = &FSInstance->RootFile->EfiFile;
return EFI_SUCCESS;
}
/**
* Install the EFI simple file system protocol
* If successful this call instantiates a new FS#: drive, that is made
* available on the next 'map -r'. Note that all this call does is add
* the FS protocol. OpenVolume won't be called until a process tries
* to access a file or the root directory on the volume.
*/
EFI_STATUS
FSInstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
{
EFI_STATUS Status;
/* Check if it's a filesystem we can handle */
if (!GrubFSProbe(This))
return EFI_UNSUPPORTED;
PrintInfo(L"FSInstall: %s\n", This->DevicePathString);
/* Initialize the root handle */
Status = GrubCreateFile(&This->RootFile, This);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not create root file");
return Status;
}
/* Setup the EFI part */
This->RootFile->EfiFile.Revision = EFI_FILE_PROTOCOL_REVISION2;
This->RootFile->EfiFile.Open = FileOpen;
This->RootFile->EfiFile.Close = FileClose;
This->RootFile->EfiFile.Delete = FileDelete;
This->RootFile->EfiFile.Read = FileRead;
This->RootFile->EfiFile.Write = FileWrite;
This->RootFile->EfiFile.GetPosition = FileGetPosition;
This->RootFile->EfiFile.SetPosition = FileSetPosition;
This->RootFile->EfiFile.GetInfo = FileGetInfo;
This->RootFile->EfiFile.SetInfo = FileSetInfo;
This->RootFile->EfiFile.Flush = FileFlush;
This->RootFile->EfiFile.OpenEx = FileOpenEx;
This->RootFile->EfiFile.ReadEx = FileReadEx;
This->RootFile->EfiFile.WriteEx = FileWriteEx;
This->RootFile->EfiFile.FlushEx = FileFlushEx;
/* Setup the other attributes */
This->RootFile->path = "/";
This->RootFile->basename = &This->RootFile->path[1];
This->RootFile->IsDir = TRUE;
/* Install the simple file system protocol. */
Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
NULL);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not install simple file system protocol");
return Status;
}
return EFI_SUCCESS;
}
/* Uninstall EFI simple file system protocol */
VOID
FSUninstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
{
PrintInfo(L"FSUninstall: %s\n", This->DevicePathString);
BS->UninstallMultipleProtocolInterfaces(ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
NULL);
}
+86
View File
@@ -0,0 +1,86 @@
/* logging.c - EFI logging */
/*
* Copyright © 2014-2017 Pete Batard <[email protected]>
*
* 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 "driver.h"
/* Not defined in gnu-efi yet */
#define SHELL_VARIABLE_GUID { \
0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \
}
extern EFI_GUID gShellVariableGuid;
EFI_GUID ShellVariable = SHELL_VARIABLE_GUID;
static UINTN PrintNone(IN CONST CHAR16 *fmt, ... ) { return 0; }
Print_t PrintError = PrintNone;
Print_t PrintWarning = PrintNone;
Print_t PrintInfo = PrintNone;
Print_t PrintDebug = PrintNone;
Print_t PrintExtra = PrintNone;
Print_t* PrintTable[] = { &PrintError, &PrintWarning, &PrintInfo,
&PrintDebug, &PrintExtra };
/* Global driver verbosity level */
#if !defined(DEFAULT_LOGLEVEL)
#define DEFAULT_LOGLEVEL FS_LOGLEVEL_NONE
#endif
UINTN LogLevel = DEFAULT_LOGLEVEL;
/**
* Print status
*
* @v Status EFI status code
*/
VOID
PrintStatus(EFI_STATUS Status)
{
#if defined(__MAKEWITH_GNUEFI)
CHAR16 StatusString[64];
StatusToString(StatusString, Status);
// Make sure the Status is unsigned 32 bits
Print(L": [%d] %s\n", (Status & 0x7FFFFFFF), StatusString);
#else
Print(L": [%d]\n", (Status & 0x7FFFFFFF));
#endif
}
int g_fs_name_nocase = 0;
/*
* You can control the verbosity of the driver output by setting the shell environment
* variable FS_LOGGING to one of the values defined in the FS_LOGLEVEL constants
*/
VOID
SetLogging(VOID)
{
EFI_STATUS Status;
CHAR16 LogVar[4];
UINTN i, LogVarSize = sizeof(LogVar);
i = LogVarSize;
Status = RT->GetVariable(L"FS_NAME_NOCASE", &ShellVariable, NULL, &i, LogVar);
if (Status == EFI_SUCCESS)
g_fs_name_nocase = 1;
Status = RT->GetVariable(L"FS_LOGGING", &ShellVariable, NULL, &LogVarSize, LogVar);
if (Status == EFI_SUCCESS)
LogLevel = Atoi(LogVar);
for (i=0; i<ARRAYSIZE(PrintTable); i++)
*PrintTable[i] = (i < LogLevel)?(Print_t)Print:(Print_t)PrintNone;
PrintExtra(L"LogLevel = %d\n", LogLevel);
}
File diff suppressed because it is too large Load Diff
+784
View File
@@ -0,0 +1,784 @@
/* file.c - SimpleFileIo Interface */
/*
* Copyright © 2014-2017 Pete Batard <[email protected]>
* Based on iPXE's efi_driver.c and efi_file.c:
* Copyright © 2011,2013 Michael Brown <[email protected]>.
*
* 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 "driver.h"
/**
* Get EFI file name (for debugging)
*
* @v file EFI file
* @ret Name Name
*/
static const CHAR16 *
FileName(EFI_GRUB_FILE *File)
{
EFI_STATUS Status;
static CHAR16 Path[MAX_PATH];
Status = Utf8ToUtf16NoAlloc(File->path, Path, sizeof(Path));
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not convert filename to UTF16");
return NULL;
}
return Path;
}
/* Simple hook to populate the timestamp and directory flag when opening a file */
static INT32
InfoHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *Info, VOID *Data)
{
EFI_GRUB_FILE *File = (EFI_GRUB_FILE *) Data;
/* Look for a specific file */
if (strcmpa(name, File->basename) != 0)
return 0;
File->IsDir = (BOOLEAN) (Info->Dir);
if (Info->MtimeSet)
File->Mtime = Info->Mtime;
return 0;
}
/**
* Open file
*
* @v This File handle
* @ret new New file handle
* @v Name File name
* @v Mode File mode
* @v Attributes File attributes (for newly-created files)
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New,
CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
{
EFI_STATUS Status;
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
EFI_GRUB_FILE *NewFile;
// TODO: Use dynamic buffers?
char path[MAX_PATH], clean_path[MAX_PATH], *dirname;
INTN i, len;
BOOLEAN AbsolutePath = (*Name == L'\\');
PrintInfo(L"Open(" PERCENT_P L"%s, \"%s\")\n", (UINTN) This,
IS_ROOT(File)?L" <ROOT>":L"", Name);
/* Fail unless opening read-only */
if (Mode != EFI_FILE_MODE_READ) {
PrintWarning(L"File '%s' can only be opened in read-only mode\n", Name);
return EFI_WRITE_PROTECTED;
}
/* Additional failures */
if ((StrCmp(Name, L"..") == 0) && IS_ROOT(File)) {
PrintInfo(L"Trying to open <ROOT>'s parent\n");
return EFI_NOT_FOUND;
}
/* See if we're trying to reopen current (which the EFI Shell insists on doing) */
if ((*Name == 0) || (StrCmp(Name, L".") == 0)) {
PrintInfo(L" Reopening %s\n", IS_ROOT(File)?L"<ROOT>":FileName(File));
File->RefCount++;
*New = This;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
/* If we have an absolute path, don't bother completing with the parent */
if (AbsolutePath) {
len = 0;
} else {
strcpya(path, File->path);
len = strlena(path);
/* Add delimiter if needed */
if ((len == 0) || (path[len-1] != '/'))
path[len++] = '/';
}
/* Copy the rest of the path (converted to UTF-8) */
Status = Utf16ToUtf8NoAlloc(Name, &path[len], sizeof(path) - len);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not convert path to UTF-8");
return Status;
}
/* Convert the delimiters */
for (i = strlena(path) - 1 ; i >= len; i--) {
if (path[i] == '\\')
path[i] = '/';
}
/* We only want to handle with absolute paths */
clean_path[0] = '/';
/* Find out if we're dealing with root by removing the junk */
CopyPathRelative(&clean_path[1], path, MAX_PATH - 1);
if (clean_path[1] == 0) {
/* We're dealing with the root */
PrintInfo(L" Reopening <ROOT>\n");
*New = &File->FileSystem->RootFile->EfiFile;
/* Must make sure that DirIndex is reset too (NB: no concurrent access!) */
File->FileSystem->RootFile->DirIndex = 0;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
// TODO: eventually we should seek for already opened files and increase RefCount
/* Allocate and initialise an instance of a file */
Status = GrubCreateFile(&NewFile, File->FileSystem);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not instantiate file");
return Status;
}
NewFile->path = AllocatePool(strlena(clean_path)+1);
if (NewFile->path == NULL) {
GrubDestroyFile(NewFile);
PrintError(L"Could not instantiate path\n");
return EFI_OUT_OF_RESOURCES;
}
strcpya(NewFile->path, clean_path);
/* Isolate the basename and dirname */
for (i = strlena(clean_path) - 1; i >= 0; i--) {
if (clean_path[i] == '/') {
clean_path[i] = 0;
break;
}
}
dirname = (i <= 0) ? "/" : clean_path;
NewFile->basename = &NewFile->path[i+1];
/* Find if we're working with a directory and fill the grub timestamp */
Status = GrubDir(NewFile, dirname, InfoHook, (VOID *) NewFile);
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_FOUND)
PrintStatusError(Status, L"Could not get file attributes for '%s'", Name);
FreePool(NewFile->path);
GrubDestroyFile(NewFile);
return Status;
}
/* Finally we can call on GRUB open() if it's a regular file */
if (!NewFile->IsDir) {
Status = GrubOpen(NewFile);
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_FOUND)
PrintStatusError(Status, L"Could not open file '%s'", Name);
FreePool(NewFile->path);
GrubDestroyFile(NewFile);
return Status;
}
}
NewFile->RefCount++;
*New = &NewFile->EfiFile;
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
return EFI_SUCCESS;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileOpenEx(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name,
UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
{
return FileOpen(This, New, Name, Mode, Attributes);
}
/**
* Close file
*
* @v This File handle
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileClose(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Close(" PERCENT_P L"|'%s') %s\n", (UINTN) This, FileName(File),
IS_ROOT(File)?L"<ROOT>":L"");
/* Nothing to do it this is the root */
if (IS_ROOT(File))
return EFI_SUCCESS;
if (--File->RefCount == 0) {
/* Close the file if it's a regular one */
if (!File->IsDir)
GrubClose(File);
/* NB: basename points into File->path and does not need to be freed */
if (File->path != NULL)
FreePool(File->path);
GrubDestroyFile(File);
}
return EFI_SUCCESS;
}
/**
* Close and delete file
*
* @v This File handle
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileDelete(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintError(L"Cannot delete '%s'\n", FileName(File));
/* Close file */
FileClose(This);
/* Warn of failure to delete */
return EFI_WARN_DELETE_FAILURE;
}
/* GRUB uses a callback for each directory entry, whereas EFI uses repeated
* firmware generated calls to FileReadDir() to get the info for each entry,
* so we have to reconcile the twos. For now, we'll re-issue a call to GRUB
* dir(), and run through all the entries (to find the one we
* are interested in) multiple times. Maybe later we'll try to optimize this
* by building a one-off chained list of entries that we can parse...
*/
static INT32
DirHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *DirInfo, VOID *Data)
{
EFI_STATUS Status;
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
INT64 *Index = (INT64 *) &Info->FileSize;
CHAR8 *filename = (CHAR8 *) (UINTN) Info->PhysicalSize;
EFI_TIME Time = { 1970, 01, 01, 00, 00, 00, 0, 0, 0, 0, 0};
// Eliminate '.' or '..'
if ((name[0] == '.') && ((name[1] == 0) || ((name[1] == '.') && (name[2] == 0))))
return 0;
/* Ignore any entry that doesn't match our index */
if ((*Index)-- != 0)
return 0;
strcpya(filename, name);
Status = Utf8ToUtf16NoAlloc(filename, Info->FileName, (INTN)(Info->Size - sizeof(EFI_FILE_INFO)));
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert directory entry to UTF-8");
return (INT32) Status;
}
/* The Info struct size already accounts for the extra NUL */
Info->Size = sizeof(*Info) + StrLen(Info->FileName) * sizeof(CHAR16);
// Oh, and of course GRUB uses a 32 bit signed mtime value (seriously, wtf guys?!?)
if (DirInfo->MtimeSet)
GrubTimeToEfiTime(DirInfo->Mtime, &Time);
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
Info->Attribute = EFI_FILE_READ_ONLY;
if (DirInfo->Dir)
Info->Attribute |= EFI_FILE_DIRECTORY;
return 0;
}
/**
* Read directory entry
*
* @v file EFI file
* @v Len Length to read
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS
FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data)
{
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
EFI_STATUS Status;
/* We temporarily repurpose the FileSize as a *signed* entry index */
INT64 *Index = (INT64 *) &Info->FileSize;
/* And PhysicalSize as a pointer to our filename */
CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize;
CHAR8 path[MAX_PATH];
EFI_GRUB_FILE *TmpFile = NULL;
INTN len;
/* Unless we can fit our maximum size, forget it */
if (*Len < MINIMUM_INFO_LENGTH) {
*Len = MINIMUM_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
/* Populate our Info template */
ZeroMem(Data, *Len);
Info->Size = *Len;
*Index = File->DirIndex;
strcpya(path, File->path);
len = strlena(path);
if (path[len-1] != '/')
path[len++] = '/';
*basename = &path[len];
/* Invoke GRUB's directory listing */
Status = GrubDir(File, File->path, DirHook, Data);
if (*Index >= 0) {
/* No more entries */
*Len = 0;
return EFI_SUCCESS;
}
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Directory listing failed");
return Status;
}
/* Our Index/FileSize must be reset */
Info->FileSize = 0;
Info->PhysicalSize = 0;
/* For regular files, we still need to fill the size */
if (!(Info->Attribute & EFI_FILE_DIRECTORY)) {
/* Open the file and read its size */
Status = GrubCreateFile(&TmpFile, File->FileSystem);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Unable to create temporary file");
return Status;
}
TmpFile->path = path;
Status = GrubOpen(TmpFile);
if (EFI_ERROR(Status)) {
// TODO: EFI_NO_MAPPING is returned for links...
PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName);
/* Non fatal error */
} else {
Info->FileSize = GrubGetFileSize(TmpFile);
Info->PhysicalSize = GrubGetFileSize(TmpFile);
GrubClose(TmpFile);
}
GrubDestroyFile(TmpFile);
}
*Len = (UINTN) Info->Size;
/* Advance to the next entry */
File->DirIndex++;
// PrintInfo(L" Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName,
// (Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L"");
return EFI_SUCCESS;
}
/**
* Read from file
*
* @v This File handle
* @v Len Length to read
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileRead(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Read(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File),
*Len, File->IsDir?L"<DIR>":L"");
/* If this is a directory, then fetch the directory entries */
if (File->IsDir)
return FileReadDir(File, Len, Data);
return GrubRead(File, Data, Len);
}
/* Ex version */
static EFI_STATUS EFIAPI
FileReadEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
{
return FileRead(This, &(Token->BufferSize), Token->Buffer);
}
/**
* Write to file
*
* @v This File handle
* @v Len Length to write
* @v Data Data buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileWrite(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintError(L"Cannot write to '%s'\n", FileName(File));
return EFI_WRITE_PROTECTED;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileWriteEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
{
return FileWrite(This, &(Token->BufferSize), Token->Buffer);
}
/**
* Set file position
*
* @v This File handle
* @v Position New file position
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
UINT64 FileSize;
PrintInfo(L"SetPosition(" PERCENT_P L"|'%s', %lld) %s\n", (UINTN) This,
FileName(File), Position, (File->IsDir)?L"<DIR>":L"");
/* If this is a directory, reset the Index to the start */
if (File->IsDir) {
if (Position != 0)
return EFI_INVALID_PARAMETER;
File->DirIndex = 0;
return EFI_SUCCESS;
}
/* Fail if we attempt to seek past the end of the file (since
* we do not support writes).
*/
FileSize = GrubGetFileSize(File);
if (Position > FileSize) {
PrintError(L"'%s': Cannot seek to #%llx of %llx\n",
FileName(File), Position, FileSize);
return EFI_UNSUPPORTED;
}
/* Set position */
GrubSetFileOffset(File, Position);
PrintDebug(L"'%s': Position set to %llx\n",
FileName(File), Position);
return EFI_SUCCESS;
}
/**
* Get file position
*
* @v This File handle
* @ret Position New file position
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileGetPosition(EFI_FILE_HANDLE This, UINT64 *Position)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"GetPosition(" PERCENT_P L"|'%s', %lld)\n", (UINTN) This, FileName(File));
if (File->IsDir)
*Position = File->DirIndex;
else
*Position = GrubGetFileOffset(File);
return EFI_SUCCESS;
}
/**
* Get file information
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
{
EFI_STATUS Status;
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data;
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *VLInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Data;
EFI_TIME Time;
CHAR8* label;
UINTN tmpLen;
PrintInfo(L"GetInfo(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This,
FileName(File), *Len, File->IsDir?L"<DIR>":L"");
/* Determine information to return */
if (CompareMem(Type, &gEfiFileInfoGuid, sizeof(*Type)) == 0) {
/* Fill file information */
PrintExtra(L"Get regular file information\n");
if (*Len < MINIMUM_INFO_LENGTH) {
*Len = MINIMUM_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
ZeroMem(Data, sizeof(EFI_FILE_INFO));
Info->Attribute = EFI_FILE_READ_ONLY;
GrubTimeToEfiTime(File->Mtime, &Time);
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
if (File->IsDir) {
Info->Attribute |= EFI_FILE_DIRECTORY;
} else {
Info->FileSize = GrubGetFileSize(File);
Info->PhysicalSize = GrubGetFileSize(File);
}
tmpLen = (UINTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1);
Status = Utf8ToUtf16NoAllocUpdateLen(File->basename, Info->FileName, &tmpLen);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert basename to UTF-16");
return Status;
}
/* The Info struct size already accounts for the extra NUL */
Info->Size = sizeof(EFI_FILE_INFO) + tmpLen;
*Len = (INTN)Info->Size;
return EFI_SUCCESS;
} else if (CompareMem(Type, &gEfiFileSystemInfoGuid, sizeof(*Type)) == 0) {
/* Get file system information */
PrintExtra(L"Get file system information\n");
if (*Len < MINIMUM_FS_INFO_LENGTH) {
*Len = MINIMUM_FS_INFO_LENGTH;
return EFI_BUFFER_TOO_SMALL;
}
ZeroMem(Data, sizeof(EFI_FILE_INFO));
FSInfo->Size = *Len;
FSInfo->ReadOnly = 1;
/* NB: This should really be cluster size, but we don't have access to that */
if (File->FileSystem->BlockIo2 != NULL) {
FSInfo->BlockSize = File->FileSystem->BlockIo2->Media->BlockSize;
} else {
FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize;
}
if (FSInfo->BlockSize == 0) {
PrintWarning(L"Corrected Media BlockSize\n");
FSInfo->BlockSize = 512;
}
if (File->FileSystem->BlockIo2 != NULL) {
FSInfo->VolumeSize = (File->FileSystem->BlockIo2->Media->LastBlock + 1) *
FSInfo->BlockSize;
} else {
FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) *
FSInfo->BlockSize;
}
/* No idea if we can easily get this for GRUB, and the device is RO anyway */
FSInfo->FreeSpace = 0;
Status = GrubLabel(File, &label);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not read disk label");
FSInfo->VolumeLabel[0] = 0;
*Len = sizeof(EFI_FILE_SYSTEM_INFO);
} else {
tmpLen = (INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO) - 1);
Status = Utf8ToUtf16NoAllocUpdateLen(label, FSInfo->VolumeLabel, &tmpLen);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert label to UTF-16");
return Status;
}
FSInfo->Size = sizeof(EFI_FILE_SYSTEM_INFO) - 1 + tmpLen;
*Len = (INTN)FSInfo->Size;
}
return EFI_SUCCESS;
} else if (CompareMem(Type, &gEfiFileSystemVolumeLabelInfoIdGuid, sizeof(*Type)) == 0) {
/* Get the volume label */
Status = GrubLabel(File, &label);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not read disk label");
}
else {
Status = Utf8ToUtf16NoAllocUpdateLen(label, VLInfo->VolumeLabel, Len);
if (EFI_ERROR(Status)) {
if (Status != EFI_BUFFER_TOO_SMALL)
PrintStatusError(Status, L"Could not convert label to UTF-16");
return Status;
}
}
return EFI_SUCCESS;
} else {
Print(L"'%s': Cannot get information of type ", FileName(File));
PrintGuid(Type);
Print(L"\n");
return EFI_UNSUPPORTED;
}
}
/**
* Set file information
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileSetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
Print(L"Cannot set information of type ");
PrintGuid(Type);
Print(L" for file '%s'\n", FileName(File));
return EFI_WRITE_PROTECTED;
}
/**
* Flush file modified data
*
* @v This File handle
* @v Type Type of information
* @v Len Buffer size
* @v Data Buffer
* @ret Status EFI status code
*/
static EFI_STATUS EFIAPI
FileFlush(EFI_FILE_HANDLE This)
{
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
PrintInfo(L"Flush(" PERCENT_P L"|'%s')\n", (UINTN) This, FileName(File));
return EFI_SUCCESS;
}
/* Ex version */
static EFI_STATUS EFIAPI
FileFlushEx(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
{
return FileFlush(This);
}
/**
* Open root directory
*
* @v This EFI simple file system
* @ret Root File handle for the root directory
* @ret Status EFI status code
*/
EFI_STATUS EFIAPI
FileOpenVolume(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, EFI_FILE_HANDLE *Root)
{
EFI_FS *FSInstance = _CR(This, EFI_FS, FileIoInterface);
PrintInfo(L"OpenVolume\n");
*Root = &FSInstance->RootFile->EfiFile;
return EFI_SUCCESS;
}
/**
* Install the EFI simple file system protocol
* If successful this call instantiates a new FS#: drive, that is made
* available on the next 'map -r'. Note that all this call does is add
* the FS protocol. OpenVolume won't be called until a process tries
* to access a file or the root directory on the volume.
*/
EFI_STATUS
FSInstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
{
EFI_STATUS Status;
/* Check if it's a filesystem we can handle */
if (!GrubFSProbe(This))
return EFI_UNSUPPORTED;
PrintInfo(L"FSInstall: %s\n", This->DevicePathString);
/* Initialize the root handle */
Status = GrubCreateFile(&This->RootFile, This);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not create root file");
return Status;
}
/* Setup the EFI part */
This->RootFile->EfiFile.Revision = EFI_FILE_PROTOCOL_REVISION2;
This->RootFile->EfiFile.Open = FileOpen;
This->RootFile->EfiFile.Close = FileClose;
This->RootFile->EfiFile.Delete = FileDelete;
This->RootFile->EfiFile.Read = FileRead;
This->RootFile->EfiFile.Write = FileWrite;
This->RootFile->EfiFile.GetPosition = FileGetPosition;
This->RootFile->EfiFile.SetPosition = FileSetPosition;
This->RootFile->EfiFile.GetInfo = FileGetInfo;
This->RootFile->EfiFile.SetInfo = FileSetInfo;
This->RootFile->EfiFile.Flush = FileFlush;
This->RootFile->EfiFile.OpenEx = FileOpenEx;
This->RootFile->EfiFile.ReadEx = FileReadEx;
This->RootFile->EfiFile.WriteEx = FileWriteEx;
This->RootFile->EfiFile.FlushEx = FileFlushEx;
/* Setup the other attributes */
This->RootFile->path = "/";
This->RootFile->basename = &This->RootFile->path[1];
This->RootFile->IsDir = TRUE;
/* Install the simple file system protocol. */
Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
NULL);
if (EFI_ERROR(Status)) {
PrintStatusError(Status, L"Could not install simple file system protocol");
return Status;
}
return EFI_SUCCESS;
}
/* Uninstall EFI simple file system protocol */
VOID
FSUninstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
{
PrintInfo(L"FSUninstall: %s\n", This->DevicePathString);
BS->UninstallMultipleProtocolInterfaces(ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
NULL);
}
+80
View File
@@ -0,0 +1,80 @@
/* logging.c - EFI logging */
/*
* Copyright © 2014-2017 Pete Batard <[email protected]>
*
* 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 "driver.h"
/* Not defined in gnu-efi yet */
#define SHELL_VARIABLE_GUID { \
0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \
}
extern EFI_GUID gShellVariableGuid;
EFI_GUID ShellVariable = SHELL_VARIABLE_GUID;
static UINTN PrintNone(IN CONST CHAR16 *fmt, ... ) { return 0; }
Print_t PrintError = PrintNone;
Print_t PrintWarning = PrintNone;
Print_t PrintInfo = PrintNone;
Print_t PrintDebug = PrintNone;
Print_t PrintExtra = PrintNone;
Print_t* PrintTable[] = { &PrintError, &PrintWarning, &PrintInfo,
&PrintDebug, &PrintExtra };
/* Global driver verbosity level */
#if !defined(DEFAULT_LOGLEVEL)
#define DEFAULT_LOGLEVEL FS_LOGLEVEL_NONE
#endif
UINTN LogLevel = DEFAULT_LOGLEVEL;
/**
* Print status
*
* @v Status EFI status code
*/
VOID
PrintStatus(EFI_STATUS Status)
{
#if defined(__MAKEWITH_GNUEFI)
CHAR16 StatusString[64];
StatusToString(StatusString, Status);
// Make sure the Status is unsigned 32 bits
Print(L": [%d] %s\n", (Status & 0x7FFFFFFF), StatusString);
#else
Print(L": [%d]\n", (Status & 0x7FFFFFFF));
#endif
}
/*
* You can control the verbosity of the driver output by setting the shell environment
* variable FS_LOGGING to one of the values defined in the FS_LOGLEVEL constants
*/
VOID
SetLogging(VOID)
{
EFI_STATUS Status;
CHAR16 LogVar[4];
UINTN i, LogVarSize = sizeof(LogVar);
Status = RT->GetVariable(L"FS_LOGGING", &ShellVariable, NULL, &LogVarSize, LogVar);
if (Status == EFI_SUCCESS)
LogLevel = Atoi(LogVar);
for (i=0; i<ARRAYSIZE(PrintTable); i++)
*PrintTable[i] = (i < LogLevel)?(Print_t)Print:(Print_t)PrintNone;
PrintExtra(L"LogLevel = %d\n", LogLevel);
}