From b87fc6b140772ba3017de311c7063c259424264c Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Aug 2016 17:11:31 +0200 Subject: First public release. Used by VeraCrypt 1.18. --- Library/CommonLib/EfiBio.c | 232 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 Library/CommonLib/EfiBio.c (limited to 'Library/CommonLib/EfiBio.c') diff --git a/Library/CommonLib/EfiBio.c b/Library/CommonLib/EfiBio.c new file mode 100644 index 0000000..9577c08 --- /dev/null +++ b/Library/CommonLib/EfiBio.c @@ -0,0 +1,232 @@ +/** @file +EFI block I/O helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Print handle info +////////////////////////////////////////////////////////////////////////// + +VOID +EfiPrintDevicePath( + IN EFI_HANDLE handle) +{ + CHAR16 *StrPath; + EFI_DEVICE_PATH *DevicePath; + OUT_PRINT(L"(%0X): ", handle); + DevicePath = DevicePathFromHandle(handle); + if (DevicePath == NULL) { + ERR_PRINT(L"No path found"); + return; + } + StrPath = ConvertDevicePathToText(DevicePath, FALSE, FALSE); + OUT_PRINT(StrPath); + MEM_FREE(StrPath); +} + +VOID +EfiPrintProtocols( + IN EFI_HANDLE handle) +{ + EFI_GUID **guids; + UINTN count; + EFI_STATUS status; + status = gBS->ProtocolsPerHandle(handle, &guids, &count); + if (!EFI_ERROR(status)) { + UINTN i; + for (i = 0; i < count; ++i) { + OUT_PRINT(L"%d: %g\n", i, guids[i]); + } + FreePool(guids); + } +} + +////////////////////////////////////////////////////////////////////////// +// Handles +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiGetHandles( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + OUT EFI_HANDLE **Buffer, + OUT UINTN *Count + ) +{ + EFI_STATUS res = EFI_BUFFER_TOO_SMALL; + UINTN BufferSize; + if(*Buffer != NULL) MEM_FREE(*Buffer); + *Count = 0; + *Buffer = (EFI_HANDLE*) MEM_ALLOC(sizeof(EFI_HANDLE)); + if (*Buffer) { + BufferSize = sizeof(EFI_HANDLE); + res = gBS->LocateHandle(SearchType, Protocol, SearchKey, &BufferSize, *Buffer); + if (res == RETURN_BUFFER_TOO_SMALL) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)MEM_ALLOC(BufferSize); + if (!Buffer) { + return EFI_OUT_OF_RESOURCES; + } + res = gBS->LocateHandle(SearchType, Protocol, SearchKey, &BufferSize, *Buffer); + if(res != EFI_SUCCESS) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)NULL; + return res; + } + } else if (EFI_ERROR(res)) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)NULL; + return res; + } + *Count = (UINTN)(BufferSize / sizeof(EFI_HANDLE)); + } + return res; +} + +EFI_STATUS +EfiGetStartDevice( + OUT EFI_HANDLE* handle) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + Status = gBS->HandleProtocol(gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); + if (EFI_ERROR(Status)) { + return Status; + } + *handle = LoadedImage->DeviceHandle; + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// Block I/O +////////////////////////////////////////////////////////////////////////// + +EFI_BLOCK_IO_PROTOCOL* +EfiGetBlockIO( + IN EFI_HANDLE handle + ) +{ + EFI_STATUS res; + EFI_BLOCK_IO_PROTOCOL* blockIOProtocol = NULL; + res = gBS->HandleProtocol(handle, &gEfiBlockIoProtocolGuid, (VOID**)&blockIOProtocol); + if (res == RETURN_SUCCESS && + blockIOProtocol != NULL && + blockIOProtocol->Media->MediaPresent) { + return blockIOProtocol; + } + return NULL; +} + + +EFI_HANDLE* gBIOHandles; +UINTN gBIOCount; + +EFI_STATUS +InitBio() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiBlockIoProtocolGuid, 0, &gBIOHandles, &gBIOCount); + return res; +} + +BOOLEAN +EfiIsPartition( + IN EFI_HANDLE h + ) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + node = DevicePathFromHandle(h); + if (node == NULL) return FALSE; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + return TRUE; + } + node = NextDevicePathNode(node); + } + return FALSE; +} + +EFI_STATUS +EfiGetPartDetails( + IN EFI_HANDLE h, + OUT HARDDRIVE_DEVICE_PATH* dpVolme, + OUT EFI_HANDLE* hDisk) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + EFI_DEVICE_PATH_PROTOCOL* dpVolume; + EFI_DEVICE_PATH_PROTOCOL* dpDisk; + EFI_STATUS res; + dpVolume = DevicePathFromHandle(h); + dpDisk = DuplicateDevicePath(dpVolume); + node = (EFI_DEVICE_PATH_PROTOCOL *)dpDisk; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + CopyMem(dpVolme, node, sizeof(HARDDRIVE_DEVICE_PATH)); + SetDevicePathEndNode(node); + res = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &dpDisk, hDisk); + return res; + } + node = NextDevicePathNode(node); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiGetPartGUID( + IN EFI_HANDLE h, + OUT EFI_GUID* guid) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + EFI_DEVICE_PATH_PROTOCOL* dpVolume; + if (guid == NULL) return EFI_INVALID_PARAMETER; + dpVolume = DevicePathFromHandle(h); + node = (EFI_DEVICE_PATH_PROTOCOL *)dpVolume; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + HARDDRIVE_DEVICE_PATH* hdpNode = (HARDDRIVE_DEVICE_PATH*)node; + CopyMem(guid, hdpNode->Signature, sizeof(*guid)); + return EFI_SUCCESS; + } + node = NextDevicePathNode(node); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiFindPartByGUID( + IN EFI_GUID* guid, + OUT EFI_HANDLE* h + ) +{ + EFI_STATUS res; + EFI_GUID guidI; + UINTN i; + if (guid == NULL || h == NULL) return EFI_INVALID_PARAMETER; + for (i = 0; i < gBIOCount; ++i) { + res = EfiGetPartGUID(gBIOHandles[i], &guidI); + if (!EFI_ERROR(res)) { + if (CompareMem(&guidI, guid, sizeof(guidI)) == 0) { + *h = gBIOHandles[i]; + return EFI_SUCCESS; + } + } + } + return EFI_NOT_FOUND; +} + + -- cgit v1.2.3