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 + Library/DcsCfgLib/DcsCfgLib.inf | 80 +++ Library/DcsCfgLib/DcsRandom.c | 460 +++++++++++++++++ Library/DcsCfgLib/GptEdit.c | 935 ++++++++++++++++++++++++++++++++++ Library/GraphLib/EfiGraph.c | 670 ++++++++++++++++++++++++ Library/GraphLib/GraphLib.inf | 43 ++ Library/GraphLib/font.c | 586 +++++++++++++++++++++ Library/PasswordLib/ConsolePassword.c | 128 +++++ Library/PasswordLib/PasswordLib.inf | 46 ++ Library/PasswordLib/PicturePassword.c | 629 +++++++++++++++++++++++ Library/PasswordLib/PlatformID.c | 266 ++++++++++ Library/VeraCryptLib/DcsVeraCrypt.c | 391 ++++++++++++++ Library/VeraCryptLib/DcsVeraCrypt.h | 84 +++ Library/VeraCryptLib/VeraCryptLib.inf | 120 +++++ Library/VeraCryptLib/llmath.c | 383 ++++++++++++++ Library/VeraCryptLib/mklinks_src.bat | 112 ++++ 28 files changed, 7034 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 create mode 100644 Library/DcsCfgLib/DcsCfgLib.inf create mode 100644 Library/DcsCfgLib/DcsRandom.c create mode 100644 Library/DcsCfgLib/GptEdit.c create mode 100644 Library/GraphLib/EfiGraph.c create mode 100644 Library/GraphLib/GraphLib.inf create mode 100644 Library/GraphLib/font.c create mode 100644 Library/PasswordLib/ConsolePassword.c create mode 100644 Library/PasswordLib/PasswordLib.inf create mode 100644 Library/PasswordLib/PicturePassword.c create mode 100644 Library/PasswordLib/PlatformID.c create mode 100644 Library/VeraCryptLib/DcsVeraCrypt.c create mode 100644 Library/VeraCryptLib/DcsVeraCrypt.h create mode 100644 Library/VeraCryptLib/VeraCryptLib.inf create mode 100644 Library/VeraCryptLib/llmath.c create mode 100644 Library/VeraCryptLib/mklinks_src.bat (limited to 'Library') 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 diff --git a/Library/DcsCfgLib/DcsCfgLib.inf b/Library/DcsCfgLib/DcsCfgLib.inf new file mode 100644 index 0000000..8607cb4 --- /dev/null +++ b/Library/DcsCfgLib/DcsCfgLib.inf @@ -0,0 +1,80 @@ +## @file +# Library for DCS configuration +# +# 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 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsCfgLib + MODULE_UNI_FILE = DcsCfgLib.uni + FILE_GUID = 3E61F9E0-0844-44F2-A177-A72FE81D6F07 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DcsCfgLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] +GptEdit.c +DcsRandom.c + +[Sources.X64] + +[Sources.IA32] + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + RngLib + +[Protocols] + + +[BuildOptions.IA32] +DEBUG_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +DEBUG_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +RELEASE_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +RELEASE_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +[BuildOptions.X64] +DEBUG_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +DEBUG_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +RELEASE_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 + +RELEASE_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 diff --git a/Library/DcsCfgLib/DcsRandom.c b/Library/DcsCfgLib/DcsRandom.c new file mode 100644 index 0000000..a269a46 --- /dev/null +++ b/Library/DcsCfgLib/DcsRandom.c @@ -0,0 +1,460 @@ +/** @file +Random number generators for DCS + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +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 + +!NOTE: Very simple! Need to select several sources of random like user input or other. +**/ + +#include +#include +#include +#include +#include + +#include +#include + +DCS_RND* gRnd = NULL; + +////////////////////////////////////////////////////////////////////////// +// Random data from file +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndFilePrepare( + IN DCS_RND* rnd + ) +{ + EFI_STATUS res = EFI_NOT_READY; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + rnd->State.File.Pos = 0; + res = EFI_SUCCESS; + } + return res; +} + +EFI_STATUS +RndFileGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINTN i; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + for (i = 0; i < len; i++, rnd->State.File.Pos++) { + if (rnd->State.File.Pos >= rnd->State.File.Size) { + rnd->State.File.Pos = 0; + } + buf[i] = rnd->State.File.Data[rnd->State.File.Pos]; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndFileInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_NOT_FOUND; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeFile; + rnd->GetBytes = RndFileGetBytes; + rnd->Prepare = RndFilePrepare; + if (Context != NULL) { + res = FileLoad(NULL, (CHAR16*)Context, &rnd->State.File.Data, &rnd->State.File.Size); + if (!EFI_ERROR(res)) { + return rnd->Prepare(rnd); + } + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Random data from CPU RDRAND +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndRDRandPrepare( + IN DCS_RND* rnd + ) +{ + UINT64 rndTmp; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + if (GetRandomNumber64((UINT64*)&rndTmp)) { + return EFI_SUCCESS; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndRDRandGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINT8 tmpRnd[8]; + UINTN i = 0; + UINTN j = 0; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + for (i = 0; i < len; ++i, ++j) { + j &= 7; + if (j == 0) { + if (!GetRandomNumber64((UINT64*)tmpRnd)) return EFI_NOT_READY; + } + buf[i] = tmpRnd[j]; + } + } else { + return EFI_NOT_READY; + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndRDRandInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeRDRand; + rnd->GetBytes = RndRDRandGetBytes; + rnd->Prepare = RndRDRandPrepare; + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// DRBG HMAC (SHA512) (NIST SP 800-90A) (simplified) +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +HmacSha512( + IN UINT8 *k, /* secret key */ + OUT UINT8 *out, /* output buffer */ + ... + ) +{ + sha512_ctx ctx; + char inner[SHA512_DIGEST_SIZE], outer[SHA512_DIGEST_SIZE]; + char key[SHA512_DIGEST_SIZE]; + char buf[SHA512_BLOCK_SIZE]; + int32 i; + int32 lk = SHA512_DIGEST_SIZE; /* length of the key in bytes */ + VA_LIST args; + UINT8* data; + UINTN len; + + /**** Inner Digest ****/ + sha512_begin(&ctx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x36); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x36; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + + VA_START(args, out); + while ((data = VA_ARG(args, UINT8 *)) != NULL) { + len = VA_ARG(args, UINTN); + sha512_hash(data, (UINT32)len, &ctx); + } + VA_END(args); + + sha512_end((unsigned char *)inner, &ctx); + + /**** Outer Digest ****/ + + sha512_begin(&ctx); + + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x5C); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x5C; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + sha512_hash((unsigned char *)inner, SHA512_DIGEST_SIZE, &ctx); + + sha512_end((unsigned char *)out, &ctx); + + /* Prevent possible leaks. */ + burn(&ctx, sizeof(ctx)); + burn(outer, sizeof(outer)); + burn(inner, sizeof(inner)); + burn(buf, sizeof(buf)); + burn(key, sizeof(key)); + return EFI_SUCCESS; +} + +EFI_STATUS +RndDtrmHmacSha512Update( + RND_DTRM_HMAC_SHA512_STATE *state, + UINT8 *seed, + UINTN seedLen, + BOOLEAN reseed + ) +{ + EFI_STATUS res = EFI_NOT_READY; + int i = 0; + + if (!reseed) + { + /* 10.1.2.3 */ + memset(state->V, 1, SHA512_DIGEST_SIZE); + memset(state->C, 0, SHA512_DIGEST_SIZE); + } + + /* we execute two rounds of V/K massaging */ + for (i = 2; 0 < i; i--) + { + /* first round uses 0x0, second 0x1 */ + unsigned char prefix = 0; + if (1 == i) + prefix = 1; + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ + + res = HmacSha512(state->C, state->C, + state->V, SHA512_DIGEST_SIZE, + &prefix, 1, + seed, seedLen, + NULL + ); + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 2 and 5 -- HMAC for V */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL); + + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 3 */ + if (!seed || 0 == seedLen) + return res; + } + return EFI_SUCCESS; +} + +/* generate function of HMAC DRBG as defined in 10.1.2.5 */ +EFI_STATUS +RndDtrmHmacSha512Generate( + RND_DTRM_HMAC_SHA512_STATE *state, + OUT UINT8 *buf, + IN UINTN buflen, + IN UINT8 *seed, + IN UINTN seedLen + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len = 0; + + /* 10.1.2.5 step 2 */ + if (seed && 0 < seedLen) + { + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + if (EFI_ERROR(res)) + return res; + } + + while (len < buflen) + { + UINTN outlen = 0; + /* 10.1.2.5 step 4.1 */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL + ); + if (EFI_ERROR(res)) + return res; + outlen = (SHA512_DIGEST_SIZE < (buflen - len)) ? + SHA512_DIGEST_SIZE : (buflen - len); + + /* 10.1.2.5 step 4.2 */ + memcpy(buf + len, state->V, outlen); + len += outlen; + } + + /* 10.1.2.5 step 6 */ + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Prepare( + IN DCS_RND* rnd + ) +{ + if (rnd != NULL && rnd->Type == RndTypeDtrmHmacSha512) { + return EFI_SUCCESS; + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndDtrmHmacSha512GetBytes( + IN DCS_RND* rnd, + UINT8 *buf, + UINTN len + ) +{ + EFI_TIME seed; + EFI_STATUS res = EFI_NOT_READY; + RND_DTRM_HMAC_SHA512_STATE *state = &rnd->State.HMacSha512; + if (state->ReseedCtr < (1LL << 48)) { + gST->RuntimeServices->GetTime(&seed, NULL); + res = RndDtrmHmacSha512Generate(state, buf, len, (UINT8*)&seed, sizeof(seed)); + state->ReseedCtr++; + } + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Init( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_SUCCESS; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeDtrmHmacSha512; + rnd->GetBytes = RndDtrmHmacSha512GetBytes; + rnd->Prepare = RndDtrmHmacSha512Prepare; + + if (Context != NULL) { + CHAR16* type = (CHAR16*)Context; + if (*type == '_') { + UINT8* data; + UINTN size; + type++; + res = FileLoad(NULL, (CHAR16*)type, &data, &size); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + res = RndDtrmHmacSha512Update(&rnd->State.HMacSha512, data, size, 0); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + } + } + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// Random API +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndInit( + IN UINTN rndType, + IN VOID* Context, + OUT DCS_RND **rnd) +{ + if (rnd != NULL) { + DCS_RND *rndTemp; + rndTemp = (DCS_RND*)MEM_ALLOC(sizeof(DCS_RND)); + if (rndTemp != NULL) { + EFI_STATUS res = EFI_NOT_FOUND; + rndTemp->Type = (UINT32)rndType; + switch (rndType) { + case RndTypeFile: + res = RndFileInit(rndTemp, Context); + break; + case RndTypeRDRand: + res = RndRDRandInit(rndTemp, Context); + break; + case RndTypeDtrmHmacSha512: + res = RndDtrmHmacSha512Init(rndTemp, Context); + break; + } + if (EFI_ERROR(res)) { + MEM_FREE(rndTemp); + return res; + } + *rnd = rndTemp; + return res; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndGetBytes( + UINT8 *buf, + UINTN len) +{ + if (gRnd != NULL) { + return gRnd->GetBytes(gRnd, buf, len); + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndPreapare() +{ + if (gRnd != NULL) { + return gRnd->Prepare(gRnd); + } + return EFI_NOT_READY; +} + +UINT64 gRndHeaderSign = RND_HEADER_SIGN; + +EFI_STATUS +RndSave( + IN DCS_RND *rnd, + OUT DCS_RND_SAVED **rndSaved + ) +{ + EFI_STATUS res = EFI_NOT_READY; + DCS_RND_SAVED *RndSaved; + UINT32 crc; + if (rnd != NULL && rndSaved != NULL && rnd->Type != RndTypeFile) { + RndSaved = MEM_ALLOC(sizeof(DCS_RND_SAVED)); + if (RndSaved != NULL) { + RndSaved->Size = sizeof(DCS_RND_SAVED); + CopyMem(&RndSaved->State, &rnd->State, sizeof(DCS_RND_STATE)); + RndSaved->Type = rnd->Type; + RndSaved->Sign = gRndHeaderSign; + gST->RuntimeServices->GetTime(&RndSaved->SavedAt, NULL); + res = gBS->CalculateCrc32(RndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res)) { + MEM_FREE(RndSaved); + return res; + } + RndSaved->CRC = crc; + *rndSaved = RndSaved; + } + } + return res; +} + +EFI_STATUS +RndLoad( + IN DCS_RND_SAVED *rndSaved, + OUT DCS_RND **rndOut + ) { + EFI_STATUS res = EFI_SUCCESS; + UINT32 crc; + UINT32 crcSaved; + + crcSaved = rndSaved->CRC; + rndSaved->CRC = 0; + res = gBS->CalculateCrc32(rndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res) || crc != crcSaved || rndSaved->Sign != gRndHeaderSign) { + return EFI_CRC_ERROR; + } + res = RndInit(rndSaved->Type, NULL, rndOut); + if (!EFI_ERROR(res)) { + CopyMem(&((*rndOut)->State), &rndSaved->State, sizeof(DCS_RND_STATE)); + } + return res; +} diff --git a/Library/DcsCfgLib/GptEdit.c b/Library/DcsCfgLib/GptEdit.c new file mode 100644 index 0000000..702ce5d --- /dev/null +++ b/Library/DcsCfgLib/GptEdit.c @@ -0,0 +1,935 @@ +/** @file +GPT actions + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +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 +#include + +EFI_GUID gEfiPartTypeMsReservedPartGuid = EFI_PART_TYPE_MS_RESERVED_PART_GUID; +EFI_GUID gEfiPartTypeBasicDataPartGuid = EFI_PART_TYPE_BASIC_DATA_PART_GUID; +EFI_GUID gEfiPartTypeMsRecoveryPartGuid = EFI_PART_TYPE_MS_RECOVERY_PART_GUID; + +UINT64 gDcsDiskEntryListHeaderID = DCS_DISK_ENTRY_LIST_HEADER_SIGN; +UINT64 gDcsDiskEntryPwdCacheID = DCS_DEP_PWD_CACHE_SIGN; + +DCS_DISK_ENTRY_LIST *DeList = NULL; + +UINT8 *CryptoHeader = NULL; + +EFI_PARTITION_TABLE_HEADER *GptMainHdr = NULL; +EFI_PARTITION_ENTRY *GptMainEntrys = NULL; +EFI_PARTITION_TABLE_HEADER *GptAltHdr = NULL; +EFI_PARTITION_ENTRY *GptAltEntrys = NULL; + +UINT32 DiskIdMbr = 0; +EFI_GUID DiskIdGpt = EFI_PART_TYPE_UNUSED_GUID; +DCS_DISK_ENTRY_DISKID DeDiskId; + +DCS_DEP_EXEC *DeExecParams = NULL; + +DCS_DEP_PWD_CACHE *DePwdCache = NULL; + +DCS_RND_SAVED *DeRndSaved; + +EFI_BLOCK_IO_PROTOCOL* BlockIo = NULL; +CONST CHAR16* DcsDiskEntrysFileName = L"DcsDiskEntrys"; + +EFI_PARTITION_ENTRY DcsHidePart; + +UINTN BootPartIdx; +UINTN MirrorPartIdx; + +////////////////////////////////////////////////////////////////////////// +// Partitions +////////////////////////////////////////////////////////////////////////// + + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Size The size of the table +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrcAltSize( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + UINT32 Crc; + UINT32 OrgCrc; + EFI_STATUS Status; + + Crc = 0; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + + if ((MaxSize != 0) && (Size > MaxSize)) { + return FALSE; + } + // + // clear old crc from header + // + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc); + if (EFI_ERROR(Status)) { + return FALSE; + } + // + // set results + // + Hdr->CRC32 = OrgCrc; + + return (BOOLEAN)(OrgCrc == Crc); +} + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrc( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr); +} + +EFI_STATUS +GptCheckEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return EFI_CRC_ERROR; + } + Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR; + return Status; +} + +EFI_STATUS +GptUpdateCRC( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->PartitionEntryArrayCRC32 = Crc; + PartHeader->Header.CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->Header.CRC32 = Crc; + return Status; +} + +/** +Read GPT +Check if the CRC field in the Partition table header is valid +for Partition entry array. + +@param[in] DiskIo Disk Io Protocol. +@param[in] PartHeader Partition table header structure + +@retval EFI_SUCCESS the CRC is valid +**/ +EFI_STATUS +GptReadEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + OUT EFI_PARTITION_ENTRY **Entrys + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + + // + // Read the EFI Partition Entries + // + Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + Status = BlockIo->ReadBlocks( + BlockIo, + BlockIo->Media->MediaId, + PartHeader->PartitionEntryLBA, + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR(Status)) { + MEM_FREE(Ptr); + return Status; + } + + *Entrys = (EFI_PARTITION_ENTRY*)Ptr; + return GptCheckEntryArray(PartHeader, *Entrys); +} + +EFI_STATUS +GptReadHeader( + IN EFI_LBA HeaderLba, + OUT EFI_PARTITION_TABLE_HEADER **PartHeader + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + UINT32 MediaId; + + BlockSize = BlockIo->Media->BlockSize; + MediaId = BlockIo->Media->MediaId; + PartHdr = MEM_ALLOC(BlockSize); + + res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr); + if (EFI_ERROR(res)) { + MEM_FREE(PartHdr); + return res; + } + + // Check header + if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(BlockSize, &PartHdr->Header) || + PartHdr->MyLBA != HeaderLba || + (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) + ) { + MEM_FREE(PartHdr); + return EFI_CRC_ERROR; + } + *PartHeader = PartHdr; + return EFI_SUCCESS; +} + +VOID +GptPrint( + IN EFI_PARTITION_TABLE_HEADER *PartHdr, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_PARTITION_ENTRY *Entry; + UINTN index; + if (PartHdr == NULL) { + ERR_PRINT(L"No GPT is loaded\n"); + return; + } + Entry = Entrys; + for (index = 0; index < PartHdr->NumberOfPartitionEntries; ++index, ++Entry) { + if (CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + OUT_PRINT(L"%H%02d%N I:%g T:%g [%lld, %lld] %s\n", + index, + &Entry->UniquePartitionGUID, + &Entry->PartitionTypeGUID, + Entry->StartingLBA, + Entry->EndingLBA, + &Entry->PartitionName + ); + } +} + +EFI_STATUS +GptLoadFromDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + InitBio(); + + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + res = GptReadHeader(1, &GptMainHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read main GPT header: %r\n", res); + goto error; + } + + res = GptReadHeader(GptMainHdr->AlternateLBA, &GptAltHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read alt GPT header: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptMainHdr, &GptMainEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT error: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptAltHdr, &GptAltEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT error: %r\n", res); + goto error; + } + + CryptoHeader = MEM_ALLOC(512); + if (CryptoHeader == NULL) { + ERR_PRINT(L"Can't alloc CryptoHeader\n"); + res = EFI_BUFFER_TOO_SMALL; + goto error; + } + + // Load disk IDs + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't MBR \n"); + goto error; + } + + SetMem(&DeDiskId, sizeof(DeDiskId), 0); + DeDiskId.Type = DE_DISKID; + CopyMem(&DeDiskId.MbrID, &CryptoHeader[0x1b8], sizeof(DiskIdMbr)); + CopyMem(&DeDiskId.GptID, &GptMainHdr->DiskGUID, sizeof(DiskIdGpt)); + + // Load crypto header + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 62, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read CryptoHeader\n"); + goto error; + } + + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + CHAR16* defExec = L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi"; + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + ZeroMem(DeExecParams, sizeof(*DeExecParams)); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + CopyMem(&DeExecParams->ExecCmd, defExec, (StrLen(defExec) + 1 ) * 2); + break; + } + } + return res; + +error: + MEM_FREE(GptMainHdr); + MEM_FREE(GptMainEntrys); + MEM_FREE(GptAltHdr); + MEM_FREE(GptAltEntrys); + MEM_FREE(CryptoHeader); + return res; +} + +VOID +DeListPrint() { + OUT_PRINT(L"Diskid %08x, %g\n", DeDiskId.MbrID, &DeDiskId.GptID); + if (DeExecParams != NULL) { + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + } + if (DePwdCache != NULL) { + OUT_PRINT(L"PwdCache %d\n", DePwdCache->Count); + } + if (DeRndSaved != NULL) { + OUT_PRINT(L"Rnd %d\n", DeRndSaved->Type); + } + GptPrint(GptMainHdr, GptMainEntrys); +} + +#define DeList_UPDATE_BEGIN(Data, DEType, Index, Len) \ + if (Data != NULL) { \ + DeData[Index] = Data; \ + DeList->DE[Index].Type = DEType; \ + DeList->DE[Index].Offset = Offset; \ + DeList->DE[Index].Length = Len; \ + Offset += ((Len + 511) >> 9) << 9; + +#define DeList_UPDATE_END \ + } + +VOID +DeListSaveToFile() { + EFI_STATUS res = EFI_SUCCESS; + UINT32 Offset; + VOID* DeData[DE_IDX_TOTAL]; + UINT8* pad512buf = NULL; + + ZeroMem(DeData, sizeof(DeData)); + + res = EFI_BUFFER_TOO_SMALL; + DeList = MEM_ALLOC(sizeof(*DeList)); + if (DeList == NULL) { + ERR_PRINT(L"Can't alloc DeList\n"); + goto error; + } + + pad512buf = MEM_ALLOC(512); + if (pad512buf == NULL) { + ERR_PRINT(L"No memory\n"); + goto error; + } + + DeList->Signature = DCS_DISK_ENTRY_LIST_HEADER_SIGN; + DeList->HeaderSize = sizeof(*DeList); + DeList->Count = DE_IDX_TOTAL; + Offset = 0; + + DeList_UPDATE_BEGIN(CryptoHeader, DE_Sectors, DE_IDX_CRYPTOHEADER, 512) + DeList->DE[DE_IDX_CRYPTOHEADER].Sectors.Start = 62 * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeList, DE_List, DE_IDX_LIST, 512) + DeList_UPDATE_END + + CopyMem(&DeList->DE[DE_IDX_DISKID], &DeDiskId, sizeof(DeDiskId)); + + DeList_UPDATE_BEGIN(GptMainHdr, DE_Sectors, DE_IDX_MAINGPTHDR, 512) + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start = GptMainHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptMainEntrys, DE_Sectors, DE_IDX_MAINGPTENTRYS, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Start = GptMainHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltHdr, DE_Sectors, DE_IDX_ALTGPTHDR, 512) + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start = GptAltHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltEntrys, DE_Sectors, DE_IDX_ALTGPTENTRYS, GptAltHdr->NumberOfPartitionEntries * GptAltHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Start = GptAltHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeExecParams, DE_ExecParams, DE_IDX_EXEC, sizeof(*DeExecParams)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DePwdCache, DE_PwdCache, DE_IDX_PWDCACHE, sizeof(*DePwdCache)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeRndSaved, DE_Rnd, DE_IDX_RND, sizeof(*DeRndSaved)) + DeList_UPDATE_END + + DeList->DataSize = Offset; + res = gBS->CalculateCrc32(DeList, 512, &DeList->CRC32); + if (EFI_ERROR(res)) { + ERR_PRINT(L"CRC: %r\n", res); + goto error; + } + { + EFI_FILE* file; + UINTN i; + + FileDelete(NULL, (CHAR16*)DcsDiskEntrysFileName); + res = FileOpen(NULL, (CHAR16*)DcsDiskEntrysFileName, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) { + ERR_PRINT(L"File: %r\n", res); + goto error; + } + for (i = 0; i < DeList->Count; ++i) { + if (DeData[i] != 0 && DeList->DE[i].Type != DE_DISKID) { + UINTN len; + UINTN pad; + len = (UINTN)DeList->DE[i].Length; + pad = (((len + 511) >> 9) << 9) - len; + res = FileWrite(file, DeData[i], &len, NULL); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + if (pad > 0) { + res = FileWrite(file, pad512buf, &pad, NULL); + } + } + } + FileClose(file); + } + +error: + MEM_FREE(DeList); + MEM_FREE(pad512buf); +} + +EFI_STATUS +DeListZero() { + if (DePwdCache != NULL) { + DePwdCache = AskConfirm("Remove passwords cache?", 1) ? NULL : DePwdCache; + } + if (DeExecParams != NULL) { + DeExecParams = AskConfirm("Remove exec?", 1) ? NULL : DeExecParams; + } + if (DeRndSaved != NULL) { + DeRndSaved = AskConfirm("Remove rnd?", 1) ? NULL : DeRndSaved; + } + if (GptMainHdr != NULL) { + if (AskConfirm("Remove GPT?", 1)) { + GptMainHdr = NULL; + GptMainEntrys = NULL; + GptAltHdr = NULL; + GptAltEntrys = NULL; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListParseSaved( + IN UINT8 *DeBuffer + ) +{ + EFI_STATUS res = EFI_SUCCESS; + CryptoHeader = DeBuffer; + DeList = (DCS_DISK_ENTRY_LIST*)(DeBuffer + 512); + CopyMem(&DeDiskId, &DeList->DE[DE_IDX_DISKID], sizeof(DeDiskId)); + + if (DeList->DE[DE_IDX_EXEC].Type == DE_ExecParams) { + DeExecParams = (DCS_DEP_EXEC *)(DeBuffer + DeList->DE[DE_IDX_EXEC].Offset); + } + + if (DeList->DE[DE_IDX_RND].Type == DE_Rnd) { + DeRndSaved = (DCS_RND_SAVED *)(DeBuffer + DeList->DE[DE_IDX_RND].Offset); + if ((UINTN)DeList->DE[DE_IDX_RND].Length != sizeof(*DeRndSaved)) { + return EFI_CRC_ERROR; + } + } + + if (DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { + UINT32 crc = 0; + UINT32 crcSaved = 0; + DePwdCache = (DCS_DEP_PWD_CACHE*)(DeBuffer + DeList->DE[DE_IDX_PWDCACHE].Offset); + if (DePwdCache->Sign != gDcsDiskEntryPwdCacheID) { + return EFI_CRC_ERROR; + } + crcSaved = DePwdCache->CRC; + DePwdCache->CRC = 0; + res = gBS->CalculateCrc32(DePwdCache, sizeof(*DePwdCache), &crc); + if (crc != crcSaved) { + ERR_PRINT(L"Pwd cache crc\n"); + return EFI_CRC_ERROR; + } + DePwdCache->CRC = crcSaved; + } + + if (DeList->DE[DE_IDX_MAINGPTHDR].Type == DE_Sectors) { + GptMainHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Offset); + if ((GptMainHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptMainHdr->Header) || + (DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start >> 9) != GptMainHdr->MyLBA || + (GptMainHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Main GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_MAINGPTENTRYS].Type == DE_Sectors) { + GptMainEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTHDR].Type == DE_Sectors) { + GptAltHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Offset); + if ((GptAltHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptAltHdr->Header) || + (DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start >> 9) != GptAltHdr->MyLBA || + (GptAltHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Alt GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTENTRYS].Type == DE_Sectors) { + GptAltEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT: %r\n", res); + return res; + } + } + + if (GptMainEntrys != NULL && GptAltEntrys != NULL && GptMainHdr != NULL) { + if (CompareMem(GptMainEntrys, GptAltEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) != 0) { + ERR_PRINT(L"Alt GPT != Main GPT\n", ); + return EFI_CRC_ERROR; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListLoadFromFile() +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len; + UINT8 *DeBuffer; + + InitFS(); + res = FileLoad(NULL, (CHAR16*)DcsDiskEntrysFileName, &DeBuffer, &len); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Load: %r\n", res); + return res; + } + return DeListParseSaved(DeBuffer); +} + +EFI_STATUS +DeListApplySectorsToDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + UINT8 *Mbr; + + InitBio(); + InitFS(); + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + // Compare MBR disk ID + Mbr = MEM_ALLOC(512); + if (Mbr == NULL) { + ERR_PRINT(L"Can't load MBR\n"); + return EFI_BUFFER_TOO_SMALL; + } + + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, Mbr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read MBR: %r\n", res); + MEM_FREE(Mbr); + return res; + } + + if (CompareMem(Mbr + 0x1b8, &DeDiskId.MbrID, sizeof(UINT32)) != 0) { + ERR_PRINT(L"Disk MBR ID %08x != %08x \n", *((UINT32*)(Mbr + 0x1b8)), DeDiskId.MbrID); + MEM_FREE(Mbr); + return res; + } + MEM_FREE(Mbr); + + // Save sectors + for (i = 0; i < DeList->Count; ++i) { + if (DeList->DE[i].Type == DE_Sectors) { + OUT_PRINT(L"%d Write: %lld, %lld\n", i, DeList->DE[i].Sectors.Start, DeList->DE[i].Sectors.Length); + res = BlockIo->WriteBlocks(BlockIo, BlockIo->Media->MediaId, + DeList->DE[i].Sectors.Start >> 9, + (UINTN)DeList->DE[i].Sectors.Length, + CryptoHeader + DeList->DE[i].Sectors.Offset); + } + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + return res; + } + } + return EFI_SUCCESS; +} + + +EFI_STATUS +GptSyncMainAlt() { + EFI_STATUS res = EFI_SUCCESS; + // Duplicate parts array + CopyMem(GptAltEntrys, GptMainEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry); + + res = GptUpdateCRC(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main CRC: %r\n", res); + return res; + } + GptUpdateCRC(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt CRC: %r\n", res); + return res; + } + return res; +} + +VOID +GptSqueze() { + UINTN i = 0; + UINTN emptyIdx = 0; + UINTN count; + count = GptMainHdr->NumberOfPartitionEntries; + while (i < count) { + if (CompareGuid(&GptMainEntrys[i].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + ++i; + continue; + } + else { + if (emptyIdx != i) { + CopyMem(&GptMainEntrys[emptyIdx], &GptMainEntrys[i], sizeof(*GptMainEntrys) * (count - i)); + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + } + ++emptyIdx; + i = emptyIdx; + } + } +} + +VOID +GptSort() { + UINTN i = 0; + UINTN j = 0; + UINTN n = 0; + UINTN count; + EFI_PARTITION_ENTRY tmp; + BOOLEAN swapped = TRUE; + count = GptMainHdr->NumberOfPartitionEntries; + + while (n < count) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + break; + } + ++n; + } + + while (swapped) { + swapped = FALSE; + j++; + for (i = 0; i < n - j; ++i) { + if (GptMainEntrys[i].StartingLBA > GptMainEntrys[i + 1].StartingLBA) { + CopyMem(&tmp, &GptMainEntrys[i], sizeof(tmp)); + CopyMem(&GptMainEntrys[i], &GptMainEntrys[i + 1], sizeof(tmp)); + CopyMem(&GptMainEntrys[i + 1], &tmp, sizeof(tmp)); + swapped = TRUE; + } + } + } +} + +// Checks if two regions overlap (borders are parts of regions) +BOOLEAN +IsRegionOverlap(UINT64 start1, UINT64 end1, UINT64 start2, UINT64 end2) { + return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); +} + +VOID +GptHideParts() { + UINTN count; + UINTN n; + BOOLEAN set = FALSE; + count = GptMainHdr->NumberOfPartitionEntries; + + for (n = 0; n < count; ++n) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + if (IsRegionOverlap( + GptMainEntrys[n].StartingLBA, GptMainEntrys[n].EndingLBA, + DcsHidePart.StartingLBA, DcsHidePart.EndingLBA)) { + if (set) { + SetMem(&GptMainEntrys[n], sizeof(*GptMainEntrys), 0); + } + else { + set = TRUE; + CopyMem(&GptMainEntrys[n], &DcsHidePart, sizeof(*GptMainEntrys)); + } + } + } + GptSqueze(); + GptSort(); + GptSyncMainAlt(); +} + +BOOLEAN +GptAskGUID( + IN char* prompt, + IN OUT EFI_GUID* guid) +{ + CHAR8 buf[128]; + UINTN len = 0; + EFI_GUID result; + BOOLEAN ok = TRUE; + OUT_PRINT(L"[%g] %a", guid, prompt); + + // (msr, data, oem, efi, del or guid) + GetLine(&len, NULL, buf, sizeof(buf), 1); + if (AsciiStrCmp(buf, "msr") == 0) { + CopyMem(guid, &gEfiPartTypeMsReservedPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "data") == 0) { + CopyMem(guid, &gEfiPartTypeBasicDataPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "wre") == 0) { + CopyMem(guid, &gEfiPartTypeMsRecoveryPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "efi") == 0) { + CopyMem(guid, &gEfiPartTypeSystemPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "del") == 0) { + CopyMem(guid, &gEfiPartTypeUnusedGuid, sizeof(EFI_GUID)); + } + else if (len == 0) { + ok = TRUE; + } + else { + ok = AsciiStrToGuid(&result, buf); + if (ok) { + CopyMem(guid, &result, sizeof(result)); + } + } + return ok; +} + +EFI_STATUS +DeListExecEdit() +{ + UINTN len; + UINTN i; + CHAR16 execCmd[FIELD_SIZEOF(DCS_DEP_EXEC, ExecCmd)]; + if (DeExecParams == NULL) { + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + } + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + if (GptMainHdr != NULL) { + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + if (CompareMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)) != 0) { + OUT_PRINT(L"EFI partition missmatched, updated"); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + } + break; + } + } + } + while (!GptAskGUID("\n\r:",(EFI_GUID*) &DeExecParams->ExecPartGuid)); + OUT_PRINT(L"[%s]\n\r:", &DeExecParams->ExecCmd); + GetLine(&len, execCmd, NULL, sizeof(execCmd) / 2 - 1, 1); + if (len != 0) { + CopyMem(&DeExecParams->ExecCmd, execCmd, sizeof(execCmd)); + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListPwdCacheEdit() +{ + UINTN count; + UINTN len; + UINTN i; + UINT32 crc = 0; + Password pwd; + UINTN pim; + EFI_STATUS res; + if (DePwdCache == NULL) { + DePwdCache = MEM_ALLOC(sizeof(*DePwdCache)); + DePwdCache->Sign = DCS_DEP_PWD_CACHE_SIGN; + } + OUT_PRINT(L"PwdCache\n"); + do { + count = (uint32)AskUINTN("Count[0-4]:", DePwdCache->Count); + } while (count > 4); + DePwdCache->Count = (uint32)count; + for (i = 0; i < 4; ++i) { + ZeroMem(&pwd, sizeof(pwd)); + pim = 0; + if (i < DePwdCache->Count) { + OUT_PRINT(L"%H%d%N [%a] [%d]\n:", i, DePwdCache->Pwd[i].Text, DePwdCache->Pim[i]); + GetLine(&len, NULL, pwd.Text, MAX_PASSWORD, 1); + if (len != 0) { + pwd.Length = (uint32)len; + pim = (uint32)AskUINTN("Pim:", DePwdCache->Pim[i]); + } + } + DePwdCache->Pim[i] = (uint32)pim; + CopyMem(&DePwdCache->Pwd[i], &pwd, sizeof(pwd)); + } + ZeroMem(&DePwdCache->pad, sizeof(DePwdCache->pad)); + DePwdCache->CRC = 0; + res =gBS->CalculateCrc32(DePwdCache, 512, &crc); + DePwdCache->CRC = crc; + return res; +} + +EFI_STATUS +DeListRndSave() +{ + EFI_STATUS res; + if (gRnd == NULL) { + DeRndSaved = NULL; + return EFI_SUCCESS; + } + res = RndSave(gRnd,&DeRndSaved); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", DeRndSaved->Type); + return res; +} + +EFI_STATUS +DeListRndLoad() +{ + EFI_STATUS res = EFI_NOT_FOUND; + if (DeRndSaved != NULL) { + res = RndLoad(DeRndSaved,&gRnd); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", gRnd->Type); + } + return res; +} diff --git a/Library/GraphLib/EfiGraph.c b/Library/GraphLib/EfiGraph.c new file mode 100644 index 0000000..b8e8e2e --- /dev/null +++ b/Library/GraphLib/EfiGraph.c @@ -0,0 +1,670 @@ +/** @file +Graph library + +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_HANDLE* gGraphHandles = NULL; +UINTN gGraphCount = 0; + +EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphOut = NULL; + +EFI_STATUS +InitGraph() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiGraphicsOutputProtocolGuid, 0, &gGraphHandles, &gGraphCount); + if (gGraphCount > 0) { + GraphGetIO(gGraphHandles[gGraphCount - 1], &gGraphOut); + } + return res; +} + +EFI_STATUS +GraphGetIO( + IN EFI_HANDLE Handle, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL** io + ) { + if (!io) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiGraphicsOutputProtocolGuid, (VOID**)io); +} + +EFI_STATUS +GraphGetModeInfo( + IN UINTN mode, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **info, + OUT UINTN* szInfo + ) { + if (!info || !gGraphOut || mode > gGraphOut->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + return gGraphOut->QueryMode(gGraphOut, (UINT32)mode, szInfo, info); +} + + +////////////////////////////////////////////////////////////////////////// +// Screen +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +ScreenGetSize( + OUT UINTN *Height, + OUT UINTN *Width + ) +{ + if (gGraphOut == NULL) return EFI_INVALID_PARAMETER; + *Height = gGraphOut->Mode->Info->VerticalResolution; + *Width = gGraphOut->Mode->Info->HorizontalResolution; + return EFI_SUCCESS; +} + +EFI_STATUS ScreenFillRect( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color, + IN UINTN x, + IN UINTN y, + IN UINTN width, + IN UINTN height + ) +{ + if (gGraphOut == NULL) return EFI_INVALID_PARAMETER; + + return gGraphOut->Blt(gGraphOut, color, EfiBltVideoFill, 0, 0, x, y, width, height, width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +EFI_STATUS ScreenDrawBlt( + IN BLT_HEADER *blt, + IN UINTN x, + IN UINTN y + ) +{ + return gGraphOut->Blt(gGraphOut, blt->Pixels, EfiBltBufferToVideo, 0, 0, x, y, blt->Width, blt->Height, blt->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +EFI_STATUS ScreenUpdateDirty( + IN BLT_HEADER *bltScreen + ) +{ + EFI_STATUS res = EFI_SUCCESS; + if (bltScreen->Dirty.top != bltScreen->Dirty.bottom || bltScreen->Dirty.left != bltScreen->Dirty.right) { + res = gGraphOut->Blt(gGraphOut, bltScreen->Pixels, EfiBltBufferToVideo, + bltScreen->Dirty.top, bltScreen->Dirty.left, // Source x,y + bltScreen->Dirty.top, bltScreen->Dirty.left, // Dest x,y + bltScreen->Dirty.right - bltScreen->Dirty.left + 1, bltScreen->Dirty.bottom - bltScreen->Dirty.top + 1, // width , height + bltScreen->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + SetMem(&bltScreen->Dirty, sizeof(bltScreen->Dirty), 0); + } + return res; +} + +EFI_STATUS +ScreenSaveBlt( + OUT BLT_HEADER **bltScreen + ) +{ + UINTN height; + UINTN width; + EFI_STATUS res; + BLT_HEADER* blt; + if (!bltScreen) return EFI_INVALID_PARAMETER; + res = ScreenGetSize(&height, &width); + if (EFI_ERROR(res)) return res; + blt = (BLT_HEADER*)MEM_ALLOC(sizeof(BLT_HEADER) + height * width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + blt->Height = (UINT32)height; + blt->Width = (UINT32)width; + *bltScreen = blt; + return gGraphOut->Blt(gGraphOut, blt->Pixels, EfiBltVideoToBltBuffer, 0, 0, 0, 0, blt->Width, blt->Height, blt->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +////////////////////////////////////////////////////////////////////////// +// Colors +////////////////////////////////////////////////////////////////////////// + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlack = { 0,0,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorWhite = { 255,255,255,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlue = { 255,0,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGreen = { 0,255,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorRed = { 0,0,255,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGray = { 128,128,128,0 }; +DRAW_CONTEXT gDrawContext = { { 255, 255, 255, 0 }, DrawOpSet, 0xFFFFFFFF, 128, { 128,128,128, 0}, NULL }; +INT32 gBrush3[5*2] = { -1,0, 1,0, 0,1, 0,-1, 0,0 }; + +////////////////////////////////////////////////////////////////////////// +// Blt +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +BltDrawBlt( + IN OUT BLT_HEADER* canvas, + IN BLT_HEADER* blt, + IN UINTN x, + IN UINTN y + ) { + UINTN row, col; + DRAW_CONTEXT ctx; + ctx.Op = DrawOpSet; + ctx.Brush = NULL; + for (row = 0; row < blt->Height; ++row) { + for (col = 0; col < blt->Width; ++col) { + ctx.Color = blt->Pixels[col + row * blt->Width]; + BltPoint(canvas, &ctx, x + col, y + row); + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +RectMarkDirty( + IN OUT PRECT rect, + IN UINTN x, + IN UINTN y + ) { + if (!rect) return EFI_INVALID_PARAMETER; + if (rect->top > y) rect->top = (UINT32)y; + if (rect->bottom < y) rect->bottom = (UINT32)y; + if (rect->left > x) rect->left = (UINT32)x; + if (rect->right < x) rect->right = (UINT32)x; + return EFI_SUCCESS; +} + + +EFI_STATUS +BltPointSingle( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN UINTN x, + IN UINTN y + ) { + UINTN pos; + if (!blt || x >= blt->Width || y >= blt->Height) return EFI_INVALID_PARAMETER; + RectMarkDirty(&blt->Dirty, x, y); + pos = x + y * blt->Width; + if (!draw) draw = &gDrawContext; + switch (draw->Op) + { + case DrawOpClear: + *(UINT32*)&blt->Pixels[pos] &= ~(*(UINT32*)&draw->Color); + break; + case DrawOpXor: + *(UINT32*)&blt->Pixels[pos] ^= *(UINT32*)&draw->Color; + break; + case DrawOpOr: + *(UINT32*)&blt->Pixels[pos] |= *(UINT32*)&draw->Color; + break; + case DrawOpSet: + blt->Pixels[pos] = draw->Color; + break; + case DrawOpAlpha: + { + UINT8 val; + val = blt->Pixels[pos].Red; + blt->Pixels[pos].Red = (UINT8)(val + (((draw->AlphaColor.Red - val) * draw->Alpha) >> 8)); + + val = blt->Pixels[pos].Green; + blt->Pixels[pos].Green = (UINT8)(val + (((draw->AlphaColor.Green - val) * draw->Alpha) >> 8)); + + val = blt->Pixels[pos].Blue; + blt->Pixels[pos].Blue = (UINT8)(val + (((draw->AlphaColor.Blue - val) * draw->Alpha) >> 8)); + + break; + } + default: + break; + } + return EFI_SUCCESS; +} + +EFI_STATUS +BltPoint( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN UINTN x, + IN UINTN y + ) { + if (draw->Brush == NULL) return BltPointSingle(blt, draw, x, y); + else + { + INT32* offset = draw->Brush; + do { + BltPointSingle(blt, draw, x + offset[0], y + +offset[1]); + offset += 2; + } while (!(offset[0] == 0 && offset[1] == 0)); + return BltPointSingle(blt, draw, x, y); + } +} + +VOID +BltBox( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + BltLine(blt, draw, x0, y0, x1, y0); + BltLine(blt, draw, x0, y0, x0, y1); + BltLine(blt, draw, x0, y1, x1, y1); + BltLine(blt, draw, x1, y0, x1, y1); +} + +VOID +BltFill( + IN BLT_HEADER* blt, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL fill, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + INT32 x; + INT32 y; + DRAW_CONTEXT ctx; + ctx.Op = DrawOpSet; + ctx.Brush = NULL; + ctx.Color = fill; + for (y = y0; y < y1; ++y) { + for (x = x0; x < x1; ++x) { + BltPoint(blt, &ctx, x, y); + } + } +} + +VOID +BltLine( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + int dx = ABS(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -ABS(y1 - y0), sy = y0 < y1 ? 1 : -1; + UINT32 mask, dmask, cmask; + int err = dx + dy, e2; /* error value e_xy */ + mask = draw ? draw->DashLine : gDrawContext.DashLine; + dmask = mask; + cmask = 32; + for (;;) { /* loop */ + // Dash + if ((dmask & 1) == 1) { + BltPoint(blt, draw, x0, y0); + } + dmask >>= 1; + cmask--; + if (cmask == 0) { + dmask = mask; + cmask = 32; + } + // next point + e2 = 2 * err; + if (e2 >= dy) { /* e_xy+e_x > 0 */ + if (x0 == x1) break; + err += dy; x0 += sx; + } + if (e2 <= dx) { /* e_xy+e_y < 0 */ + if (y0 == y1) break; + err += dx; y0 += sy; + } + } +} + + + +VOID +BltCircle( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 xm, + IN INT32 ym, + IN INT32 r, + IN BOOLEAN fill) +{ + int sx = 1; + int x = -r, y = 0, err = 2 - 2 * r; /* bottom left to top right */ + UINT32 mask, dmask, cmask; + mask = draw ? draw->DashLine : gDrawContext.DashLine; + dmask = mask; + cmask = 32; + do { + if (fill) { + if (sx != x) { + int i; + for (i = ym - y; i <= ym + y; i++) { + BltPoint(blt, draw, xm + x, i); + if( x != 0 ) BltPoint(blt, draw, xm - x, i); + } + sx = x; + } + } else { + if ((dmask & 1) == 1) { + BltPoint(blt, draw, xm - x, ym + y); /* I. Quadrant +x +y */ + BltPoint(blt, draw, xm - y, ym - x); /* II. Quadrant -x +y */ + BltPoint(blt, draw, xm + x, ym - y); /* III. Quadrant -x -y */ + BltPoint(blt, draw, xm + y, ym + x); /* IV. Quadrant +x -y */ + } + dmask >>= 1; + cmask--; + } + if (cmask == 0) { + dmask = mask; + cmask = 32; + } + r = err; + if (r <= y) err += ++y * 2 + 1; /* e_xy+e_y < 0 */ + if (r >= x || err > y) /* e_xy+e_x > 0 or no 2nd y-step */ + err += ++x * 2 + 1; /* -> x-step now */ + } while (x <= 0); +} + +extern __int8 gSimplex_ascii_32_126[95][112]; +VOID +BltText( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x, + IN INT32 y, + IN INT32 scale, // 0..256 reduce 256... enlarge + IN CONST CHAR8 *text) +{ + INT32 posX = x; + INT32 posY = y; + const char *c; + for (c = text; *c; ++c) + { + INT8 ch = *c; + if (ch >= 32 && ch <= 126) { + INT8 *it = gSimplex_ascii_32_126[ch - 32]; + INT32 nvtcs = *it++; + INT32 spacing = *it++; + INT32 fromX = -1; + INT32 fromY = -1; + INTN i; + for (i = 0; i < nvtcs; ++i) { + INT32 toX = *it++; + INT32 toY = *it++; + if ((fromX != -1 || fromY != -1) && (toX != -1 || toY != -1)) { + BltLine( + blt, draw, + posX + ((fromX * scale) >> 8), posY + (((25 - fromY) * scale) >> 8), + posX + ((toX * scale) >> 8), posY + (((25 - toY) * scale) >> 8)); + } + fromX = toX; + fromY = toY; + } + posX += (spacing * scale) >> 8; + } + // Next line + if (ch == '\n') { + posX = x; + posY += 30 * scale >> 8; + } + } +} + +////////////////////////////////////////////////////////////////////////// +// Bmp +////////////////////////////////////////////////////////////////////////// + +#pragma pack(1) +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} BMP_COLOR_MAP; + +typedef struct { + CHAR8 CharB; + CHAR8 CharM; + UINT32 Size; + UINT16 Reserved[2]; + UINT32 ImageOffset; + UINT32 HeaderSize; + UINT32 PixelWidth; + UINT32 PixelHeight; + UINT16 Planes; // Must be 1 + UINT16 BitPerPixel; // 1, 4, 8, or 24 + UINT32 CompressionType; + UINT32 ImageSize; // Compressed image size in bytes + UINT32 XPixelsPerMeter; + UINT32 YPixelsPerMeter; + UINT32 NumberOfColors; + UINT32 ImportantColors; +} BMP_IMAGE_HEADER; +#pragma pack() + +EFI_STATUS BmpGetSize( + IN const unsigned char* BmpImage, + IN UINTN BmpImageSize, + OUT UINTN *Height, + OUT UINTN *Width + ) +{ + BMP_IMAGE_HEADER *BmpHeader; + + if (sizeof(BMP_IMAGE_HEADER) > BmpImageSize) { + return EFI_INVALID_PARAMETER; + } + + BmpHeader = (BMP_IMAGE_HEADER *)BmpImage; + + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + // + // Only support BITMAPINFOHEADER format. + // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER + // + if (BmpHeader->HeaderSize != sizeof(BMP_IMAGE_HEADER) - ((UINTN)&(((BMP_IMAGE_HEADER *)0)->HeaderSize))) { + return EFI_UNSUPPORTED; + } + + *Height = BmpHeader->PixelHeight; + *Width = BmpHeader->PixelWidth; + return EFI_SUCCESS; +} + +EFI_STATUS +BmpToBlt( + IN CONST VOID *BmpImage, + IN UINTN BmpImageSize, + OUT BLT_HEADER **blt + ) +{ + UINT8 *Image; + UINT8 *ImageHeader; + BMP_IMAGE_HEADER *BmpHeader; + BMP_COLOR_MAP *BmpColorMap; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt_; + UINT64 BltBufferSize; + UINTN Index; + UINTN Height; + UINTN Width; + UINTN ImageIndex; + UINTN DataSizePerLine; + UINT32 ColorMapNum; + + if (sizeof(BMP_IMAGE_HEADER) > BmpImageSize) { + return EFI_INVALID_PARAMETER; + } + + BmpHeader = (BMP_IMAGE_HEADER *)BmpImage; + + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + // + // Doesn't support compress. + // + if (BmpHeader->CompressionType != 0) { + return EFI_UNSUPPORTED; + } + + // + // Only support BITMAPINFOHEADER format. + // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER + // + if (BmpHeader->HeaderSize != sizeof(BMP_IMAGE_HEADER) - ((UINTN)&(((BMP_IMAGE_HEADER *)0)->HeaderSize))) { + return EFI_UNSUPPORTED; + } + + // + // The data size in each line must be 4 byte alignment. + // + DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3); + BltBufferSize = MultU64x32(DataSizePerLine, BmpHeader->PixelHeight); + if (BltBufferSize > (UINT32)~0) { + return EFI_INVALID_PARAMETER; + } + + if ((BmpHeader->Size != BmpImageSize) || + (BmpHeader->Size < BmpHeader->ImageOffset) || + (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate Color Map offset in the image. + // + Image = (UINT8 *)BmpImage; + BmpColorMap = (BMP_COLOR_MAP *)(Image + sizeof(BMP_IMAGE_HEADER)); + if (BmpHeader->ImageOffset < sizeof(BMP_IMAGE_HEADER)) { + return EFI_INVALID_PARAMETER; + } + + if (BmpHeader->ImageOffset > sizeof(BMP_IMAGE_HEADER)) { + switch (BmpHeader->BitPerPixel) { + case 1: + ColorMapNum = 2; + break; + case 4: + ColorMapNum = 16; + break; + case 8: + ColorMapNum = 256; + break; + default: + ColorMapNum = 0; + break; + } + if (BmpHeader->ImageOffset - sizeof(BMP_IMAGE_HEADER) != sizeof(BMP_COLOR_MAP) * ColorMapNum) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Calculate graphics image data address in the image + // + Image = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset; + ImageHeader = Image; + + BltBufferSize = MultU64x32((UINT64)BmpHeader->PixelWidth, BmpHeader->PixelHeight); + // + // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow + // + if (BltBufferSize > DivU64x32((UINTN)~0, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { + return EFI_UNSUPPORTED; + } + BltBufferSize = MultU64x32(BltBufferSize, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + + *blt = MEM_ALLOC((UINTN)BltBufferSize + sizeof(**blt)); + + (*blt)->Width = BmpHeader->PixelWidth; + (*blt)->Height = BmpHeader->PixelHeight; + + // + // Convert image from BMP to Blt buffer format + // + BltBuffer = (*blt)->Pixels; + for (Height = 0; Height < BmpHeader->PixelHeight; Height++) { + Blt_ = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth]; + for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt_++) { + switch (BmpHeader->BitPerPixel) { + case 1: + // + // Convert 1bit BMP to 24-bit color + // + for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) { + Blt_->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red; + Blt_->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green; + Blt_->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue; + Blt_++; + Width++; + } + + Blt_--; + Width--; + break; + + case 4: + // + // Convert BMP Palette to 24-bit color + // + Index = (*Image) >> 4; + Blt_->Red = BmpColorMap[Index].Red; + Blt_->Green = BmpColorMap[Index].Green; + Blt_->Blue = BmpColorMap[Index].Blue; + if (Width < (BmpHeader->PixelWidth - 1)) { + Blt_++; + Width++; + Index = (*Image) & 0x0f; + Blt_->Red = BmpColorMap[Index].Red; + Blt_->Green = BmpColorMap[Index].Green; + Blt_->Blue = BmpColorMap[Index].Blue; + } + break; + + case 8: + // + // Convert BMP Palette to 24-bit color + // + Blt_->Red = BmpColorMap[*Image].Red; + Blt_->Green = BmpColorMap[*Image].Green; + Blt_->Blue = BmpColorMap[*Image].Blue; + break; + + case 24: + Blt_->Blue = *Image++; + Blt_->Green = *Image++; + Blt_->Red = *Image; + break; + + default: + MEM_FREE(*blt); + *blt = NULL; + return EFI_UNSUPPORTED; + break; + }; + + } + + ImageIndex = (UINTN)(Image - ImageHeader); + if ((ImageIndex % 4) != 0) { + // + // Bmp Image starts each row on a 32-bit boundary! + // + Image = Image + (4 - (ImageIndex % 4)); + } + } + + return EFI_SUCCESS; +} diff --git a/Library/GraphLib/GraphLib.inf b/Library/GraphLib/GraphLib.inf new file mode 100644 index 0000000..8201c82 --- /dev/null +++ b/Library/GraphLib/GraphLib.inf @@ -0,0 +1,43 @@ +## @file +# Graph library +# +# 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 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = GraphLib + MODULE_UNI_FILE = GraphLib.uni + FILE_GUID = 9BD93C5C-7EF7-4B07-A53D-1E84A9F00F2C + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GraphLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + + +[Sources.common] + EfiGraph.c + font.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + +[Protocols] + gEfiGraphicsOutputProtocolGuid diff --git a/Library/GraphLib/font.c b/Library/GraphLib/font.c new file mode 100644 index 0000000..c3ba9b2 --- /dev/null +++ b/Library/GraphLib/font.c @@ -0,0 +1,586 @@ +/** @file +Vector font definition based on Hershey Vector Font + +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 +**/ + +__int8 gSimplex_ascii_32_126[95][112] = { + 0,16, /* Ascii 32 */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,10, /* Ascii 33 */ + 5,21, 5, 7,-1,-1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 34 */ + 4,21, 4,14,-1,-1,12,21,12,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,21, /* Ascii 35 */ + 11,25, 4,-7,-1,-1,17,25,10,-7,-1,-1, 4,12,18,12,-1,-1, 3, 6,17, 6,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 26,20, /* Ascii 36 */ + 8,25, 8,-4,-1,-1,12,25,12,-4,-1,-1,17,18,15,20,12,21, 8,21, 5,20, 3, + 18, 3,16, 4,14, 5,13, 7,12,13,10,15, 9,16, 8,17, 6,17, 3,15, 1,12, 0, + 8, 0, 5, 1, 3, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 31,24, /* Ascii 37 */ + 21,21, 3, 0,-1,-1, 8,21,10,19,10,17, 9,15, 7,14, 5,14, 3,16, 3,18, 4, + 20, 6,21, 8,21,10,20,13,19,16,19,19,20,21,21,-1,-1,17, 7,15, 6,14, 4, + 14, 2,16, 0,18, 0,20, 1,21, 3,21, 5,19, 7,17, 7,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 34,26, /* Ascii 38 */ + 23,12,23,13,22,14,21,14,20,13,19,11,17, 6,15, 3,13, 1,11, 0, 7, 0, 5, + 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9,12,13,13,14,14,16,14,18,13,20,11,21, + 9,20, 8,18, 8,16, 9,13,11,10,16, 3,18, 1,20, 0,22, 0,23, 1,23, 2,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 7,10, /* Ascii 39 */ + 5,19, 4,20, 5,21, 6,20, 6,18, 5,16, 4,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,14, /* Ascii 40 */ + 11,25, 9,23, 7,20, 5,16, 4,11, 4, 7, 5, 2, 7,-2, 9,-5,11,-7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,14, /* Ascii 41 */ + 3,25, 5,23, 7,20, 9,16,10,11,10, 7, 9, 2, 7,-2, 5,-5, 3,-7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,16, /* Ascii 42 */ + 8,21, 8, 9,-1,-1, 3,18,13,12,-1,-1,13,18, 3,12,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,26, /* Ascii 43 */ + 13,18,13, 0,-1,-1, 4, 9,22, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,10, /* Ascii 44 */ + 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6,-1, 5,-3, 4,-4,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,26, /* Ascii 45 */ + 4, 9,22, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,10, /* Ascii 46 */ + 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,22, /* Ascii 47 */ + 20,25, 2,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,20, /* Ascii 48 */ + 9,21, 6,20, 4,17, 3,12, 3, 9, 4, 4, 6, 1, 9, 0,11, 0,14, 1,16, 4,17, + 9,17,12,16,17,14,20,11,21, 9,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 4,20, /* Ascii 49 */ + 6,17, 8,18,11,21,11, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,20, /* Ascii 50 */ + 4,16, 4,17, 5,19, 6,20, 8,21,12,21,14,20,15,19,16,17,16,15,15,13,13, + 10, 3, 0,17, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 15,20, /* Ascii 51 */ + 5,21,16,21,10,13,13,13,15,12,16,11,17, 8,17, 6,16, 3,14, 1,11, 0, 8, + 0, 5, 1, 4, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 6,20, /* Ascii 52 */ + 13,21, 3, 7,18, 7,-1,-1,13,21,13, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,20, /* Ascii 53 */ + 15,21, 5,21, 4,12, 5,13, 8,14,11,14,14,13,16,11,17, 8,17, 6,16, 3,14, + 1,11, 0, 8, 0, 5, 1, 4, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,20, /* Ascii 54 */ + 16,18,15,20,12,21,10,21, 7,20, 5,17, 4,12, 4, 7, 5, 3, 7, 1,10, 0,11, + 0,14, 1,16, 3,17, 6,17, 7,16,10,14,12,11,13,10,13, 7,12, 5,10, 4, 7, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,20, /* Ascii 55 */ + 17,21, 7, 0,-1,-1, 3,21,17,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 29,20, /* Ascii 56 */ + 8,21, 5,20, 4,18, 4,16, 5,14, 7,13,11,12,14,11,16, 9,17, 7,17, 4,16, + 2,15, 1,12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6,11, 9,12,13,13, + 15,14,16,16,16,18,15,20,12,21, 8,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,20, /* Ascii 57 */ + 16,14,15,11,13, 9,10, 8, 9, 8, 6, 9, 4,11, 3,14, 3,15, 4,18, 6,20, 9, + 21,10,21,13,20,15,18,16,14,16, 9,15, 4,13, 1,10, 0, 8, 0, 5, 1, 4, 3, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,10, /* Ascii 58 */ + 5,14, 4,13, 5,12, 6,13, 5,14,-1,-1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,10, /* Ascii 59 */ + 5,14, 4,13, 5,12, 6,13, 5,14,-1,-1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, + -1, 5,-3, 4,-4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 3,24, /* Ascii 60 */ + 20,18, 4, 9,20, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,26, /* Ascii 61 */ + 4,12,22,12,-1,-1, 4, 6,22, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 3,24, /* Ascii 62 */ + 4,18,20, 9, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 20,18, /* Ascii 63 */ + 3,16, 3,17, 4,19, 5,20, 7,21,11,21,13,20,14,19,15,17,15,15,14,13,13, + 12, 9,10, 9, 7,-1,-1, 9, 2, 8, 1, 9, 0,10, 1, 9, 2,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 55,27, /* Ascii 64 */ + 18,13,17,15,15,16,12,16,10,15, 9,14, 8,11, 8, 8, 9, 6,11, 5,14, 5,16, + 6,17, 8,-1,-1,12,16,10,14, 9,11, 9, 8,10, 6,11, 5,-1,-1,18,16,17, 8, + 17, 6,19, 5,21, 5,23, 7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12, + 21, 9,20, 7,19, 5,17, 4,15, 3,12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1,12, 0, + 15, 0,18, 1,20, 2,21, 3,-1,-1,19,16,18, 8,18, 6,19, 5, + 8,18, /* Ascii 65 */ + 9,21, 1, 0,-1,-1, 9,21,17, 0,-1,-1, 4, 7,14, 7,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,21, /* Ascii 66 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13, + 11,-1,-1, 4,11,13,11,16,10,17, 9,18, 7,18, 4,17, 2,16, 1,13, 0, 4, 0, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 18,21, /* Ascii 67 */ + 18,16,17,18,15,20,13,21, 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0,13, 0,15, 1,17, 3,18, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 15,21, /* Ascii 68 */ + 4,21, 4, 0,-1,-1, 4,21,11,21,14,20,16,18,17,16,18,13,18, 8,17, 5,16, + 3,14, 1,11, 0, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,19, /* Ascii 69 */ + 4,21, 4, 0,-1,-1, 4,21,17,21,-1,-1, 4,11,12,11,-1,-1, 4, 0,17, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,18, /* Ascii 70 */ + 4,21, 4, 0,-1,-1, 4,21,17,21,-1,-1, 4,11,12,11,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 22,21, /* Ascii 71 */ + 18,16,17,18,15,20,13,21, 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0,13, 0,15, 1,17, 3,18, 5,18, 8,-1,-1,13, 8,18, 8,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,22, /* Ascii 72 */ + 4,21, 4, 0,-1,-1,18,21,18, 0,-1,-1, 4,11,18,11,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 73 */ + 4,21, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,16, /* Ascii 74 */ + 12,21,12, 5,11, 2,10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,21, /* Ascii 75 */ + 4,21, 4, 0,-1,-1,18,21, 4, 7,-1,-1, 9,12,18, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,17, /* Ascii 76 */ + 4,21, 4, 0,-1,-1, 4, 0,16, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,24, /* Ascii 77 */ + 4,21, 4, 0,-1,-1, 4,21,12, 0,-1,-1,20,21,12, 0,-1,-1,20,21,20, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,22, /* Ascii 78 */ + 4,21, 4, 0,-1,-1, 4,21,18, 0,-1,-1,18,21,18, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 21,22, /* Ascii 79 */ + 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0,13, 0,15, + 1,17, 3,18, 5,19, 8,19,13,18,16,17,18,15,20,13,21, 9,21,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 13,21, /* Ascii 80 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13, + 10, 4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 24,22, /* Ascii 81 */ + 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0,13, 0,15, + 1,17, 3,18, 5,19, 8,19,13,18,16,17,18,15,20,13,21, 9,21,-1,-1,12, 4, + 18,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 16,21, /* Ascii 82 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13, + 11, 4,11,-1,-1,11,11,18, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 20,20, /* Ascii 83 */ + 17,18,15,20,12,21, 8,21, 5,20, 3,18, 3,16, 4,14, 5,13, 7,12,13,10,15, + 9,16, 8,17, 6,17, 3,15, 1,12, 0, 8, 0, 5, 1, 3, 3,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 84 */ + 8,21, 8, 0,-1,-1, 1,21,15,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,22, /* Ascii 85 */ + 4,21, 4, 6, 5, 3, 7, 1,10, 0,12, 0,15, 1,17, 3,18, 6,18,21,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,18, /* Ascii 86 */ + 1,21, 9, 0,-1,-1,17,21, 9, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,24, /* Ascii 87 */ + 2,21, 7, 0,-1,-1,12,21, 7, 0,-1,-1,12,21,17, 0,-1,-1,22,21,17, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,20, /* Ascii 88 */ + 3,21,17, 0,-1,-1,17,21, 3, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 6,18, /* Ascii 89 */ + 1,21, 9,11, 9, 0,-1,-1,17,21, 9,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,20, /* Ascii 90 */ + 17,21, 3, 0,-1,-1, 3,21,17,21,-1,-1, 3, 0,17, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,14, /* Ascii 91 */ + 4,25, 4,-7,-1,-1, 5,25, 5,-7,-1,-1, 4,25,11,25,-1,-1, 4,-7,11,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,14, /* Ascii 92 */ + 0,21,14,-3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,14, /* Ascii 93 */ + 9,25, 9,-7,-1,-1,10,25,10,-7,-1,-1, 3,25,10,25,-1,-1, 3,-7,10,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,16, /* Ascii 94 */ + 6,15, 8,18,10,15,-1,-1, 3,12, 8,17,13,12,-1,-1, 8,17, 8, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,16, /* Ascii 95 */ + 0,-2,16,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 7,10, /* Ascii 96 */ + 6,21, 5,20, 4,18, 4,16, 5,15, 6,16, 5,17,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 97 */ + 15,14,15, 0,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 98 */ + 4,21, 4, 0,-1,-1, 4,11, 6,13, 8,14,11,14,13,13,15,11,16, 8,16, 6,15, + 3,13, 1,11, 0, 8, 0, 6, 1, 4, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,18, /* Ascii 99 */ + 15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, + 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 100 */ + 15,21,15, 0,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,18, /* Ascii 101 */ + 3, 8,15, 8,15,10,14,12,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,12, /* Ascii 102 */ + 10,21, 8,21, 6,20, 5,17, 5, 0,-1,-1, 2,14, 9,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 22,19, /* Ascii 103 */ + 15,14,15,-2,14,-5,13,-6,11,-7, 8,-7, 6,-6,-1,-1,15,11,13,13,11,14, 8, + 14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 104 */ + 4,21, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8, 8, /* Ascii 105 */ + 3,21, 4,20, 5,21, 4,22, 3,21,-1,-1, 4,14, 4, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,10, /* Ascii 106 */ + 5,21, 6,20, 7,21, 6,22, 5,21,-1,-1, 6,14, 6,-3, 5,-6, 3,-7, 1,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,17, /* Ascii 107 */ + 4,21, 4, 0,-1,-1,14,14, 4, 4,-1,-1, 8, 8,15, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 108 */ + 4,21, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 18,30, /* Ascii 109 */ + 4,14, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,15, + 10,18,13,20,14,23,14,25,13,26,10,26, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 110 */ + 4,14, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 111 */ + 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,16, + 6,16, 8,15,11,13,13,11,14, 8,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 112 */ + 4,14, 4,-7,-1,-1, 4,11, 6,13, 8,14,11,14,13,13,15,11,16, 8,16, 6,15, + 3,13, 1,11, 0, 8, 0, 6, 1, 4, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 113 */ + 15,14,15,-7,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,13, /* Ascii 114 */ + 4,14, 4, 0,-1,-1, 4, 8, 5,11, 7,13, 9,14,12,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,17, /* Ascii 115 */ + 14,11,13,13,10,14, 7,14, 4,13, 3,11, 4, 9, 6, 8,11, 7,13, 6,14, 4,14, + 3,13, 1,10, 0, 7, 0, 4, 1, 3, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,12, /* Ascii 116 */ + 5,21, 5, 4, 6, 1, 8, 0,10, 0,-1,-1, 2,14, 9,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 117 */ + 4,14, 4, 4, 5, 1, 7, 0,10, 0,12, 1,15, 4,-1,-1,15,14,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 118 */ + 2,14, 8, 0,-1,-1,14,14, 8, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,22, /* Ascii 119 */ + 3,14, 7, 0,-1,-1,11,14, 7, 0,-1,-1,11,14,15, 0,-1,-1,19,14,15, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,17, /* Ascii 120 */ + 3,14,14, 0,-1,-1,14,14, 3, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 9,16, /* Ascii 121 */ + 2,14, 8, 0,-1,-1,14,14, 8, 0, 6,-4, 4,-6, 2,-7, 1,-7,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,17, /* Ascii 122 */ + 14,14, 3, 0,-1,-1, 3,14,14,14,-1,-1, 3, 0,14, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 39,14, /* Ascii 123 */ + 9,25, 7,24, 6,23, 5,21, 5,19, 6,17, 7,16, 8,14, 8,12, 6,10,-1,-1, 7, + 24, 6,22, 6,20, 7,18, 8,17, 9,15, 9,13, 8,11, 4, 9, 8, 7, 9, 5, 9, 3, + 8, 1, 7, 0, 6,-2, 6,-4, 7,-6,-1,-1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, + -1, 5,-3, 6,-5, 7,-6, 9,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 124 */ + 4,25, 4,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 39,14, /* Ascii 125 */ + 5,25, 7,24, 8,23, 9,21, 9,19, 8,17, 7,16, 6,14, 6,12, 8,10,-1,-1, 7, + 24, 8,22, 8,20, 7,18, 6,17, 5,15, 5,13, 6,11,10, 9, 6, 7, 5, 5, 5, 3, + 6, 1, 7, 0, 8,-2, 8,-4, 7,-6,-1,-1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, + -1, 9,-3, 8,-5, 7,-6, 5,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,24, /* Ascii 126 */ + 3, 6, 3, 8, 4,11, 6,12, 8,12,10,11,14, 8,16, 7,18, 7,20, 8,21,10,-1, + -1, 3, 8, 4,10, 6,11, 8,11,10,10,14, 7,16, 6,18, 6,20, 7,21,10,21,12, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; \ No newline at end of file diff --git a/Library/PasswordLib/ConsolePassword.c b/Library/PasswordLib/ConsolePassword.c new file mode 100644 index 0000000..c195b48 --- /dev/null +++ b/Library/PasswordLib/ConsolePassword.c @@ -0,0 +1,128 @@ +/** @file +Ask password from console + +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 "Library/CommonLib.h" +#include "Library/PasswordLib.h" +#include + +VOID +AskConsolePwdInt( + OUT UINT32 *length, + OUT CHAR8 *asciiLine, + OUT INT32 *retCode, + IN UINTN line_max, + IN UINT8 show + ) +{ + EFI_INPUT_KEY key; + UINT32 count = 0; + UINTN i; + + gST->ConOut->EnableCursor(gST->ConOut, TRUE); + + do { + key = GetKey(); + // Remove dirty chars 0.1s + FlushInputDelay(100000); + + if (key.ScanCode == SCAN_ESC) { + *retCode = AskPwdRetCancel; + break; + } + + if (key.ScanCode == SCAN_F2) { + *retCode = AskPwdRetChange; + break; + } + + if (key.ScanCode == SCAN_F5) { + show = show ? 0 : 1; + if (show) { + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b"); + } + OUT_PRINT(L"%a", asciiLine); + } + else { + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b"); + } + for (i = 0; i < count; i++) { + OUT_PRINT(L"*"); + } + } + } + + if (key.ScanCode == SCAN_F7) { + gPlatformLocked = gPlatformLocked ? 0 : 1; + ConsoleShowTip(gPlatformLocked ? L" Platform locked!" : L" Platform unlocked!", 10000000); + } + + if (key.ScanCode == SCAN_F8) { + gTPMLocked = gTPMLocked ? 0 : 1; + ConsoleShowTip(gTPMLocked ? L" TPM locked!" : L" TPM unlocked!", 10000000); + } + + + if (key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + *retCode = AskPwdRetLogin; + break; + } + + 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 (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 (asciiLine != NULL) { + asciiLine[count++] = (CHAR8)key.UnicodeChar; + asciiLine[count] = 0; + } + } + } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + if (length != NULL) *length = count; + // Set end of line + if (asciiLine != NULL) { + asciiLine[count] = '\0'; + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b \b"); + } + OUT_PRINT(L"*"); + } + OUT_PRINT(L"\n"); +} diff --git a/Library/PasswordLib/PasswordLib.inf b/Library/PasswordLib/PasswordLib.inf new file mode 100644 index 0000000..6b30c0c --- /dev/null +++ b/Library/PasswordLib/PasswordLib.inf @@ -0,0 +1,46 @@ +## @file +# Password library +# +# 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 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = GraphLib + MODULE_UNI_FILE = GraphLib.uni + FILE_GUID = A73BC841-498A-41E5-87B1-A0CED9933756 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GraphLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + PicturePassword.c + ConsolePassword.c + PlatformID.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + +[Protocols] + gEfiGraphicsOutputProtocolGuid + +[Guids] + gEfiSmbiosTableGuid diff --git a/Library/PasswordLib/PicturePassword.c b/Library/PasswordLib/PicturePassword.c new file mode 100644 index 0000000..f917899 --- /dev/null +++ b/Library/PasswordLib/PicturePassword.c @@ -0,0 +1,629 @@ +/** @file +Picture password + +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 + +CHAR16* gPasswordPictureFileName = NULL; + +CHAR8* gPasswordPictureChars = NULL; +CHAR8* gPasswordPictureCharsDefault = "MN/[aQ-eyPr}GT: |V^UqiI_gbdA9YwZ%f8t6S@D\"7uXl\\30R#+zH*,W4J?=&BLFv]hx~E;$<.o'sp1`(>C)O{!5j2nmkcK"; +//CHAR8* gPicturePasswordCharsDefault = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; +UINTN gPasswordPictureCharsLen = 95; + +UINT8 gPasswordVisible = 0; +int gPasswordShowMark = 1; + +int gPlatformLocked = 0; +int gTPMLocked = 0; +int gSCLocked = 0; + + +////////////////////////////////////////////////////////////////////////// +// Picture password +////////////////////////////////////////////////////////////////////////// +CONST CHAR16* BmpName = L"Test.bmp"; +VOID* Bmp = NULL; +UINTN BmpSize = 0; +BLT_HEADER* bltPwd = NULL; +UINTN posPictX, posPictY; +BLT_HEADER* bltScrn = NULL; +UINTN* cellSelected = NULL; +UINTN picPwdIdx = 0; +UINTN sHeight; +UINTN sWidth; +UINTN step; + +DRAW_CONTEXT ctxCursor; +DRAW_CONTEXT ctxCell; +DRAW_CONTEXT ctxMark; +DRAW_CONTEXT ctxSet; + +VOID +CellUpdate( + IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y, + IN BOOLEAN selected) { + if (selected && gPasswordShowMark) { + BltCircle(blt, &ctxMark, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), TRUE); + BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 9), TRUE); + } + else { + CHAR8 ch[2] = { 0,0 }; + BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), FALSE); + if (gPasswordVisible) { + ch[0] = gPasswordPictureChars[(x + blt->Width / step * y) % gPasswordPictureCharsLen]; + BltText(blt, &ctxCell, (INT32)(x * step + step / 2 - 12), (INT32)(y * step + step / 2 - 12), 256, ch); + } + } +} + +BOOLEAN +CellGetSelected( + IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y, + OUT UINTN* cellX, + OUT UINTN* cellY) { + RECT reg; + UINTN sen; + if (x > blt->Width || y > blt->Height) return FALSE; + *cellX = x / step; + *cellY = y / step; + sen = step / 5; // zone sensible + reg.left = (UINT32)(*cellX * step + step / 2 - sen); + reg.right = (UINT32)(*cellX * step + step / 2 + sen); + reg.top = (UINT32)(*cellY * step + step / 2 - sen); + reg.bottom = (UINT32)(*cellY * step + step / 2 + sen); + return (x > reg.left && x < reg.right && y > reg.top && y < reg.bottom); +} + +VOID +DrawCursor(IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y + ) { + BltLine(blt, &ctxCursor, (INT32)(x - 10), (INT32)y, (INT32)(x + 10), (INT32)y); + BltLine(blt, &ctxCursor, (INT32)x, (INT32)(y - 10), (INT32)x, (INT32)(y + 10)); +} + +typedef struct _TOUCH_ZONE { + UINTN Zone; + CHAR8* Message; + UINTN RetCode; + INT32 TextScale; +} TOUCH_ZONE, *PTOUCH_ZONE; + +enum TouchZoneIds { + tznLogin = 1, + tznBeep, + tznShow, + tznChange +}; + +CHAR8* msgLogin = "LOGIN"; +CHAR8* msgBeepOn = "Beep\non"; +CHAR8* msgBeepOff = "Beep\noff"; +CHAR8* msgChg = "Change\npwd"; +CHAR8* msgShowPwd = "Show\npwd"; +CHAR8* msgHidePwd = "Hide\npwd"; +CHAR8* msgNewPwd = "New\npwd"; +CHAR8* msgConfirmPwd = "Confirm\npwd"; +CHAR8* msgPlatformLocked = "PLT\nlkd"; +CHAR8* msgPlatformUnLocked = "PLT\nunlkd"; +CHAR8* msgTpmLocked = "TPM\nlkd"; +CHAR8* msgTpmUnLocked = "TPM\nunlkd"; + +TOUCH_ZONE TZN_Login = { 0, NULL, tznLogin, 128 }; +TOUCH_ZONE TZN_Speaker = { 2, NULL, tznBeep, 64 }; +TOUCH_ZONE TZN_Show = { 3, NULL, tznShow, 64 }; +TOUCH_ZONE TZN_Change = { 5, NULL, tznChange, 32 }; +TOUCH_ZONE TZN_Platform = { 6, NULL, 0, 32 }; +TOUCH_ZONE TZN_Tpm = { 7, NULL, 0, 32 }; + +VOID +DrawTouchZone( + IN PTOUCH_ZONE zone + ) { + BltFill(bltScrn, gColorBlack, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step)); + BltBox(bltScrn, &ctxCell, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step)); + BltText(bltScrn, &ctxCell, (INT32)(sWidth - step * 3 / 4), (INT32)(step * 1 / 3 + zone->Zone * step), 128, zone->Message); +} + +BOOLEAN +IsTouchZone( + IN PTOUCH_ZONE zone, + IN UINTN x, + IN UINTN y + ) { + if (x > sWidth - step && + (y > (zone->Zone * step)) && + (y < (step + zone->Zone * step))) { + return TRUE; + } + return FALSE; +} + +VOID +DrawPwdZone( + IN CHAR8* pwd, + IN UINT32 pwdMax) +{ + INT32 pwdGrphMaxLen = (INT32)(sWidth - 2 * step); + BltFill(bltScrn, gColorBlack, 0, 0, (INT32)(sWidth - 2 * step), (INT32)(posPictY)); + if (gPasswordVisible) { + BltText(bltScrn, &ctxCell, 0, 0, 256, pwd); + } + else { + INT32 pwdGrphLen = (INT32)(pwdGrphMaxLen * picPwdIdx / pwdMax); + INT32 pwdGrphHeight = (INT32)(posPictY) / 2; + INT32 pwdGrphTop = (INT32)(posPictY) / 4; + BltFill(bltScrn, gColorGreen, 0, pwdGrphTop, pwdGrphLen, pwdGrphHeight + pwdGrphTop); + BltFill(bltScrn, gColorBlack, pwdGrphLen, pwdGrphTop, pwdGrphMaxLen, pwdGrphHeight + pwdGrphTop); + } +} + +EFI_STATUS +DrawPwdPicture() +{ + EFI_STATUS res; + UINTN idx; + UINTN cellX, cellY; + + if (bltPwd != NULL) MEM_FREE(bltPwd); + + res = BmpToBlt(Bmp, BmpSize, &bltPwd); + if (EFI_ERROR(res)) { + return res; + } + cellY = 0; + do { + cellX = 0; + do { + CellUpdate(bltPwd, cellX, cellY, FALSE); + cellX++; + } while ((cellX + 1) * step <= (bltPwd->Width)); + cellY++; + } while ((cellY + 1)* step <= (bltPwd->Height)); + + // Update selected + for (idx = 0; idx < picPwdIdx; ++idx) { + if (cellSelected[idx * 2] != MAX_INTN) { + CellUpdate(bltPwd, cellSelected[idx * 2], cellSelected[idx * 2 + 1], TRUE); + } + } + return EFI_SUCCESS; +} + +VOID +CreateDraws() { + // Set + ctxSet.Color = gColorGray; + ctxSet.DashLine = 0xFFFFFFFF; + ctxSet.Op = DrawOpSet; + ctxSet.Brush = NULL; + + // Cursor + ctxCursor.Color = gColorWhite; + ctxCursor.DashLine = 0xFFFFFFFF; + ctxCursor.Op = DrawOpXor; + ctxCursor.Brush = NULL; + + // Cell + ctxCell.Color = gColorGreen; + ctxCell.DashLine = 0xFFFFFFFF; + ctxCell.Op = DrawOpSet; + ctxCell.Brush = gBrush3; + + // Shade (close to black) + ctxMark.AlphaColor = gColorWhite; + ctxMark.Alpha = 128; + ctxMark.Op = DrawOpAlpha; + ctxMark.Brush = NULL; +} + +enum PictPwdAction { + PwdActNone = 0, + PwdActLogin, + PwdActCancel, + PwdActChange, + PwdActShow, + PwdActBeep, + PwdActNewChar, + PwdActUpdateZones, +}; + +VOID +AskPictPwdInt( + IN UINTN pwdType, + IN UINTN pwdMax, + OUT CHAR8* pwd, + OUT UINT32* pwdLen, + OUT INT32* retCode + ) { + EFI_STATUS res; + UINTN cellX, cellY; + UINTN cellPrevX, cellPrevY; + UINTN curX, curY; + UINTN curPrevX, curPrevY; + EFI_INPUT_KEY key; + EFI_EVENT UpdateEvent; + EFI_EVENT BeepOffEvent; + EFI_EVENT InputEvents[3]; + UINTN EventIndex = 0; + UINTN eventsCount = 2; + EFI_ABSOLUTE_POINTER_STATE aps = {0}; + BOOLEAN showCursor = FALSE; + BOOLEAN beepOn = FALSE; + UINTN pwdAction = PwdActNone; + CHAR8 pwdNewChar = 0; + + InitConsoleControl(); + if (gBeepEnabled) { + InitSpeaker(); + } + + if (Bmp == NULL) { + if (gPasswordPictureFileName != NULL) { + res = FileLoad(NULL, (CHAR16*)gPasswordPictureFileName, &Bmp, &BmpSize); + if (EFI_ERROR(res)) { + ERR_PRINT(L"File load - %r\n", res); + return; + } + } else { + ERR_PRINT(L"Picture file name undefined\n"); + return; + } + } + // Init draws + CreateDraws(); + + // Init screen + if (bltScrn != NULL) MEM_FREE(bltScrn); + ScreenSaveBlt(&bltScrn); + sWidth = bltScrn->Width; + sHeight = bltScrn->Height; + step = sWidth >> 4; + + // Init picture password + picPwdIdx = 0; + res = DrawPwdPicture(); + if (EFI_ERROR(res)) { + MEM_FREE(bltScrn); + ERR_PRINT(L"BmpToBlt - %r", res); + return; + } + + // Touch zones + switch (pwdType) { + case AskPwdConfirm: + TZN_Login.Message = msgConfirmPwd; + break; + case AskPwdNew: + TZN_Login.Message = msgNewPwd; + break; + case AskPwdLogin: + default: + TZN_Login.Message = msgLogin; + } + DrawTouchZone(&TZN_Login); + + if (pwdType == AskPwdLogin) { + TZN_Change.Message = msgChg; + DrawTouchZone(&TZN_Change); + } + + if (gBeepControlEnabled) { + TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn; + DrawTouchZone(&TZN_Speaker); + } + + TZN_Platform.Message = gPlatformLocked? msgPlatformLocked : msgPlatformUnLocked; + DrawTouchZone(&TZN_Platform); + + TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked; + DrawTouchZone(&TZN_Tpm); + + TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd; + DrawTouchZone(&TZN_Show); + cellSelected = MEM_ALLOC(sizeof(UINTN) * 2 * (pwdMax + 1)); + + ScreenUpdateDirty(bltScrn); + + // Prepare cursors + posPictX = (sWidth - bltPwd->Width) >> 1; + posPictY = (sHeight - bltPwd->Height) >> 1; + cellPrevX = MAX_INTN; + cellPrevY = MAX_INTN; + curX = sWidth / 2; + curY = posPictY / 2; + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + + // Prepare events + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &BeepOffEvent); + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &UpdateEvent); + gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update + gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10); + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + + if (gTouchPointer != NULL) { + eventsCount = 3; + InputEvents[2] = gTouchPointer->WaitForInput; + while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) { + gTouchPointer->GetState(gTouchPointer, &aps); + } + } + while (gBS->CheckEvent(InputEvents[0]) == EFI_SUCCESS) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + do + { + curPrevX = curX; + curPrevY = curY; + res = gBS->WaitForEvent(eventsCount, InputEvents, &EventIndex); + // OUT_PRINT(L" \r%05d %05d", (UINT32)curX, (UINT32)curY, ); + // recharge timeout event and stop beep + if (gBeepControlEnabled && gBeepEnabled && beepOn) { + if (gBS->CheckEvent(BeepOffEvent) == EFI_SUCCESS) { + beepOn = FALSE; + SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0); + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + } + } + else { + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + } + + // hide cursor + if (showCursor && EventIndex != 1) { + DrawCursor(bltScrn, curX, curY); + showCursor = FALSE; + } + + // Blink cursor + if (EventIndex == 1) { + DrawCursor(bltScrn, curX, curY); + showCursor = !showCursor; + } + + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + // OUT_PRINT(L" %04x, %04x\r", key.ScanCode, key.UnicodeChar); + + // Remove dirty chars 0.1s + FlushInputDelay(100000); + switch (key.ScanCode) + { + case SCAN_HOME: + curX -= gTouchSimulateStep; + curY -= gTouchSimulateStep; + break; + case SCAN_LEFT: + curX -= gTouchSimulateStep; + break; + case SCAN_END: + curX -= gTouchSimulateStep; + curY += gTouchSimulateStep; + break; + case SCAN_DOWN: + curY += gTouchSimulateStep; + break; + case SCAN_PAGE_DOWN: + curX += gTouchSimulateStep; + curY += gTouchSimulateStep; + break; + case SCAN_RIGHT: + curX += gTouchSimulateStep; + break; + case SCAN_PAGE_UP: + curX += gTouchSimulateStep; + curY -= gTouchSimulateStep; + break; + case SCAN_UP: + curY -= gTouchSimulateStep; + break; + case SCAN_F11: + if (gTouchSimulateStep > 1) + gTouchSimulateStep--; + break; + case SCAN_F12: + gTouchSimulateStep++; + break; + case SCAN_ESC: + pwdAction = PwdActCancel; + break; + case SCAN_F2: + if (pwdType == AskPwdLogin) { + pwdAction = PwdActChange; + } + break; + case SCAN_F4: + if (gBeepControlEnabled) { + pwdAction = PwdActBeep; + } + break; + case SCAN_F5: + pwdAction = PwdActShow; + break; + case SCAN_F7: + gPlatformLocked = gPlatformLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + break; + case SCAN_F8: + gTPMLocked = gTPMLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + break; + default: + ; + } + + if (key.UnicodeChar != 0) { + if (key.UnicodeChar == 0x0d) { + pwdAction = PwdActLogin; + } + else { + pwdNewChar = (CHAR8)key.UnicodeChar; + pwdAction = PwdActNewChar; + cellSelected[picPwdIdx * 2] = MAX_INTN; + } + } + + } + + if (EventIndex == 2) { + res = gTouchPointer->GetState(gTouchPointer, &aps); + if (!EFI_ERROR(res)) { + curX = (UINTN)(aps.CurrentX * sWidth / (gTouchPointer->Mode->AbsoluteMaxX - gTouchPointer->Mode->AbsoluteMinX)); + curY = (UINTN)(aps.CurrentY * sHeight / (gTouchPointer->Mode->AbsoluteMaxY - gTouchPointer->Mode->AbsoluteMinY)); + } + } + + if (curX > sWidth) curX = sWidth; + if (curY > sHeight) curY = sHeight; + + // Cell check + if (CellGetSelected(bltPwd, curX - posPictX, curY - posPictY, &cellX, &cellY) && picPwdIdx < pwdMax) { + if (cellPrevX != cellX || cellPrevY != cellY) { + cellPrevX = cellX; + cellPrevY = cellY; + cellSelected[picPwdIdx * 2] = cellX; + cellSelected[picPwdIdx * 2 + 1] = cellY; + CellUpdate(bltPwd, cellX, cellY, TRUE); + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + pwdAction = PwdActNewChar; + pwdNewChar = gPasswordPictureChars[(cellX + bltPwd->Width / step * cellY) % gPasswordPictureCharsLen]; + } + else if (EventIndex == 2 && aps.ActiveButtons == 0) { + cellPrevX = MAX_INTN; + cellPrevY = MAX_INTN; + curX = posPictX + cellX * step; + curY = posPictY + cellY * step; + while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) { + gTouchPointer->GetState(gTouchPointer, &aps); + } + } + } + + if (pwdAction == PwdActNone) { + if (IsTouchZone(&TZN_Login, curX, curY)) { + pwdAction = PwdActLogin; + } + + if (pwdType == AskPwdLogin && IsTouchZone(&TZN_Change, curX, curY)) { + pwdAction = PwdActChange; + } + + if (curPrevX != curX || curPrevY != curY) { + if (gSpeakerCount > 0 && IsTouchZone(&TZN_Speaker, curX, curY)) { + pwdAction = PwdActBeep; + } + if (IsTouchZone(&TZN_Show, curX, curY)) { + pwdAction = PwdActShow; + } + if (IsTouchZone(&TZN_Tpm, curX, curY)) { + gTPMLocked = gTPMLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + } + if (IsTouchZone(&TZN_Platform, curX, curY)) { + gPlatformLocked = gPlatformLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + } + } + } + + if (PwdActNewChar == pwdAction) { + BOOLEAN bUpdPwdZone = FALSE; + if (pwdNewChar == '\b' && picPwdIdx > 0) { + picPwdIdx--; + pwd[picPwdIdx] = 0; + bUpdPwdZone = TRUE; + } else if ((picPwdIdx < pwdMax - 1) && (pwdNewChar >= 32)) { + pwd[picPwdIdx++] = pwdNewChar; + pwd[picPwdIdx] = 0; + bUpdPwdZone = TRUE; + } + if(bUpdPwdZone) { + *pwdLen = (int)picPwdIdx; + DrawPwdZone(pwd, (INT32)pwdMax); + if (gBeepControlEnabled && gBeepEnabled) { + SpeakerBeep((UINT16)gBeepToneDefault, gBeepNumberDefault, 0, 0); + gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10); + gBS->SetTimer(InputEvents[1], TimerRelative, gBeepDurationDefault * 10); + beepOn = TRUE; + } + } + } + else if (PwdActBeep == pwdAction && gBeepControlEnabled) { + if (gBeepEnabled && beepOn) { + beepOn = FALSE; + SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0); + } + gBeepEnabled = gBeepEnabled ? 0 : 1; + TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn; + DrawTouchZone(&TZN_Speaker); + } + else if (PwdActShow == pwdAction) { + gPasswordVisible = gPasswordVisible ? 0 : 1; + DrawPwdZone(pwd, (INT32)pwdMax); + DrawPwdPicture(); + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd; + DrawTouchZone(&TZN_Show); + } + else if (PwdActLogin == pwdAction) { + *retCode = AskPwdRetLogin; + break; + } + else if (pwdType == AskPwdLogin && PwdActChange == pwdAction) { + *retCode = AskPwdRetChange; + break; + } + else if (PwdActCancel == pwdAction){ + *retCode = AskPwdRetCancel; + break; + } + else if (PwdActUpdateZones == pwdAction) { + TZN_Platform.Message = gPlatformLocked ? msgPlatformLocked : msgPlatformUnLocked; + DrawTouchZone(&TZN_Platform); + + TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked; + DrawTouchZone(&TZN_Tpm); + } + + if (curPrevX != curX || curPrevY != curY) { + DrawCursor(bltScrn, curX, curY); + showCursor = TRUE; + } + // Time to update screen? + if (gBS->CheckEvent(UpdateEvent) == EFI_SUCCESS) { + ScreenUpdateDirty(bltScrn); + gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update + } + + pwdAction = PwdActNone; + } while (TRUE); + gBS->CloseEvent(InputEvents[1]); + gBS->CloseEvent(UpdateEvent); + gBS->CloseEvent(BeepOffEvent); + ScreenFillRect(&gColorBlack, 0, 0, sWidth, sHeight); + gBS->Stall(500000); +} diff --git a/Library/PasswordLib/PlatformID.c b/Library/PasswordLib/PlatformID.c new file mode 100644 index 0000000..351503e --- /dev/null +++ b/Library/PasswordLib/PlatformID.c @@ -0,0 +1,266 @@ +/** @file +Platform Id based on SMBIOS structures + +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 "Library/CommonLib.h" + +SMBIOS_TABLE_ENTRY_POINT* gSmbTable = NULL; +EFI_GUID* gSmbSystemUUID = NULL; // Universal unique ID +CHAR8* gSmbSystemSerial = NULL; // System serial +CHAR8* gSmbSystemSKU = NULL; // SKU number +CHAR8* gSmbBaseBoardSerial = NULL; // Base board serial +UINT64* gSmbProcessorID = NULL; // Processor ID + +UINTN gBioIndexAuth = 0; +typedef struct _DCS_AUTH_DATA_MARK { + UINT32 HeaderCrc; + UINT32 PlatformCrc; + UINT32 AuthDataSize; + UINT32 Reserved; +} DCS_AUTH_DATA_MARK; + +CHAR8* SMBIOSGetString(UINTN StringNumber, SMBIOS_STRUCTURE* smbtbl, CHAR8* lastAddr) { + CHAR8* String; + UINTN Index; + String = ((UINT8*)smbtbl) + smbtbl->Length; + for (Index = 1; Index <= StringNumber; Index++) { + if (StringNumber == Index) { + return String; + } + // + // Skip string + // + while (*String != 0) { + String++; + if (String > lastAddr) { + return NULL; + } + } + String++; +// if (*String == 0) { +// return NULL; +// } + } + return NULL; +} + +/** +* Get SMBIOS serial data +*/ +EFI_STATUS +SMBIOSGetSerials() +{ + EFI_STATUS res; + SMBIOS_STRUCTURE_POINTER pSMBIOS; + CHAR8* pos = NULL; + CHAR8* endOfTable; + + // Get SMBIOS tables pointer from System Configure table + res = EfiGetSystemConfigurationTable(&gEfiSmbiosTableGuid, (VOID**)&gSmbTable); + if (EFI_ERROR(res)) { + return res; + } + pSMBIOS.Raw = (UINT8 *)(UINTN)(gSmbTable->TableAddress); + pos = pSMBIOS.Raw; + endOfTable = pSMBIOS.Raw + gSmbTable->TableLength; + do { + SMBIOS_STRUCTURE* smbtbl = (SMBIOS_STRUCTURE*)pos; + // System info + if (smbtbl->Type == 1) { + gSmbSystemUUID = (EFI_GUID*)&pos[8]; + gSmbSystemSerial = SMBIOSGetString(4, smbtbl, endOfTable); + gSmbSystemSKU = SMBIOSGetString(5, smbtbl, endOfTable); + } + // Base board + if (smbtbl->Type == 2) { + gSmbBaseBoardSerial = SMBIOSGetString(4, smbtbl, endOfTable); + } + // Processor + if (smbtbl->Type == 4) { + gSmbProcessorID = (UINT64*)&pos[8]; + } + pos += smbtbl->Length; + while (((pos[0] != 0) || (pos[1] != 0)) && (pos < endOfTable)) pos++; + pos += 2; + } while (pos < endOfTable); + + return EFI_SUCCESS; +} + +EFI_STATUS +PlatformGetID( + IN EFI_HANDLE handle, + OUT CHAR8 **id, + OUT UINTN *idlength + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN idLen = 0; + CHAR8* idBuf = NULL; + CHAR8* handleSerial = NULL; + + UsbGetId(handle, &handleSerial); + if (gSmbSystemUUID == NULL) SMBIOSGetSerials(); + idLen += (gSmbSystemUUID == NULL) ? 0 : sizeof(*gSmbSystemUUID); + idLen += (gSmbSystemSerial == NULL) ? 0 : AsciiStrLen((char*)gSmbSystemSerial) + 1; + idLen += (gSmbSystemSKU == NULL) ? 0 : AsciiStrLen((char*)gSmbSystemSKU) + 1; + idLen += (gSmbBaseBoardSerial == NULL) ? 0 : AsciiStrLen((char*)gSmbBaseBoardSerial) + 1; + idLen += (gSmbProcessorID == NULL) ? 0 : sizeof(*gSmbProcessorID); + idLen += (handleSerial == NULL) ? 0 : AsciiStrLen((char*)handleSerial) + 1; + + idBuf = MEM_ALLOC(idLen); + if (idBuf == NULL) { + res = EFI_BUFFER_TOO_SMALL; + goto error; + } + + *id = idBuf; + *idlength = idLen; + + if (gSmbSystemUUID != NULL) { + CopyMem(idBuf, gSmbSystemUUID, sizeof(*gSmbSystemUUID)); + idBuf += sizeof(*gSmbSystemUUID); + } + + if (gSmbSystemSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbSystemSerial) + 1; + CopyMem(idBuf, gSmbSystemSerial, ssz); + idBuf += ssz; + } + + if (gSmbSystemSKU != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbSystemSKU) + 1; + CopyMem(idBuf, gSmbSystemSKU, ssz); + idBuf += ssz; + } + + if (gSmbBaseBoardSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbBaseBoardSerial) + 1; + CopyMem(idBuf, gSmbBaseBoardSerial, ssz); + idBuf += ssz; + } + + if (gSmbProcessorID != NULL) { + CopyMem(idBuf, gSmbProcessorID, sizeof(*gSmbProcessorID)); + idBuf += sizeof(*gSmbProcessorID); + } + + if (handleSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)handleSerial) + 1; + CopyMem(idBuf, handleSerial, ssz); + idBuf += ssz; + MEM_FREE(handleSerial); + } + + return res; + +error: + MEM_FREE(handleSerial); + MEM_FREE(idBuf); + return res; +} + + +EFI_STATUS +PlatformGetIDCRC( + IN EFI_HANDLE handle, + OUT UINT32 *crc32 + ) +{ + EFI_STATUS res; + UINTN crcLen; + CHAR8* crcBuf = NULL; + res = PlatformGetID(handle, &crcBuf, &crcLen); + if (EFI_ERROR(res)) { + return res; + } + res = gBS->CalculateCrc32(crcBuf, crcLen, crc32); + MEM_FREE(crcBuf); + return res; +} + +EFI_STATUS +PlatformGetAuthDataByType( + OUT UINT8 **data, + OUT UINTN *len, + OUT EFI_HANDLE *secRegionHandle, + IN BOOLEAN RemovableMedia) +{ + EFI_STATUS res; + UINT32 crc; + CHAR8* buf = NULL; + EFI_BLOCK_IO_PROTOCOL* bio; + DCS_AUTH_DATA_MARK* mark = NULL; + mark = (DCS_AUTH_DATA_MARK*)MEM_ALLOC(512); + for (; gBioIndexAuth < gBIOCount; ++gBioIndexAuth) { + bio = EfiGetBlockIO(gBIOHandles[gBioIndexAuth]); + if (bio == NULL) continue; + if(bio->Media->RemovableMedia != RemovableMedia) continue; + res = bio->ReadBlocks(bio, bio->Media->MediaId, 61, 512, mark); + if (EFI_ERROR(res)) continue; + + res = gBS->CalculateCrc32(&mark->PlatformCrc, sizeof(*mark) - 4, &crc); + if (EFI_ERROR(res)) continue; + if( crc != mark->HeaderCrc) continue; + + res = PlatformGetIDCRC(gBIOHandles[gBioIndexAuth], &crc); + if (EFI_ERROR(res)) continue; + if (crc != mark->PlatformCrc) continue; + + buf = MEM_ALLOC(mark->AuthDataSize * 1024 * 128); + if (buf == NULL) continue; + + res = bio->ReadBlocks(bio, bio->Media->MediaId, 62, mark->AuthDataSize * 1024 * 128, buf); + if (EFI_ERROR(res)) { + MEM_FREE(buf); + continue; + } + *data = buf; + *len = mark->AuthDataSize * 1024 * 128; + *secRegionHandle = gBIOHandles[gBioIndexAuth]; + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +BOOLEAN gBioIndexAuthOnRemovable = TRUE; + +EFI_STATUS +PlatformGetAuthData( + OUT UINT8 **data, + OUT UINTN *len, + OUT EFI_HANDLE *secRegionHandle + ) +{ + EFI_STATUS res; + res = PlatformGetAuthDataByType(data, len, secRegionHandle, gBioIndexAuthOnRemovable); + if (EFI_ERROR(res)) { + if (gBioIndexAuthOnRemovable) { + gBioIndexAuthOnRemovable = FALSE; + gBioIndexAuth = 0; + res = PlatformGetAuthDataByType(data, len, secRegionHandle, FALSE); + } + } + return res; +} + diff --git a/Library/VeraCryptLib/DcsVeraCrypt.c b/Library/VeraCryptLib/DcsVeraCrypt.c new file mode 100644 index 0000000..9cf57ce --- /dev/null +++ b/Library/VeraCryptLib/DcsVeraCrypt.c @@ -0,0 +1,391 @@ +/** @file +Interface for DCS + +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 Apache License, Version 2.0. + +The full text of the license may be found at +https://opensource.org/licenses/Apache-2.0 +**/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "common/Crypto.h" +#include "common/Xml.h" +#include "common/Crc.h" +#include "BootCommon.h" + +////////////////////////////////////////////////////////////////////////// +// Config +////////////////////////////////////////////////////////////////////////// +char *ConfigBuffer = NULL; +UINTN ConfigBufferSize = 0; + +BOOL ConfigRead(char *configKey, char *configValue, int maxValueSize) +{ + char *xml; + + if (ConfigBuffer == NULL) + FileLoad(NULL, L"\\EFI\\VeraCrypt\\DcsProp", &ConfigBuffer, &ConfigBufferSize); + + xml = ConfigBuffer; + if (xml != NULL) + { + xml = XmlFindElementByAttributeValue(xml, "config", "key", configKey); + if (xml != NULL) + { + XmlGetNodeText(xml, configValue, maxValueSize); + return TRUE; + } + } + + return FALSE; +} + +int ConfigReadInt(char *configKey, int defaultValue) +{ + char s[32]; + if (ConfigRead(configKey, s, sizeof(s))) { + if (*s == '-') { + return (-1) * (int)AsciiStrDecimalToUintn(&s[1]); + } + return (int)AsciiStrDecimalToUintn(s); + } + else + return defaultValue; +} + + +char *ConfigReadString(char *configKey, char *defaultValue, char *str, int maxLen) +{ + if (!ConfigRead(configKey, str, maxLen)) { + AsciiStrCpyS(str, maxLen, defaultValue); + } + return str; +} + + +/////////////////////////////////////////////////////////////////////////// +// Globals +////////////////////////////////////////////////////////////////////////// +#define MAX_MSG 256 +int gAuthPasswordType = 0; +char* gAuthPasswordMsg = NULL; +Password gAuthPassword; + +char* gAuthPimMsg = NULL; +int gAuthPimRqt = 1; +int gAuthPim = 0; + +int gAuthTcRqt = 0; +int gAuthTc = 0; + +char *gAuthHashMsg = NULL; +int gAuthHashRqt = 1; +int gAuthHash = 0; + +int gAuthBootRqt = 0; +int gAuthBoot = 1; + +int gAuthRetry = 10; +int gAuthPwdCode = 1; + +INT32 gRUD = 0; + +int gAuthSecRegionSearch = 0; + +CHAR8* gPlatformKeyFile = NULL; +UINTN gPlatformKeyFileSize = 0; + +EFI_GUID *gPartitionGuidOS = NULL; + +int gDcsBootForce = 1; + +CHAR8* gOnExitFailed = NULL; +CHAR8* gOnExitSuccess = NULL; +CHAR8* gOnExitNotFound = NULL; + +////////////////////////////////////////////////////////////////////////// +// Authorize +///////////////////////////////////////////////////////////////////////// + +VOID +VCAuthLoadConfig() +{ + int tmp; + + if (gAuthPasswordMsg != NULL) return; // Already loaded + + SetMem(&gAuthPassword, sizeof(gAuthPassword), 0); + { + char* passwordPictureAscii = NULL; + passwordPictureAscii = MEM_ALLOC(MAX_MSG); + gPasswordPictureFileName = MEM_ALLOC(MAX_MSG * 2); + ConfigReadString("PasswordPicture", "\\EFI\\VeraCrypt\\login.bmp", passwordPictureAscii, MAX_MSG); + AsciiStrToUnicodeStr(passwordPictureAscii, gPasswordPictureFileName); + MEM_FREE(passwordPictureAscii); + } + SetMem(&gAuthPassword, sizeof(gAuthPassword), 0); + + // + gAuthSecRegionSearch = ConfigReadInt("SecRegionSearch", 0); + gPlatformLocked = ConfigReadInt("PlatformLocked", 0); + gTPMLocked = ConfigReadInt("TPMLocked", 0); + gSCLocked = ConfigReadInt("SCLocked", 0); + gDcsBootForce = ConfigReadInt("DcsBootForce", 1); + + // Actions for DcsInt + gOnExitSuccess = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionSuccess", "Exit", gOnExitSuccess, MAX_MSG); + gOnExitNotFound = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionNotFound", "Exit", gOnExitNotFound, MAX_MSG); + gOnExitFailed = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionFailed", "Exit", gOnExitFailed, MAX_MSG); + + { + char* strTemp = NULL; + strTemp = MEM_ALLOC(MAX_MSG); + ConfigReadString("PartitionGuidOS", "", strTemp, MAX_MSG); + if (strTemp[0] != 0) { + EFI_GUID g; + if (AsciiStrToGuid(&g, strTemp)) { + gPartitionGuidOS = MEM_ALLOC(sizeof(EFI_GUID)); + if (gPartitionGuidOS != NULL) { + memcpy(gPartitionGuidOS, &g, sizeof(g)); + } + } + } + MEM_FREE(strTemp); + } + + gPasswordPictureChars = MEM_ALLOC(MAX_MSG); + ConfigReadString("PictureChars", gPasswordPictureCharsDefault, gPasswordPictureChars, MAX_MSG); + gPasswordPictureCharsLen = strlen(gPasswordPictureChars); + + gAuthPasswordType = ConfigReadInt("PasswordType", 0); + gAuthPasswordMsg = MEM_ALLOC(MAX_MSG); + ConfigReadString("PasswordMsg", "Password:", gAuthPasswordMsg, MAX_MSG); + + gAuthPimMsg = MEM_ALLOC(MAX_MSG); + gAuthPimRqt = ConfigReadInt("PimRqt", 1); + gAuthPim = ConfigReadInt("Pim", 0); + ConfigReadString("PimMsg", "Pim:", gAuthPimMsg, MAX_MSG); + + gAuthHashMsg = MEM_ALLOC(MAX_MSG); + gAuthHashRqt = ConfigReadInt("HashRqt", 1); + gAuthHash = ConfigReadInt("Hash", 0); + ConfigReadString("HashMsg", "(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160\n\rHash:", gAuthHashMsg, MAX_MSG); + + gPasswordVisible = (UINT8)ConfigReadInt("AuthorizeVisible", 0); + gPasswordShowMark = ConfigReadInt("AuthorizeMarkTouch", 1); + gAuthBootRqt = ConfigReadInt("BootRqt", 0); + gAuthTcRqt = ConfigReadInt("TcRqt", 0); + gRUD = ConfigReadInt("RUD", 0); + gAuthRetry = ConfigReadInt("AuthorizeRetry", 10); + + // touch + tmp = ConfigReadInt("TouchDevice", -1); + if (tmp == -1) InitTouch(); + if (tmp >= 0) { + if (gTouchCount == 0) InitTouch(); + if (tmp < (int)gTouchCount) { + TouchGetIO(gTouchHandles[tmp], &gTouchPointer); + } + } + gTouchSimulate = ConfigReadInt("TouchSimulate", 0); + + // Graph + tmp = ConfigReadInt("GraphDevice", -1); + if (tmp == -1) InitGraph(); + if (tmp >= 0) { + if (gGraphCount == 0) InitGraph(); + if (tmp < (int)gGraphCount) { + GraphGetIO(gGraphHandles[tmp], &gGraphOut); + } + } + if (gGraphOut != NULL) { + tmp = ConfigReadInt("GraphMode", -1); + if (tmp >= 0 && tmp <= (int)gGraphOut->Mode->MaxMode) { + gGraphOut->SetMode(gGraphOut, tmp); + } + } + + // Beep + gBeepEnabled = ConfigReadInt("Beep", 0); + if (gBeepEnabled) { + gBeepNumberDefault = ConfigReadInt("BeepNumber", 1); + gBeepDurationDefault = ConfigReadInt("BeepDuration", 100); + gBeepIntervalDefault = ConfigReadInt("BeepInterval", 0); + gBeepToneDefault = ConfigReadInt("BeepTone", 0x500); + gBeepControlEnabled = ConfigReadInt("BeepControl", 1) != 0; + + tmp = ConfigReadInt("BeepDevice", -1); + if (tmp == -1) InitSpeaker(); + if (tmp >= 0) { + if (gSpeakerCount == 0) InitSpeaker(); + if (tmp < (int)gSpeakerCount) { + SpeakerSelect(tmp); + } + } + } + +} + + +VOID +VCAskPwd( + IN UINTN pwdType, + OUT Password* vcPwd) { + if (gAuthPasswordMsg == NULL) VCAuthLoadConfig(); + if (gAuthPasswordType == 1 && + gGraphOut != NULL && + ((gTouchPointer != NULL) || (gTouchSimulate != 0))) { + AskPictPwdInt(pwdType, sizeof(vcPwd->Text), vcPwd->Text, &vcPwd->Length, &gAuthPwdCode); + } else { + switch (pwdType) { + case AskPwdNew: + OUT_PRINT(L"New password:"); + break; + case AskPwdConfirm: + OUT_PRINT(L"Confirm password:"); + break; + case AskPwdLogin: + default: + OUT_PRINT(L"%a", gAuthPasswordMsg); + break; + } + AskConsolePwdInt(&vcPwd->Length, vcPwd->Text, &gAuthPwdCode, sizeof(vcPwd->Text), gPasswordVisible); + } + + if (gAuthPwdCode == AskPwdRetCancel) { + return; + } + + if (gPlatformLocked) { + if (gPlatformKeyFile == NULL) { + ERR_PRINT(L"Platform key file absent\n"); + } else { + ApplyKeyFile(vcPwd, gPlatformKeyFile, gPlatformKeyFileSize); + } + } + + if (gTPMLocked) { + // TO DO + ERR_PRINT(L"TPM lock is not implemented\n"); + } +} + +VOID +VCAuthAsk() +{ + VCAskPwd(AskPwdLogin, &gAuthPassword); + + if (gAuthPwdCode == AskPwdRetCancel) { + return; + } + + if (gAuthPimRqt) { + gAuthPim = AskInt(gAuthPimMsg, gPasswordVisible); + } + if (gAuthTcRqt) { + gAuthTc = AskConfirm("True crypt mode [N]?", gPasswordVisible); + } + + if (gAuthBootRqt) { + gAuthBoot = AskConfirm("Boot mount mode [N]?", gPasswordVisible); + } + + if (gAuthHashRqt) { + do { + gAuthHash = AskInt(gAuthHashMsg, gPasswordVisible); + } while (gAuthHash < 0 || gAuthHash > 4); + } +} + + +////////////////////////////////////////////////////////////////////////// +// VeraCrypt helpers +////////////////////////////////////////////////////////////////////////// +void* VeraCryptMemAlloc(IN UINTN size) { + return MEM_ALLOC(size); +} + +void VeraCryptMemFree(IN VOID* ptr) { + MEM_FREE(ptr); +} +void ThrowFatalException(int line) { + ERR_PRINT(L"Fatal %d\n", line); +} + +////////////////////////////////////////////////////////////////////////// +// Random data +////////////////////////////////////////////////////////////////////////// +BOOL +RandgetBytes(unsigned char *buf, int len, BOOL forceSlowPoll) { + EFI_STATUS res; + res = RndGetBytes(buf, len); + return !EFI_ERROR(res); +} + +////////////////////////////////////////////////////////////////////////// +// Key file +////////////////////////////////////////////////////////////////////////// + +#define KEYFILE_POOL_SIZE 64 +#define KEYFILE_MAX_READ_LEN (1024*1024) + +VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ) +{ + unsigned __int32 crc = 0xffffffff; + int writePos = 0; + size_t totalRead = 0; + size_t i; + CHAR8 keyPool[KEYFILE_POOL_SIZE]; + + ZeroMem(keyPool, sizeof(keyPool)); + + for (i = 0; i < keyfileDataSize; i++) + { + crc = UPDC32(keyfileData[i], crc); + + keyPool[writePos++] += (unsigned __int8)(crc >> 24); + keyPool[writePos++] += (unsigned __int8)(crc >> 16); + keyPool[writePos++] += (unsigned __int8)(crc >> 8); + keyPool[writePos++] += (unsigned __int8)crc; + + if (writePos >= KEYFILE_POOL_SIZE) + writePos = 0; + + if (++totalRead >= KEYFILE_MAX_READ_LEN) + break; + } + + for (i = 0; i < sizeof(keyPool); i++) + { + if (i < password->Length) + password->Text[i] += keyPool[i]; + else + password->Text[i] = keyPool[i]; + } + + if (password->Length < (int)sizeof(keyPool)) + password->Length = sizeof(keyPool); + +} \ No newline at end of file diff --git a/Library/VeraCryptLib/DcsVeraCrypt.h b/Library/VeraCryptLib/DcsVeraCrypt.h new file mode 100644 index 0000000..aae0152 --- /dev/null +++ b/Library/VeraCryptLib/DcsVeraCrypt.h @@ -0,0 +1,84 @@ +/** @file +Interface for DCS services + +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 Apache License, Version 2.0. + +The full text of the license may be found at +https://opensource.org/licenses/Apache-2.0 +**/ + +#ifndef __DCSVERACRYPT_H__ +#define __DCSVERACRYPT_H__ + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Auth +////////////////////////////////////////////////////////////////////////// +extern int gAuthPasswordType; +extern CHAR16* gPasswordPictureFileName; +extern char* gAuthPasswordMsg; +extern Password gAuthPassword; + +extern char* gAuthPimMsg; +extern int gAuthPimRqt; +extern int gAuthPim; + +extern int gAuthTcRqt; +extern int gAuthTc; + +extern char *gAuthHashMsg; +extern int gAuthHashRqt; +extern int gAuthHash; + +extern int gAuthBootRqt; +extern int gAuthBoot; + +extern int gAuthRetry; +extern INT32 gRUD; + +extern int gAuthSecRegionSearch; + +extern int gPlatformLocked; +extern int gTPMLocked; +extern int gSCLocked; + +extern int gAuthPwdCode; + +extern CHAR8* gPlatformKeyFile; +extern UINTN gPlatformKeyFileSize; + +extern EFI_GUID *gPartitionGuidOS; +extern int gDcsBootForce; + +extern CHAR8* gOnExitFailed; +extern CHAR8* gOnExitSuccess; +extern CHAR8* gOnExitNotFound; + +void +VCAuthAsk(); + +VOID +VCAskPwd( + IN UINTN pwdType, + OUT Password* vcPwd); + +VOID +VCAuthLoadConfig(); + +VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ); + +#endif + diff --git a/Library/VeraCryptLib/VeraCryptLib.inf b/Library/VeraCryptLib/VeraCryptLib.inf new file mode 100644 index 0000000..a4f257b --- /dev/null +++ b/Library/VeraCryptLib/VeraCryptLib.inf @@ -0,0 +1,120 @@ +## @file +# Library used for DCS +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = VeraCryptLib + MODULE_UNI_FILE = VeraCryptLib.uni + FILE_GUID = 6E5F01BD-D550-40AC-AC63-167DE971E3A1 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = VeraCryptLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] +common\Crc.c +common\Crc.h +common\Crypto.c +common\Crypto.h +common\Endian.c +common\Endian.h +common\GfMul.h +common\Password.h +common\Pkcs5.c +common\Pkcs5.h +common\Tcdefs.h +common\Volumes.c +common\Volumes.h +common\Xts.c +common\Xts.h +common\Xml.c +common\Xml.h +crypto\Aes.h +crypto\Aeskey.c +crypto\Aesopt.h +crypto\Aestab.c +crypto\Aestab.h +crypto\Aes_hw_cpu.nasm +crypto\Aes_hw_cpu.h +crypto\config.h +crypto\Rmd160.c +crypto\Rmd160.h +crypto\Serpent.c +crypto\Serpent.h +crypto\Sha2.c +crypto\Sha2.h +crypto\Twofish.c +crypto\Twofish.h +crypto\Whirlpool.c +crypto\Whirlpool.h +crypto\GostCipher.c +crypto\GostCipher.h +crypto\Streebog.c +crypto\Streebog.h +crypto\kuznyechik.c +crypto\kuznyechik.h +crypto\Camellia.c +crypto\Camellia.h +crypto\cpu.c +crypto\cpu.h +DcsVeraCrypt.c +DcsVeraCrypt.h + +[Sources.X64] +crypto\Aes_x64.nasm +crypto\Gost89_x64.nasm + +[Sources.IA32] +llmath.c +crypto\Aes_x86.nasm + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + RngLib + +[Protocols] + + +[BuildOptions.IA32] +DEBUG_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +DEBUG_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +RELEASE_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +RELEASE_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +[BuildOptions.X64] +DEBUG_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +DEBUG_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +RELEASE_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 + +RELEASE_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 diff --git a/Library/VeraCryptLib/llmath.c b/Library/VeraCryptLib/llmath.c new file mode 100644 index 0000000..6b4360c --- /dev/null +++ b/Library/VeraCryptLib/llmath.c @@ -0,0 +1,383 @@ +#include +void __cdecl atexit() {} + +int __cdecl _purecall() { return 0; } + +#if defined(_M_IX86) +////////////////////////////////////////////////////////////////////////// +// _allmul +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _allmul(void) +{ + _asm { + mov ebx, [esp + 4] ; ebx <- M1[0..31] + mov edx, [esp + 12] ; edx <- M2[0..31] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 16] ; ebx <- M1[0..31] * M2[32..63] + imul edx, [esp + 8] ; edx <- M1[32..63] * M2[0..31] + add ebx, edx ; carries are abandoned + mul ecx ; edx:eax <- M1[0..31] * M2[0..31] + add edx, ebx ; carries are abandoned + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _aullmul +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aullmul() +{ + _asm { + mov ebx, [esp + 4] ; ebx <- M1[0..31] + mov edx, [esp + 12] ; edx <- M2[0..31] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 16] ; ebx <- M1[0..31] * M2[32..63] + imul edx, [esp + 8] ; edx <- M1[32..63] * M2[0..31] + add ebx, edx ; carries are abandoned + mul ecx ; edx:eax <- M1[0..31] * M2[0..31] + add edx, ebx ; carries are abandoned + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _alldiv +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _alldiv() +{ + _asm { + ; Check sign of res + mov ebx, [esp + 8] ; dividend msdw + mov ecx, [esp + 16] ; divisor msdw + xor ebx, ecx + shr ebx, 31 + jz _PosRes ; if Result is positive + push 1 ; if is negative + jmp _Preparing + _PosRes: + push 0 + + ; Preparing operands + ; Dividend + _Preparing: + mov ecx, [esp + 12] + shr ecx, 31 + jz _ChkDvsr ; Divident is positive + mov eax, [esp + 12] ; is negative + mov ecx, [esp + 8] + xor eax, 0xFFFFFFFF + xor ecx, 0xFFFFFFFF + add ecx, 1 + jnc _DvntOK + adc eax, 0 + _DvntOK: + mov [esp + 12], eax + mov [esp + 8], ecx + + ; Divisor + _ChkDvsr: + mov ecx, [esp + 20] + shr ecx, 31 + jz _Divide ; Divisor is positive + mov eax, [esp + 20] ; is negative + mov ecx, [esp + 16] + xor eax, 0xFFFFFFFF + xor ecx, 0xFFFFFFFF + add ecx, 1 + jnc _DvsrOK + adc eax, 0 + _DvsrOK: + mov [esp + 20], eax + mov [esp + 16], ecx + + _Divide: + mov ecx, [esp + 20] ; ecx <- divisor[32..63] + test ecx, ecx + jnz __DivRemU64x64 ; call __DivRemU64x64 if Divisor > 2^32 + mov ecx, [esp + 16] ; ecx <- divisor + mov eax, [esp + 12] ; eax <- dividend[32..63] + xor edx, edx + div ecx ; eax <- quotient[32..63], edx <- remainder + push eax + mov eax, [esp + 12] ; eax <- dividend[0..31] + div ecx ; eax <- quotient[0..31] + pop edx ; edx <- quotient[32..63] - edx:eax + jmp _GetSign + + __DivRemU64x64: + mov edx, dword ptr [esp + 12] + mov eax, dword ptr [esp + 8] ; edx:eax <- dividend + mov edi, edx + mov esi, eax ; edi:esi <- dividend + mov ebx, dword ptr [esp + 16] ; ecx:ebx <- divisor + _B: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz _B + div ebx + mov ebx, eax ; ebx <- quotient + mov ecx, [esp + 20] ; ecx <- high dword of divisor + mul dword ptr [esp + 16] ; edx:eax <- quotient * divisor[0..31] + imul ecx, ebx ; ecx <- quotient * divisor[32..63] + add edx, ecx ; edx <- (quotient * divisor)[32..63] + ;mov ecx, dword ptr [esp + 32] ; ecx <- addr for Remainder + jc _TooLarge ; product > 2^64 + cmp edi, edx ; compare high 32 bits + ja _Correct + jb _TooLarge ; product > dividend + cmp esi, eax + jae _Correct ; product <= dividend + _TooLarge: + dec ebx ; adjust quotient by -1 + jecxz _Return ; return if Remainder == NULL + sub eax, dword ptr [esp + 16] + sbb edx, dword ptr [esp + 20] ; edx:eax <- (quotient - 1) * divisor + _Correct: + jecxz _Return + sub esi, eax + sbb edi, edx ; edi:esi <- remainder + ;mov [ecx], esi + ;mov [ecx + 4], edi + _Return: + mov eax, ebx ; eax <- quotient + xor edx, edx ; quotient is 32 bits long + + ; Get sign of result + _GetSign: + pop ecx ; Sign of res + jecxz _Rtrn ; Result is positive + xor eax, 0xFFFFFFFF + xor edx, 0xFFFFFFFF + add eax, 1 ; edx:eax + jnc _Rtrn + adc edx, 0 + + _Rtrn: + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _aulldiv +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aulldiv() +{ + _asm { + mov ecx, [esp + 16] ; ecx <- divisor[32..63] + test ecx, ecx + jnz __DivRemU64x64 ; call __DivRemU64x64 if Divisor > 2^32 + mov ecx, [esp + 12] ; ecx <- divisor + mov eax, [esp + 8] ; eax <- dividend[32..63] + xor edx, edx + div ecx ; eax <- quotient[32..63], edx <- remainder + push eax + mov eax, [esp + 8] ; eax <- dividend[0..31] + div ecx ; eax <- quotient[0..31] + pop edx ; edx <- quotient[32..63] + ret 16 + + __DivRemU64x64: + mov edx, dword ptr [esp + 8] + mov eax, dword ptr [esp + 4] ; edx:eax <- dividend + mov edi, edx + mov esi, eax ; edi:esi <- dividend + mov ebx, dword ptr [esp + 12] ; ecx:ebx <- divisor + _B: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz _B + div ebx + mov ebx, eax ; ebx <- quotient + mov ecx, [esp + 16] ; ecx <- high dword of divisor + mul dword ptr [esp + 12] ; edx:eax <- quotient * divisor[0..31] + imul ecx, ebx ; ecx <- quotient * divisor[32..63] + add edx, ecx ; edx <- (quotient * divisor)[32..63] + ;mov ecx, dword ptr [esp + 32] ; ecx <- addr for Remainder + jc _TooLarge ; product > 2^64 + cmp edi, edx ; compare high 32 bits + ja _Correct + jb _TooLarge ; product > dividend + cmp esi, eax + jae _Correct ; product <= dividend + _TooLarge: + dec ebx ; adjust quotient by -1 + jecxz _Return ; return if Remainder == NULL + sub eax, dword ptr [esp + 12] + sbb edx, dword ptr [esp + 16] ; edx:eax <- (quotient - 1) * divisor + _Correct: + jecxz _Return + sub esi, eax + sbb edi, edx ; edi:esi <- remainder + ;mov [ecx], esi + ;mov [ecx + 4], edi + _Return: + mov eax, ebx ; eax <- quotient + xor edx, edx ; quotient is 32 bits long + + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// Shifts +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aullshr() { + _asm { + ; + ; Checking: Only handle 64bit shifting or more + ; + cmp cl, 64 + jae _Exit + + ; + ; Handle shifting between 0 and 31 bits + ; + cmp cl, 32 + jae More32 + shrd eax, edx, cl + shr edx, cl + ret + + ; + ; Handle shifting of 32-63 bits + ; +More32: + mov eax, edx + xor edx, edx + and cl, 31 + shr eax, cl + ret + + ; + ; Invalid number (less then 32bits), return 0 + ; +_Exit: + xor eax, eax + xor edx, edx + ret + } +} + +__declspec(naked) void __cdecl _allshl() { + _asm { + ; + ; Handle shifting of 64 or more bits (return 0) + ; + cmp cl, 64 + jae short ReturnZero + + ; + ; Handle shifting of between 0 and 31 bits + ; + cmp cl, 32 + jae short More32 + shld edx, eax, cl + shl eax, cl + ret + + ; + ; Handle shifting of between 32 and 63 bits + ; +More32: + mov edx, eax + xor eax, eax + and cl, 31 + shl edx, cl + ret + +ReturnZero: + xor eax,eax + xor edx,edx + ret + } +} + +UINT64 +EFIAPI +DivU64x64Remainder( +IN UINT64 Dividend, +IN UINT64 Divisor, +OUT UINT64 *Remainder OPTIONAL +); +/* + * Divides a 64-bit unsigned value by another 64-bit unsigned value and returns + * the 64-bit unsigned remainder. + */ +__declspec(naked) void __cdecl _aullrem(void) +{ + // + // Wrapper Implementation over EDKII DivU64x64Remainder() routine + // UINT64 + // EFIAPI + // DivU64x64Remainder ( + // IN UINT64 Dividend, + // IN UINT64 Divisor, + // OUT UINT64 *Remainder OPTIONAL + // ) + // + _asm { + ; Original local stack when calling _aullrem + ; ----------------- + ; | | + ; |---------------| + ; | | + ; |-- Divisor --| + ; | | + ; |---------------| + ; | | + ; |-- Dividend --| + ; | | + ; |---------------| + ; | ReturnAddr** | + ; ESP---->|---------------| + ; + + ; + ; Set up the local stack for Reminder pointer + ; + sub esp, 8 + push esp + + ; + ; Set up the local stack for Divisor parameter + ; + mov eax, [esp + 28] + push eax + mov eax, [esp + 28] + push eax + + ; + ; Set up the local stack for Dividend parameter + ; + mov eax, [esp + 28] + push eax + mov eax, [esp + 28] + push eax + + ; + ; Call native DivU64x64Remainder of BaseLib + ; + call DivU64x64Remainder + + ; + ; Put the Reminder in EDX:EAX as return value + ; + mov eax, [esp + 20] + mov edx, [esp + 24] + + ; + ; Adjust stack + ; + add esp, 28 + + ret 16 + } +} + +#endif diff --git a/Library/VeraCryptLib/mklinks_src.bat b/Library/VeraCryptLib/mklinks_src.bat new file mode 100644 index 0000000..aad3094 --- /dev/null +++ b/Library/VeraCryptLib/mklinks_src.bat @@ -0,0 +1,112 @@ +@echo off +pushd %~dp0 + +call :select_path "%veracrypt_src%" "Select VeraCrypt directory:" +set veracrypt_src=%select_path_result% + +set /P YesNo=Create links[Y/N]? +if /I ["%YesNo%"]==["Y"] goto :check_links +goto :end + +:check_links +if NOT EXIST common goto :create_links +set /P create_links_del_ren=Old links detected [D]elete or [R]ename? + +:create_links +if NOT EXIST common mkdir common +call :create_link common\Crc.c +call :create_link common\Crc.h +call :create_link common\Crypto.c +call :create_link common\Crypto.h +call :create_link common\Endian.c +call :create_link common\Endian.h +call :create_link common\GfMul.h +call :create_link common\Password.h +call :create_link common\Pkcs5.c +call :create_link common\Pkcs5.h +call :create_link common\Tcdefs.h +call :create_link common\Volumes.c +call :create_link common\Volumes.h +call :create_link common\Xml.c +call :create_link common\Xml.h +call :create_link common\Xts.c +call :create_link common\Xts.h + +if NOT EXIST crypto mkdir crypto +call :create_link crypto\GostCipher.c +call :create_link crypto\GostCipher.h +call :create_link crypto\Gost89_x64.asm Gost89_x64.nasm +call :create_link crypto\Streebog.c +call :create_link crypto\Streebog.h +call :create_link crypto\kuznyechik.c +call :create_link crypto\kuznyechik.h +call :create_link crypto\Aes.h +call :create_link crypto\Aeskey.c +call :create_link crypto\Aesopt.h +call :create_link crypto\Aestab.c +call :create_link crypto\Aestab.h +call :create_link crypto\Aes_hw_cpu.h +call :create_link crypto\Aes_hw_cpu.asm Aes_hw_cpu.nasm +call :create_link crypto\Aes_x64.asm Aes_x64.nasm +call :create_link crypto\Aes_x86.asm Aes_x86.nasm +call :create_link crypto\cpu.h +call :create_link crypto\cpu.c +call :create_link crypto\config.h +call :create_link crypto\misc.h +call :create_link crypto\Rmd160.c +call :create_link crypto\Rmd160.h +call :create_link crypto\Serpent.c +call :create_link crypto\Serpent.h +call :create_link crypto\Sha2.c +call :create_link crypto\Sha2.h +call :create_link crypto\Twofish.c +call :create_link crypto\Twofish.h +call :create_link crypto\Whirlpool.c +call :create_link crypto\Whirlpool.h +call :create_link crypto\Camellia.c +call :create_link crypto\Camellia.h + +set create_link_skip_pushd=Y +call :create_link Boot\Windows\BootCommon.h +call :create_link Boot\Windows\BootDefs.h +set create_link_skip_pushd=N + +goto :end + +:create_link +if /I NOT ["%create_link_skip_pushd%"]==["Y"] pushd %~dp1 +set fn=%~n1%~x1 +if NOT ["%2"]==[""] set fn=%2 +call :get_bak_name %fn% +if /I ["%create_links_del_ren%"]==["R"] ren %fn% %name_bak% +if EXIST "%fn%" del %fn% +@echo on +mklink /H %fn% %veracrypt_src%\%1 +@echo off +if /I NOT ["%create_link_skip_pushd%"]==["Y"] popd +goto :eof + +:get_bak_name +set name_bak=%1 +:get_bak_name_retry +if NOT EXIST %name_bak% goto :eof +set name_bak=%name_bak%.sv +goto :get_bak_name_retry + +rem call select path +:select_path +set select_path_default=%1 +if not exist "%select_path_default%" echo not found %select_path_default% +set select_path_msg=%2 +set select_path_msg=%select_path_msg:~1,-1% + +:select_path_retry +set select_path_result= +set /p select_path_result=[%select_path_default:~1,-1%] %select_path_msg% +if ["%select_path_result%"]==[""] set select_path_result=%select_path_default:~1,-1% +if exist %select_path_result% goto :eof +echo can not find %select_path_result% +goto :select_path_retry + +:end +popd \ No newline at end of file -- cgit v1.2.3