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/CommonLib.inf | 65 +++++ Library/CommonLib/EfiAttrPrint.c | 477 ++++++++++++++++++++++++++++++++++ Library/CommonLib/EfiBeep.c | 69 +++++ Library/CommonLib/EfiBio.c | 232 +++++++++++++++++ Library/CommonLib/EfiConsole.c | 347 +++++++++++++++++++++++++ Library/CommonLib/EfiExec.c | 88 +++++++ Library/CommonLib/EfiFile.c | 350 +++++++++++++++++++++++++ Library/CommonLib/EfiMem.c | 74 ++++++ Library/CommonLib/EfiTouch.c | 47 ++++ Library/CommonLib/EfiUsb.c | 88 +++++++ Library/CommonLib/EfiVar.c | 228 ++++++++++++++++ Library/CommonLib/IA32/EfiCpuHalt.asm | 19 ++ Library/CommonLib/X64/EfiCpuHalt.asm | 17 ++ 13 files changed, 2101 insertions(+) create mode 100644 Library/CommonLib/CommonLib.inf create mode 100644 Library/CommonLib/EfiAttrPrint.c create mode 100644 Library/CommonLib/EfiBeep.c create mode 100644 Library/CommonLib/EfiBio.c create mode 100644 Library/CommonLib/EfiConsole.c create mode 100644 Library/CommonLib/EfiExec.c create mode 100644 Library/CommonLib/EfiFile.c create mode 100644 Library/CommonLib/EfiMem.c create mode 100644 Library/CommonLib/EfiTouch.c create mode 100644 Library/CommonLib/EfiUsb.c create mode 100644 Library/CommonLib/EfiVar.c create mode 100644 Library/CommonLib/IA32/EfiCpuHalt.asm create mode 100644 Library/CommonLib/X64/EfiCpuHalt.asm (limited to 'Library/CommonLib') diff --git a/Library/CommonLib/CommonLib.inf b/Library/CommonLib/CommonLib.inf new file mode 100644 index 0000000..2c379b8 --- /dev/null +++ b/Library/CommonLib/CommonLib.inf @@ -0,0 +1,65 @@ +## @file +# EFI common library (helpers) +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, 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 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = CommonLib + MODULE_UNI_FILE = CommonLib.uni + FILE_GUID = F779769D-58F4-4A49-A7D7-59473BBD3CCE + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = CommonLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + EfiMem.c + EfiBio.c + EfiVar.c + EfiFile.c + EfiConsole.c + EfiAttrPrint.c + EfiBeep.c + EfiExec.c + EfiUsb.c + EfiTouch.c + +[Sources.IA32] + IA32/EfiCpuHalt.asm + +[Sources.X64] + X64/EfiCpuHalt.asm + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + ShellPkg/ShellPkg.dec + + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + UefiUsbLib + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiUsbIoProtocolGuid + gEfiAbsolutePointerProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiSimpleTextOutProtocolGuid diff --git a/Library/CommonLib/EfiAttrPrint.c b/Library/CommonLib/EfiAttrPrint.c new file mode 100644 index 0000000..adcd606 --- /dev/null +++ b/Library/CommonLib/EfiAttrPrint.c @@ -0,0 +1,477 @@ +/** @file +EFI console print with attribute (based on shell print) + +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 +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Custom print based on shell print (copied here to avoid runtime limitation) +////////////////////////////////////////////////////////////////////////// + +#define ATTRPRINT_BUFSIZE 4096 + +BOOLEAN gShellReady = FALSE; +EFI_SHELL_PARAMETERS_PROTOCOL* mEfiShellParametersProtocol = NULL; +EFI_SHELL_PROTOCOL* mEfiShellProtocol = NULL; + +VOID +SetShellAPI( + IN VOID* shellProtocol, + IN VOID* shellParametersProtocol) { + mEfiShellParametersProtocol = (EFI_SHELL_PARAMETERS_PROTOCOL*)shellParametersProtocol; + mEfiShellProtocol = (EFI_SHELL_PROTOCOL*)shellProtocol; +} + +/** + Safely append with automatic string resizing given length of Destination and + desired length of copy from Source. + + append the first D characters of Source to the end of Destination, where D is + the lesser of Count and the StrLen() of Source. If appending those D characters + will fit within Destination (whose Size is given as CurrentSize) and + still leave room for a NULL terminator, then those characters are appended, + starting at the original terminating NULL of Destination, and a new terminating + NULL is appended. + + If appending D characters onto Destination will result in a overflow of the size + given in CurrentSize the string will be grown such that the copy can be performed + and CurrentSize will be updated to the new size. + + If Source is NULL, there is nothing to append, just return the current buffer in + Destination. + + if Destination is NULL, then ASSERT() + if Destination's current length (including NULL terminator) is already more then + CurrentSize, then ASSERT() + + @param[in, out] Destination The String to append onto + @param[in, out] CurrentSize on call the number of bytes in Destination. On + return possibly the new size (still in bytes). if NULL + then allocate whatever is needed. + @param[in] Source The String to append from + @param[in] Count Maximum number of characters to append. if 0 then + all are appended. + + @return Destination return the resultant string. +**/ +CHAR16* +EFIAPI +StrnCatGrow2 ( + IN OUT CHAR16 **Destination, + IN OUT UINTN *CurrentSize, + IN CONST CHAR16 *Source, + IN UINTN Count + ) +{ + UINTN DestinationStartSize; + UINTN NewSize; + + // + // ASSERTs + // + ASSERT(Destination != NULL); + + // + // If there's nothing to do then just return Destination + // + if (Source == NULL) { + return (*Destination); + } + + // + // allow for un-initialized pointers, based on size being 0 + // + if (CurrentSize != NULL && *CurrentSize == 0) { + *Destination = NULL; + } + + // + // allow for NULL pointers address as Destination + // + if (*Destination != NULL) { + ASSERT(CurrentSize != 0); + DestinationStartSize = StrSize(*Destination); + ASSERT(DestinationStartSize <= *CurrentSize); + } else { + DestinationStartSize = 0; +// ASSERT(*CurrentSize == 0); + } + + // + // Append all of Source? + // + if (Count == 0) { + Count = StrLen(Source); + } + + // + // Test and grow if required + // + if (CurrentSize != NULL) { + NewSize = *CurrentSize; + if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) { + while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) { + NewSize += 2 * Count * sizeof(CHAR16); + } + *Destination = MEM_REALLOC(*CurrentSize, NewSize, *Destination); + *CurrentSize = NewSize; + } + } else { + NewSize = (Count+1)*sizeof(CHAR16); + *Destination = MEM_ALLOC(NewSize); + } + + // + // Now use standard StrnCat on a big enough buffer + // + if (*Destination == NULL) { + return (NULL); + } + + StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count); + return *Destination; +} + + +/** + This is a find and replace function. Upon successful return the NewString is a copy of + SourceString with each instance of FindTarget replaced with ReplaceWith. + + If SourceString and NewString overlap the behavior is undefined. + + If the string would grow bigger than NewSize it will halt and return error. + + @param[in] SourceString The string with source buffer. + @param[in, out] NewString The string with resultant buffer. + @param[in] NewSize The size in bytes of NewString. + @param[in] FindTarget The string to look for. + @param[in] ReplaceWith The string to replace FindTarget with. + @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^' + immediately before it. + @param[in] ParameterReplacing If TRUE will add "" around items with spaces. + + @retval EFI_INVALID_PARAMETER SourceString was NULL. + @retval EFI_INVALID_PARAMETER NewString was NULL. + @retval EFI_INVALID_PARAMETER FindTarget was NULL. + @retval EFI_INVALID_PARAMETER ReplaceWith was NULL. + @retval EFI_INVALID_PARAMETER FindTarget had length < 1. + @retval EFI_INVALID_PARAMETER SourceString had length < 1. + @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold + the new string (truncation occurred). + @retval EFI_SUCCESS The string was successfully copied with replacement. +**/ +EFI_STATUS +EFIAPI +StrCopySearchAndReplace( + IN CHAR16 CONST *SourceString, + IN OUT CHAR16 *NewString, + IN UINTN NewSize, + IN CONST CHAR16 *FindTarget, + IN CONST CHAR16 *ReplaceWith, + IN CONST BOOLEAN SkipPreCarrot, + IN CONST BOOLEAN ParameterReplacing + ) +{ + UINTN Size; + CHAR16 *Replace; + + if ( (SourceString == NULL) + || (NewString == NULL) + || (FindTarget == NULL) + || (ReplaceWith == NULL) + || (StrLen(FindTarget) < 1) + || (StrLen(SourceString) < 1) + ){ + return (EFI_INVALID_PARAMETER); + } + Replace = NULL; + if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) { + Replace = StrnCatGrow2(&Replace, NULL, ReplaceWith, 0); + } else { + Replace = MEM_ALLOC(StrSize(ReplaceWith) + 2*sizeof(CHAR16)); + if (Replace != NULL) { + UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith); + } + } + if (Replace == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + NewString = ZeroMem(NewString, NewSize); + while (*SourceString != CHAR_NULL) { + // + // if we find the FindTarget and either Skip == FALSE or Skip and we + // dont have a carrot do a replace... + // + if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0 + && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot) + ){ + SourceString += StrLen(FindTarget); + Size = StrSize(NewString); + if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) { + MEM_FREE(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrCatS(NewString, NewSize/sizeof(CHAR16), Replace); + } else { + Size = StrSize(NewString); + if (Size + sizeof(CHAR16) > NewSize) { + MEM_FREE(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1); + SourceString++; + } + } + MEM_FREE(Replace); + return (EFI_SUCCESS); +} + +/** + Internal worker function to output a string. + + This function will output a string to the correct StdOut. + + @param[in] String The string to print out. + + @retval EFI_SUCCESS The operation was successful. + @retval !EFI_SUCCESS The operation failed. +**/ +EFI_STATUS +EFIAPI +AttrPrintTo ( + IN CONST CHAR16 *String + ) +{ + UINTN Size; + Size = StrSize(String) - sizeof(CHAR16); + if (Size == 0) { + return (EFI_SUCCESS); + } + if (mEfiShellParametersProtocol != NULL) { + return (mEfiShellProtocol->WriteFile(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String)); + } + return gST->ConOut->OutputString(gST->ConOut, (CHAR16*)String); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + if either Row or Col is out of range for the current console, then ASSERT + if Format is NULL, then ASSERT + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] Marker the marker for the variable argument list + + @return EFI_SUCCESS The operation was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +InternalAttrPrintWorker( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + CHAR16 *ResumeLocation; + CHAR16 *FormatWalker; + UINTN OriginalAttribute; + CHAR16 *mPostReplaceFormat; + CHAR16 *mPostReplaceFormat2; + + mPostReplaceFormat = (CHAR16*)MEM_ALLOC (ATTRPRINT_BUFSIZE); + mPostReplaceFormat2 = (CHAR16*)MEM_ALLOC (ATTRPRINT_BUFSIZE); + + if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) { + MEM_FREE(mPostReplaceFormat); + MEM_FREE(mPostReplaceFormat2); + return (EFI_OUT_OF_RESOURCES); + } + + Status = EFI_SUCCESS; + OriginalAttribute = gST->ConOut->Mode->Attribute; + + // + // Back and forth each time fixing up 1 of our flags... + // + Status = StrCopySearchAndReplace(Format, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%N", L"%%N", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, ATTRPRINT_BUFSIZE, L"%E", L"%%E", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%H", L"%%H", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, ATTRPRINT_BUFSIZE, L"%B", L"%%B", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%V", L"%%V", FALSE, FALSE); + + // + // Use the last buffer from replacing to print from... + // + UnicodeVSPrint (mPostReplaceFormat2, ATTRPRINT_BUFSIZE, mPostReplaceFormat, Marker); + + if (Col != -1 && Row != -1) { + Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row); + } + + FormatWalker = mPostReplaceFormat2; + while (*FormatWalker != CHAR_NULL) { + // + // Find the next attribute change request + // + ResumeLocation = StrStr(FormatWalker, L"%"); + if (ResumeLocation != NULL) { + *ResumeLocation = CHAR_NULL; + } + // + // print the current FormatWalker string + // + if (StrLen(FormatWalker)>0) { + Status = AttrPrintTo(FormatWalker); + if (EFI_ERROR(Status)) { + break; + } + } + + // + // update the attribute + // + if (ResumeLocation != NULL) { + if (*(ResumeLocation-1) == L'^') { + // + // Move cursor back 1 position to overwrite the ^ + // + gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow); + + // + // Print a simple '%' symbol + // + Status = AttrPrintTo(L"%"); + ResumeLocation = ResumeLocation - 1; + } else { + switch (*(ResumeLocation+1)) { + case (L'N'): + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + break; + case (L'E'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'H'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'B'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'V'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + default: + // + // Print a simple '%' symbol + // + Status = AttrPrintTo(L"%"); + if (EFI_ERROR(Status)) { + break; + } + ResumeLocation = ResumeLocation - 1; + break; + } + } + } else { + // + // reset to normal now... + // + break; + } + + // + // update FormatWalker to Resume + 2 (skip the % and the indicator) + // + FormatWalker = ResumeLocation + 2; + } + + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + + MEM_FREE(mPostReplaceFormat); + MEM_FREE(mPostReplaceFormat2); + return (Status); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +AttrPrintEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + EFI_STATUS RetVal; + if (Format == NULL) { + return (EFI_INVALID_PARAMETER); + } + VA_START (Marker, Format); + RetVal = InternalAttrPrintWorker(Col, Row, Format, Marker); + VA_END(Marker); + return(RetVal); +} diff --git a/Library/CommonLib/EfiBeep.c b/Library/CommonLib/EfiBeep.c new file mode 100644 index 0000000..2522078 --- /dev/null +++ b/Library/CommonLib/EfiBeep.c @@ -0,0 +1,69 @@ +/** @file +EFI speaker beep 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 + +////////////////////////////////////////////////////////////////////////// +// Beep +////////////////////////////////////////////////////////////////////////// +EFI_HANDLE* gSpeakerHandles = NULL; +UINTN gSpeakerCount = 0; +EFI_SPEAKER_IF_PROTOCOL* gSpeaker = NULL; +EFI_GUID gSpeakerGuid = EFI_SPEAKER_INTERFACE_PROTOCOL_GUID; + +// Beep defaults +int gBeepEnabled = 1; +BOOLEAN gBeepControlEnabled = 1; +int gBeepDevice = -1; +int gBeepNumberDefault = 1; +int gBeepDurationDefault = 100; +int gBeepIntervalDefault = 0; +int gBeepToneDefault = 0x500; + +EFI_STATUS +InitSpeaker() { + EFI_STATUS res; + // Init Console control if supported + res = EfiGetHandles(ByProtocol, &gSpeakerGuid, 0, &gSpeakerHandles, &gSpeakerCount); + if (gSpeakerCount > 0) { + return SpeakerSelect(gSpeakerCount - 1); + } + return res; +} + +EFI_STATUS +SpeakerSelect( + IN UINTN index) { + if (index < gSpeakerCount) { + return gBS->HandleProtocol(gSpeakerHandles[index], &gSpeakerGuid, (VOID**)&gSpeaker); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +SpeakerBeep( + IN UINT16 Tone, + IN UINTN NumberOfBeeps, + IN UINTN Duration, + IN UINTN Interval + ) +{ + if (gSpeaker != NULL) { + gSpeaker->SetSpeakerToneFrequency(gSpeaker, Tone); + return gSpeaker->GenerateBeep(gSpeaker, NumberOfBeeps, Duration, Interval); + } + return EFI_UNSUPPORTED; +} + 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; +} + + diff --git a/Library/CommonLib/EfiConsole.c b/Library/CommonLib/EfiConsole.c new file mode 100644 index 0000000..8a87ec8 --- /dev/null +++ b/Library/CommonLib/EfiConsole.c @@ -0,0 +1,347 @@ +/** @file +EFI console helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, 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 +#include + +////////////////////////////////////////////////////////////////////////// +// Print +////////////////////////////////////////////////////////////////////////// + +VOID +FlushInputDelay( + IN UINTN delay + ) +{ + EFI_INPUT_KEY key; + EFI_EVENT InputEvents[2]; + UINTN EventIndex = 0; + + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, delay); + while (EventIndex == 0) { + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + } + gBS->CloseEvent(InputEvents[1]); +} + +VOID +FlushInput() { + FlushInputDelay(1000000); +} + +EFI_INPUT_KEY +KeyWait( + CHAR16* Prompt, + UINTN mDelay, + UINT16 scanCode, + UINT16 unicodeChar) +{ + EFI_INPUT_KEY key; + EFI_EVENT InputEvents[2]; + UINTN EventIndex; + + FlushInput(); + key.ScanCode = scanCode; + key.UnicodeChar = unicodeChar; + + InputEvents[0] = gST->ConIn->WaitForKey; + + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, 10000000); + while (mDelay > 0) { + OUT_PRINT(Prompt, mDelay); + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + break; + } + else { + mDelay--; + } + } + OUT_PRINT(Prompt, mDelay); + gBS->CloseEvent(InputEvents[1]); + return key; +} + +EFI_INPUT_KEY +GetKey(void) +{ + EFI_INPUT_KEY key; + UINTN EventIndex; + + gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &EventIndex); + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + return key; +} + +VOID +ConsoleShowTip( + IN CHAR16* tip, + IN UINTN delay) +{ + EFI_EVENT InputEvents[2]; + UINTN EventIndex = 0; + UINTN i = 0; + EFI_INPUT_KEY key; + OUT_PRINT(L"%s", tip); + + // delay + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, delay); + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + + // remove tip + for (i = 0; i < StrLen(tip); ++i) { + OUT_PRINT(L"\b \b", tip); + } +} + + +VOID +GetLine ( + UINTN *length, + CHAR16 *line, + CHAR8 *asciiLine, + UINTN line_max, + UINT8 show) +{ + EFI_INPUT_KEY key; + UINT32 count = 0; + + do { + key = GetKey(); + + if ((count >= line_max && + key.UnicodeChar != CHAR_BACKSPACE) || + key.UnicodeChar == CHAR_NULL || + key.UnicodeChar == CHAR_TAB || + key.UnicodeChar == CHAR_LINEFEED || + key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + continue; + } + + if (count == 0 && key.UnicodeChar == CHAR_BACKSPACE) { + continue; + } else if (key.UnicodeChar == CHAR_BACKSPACE) { + OUT_PRINT(L"\b \b"); + if (line != NULL) line[--count] = '\0'; + if (asciiLine != NULL) asciiLine[--count] = '\0'; + continue; + } + + // check size of line + if (count < line_max - 1) { + if (show) { + OUT_PRINT(L"%c", key.UnicodeChar); + } + else { + OUT_PRINT(L"*"); + } + // save char + if (line != NULL) line[count++] = key.UnicodeChar; + if (asciiLine != NULL) asciiLine[count++] = (CHAR8)key.UnicodeChar; + } + } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + OUT_PRINT(L"\n"); + if (length != NULL) *length = count; + // Set end of line + if (line != NULL) line[count] = '\0'; + if (asciiLine != NULL) asciiLine[count] = '\0'; +} + +int +AskAsciiString( + CHAR8* prompt, + CHAR8* str, + UINTN max_len, + UINT8 visible) +{ + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, NULL, str, max_len, visible); + return (UINT32)len; +} + +int +AskInt( + CHAR8* prompt, + UINT8 visible) +{ + CHAR16 buf[32]; + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, visible); + return (UINT32)StrDecimalToUintn(buf); +} + +UINT8 +AskConfirm( + CHAR8* prompt, + UINT8 visible) +{ + CHAR16 buf[2]; + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, visible); + return (buf[0] == 'y') || (buf[0] == 'Y') ? 1 : 0; +} + +UINT64 +AskUINT64( + IN char* prompt, + IN UINT64 def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[%lld] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : (UINT64)StrDecimalToUint64(buf); +} + +UINT64 +AskHexUINT64( + IN char* prompt, + IN UINT64 def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[0x%llx] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : (UINT64)StrHexToUint64(buf); +} + +UINTN +AskUINTN( + IN char* prompt, + IN UINTN def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[%d] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : StrDecimalToUintn(buf); +} + +EFI_STATUS +ConsoleGetOutput( + IN EFI_HANDLE handle, + OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL** io + ) { + return gBS->HandleProtocol(handle, &gEfiSimpleTextOutProtocolGuid, (VOID**)io); +} + +////////////////////////////////////////////////////////////////////////// +// Ascii converters +////////////////////////////////////////////////////////////////////////// +BOOLEAN +AsciiHexToDigit( + OUT UINT8 *b, + IN CHAR8 *str + ) +{ + CHAR8 ch; + ch = str[0]; + if (ch >= '0' && ch <= '9') { + *b = ch - '0'; + return TRUE; + } + else { + ch = ch & ~0x20; + if (ch >= 'A' && ch <= 'F') { + *b = ch - 'A' + 10; + return TRUE; + } + } + return FALSE; +} + +BOOLEAN +AsciiHexToByte( + OUT UINT8 *b, + IN CHAR8 *str + ) +{ + UINT8 low = 0; + UINT8 high = 0; + BOOLEAN res; + res = AsciiHexToDigit(&high, str); + res = res && AsciiHexToDigit(&low, str + 1); + *b = low | high << 4; + return res; +} + +BOOLEAN +AsciiStrToGuid( + OUT EFI_GUID *guid, + IN CHAR8 *str + ) +{ + UINT8 b[16]; + BOOLEAN res = TRUE; + int i; + CHAR8* pos = str; + if (guid == NULL || str == NULL) return FALSE; + for (i = 0; i < 16; ++i) { + if (*pos == '-') pos++; + res = res && AsciiHexToByte(&b[i], pos); + pos += 2; + if (!res) return FALSE; + } + guid->Data1 = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; + guid->Data2 = b[4] << 8 | b[5]; + guid->Data3 = b[6] << 8 | b[7]; + CopyMem(&guid->Data4, &b[8], 8); + return res; +} + + + +////////////////////////////////////////////////////////////////////////// +// Console control +////////////////////////////////////////////////////////////////////////// + +EFI_HANDLE* gConsoleControlHandles = NULL; +UINTN gConsoleControlCount = 0; + +EFI_STATUS +InitConsoleControl() { + EFI_STATUS res; + // Init Console control if supported + EFI_GUID gConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + EFI_CONSOLE_CONTROL_PROTOCOL* ConsoleControl; + res = EfiGetHandles(ByProtocol, &gConsoleControlProtocolGuid, 0, &gConsoleControlHandles, &gConsoleControlCount); + if (gConsoleControlCount > 0) { + res = gBS->HandleProtocol(gConsoleControlHandles[0], &gConsoleControlProtocolGuid, (VOID**)&ConsoleControl); + if (!EFI_ERROR(res)) { + // Unlock graphics + ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenGraphics); + } + } + return res; +} diff --git a/Library/CommonLib/EfiExec.c b/Library/CommonLib/EfiExec.c new file mode 100644 index 0000000..ff0aa95 --- /dev/null +++ b/Library/CommonLib/EfiExec.c @@ -0,0 +1,88 @@ +/** @file +EFI execute helpers + +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 + +EFI_STATUS +EfiExec( + IN EFI_HANDLE deviceHandle, + IN CHAR16* path + ) +{ + EFI_STATUS res; + EFI_DEVICE_PATH* DevicePath; + EFI_HANDLE ImageHandle; + UINTN ExitDataSize; + CHAR16 *ExitData; + if (deviceHandle == NULL) { + deviceHandle = gFileRootHandle; + } + if (!path || !deviceHandle) return EFI_INVALID_PARAMETER; + DevicePath = FileDevicePath(deviceHandle, path); + + res = gBS->LoadImage(FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle); + if (EFI_ERROR(res)) { + return res; + } + res = gBS->StartImage(ImageHandle, &ExitDataSize, &ExitData); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +/** +This function will connect all current system handles recursively. The +connection will finish until every handle's child handle created if it have. + +@retval EFI_SUCCESS All handles and it's child handle have been +connected +@retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +ConnectAllEfi( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR(Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController(HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/Library/CommonLib/EfiFile.c b/Library/CommonLib/EfiFile.c new file mode 100644 index 0000000..b1e2076 --- /dev/null +++ b/Library/CommonLib/EfiFile.c @@ -0,0 +1,350 @@ +/** @file +EFI file system helpers + +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 +#include + +////////////////////////////////////////////////////////////////////////// +// EFI file +////////////////////////////////////////////////////////////////////////// + +EFI_FILE* gFileRoot = NULL; +EFI_HANDLE gFileRootHandle = NULL; + +EFI_HANDLE* gFSHandles = NULL; +UINTN gFSCount = 0; + +EFI_STATUS +InitFS() { + EFI_STATUS res; + EfiGetHandles(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 0, &gFSHandles, &gFSCount); + res = EfiGetStartDevice(&gFileRootHandle); + if (!EFI_ERROR(res)) { + res = FileOpenRoot(gFileRootHandle, &gFileRoot); + } + return res; +} + +EFI_STATUS +FileOpenRoot( + IN EFI_HANDLE rootHandle, + OUT EFI_FILE** rootFile) +{ + EFI_STATUS res = 0; + EFI_FILE_IO_INTERFACE* fSysProtocol = NULL; + res = gBS->HandleProtocol(rootHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&fSysProtocol); + if (res == RETURN_SUCCESS && fSysProtocol != NULL) { + res = fSysProtocol->OpenVolume(fSysProtocol, rootFile); + } + return res; +} + +EFI_STATUS +FileOpen( + IN EFI_FILE* root, + IN CHAR16* name, + OUT EFI_FILE** file, + IN UINT64 mode, + IN UINT64 attributes + ) +{ + EFI_STATUS res; + + if (!name || !file) { return EFI_INVALID_PARAMETER; } + if (!root) root = gFileRoot; + if (!root) { return EFI_INVALID_PARAMETER; } + if (mode == 0) { + mode = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE; + } + res = root->Open(root, file, name, mode , attributes); + return res; +} + +EFI_STATUS +FileClose( + IN EFI_FILE* f) +{ + if (!f) { return EFI_INVALID_PARAMETER; } + return f->Close(f); +} + +EFI_STATUS +FileDelete( + IN EFI_FILE* root, + IN CHAR16* name + ) +{ + EFI_FILE* f; + EFI_STATUS res; + if (!name) { return EFI_INVALID_PARAMETER; } + res = FileOpen(root, name, &f, 0, 0); + if (EFI_ERROR(res)) { + return res; + } + res = f->Delete(f); +// f->Close(f); + return res; +} + +EFI_STATUS +FileRead( + IN EFI_FILE* f, + OUT VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Read(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileWrite( + IN EFI_FILE* f, + IN VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Write(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileGetInfo( + IN EFI_FILE* f, + OUT EFI_FILE_INFO** info, + OUT UINTN* size + ) +{ + EFI_STATUS res; + UINTN sz = 0; + if (!f || !info) { return EFI_INVALID_PARAMETER; } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, NULL); + if (res == RETURN_BUFFER_TOO_SMALL) { + *info = (EFI_FILE_INFO*)MEM_ALLOC(sz); + if (!(*info)) { + return res; + } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, *info); + if (EFI_ERROR(res)) { + MEM_FREE(*info); + *info = NULL; + sz = 0; + } + } + if (size) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileGetSize( + IN EFI_FILE* f, + OUT UINTN* size + ) +{ + EFI_STATUS res; + EFI_FILE_INFO* info = NULL; + if (!f || !size) { return EFI_INVALID_PARAMETER; } + res = FileGetInfo(f, &info, NULL); + if (!EFI_ERROR(res)) { + *size = (UINTN)info->FileSize; + MEM_FREE(info); + } + return res; +} + +EFI_STATUS +FileLoad( + IN EFI_FILE* root, + IN CHAR16* name, + OUT VOID** data, + OUT UINTN* size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz; + if (!data) { + return EFI_INVALID_PARAMETER; + } + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(file, &sz); + if (EFI_ERROR(res)) { + FileClose(file); + return res; + } + *data = MEM_ALLOC(sz); + if (*data == NULL) { + FileClose(file); + return EFI_BUFFER_TOO_SMALL; + } + res = FileRead(file, *data, &sz, NULL); + if (EFI_ERROR(res)) { + FileClose(file); + MEM_FREE(*data); + return res; + } + FileClose(file); + if (size != NULL) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileSave( + IN EFI_FILE* root, + IN CHAR16* name, + IN VOID* data, + IN UINTN size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz = size; + if (!data || !name) { return EFI_INVALID_PARAMETER; } + FileDelete(root, name); + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) return res; + res = FileWrite(file, data, &sz, NULL); + FileClose(file); + return res; +} + +EFI_STATUS +FileExist( + IN EFI_FILE* root, + IN CHAR16* name) +{ + EFI_FILE* file; + EFI_STATUS res; + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + FileClose(file); + return EFI_SUCCESS; +} + +EFI_STATUS +FileRename( + IN EFI_FILE* root, + IN CHAR16* src, + IN CHAR16* dst) +{ + EFI_STATUS res; + EFI_FILE* file; + EFI_FILE_INFO* info = NULL; + UINTN sz; + EFI_FILE_INFO* dstinfo = NULL; + UINTN dstinfosz; + + res = FileOpen(root, src, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetInfo(file, &info, &sz); + if (EFI_ERROR(res)) return res; + dstinfosz = SIZE_OF_EFI_FILE_INFO + StrSize(dst); + dstinfo = (EFI_FILE_INFO*)MEM_ALLOC(dstinfosz); + if (dstinfo != NULL) { + CopyMem(dstinfo, info, SIZE_OF_EFI_FILE_INFO); + dstinfo->FileName[0] = 0; + StrCat(dstinfo->FileName, dst); + res = file->SetInfo(file, &gEfiFileInfoGuid, dstinfosz, dstinfo); + } else { + res = EFI_BUFFER_TOO_SMALL; + } + + MEM_FREE(info); + MEM_FREE(dstinfo); + FileClose(file); + return res; +} + +EFI_STATUS +FileCopy( + IN EFI_FILE* srcroot, + IN CHAR16* src, + IN EFI_FILE* dstroot, + IN CHAR16* dst, + IN UINTN bufSz + ) +{ + EFI_STATUS res; + EFI_FILE* srcfile = NULL; + EFI_FILE* dstfile = NULL; + UINTN remains; + CHAR8* data = NULL; + UINTN datasz = bufSz; + + res = FileOpen(srcroot, src, &srcfile, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(srcfile, &remains); + if (EFI_ERROR(res)) return res; + + data = (CHAR8*)MEM_ALLOC(bufSz); + if (data == NULL) { + res = EFI_BUFFER_TOO_SMALL; + goto copyerr; + } + + res = FileOpen(dstroot, dst, &dstfile, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) goto copyerr; + + do { + datasz = remains > bufSz ? bufSz : remains; + res =FileRead(srcfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + res = FileWrite(dstfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + remains -= datasz; + } while (remains > 0); + +copyerr: + MEM_FREE(data); + FileClose(srcfile); + FileClose(dstfile); + return res; +} diff --git a/Library/CommonLib/EfiMem.c b/Library/CommonLib/EfiMem.c new file mode 100644 index 0000000..d9386c0 --- /dev/null +++ b/Library/CommonLib/EfiMem.c @@ -0,0 +1,74 @@ +/** @file +EFI memory 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 "Library/CommonLib.h" + + +////////////////////////////////////////////////////////////////////////// +// Memory procedures wrappers +////////////////////////////////////////////////////////////////////////// + +VOID* +MemAlloc( + IN UINTN size + ) { + return AllocateZeroPool(size); +} + +VOID* +MemRealloc( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) { + return ReallocatePool(OldSize, NewSize, OldBuffer); +} + +VOID +MemFree( + IN VOID* ptr + ) { + if(ptr != NULL) FreePool(ptr); +} + +////////////////////////////////////////////////////////////////////////// +// Memory mapped IO +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +PrepareMemory( + IN UINTN address, + IN UINTN len, + OUT VOID** mem) +{ + EFI_STATUS status; + EFI_PHYSICAL_ADDRESS ptr; + VOID* buf; + UINTN pages; + pages = ((len & ~0x0FFF) + 0x1000) >> 12; + ptr = address & ~0x0FFF; +// OUT_PRINT(L"mem try %0x, %0x\n", pages, (UINTN)ptr); + status = gBS->AllocatePages(AllocateAddress, EfiMemoryMappedIO, pages, &ptr); + if (EFI_ERROR(status)) { + return status; + } + buf = (void*)(UINTN)ptr; + SetMem(buf, pages << 12, 0); + *mem = buf; + return status; +} diff --git a/Library/CommonLib/EfiTouch.c b/Library/CommonLib/EfiTouch.c new file mode 100644 index 0000000..9009f82 --- /dev/null +++ b/Library/CommonLib/EfiTouch.c @@ -0,0 +1,47 @@ +/** @file +EFI touch/absolute pointer helpers + +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 + +EFI_HANDLE* gTouchHandles = NULL; +UINTN gTouchCount = 0; +int gTouchSimulate = 0; +UINT32 gTouchSimulateStep = 1; + +EFI_ABSOLUTE_POINTER_PROTOCOL* gTouchPointer = NULL; + +EFI_STATUS +InitTouch() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiAbsolutePointerProtocolGuid, 0, &gTouchHandles, &gTouchCount); + if (gTouchCount > 0) { + TouchGetIO(gTouchHandles[gTouchCount - 1], &gTouchPointer); + } + return res; +} + + +EFI_STATUS +TouchGetIO( + IN EFI_HANDLE Handle, + OUT EFI_ABSOLUTE_POINTER_PROTOCOL** io + ) { + if (!io) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiAbsolutePointerProtocolGuid, (VOID**)io); +} + diff --git a/Library/CommonLib/EfiUsb.c b/Library/CommonLib/EfiUsb.c new file mode 100644 index 0000000..b5bdac5 --- /dev/null +++ b/Library/CommonLib/EfiUsb.c @@ -0,0 +1,88 @@ +/** @file +EFI USB helpers + +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 + +EFI_HANDLE* gUSBHandles = NULL; +UINTN gUSBCount = 0; + +EFI_STATUS +InitUsb() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiUsbIoProtocolGuid, 0, &gUSBHandles, &gUSBCount); + return res; +} + +EFI_STATUS +UsbGetIO( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo + ) { + if (!UsbIo) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiUsbIoProtocolGuid, (VOID**)UsbIo); +} + +EFI_STATUS +UsbGetIOwithDescriptor( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo, + OUT EFI_USB_DEVICE_DESCRIPTOR* UsbDescriptor + ) { + EFI_STATUS res; + if (!UsbIo || !UsbDescriptor) { + return EFI_INVALID_PARAMETER; + } + res = UsbGetIO(Handle, UsbIo); + if (EFI_ERROR(res)) { + return res; + } + return (*UsbIo)->UsbGetDeviceDescriptor(*UsbIo, UsbDescriptor); +} + +EFI_STATUS +UsbGetId( + IN EFI_HANDLE Handle, + OUT CHAR8** id + ) +{ + EFI_STATUS res; + EFI_USB_IO_PROTOCOL *usbIO = NULL; + EFI_USB_DEVICE_DESCRIPTOR usbDescriptor; + CHAR16* serial = NULL; + CHAR8* buff; + UINTN len; + res = UsbGetIOwithDescriptor(Handle, &usbIO, &usbDescriptor); + if (EFI_ERROR(res)) { + return res; + } +// Print(L" %02x ", (UINTN)usbDescriptor.StrSerialNumber); + res = usbIO->UsbGetStringDescriptor(usbIO, 0x409, usbDescriptor.StrSerialNumber, &serial); + if (!EFI_ERROR(res)) { + len = 11 + StrLen(serial); + buff = (CHAR8*)MEM_ALLOC(len); + AsciiSPrint(buff, len, "%04x_%04x_%s", usbDescriptor.IdVendor, usbDescriptor.IdProduct, serial); + } else { +// Print(L" %04x %r ", res, res); + len = 10; + buff = (CHAR8*)MEM_ALLOC(len); + AsciiSPrint(buff, len, "%04x_%04x", usbDescriptor.IdVendor, usbDescriptor.IdProduct); + } + *id = buff; + return EFI_SUCCESS; +} diff --git a/Library/CommonLib/EfiVar.c b/Library/CommonLib/EfiVar.c new file mode 100644 index 0000000..2a6e59e --- /dev/null +++ b/Library/CommonLib/EfiVar.c @@ -0,0 +1,228 @@ +/** @file +EFI firmware variable helpers + +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 +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Efi variables +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiGetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + OUT VOID** varValue, + OUT UINTN* varSize, + OUT UINT32* varAttr + ) { + EFI_STATUS Status; + CHAR8 *varData = NULL; + if (varSize == NULL) return EFI_INVALID_PARAMETER; + *varSize = 0; + if (varGuid == NULL) varGuid = &gEfiDcsVariableGuid; + Status = gST->RuntimeServices->GetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varData); + if (Status == EFI_BUFFER_TOO_SMALL) { + varData = MEM_ALLOC(*varSize); + if (varData == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + Status = gST->RuntimeServices->GetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varData); + *varValue = varData; + } + return Status; +} + + +EFI_STATUS +EfiSetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + IN VOID* varValue, + IN UINTN varSize, + IN UINT32 varAttr + ) { + EFI_STATUS Status; + if (varGuid == NULL) varGuid = &gEfiDcsVariableGuid; + Status = gST->RuntimeServices->SetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varValue); + return Status; +} + +EFI_STATUS +BootOrderInsert( + IN CHAR16 *OrderVarName, + IN UINTN index, + UINT16 value) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT16* varBootOrderNew; + UINT16* varBootOrder; + UINTN varBootOrderSize; + UINT32 varBootOrderAttr; + UINTN BootOrderCount; + UINTN i; + UINTN j; + res = EfiGetVar(OrderVarName, &gEfiGlobalVariableGuid, &varBootOrder, &varBootOrderSize, &varBootOrderAttr); + if (EFI_ERROR(res)) return res; + BootOrderCount = varBootOrderSize / sizeof(UINT16); + varBootOrderNew = MEM_ALLOC((BootOrderCount + 1) * sizeof(UINT16)); + if (BootOrderCount < index) index = BootOrderCount - 1; + for (j = 0, i = 0; i < BootOrderCount; ++i) { + if (j == index) { + varBootOrderNew[j] = value; + j++; + } + if (varBootOrder[i] == value) { + continue; + } + varBootOrderNew[j] = varBootOrder[i]; + ++j; + } + BootOrderCount = j; + + res = EfiSetVar(OrderVarName, &gEfiGlobalVariableGuid, + varBootOrderNew, BootOrderCount * sizeof(UINT16), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + MEM_FREE(varBootOrderNew); + MEM_FREE(varBootOrder); + return res; +} + +EFI_STATUS +BootOrderRemove( + IN CHAR16 *OrderVarName, + UINT16 value) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT16* varBootOrderNew; + UINT16* varBootOrder; + UINTN varBootOrderSize; + UINT32 varBootOrderAttr; + UINTN BootOrderCount; + UINTN i; + UINTN j; + + res = EfiGetVar(OrderVarName, &gEfiGlobalVariableGuid, &varBootOrder, &varBootOrderSize, &varBootOrderAttr); + if (EFI_ERROR(res)) return res; + BootOrderCount = varBootOrderSize / sizeof(UINT16); + varBootOrderNew = MEM_ALLOC((BootOrderCount + 1) * sizeof(UINT16)); + for (j = 0, i = 0; i < BootOrderCount; ++i) { + if (varBootOrder[i] == value) { + continue; + } + varBootOrderNew[j] = varBootOrder[i]; + ++j; + } + BootOrderCount = j; + + res = EfiSetVar(OrderVarName, &gEfiGlobalVariableGuid, + varBootOrderNew, BootOrderCount * sizeof(UINT16), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + + MEM_FREE(varBootOrderNew); + MEM_FREE(varBootOrder); + return res; +} + +EFI_STATUS +BootMenuItemRemove( + IN CHAR16 *VarName + ) +{ + EFI_STATUS res = EFI_NOT_READY; + res = EfiSetVar( + VarName, &gEfiGlobalVariableGuid, + NULL, 0, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + return res; +} + +EFI_STATUS +BootMenuItemCreate( + IN CHAR16 *VarName, + IN CHAR16 *Desc, + IN EFI_HANDLE volumeHandle, + IN CHAR16 *Path, + IN BOOLEAN Reduced + ) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT8* varBoot; + UINT8* TempByteBuffer; + UINTN DescSize; + UINTN FilePathSize; + EFI_DEVICE_PATH_PROTOCOL* DevPath; + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + EFI_DEVICE_PATH_PROTOCOL* FileNode; + EFI_DEVICE_PATH_PROTOCOL* FilePath; + + // Prepare + DevicePath = DevicePathFromHandle(volumeHandle); + if (Reduced) { + DevPath = DevicePath; + while (!IsDevicePathEnd(DevPath)) { + if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { + + // + // If we find it use it instead + // + DevicePath = DevPath; + break; + } + DevPath = NextDevicePathNode(DevPath); + } + } + // + // append the file + // + FileNode = FileDevicePath(NULL, Path); + FilePath = AppendDevicePath(DevicePath, FileNode); + FreePool(FileNode); + // + // Add the option + // + DescSize = StrSize(Desc); + FilePathSize = GetDevicePathSize(FilePath); + + varBoot = MEM_ALLOC(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize); + if (varBoot != NULL) { + TempByteBuffer = varBoot; + *((UINT32 *)TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes + TempByteBuffer += sizeof(UINT32); + + *((UINT16 *)TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength + TempByteBuffer += sizeof(UINT16); + + CopyMem(TempByteBuffer, Desc, DescSize); + TempByteBuffer += DescSize; + CopyMem(TempByteBuffer, FilePath, FilePathSize); + + res = EfiSetVar(VarName, &gEfiGlobalVariableGuid, + varBoot, sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + } + else { + return EFI_BUFFER_TOO_SMALL; + } + + MEM_FREE(varBoot); + return res; +} diff --git a/Library/CommonLib/IA32/EfiCpuHalt.asm b/Library/CommonLib/IA32/EfiCpuHalt.asm new file mode 100644 index 0000000..3c5bb0d --- /dev/null +++ b/Library/CommonLib/IA32/EfiCpuHalt.asm @@ -0,0 +1,19 @@ + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuHalt ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiCpuHalt PROC + cli +l: hlt + jmp l + ret +EfiCpuHalt ENDP + + END diff --git a/Library/CommonLib/X64/EfiCpuHalt.asm b/Library/CommonLib/X64/EfiCpuHalt.asm new file mode 100644 index 0000000..7893234 --- /dev/null +++ b/Library/CommonLib/X64/EfiCpuHalt.asm @@ -0,0 +1,17 @@ + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuHalt ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiCpuHalt PROC + cli +l: hlt + jmp l + ret +EfiCpuHalt ENDP + + END -- cgit v1.2.3