diff options
Diffstat (limited to 'Library')
28 files changed, 7034 insertions, 0 deletions
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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/EFiShell.h>
+#include <Protocol/EfiShellParameters.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Speaker.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/LoadedImage.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/Speaker.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Library/CommonLib.h>
+
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+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 <Uefi.h>
+#include <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Library/BaseMemoryLib.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Uefi.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/AbsolutePointer.h>
+
+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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/UsbIo.h>
+
+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 <Library/CommonLib.h>
+
+#include <Uefi.h>
+#include <Guid/GlobalVariable.h>
+#include <Protocol/DevicePath.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/CommonLib.h>
+#include <Library/RngLib.h>
+#include <Library/DcsCfgLib.h>
+
+#include <common/Pkcs5.h>
+#include <crypto/sha2.h>
+
+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 <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Uefi/UefiGpt.h>
+#include <Guid/Gpt.h>
+
+#include <Library/CommonLib.h>
+#include <Library/DcsCfgLib.h>
+
+#include <common/Tcdefs.h>
+#include <BootCommon.h>
+
+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 <Library/CommonLib.h>
+#include <Library/GraphLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/GraphicsOutput.h>
+
+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 <Uefi.h>
+#include "Library/CommonLib.h"
+#include "Library/PasswordLib.h"
+#include <Library/UefiBootServicesTableLib.h>
+
+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 <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/CommonLib.h>
+#include <Library/GraphLib.h>
+#include <Library/PasswordLib.h>
+
+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 <Uefi.h>
+#include <Guid/SmBios.h>
+#include <IndustryStandard\SmBios.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#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 <DcsVeraCrypt.h>
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Library/CommonLib.h>
+#include <Library/GraphLib.h>
+#include <Library/PasswordLib.h>
+#include <Library/DcsCfgLib.h>
+
+#include <common/Password.h>
+#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 <Uefi.h>
+#include <common/Tcdefs.h>
+#include <common/Password.h>
+
+//////////////////////////////////////////////////////////////////////////
+// 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 <uefi.h>
+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 |