From b87fc6b140772ba3017de311c7063c259424264c Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Aug 2016 17:11:31 +0200 Subject: First public release. Used by VeraCrypt 1.18. --- Library/DcsCfgLib/DcsCfgLib.inf | 80 ++++ Library/DcsCfgLib/DcsRandom.c | 460 ++++++++++++++++++++ Library/DcsCfgLib/GptEdit.c | 935 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1475 insertions(+) create mode 100644 Library/DcsCfgLib/DcsCfgLib.inf create mode 100644 Library/DcsCfgLib/DcsRandom.c create mode 100644 Library/DcsCfgLib/GptEdit.c (limited to 'Library/DcsCfgLib') diff --git a/Library/DcsCfgLib/DcsCfgLib.inf b/Library/DcsCfgLib/DcsCfgLib.inf new file mode 100644 index 0000000..8607cb4 --- /dev/null +++ b/Library/DcsCfgLib/DcsCfgLib.inf @@ -0,0 +1,80 @@ +## @file +# Library for DCS configuration +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsCfgLib + MODULE_UNI_FILE = DcsCfgLib.uni + FILE_GUID = 3E61F9E0-0844-44F2-A177-A72FE81D6F07 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DcsCfgLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] +GptEdit.c +DcsRandom.c + +[Sources.X64] + +[Sources.IA32] + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + RngLib + +[Protocols] + + +[BuildOptions.IA32] +DEBUG_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +DEBUG_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +RELEASE_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +RELEASE_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +[BuildOptions.X64] +DEBUG_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +DEBUG_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +RELEASE_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 + +RELEASE_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 diff --git a/Library/DcsCfgLib/DcsRandom.c b/Library/DcsCfgLib/DcsRandom.c new file mode 100644 index 0000000..a269a46 --- /dev/null +++ b/Library/DcsCfgLib/DcsRandom.c @@ -0,0 +1,460 @@ +/** @file +Random number generators for DCS + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 + +!NOTE: Very simple! Need to select several sources of random like user input or other. +**/ + +#include +#include +#include +#include +#include + +#include +#include + +DCS_RND* gRnd = NULL; + +////////////////////////////////////////////////////////////////////////// +// Random data from file +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndFilePrepare( + IN DCS_RND* rnd + ) +{ + EFI_STATUS res = EFI_NOT_READY; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + rnd->State.File.Pos = 0; + res = EFI_SUCCESS; + } + return res; +} + +EFI_STATUS +RndFileGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINTN i; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + for (i = 0; i < len; i++, rnd->State.File.Pos++) { + if (rnd->State.File.Pos >= rnd->State.File.Size) { + rnd->State.File.Pos = 0; + } + buf[i] = rnd->State.File.Data[rnd->State.File.Pos]; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndFileInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_NOT_FOUND; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeFile; + rnd->GetBytes = RndFileGetBytes; + rnd->Prepare = RndFilePrepare; + if (Context != NULL) { + res = FileLoad(NULL, (CHAR16*)Context, &rnd->State.File.Data, &rnd->State.File.Size); + if (!EFI_ERROR(res)) { + return rnd->Prepare(rnd); + } + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Random data from CPU RDRAND +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndRDRandPrepare( + IN DCS_RND* rnd + ) +{ + UINT64 rndTmp; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + if (GetRandomNumber64((UINT64*)&rndTmp)) { + return EFI_SUCCESS; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndRDRandGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINT8 tmpRnd[8]; + UINTN i = 0; + UINTN j = 0; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + for (i = 0; i < len; ++i, ++j) { + j &= 7; + if (j == 0) { + if (!GetRandomNumber64((UINT64*)tmpRnd)) return EFI_NOT_READY; + } + buf[i] = tmpRnd[j]; + } + } else { + return EFI_NOT_READY; + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndRDRandInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeRDRand; + rnd->GetBytes = RndRDRandGetBytes; + rnd->Prepare = RndRDRandPrepare; + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// DRBG HMAC (SHA512) (NIST SP 800-90A) (simplified) +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +HmacSha512( + IN UINT8 *k, /* secret key */ + OUT UINT8 *out, /* output buffer */ + ... + ) +{ + sha512_ctx ctx; + char inner[SHA512_DIGEST_SIZE], outer[SHA512_DIGEST_SIZE]; + char key[SHA512_DIGEST_SIZE]; + char buf[SHA512_BLOCK_SIZE]; + int32 i; + int32 lk = SHA512_DIGEST_SIZE; /* length of the key in bytes */ + VA_LIST args; + UINT8* data; + UINTN len; + + /**** Inner Digest ****/ + sha512_begin(&ctx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x36); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x36; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + + VA_START(args, out); + while ((data = VA_ARG(args, UINT8 *)) != NULL) { + len = VA_ARG(args, UINTN); + sha512_hash(data, (UINT32)len, &ctx); + } + VA_END(args); + + sha512_end((unsigned char *)inner, &ctx); + + /**** Outer Digest ****/ + + sha512_begin(&ctx); + + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x5C); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x5C; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + sha512_hash((unsigned char *)inner, SHA512_DIGEST_SIZE, &ctx); + + sha512_end((unsigned char *)out, &ctx); + + /* Prevent possible leaks. */ + burn(&ctx, sizeof(ctx)); + burn(outer, sizeof(outer)); + burn(inner, sizeof(inner)); + burn(buf, sizeof(buf)); + burn(key, sizeof(key)); + return EFI_SUCCESS; +} + +EFI_STATUS +RndDtrmHmacSha512Update( + RND_DTRM_HMAC_SHA512_STATE *state, + UINT8 *seed, + UINTN seedLen, + BOOLEAN reseed + ) +{ + EFI_STATUS res = EFI_NOT_READY; + int i = 0; + + if (!reseed) + { + /* 10.1.2.3 */ + memset(state->V, 1, SHA512_DIGEST_SIZE); + memset(state->C, 0, SHA512_DIGEST_SIZE); + } + + /* we execute two rounds of V/K massaging */ + for (i = 2; 0 < i; i--) + { + /* first round uses 0x0, second 0x1 */ + unsigned char prefix = 0; + if (1 == i) + prefix = 1; + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ + + res = HmacSha512(state->C, state->C, + state->V, SHA512_DIGEST_SIZE, + &prefix, 1, + seed, seedLen, + NULL + ); + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 2 and 5 -- HMAC for V */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL); + + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 3 */ + if (!seed || 0 == seedLen) + return res; + } + return EFI_SUCCESS; +} + +/* generate function of HMAC DRBG as defined in 10.1.2.5 */ +EFI_STATUS +RndDtrmHmacSha512Generate( + RND_DTRM_HMAC_SHA512_STATE *state, + OUT UINT8 *buf, + IN UINTN buflen, + IN UINT8 *seed, + IN UINTN seedLen + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len = 0; + + /* 10.1.2.5 step 2 */ + if (seed && 0 < seedLen) + { + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + if (EFI_ERROR(res)) + return res; + } + + while (len < buflen) + { + UINTN outlen = 0; + /* 10.1.2.5 step 4.1 */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL + ); + if (EFI_ERROR(res)) + return res; + outlen = (SHA512_DIGEST_SIZE < (buflen - len)) ? + SHA512_DIGEST_SIZE : (buflen - len); + + /* 10.1.2.5 step 4.2 */ + memcpy(buf + len, state->V, outlen); + len += outlen; + } + + /* 10.1.2.5 step 6 */ + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Prepare( + IN DCS_RND* rnd + ) +{ + if (rnd != NULL && rnd->Type == RndTypeDtrmHmacSha512) { + return EFI_SUCCESS; + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndDtrmHmacSha512GetBytes( + IN DCS_RND* rnd, + UINT8 *buf, + UINTN len + ) +{ + EFI_TIME seed; + EFI_STATUS res = EFI_NOT_READY; + RND_DTRM_HMAC_SHA512_STATE *state = &rnd->State.HMacSha512; + if (state->ReseedCtr < (1LL << 48)) { + gST->RuntimeServices->GetTime(&seed, NULL); + res = RndDtrmHmacSha512Generate(state, buf, len, (UINT8*)&seed, sizeof(seed)); + state->ReseedCtr++; + } + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Init( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_SUCCESS; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeDtrmHmacSha512; + rnd->GetBytes = RndDtrmHmacSha512GetBytes; + rnd->Prepare = RndDtrmHmacSha512Prepare; + + if (Context != NULL) { + CHAR16* type = (CHAR16*)Context; + if (*type == '_') { + UINT8* data; + UINTN size; + type++; + res = FileLoad(NULL, (CHAR16*)type, &data, &size); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + res = RndDtrmHmacSha512Update(&rnd->State.HMacSha512, data, size, 0); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + } + } + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// Random API +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndInit( + IN UINTN rndType, + IN VOID* Context, + OUT DCS_RND **rnd) +{ + if (rnd != NULL) { + DCS_RND *rndTemp; + rndTemp = (DCS_RND*)MEM_ALLOC(sizeof(DCS_RND)); + if (rndTemp != NULL) { + EFI_STATUS res = EFI_NOT_FOUND; + rndTemp->Type = (UINT32)rndType; + switch (rndType) { + case RndTypeFile: + res = RndFileInit(rndTemp, Context); + break; + case RndTypeRDRand: + res = RndRDRandInit(rndTemp, Context); + break; + case RndTypeDtrmHmacSha512: + res = RndDtrmHmacSha512Init(rndTemp, Context); + break; + } + if (EFI_ERROR(res)) { + MEM_FREE(rndTemp); + return res; + } + *rnd = rndTemp; + return res; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndGetBytes( + UINT8 *buf, + UINTN len) +{ + if (gRnd != NULL) { + return gRnd->GetBytes(gRnd, buf, len); + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndPreapare() +{ + if (gRnd != NULL) { + return gRnd->Prepare(gRnd); + } + return EFI_NOT_READY; +} + +UINT64 gRndHeaderSign = RND_HEADER_SIGN; + +EFI_STATUS +RndSave( + IN DCS_RND *rnd, + OUT DCS_RND_SAVED **rndSaved + ) +{ + EFI_STATUS res = EFI_NOT_READY; + DCS_RND_SAVED *RndSaved; + UINT32 crc; + if (rnd != NULL && rndSaved != NULL && rnd->Type != RndTypeFile) { + RndSaved = MEM_ALLOC(sizeof(DCS_RND_SAVED)); + if (RndSaved != NULL) { + RndSaved->Size = sizeof(DCS_RND_SAVED); + CopyMem(&RndSaved->State, &rnd->State, sizeof(DCS_RND_STATE)); + RndSaved->Type = rnd->Type; + RndSaved->Sign = gRndHeaderSign; + gST->RuntimeServices->GetTime(&RndSaved->SavedAt, NULL); + res = gBS->CalculateCrc32(RndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res)) { + MEM_FREE(RndSaved); + return res; + } + RndSaved->CRC = crc; + *rndSaved = RndSaved; + } + } + return res; +} + +EFI_STATUS +RndLoad( + IN DCS_RND_SAVED *rndSaved, + OUT DCS_RND **rndOut + ) { + EFI_STATUS res = EFI_SUCCESS; + UINT32 crc; + UINT32 crcSaved; + + crcSaved = rndSaved->CRC; + rndSaved->CRC = 0; + res = gBS->CalculateCrc32(rndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res) || crc != crcSaved || rndSaved->Sign != gRndHeaderSign) { + return EFI_CRC_ERROR; + } + res = RndInit(rndSaved->Type, NULL, rndOut); + if (!EFI_ERROR(res)) { + CopyMem(&((*rndOut)->State), &rndSaved->State, sizeof(DCS_RND_STATE)); + } + return res; +} diff --git a/Library/DcsCfgLib/GptEdit.c b/Library/DcsCfgLib/GptEdit.c new file mode 100644 index 0000000..702ce5d --- /dev/null +++ b/Library/DcsCfgLib/GptEdit.c @@ -0,0 +1,935 @@ +/** @file +GPT actions + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +EFI_GUID gEfiPartTypeMsReservedPartGuid = EFI_PART_TYPE_MS_RESERVED_PART_GUID; +EFI_GUID gEfiPartTypeBasicDataPartGuid = EFI_PART_TYPE_BASIC_DATA_PART_GUID; +EFI_GUID gEfiPartTypeMsRecoveryPartGuid = EFI_PART_TYPE_MS_RECOVERY_PART_GUID; + +UINT64 gDcsDiskEntryListHeaderID = DCS_DISK_ENTRY_LIST_HEADER_SIGN; +UINT64 gDcsDiskEntryPwdCacheID = DCS_DEP_PWD_CACHE_SIGN; + +DCS_DISK_ENTRY_LIST *DeList = NULL; + +UINT8 *CryptoHeader = NULL; + +EFI_PARTITION_TABLE_HEADER *GptMainHdr = NULL; +EFI_PARTITION_ENTRY *GptMainEntrys = NULL; +EFI_PARTITION_TABLE_HEADER *GptAltHdr = NULL; +EFI_PARTITION_ENTRY *GptAltEntrys = NULL; + +UINT32 DiskIdMbr = 0; +EFI_GUID DiskIdGpt = EFI_PART_TYPE_UNUSED_GUID; +DCS_DISK_ENTRY_DISKID DeDiskId; + +DCS_DEP_EXEC *DeExecParams = NULL; + +DCS_DEP_PWD_CACHE *DePwdCache = NULL; + +DCS_RND_SAVED *DeRndSaved; + +EFI_BLOCK_IO_PROTOCOL* BlockIo = NULL; +CONST CHAR16* DcsDiskEntrysFileName = L"DcsDiskEntrys"; + +EFI_PARTITION_ENTRY DcsHidePart; + +UINTN BootPartIdx; +UINTN MirrorPartIdx; + +////////////////////////////////////////////////////////////////////////// +// Partitions +////////////////////////////////////////////////////////////////////////// + + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Size The size of the table +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrcAltSize( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + UINT32 Crc; + UINT32 OrgCrc; + EFI_STATUS Status; + + Crc = 0; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + + if ((MaxSize != 0) && (Size > MaxSize)) { + return FALSE; + } + // + // clear old crc from header + // + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc); + if (EFI_ERROR(Status)) { + return FALSE; + } + // + // set results + // + Hdr->CRC32 = OrgCrc; + + return (BOOLEAN)(OrgCrc == Crc); +} + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrc( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr); +} + +EFI_STATUS +GptCheckEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return EFI_CRC_ERROR; + } + Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR; + return Status; +} + +EFI_STATUS +GptUpdateCRC( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->PartitionEntryArrayCRC32 = Crc; + PartHeader->Header.CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->Header.CRC32 = Crc; + return Status; +} + +/** +Read GPT +Check if the CRC field in the Partition table header is valid +for Partition entry array. + +@param[in] DiskIo Disk Io Protocol. +@param[in] PartHeader Partition table header structure + +@retval EFI_SUCCESS the CRC is valid +**/ +EFI_STATUS +GptReadEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + OUT EFI_PARTITION_ENTRY **Entrys + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + + // + // Read the EFI Partition Entries + // + Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + Status = BlockIo->ReadBlocks( + BlockIo, + BlockIo->Media->MediaId, + PartHeader->PartitionEntryLBA, + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR(Status)) { + MEM_FREE(Ptr); + return Status; + } + + *Entrys = (EFI_PARTITION_ENTRY*)Ptr; + return GptCheckEntryArray(PartHeader, *Entrys); +} + +EFI_STATUS +GptReadHeader( + IN EFI_LBA HeaderLba, + OUT EFI_PARTITION_TABLE_HEADER **PartHeader + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + UINT32 MediaId; + + BlockSize = BlockIo->Media->BlockSize; + MediaId = BlockIo->Media->MediaId; + PartHdr = MEM_ALLOC(BlockSize); + + res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr); + if (EFI_ERROR(res)) { + MEM_FREE(PartHdr); + return res; + } + + // Check header + if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(BlockSize, &PartHdr->Header) || + PartHdr->MyLBA != HeaderLba || + (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) + ) { + MEM_FREE(PartHdr); + return EFI_CRC_ERROR; + } + *PartHeader = PartHdr; + return EFI_SUCCESS; +} + +VOID +GptPrint( + IN EFI_PARTITION_TABLE_HEADER *PartHdr, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_PARTITION_ENTRY *Entry; + UINTN index; + if (PartHdr == NULL) { + ERR_PRINT(L"No GPT is loaded\n"); + return; + } + Entry = Entrys; + for (index = 0; index < PartHdr->NumberOfPartitionEntries; ++index, ++Entry) { + if (CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + OUT_PRINT(L"%H%02d%N I:%g T:%g [%lld, %lld] %s\n", + index, + &Entry->UniquePartitionGUID, + &Entry->PartitionTypeGUID, + Entry->StartingLBA, + Entry->EndingLBA, + &Entry->PartitionName + ); + } +} + +EFI_STATUS +GptLoadFromDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + InitBio(); + + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + res = GptReadHeader(1, &GptMainHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read main GPT header: %r\n", res); + goto error; + } + + res = GptReadHeader(GptMainHdr->AlternateLBA, &GptAltHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read alt GPT header: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptMainHdr, &GptMainEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT error: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptAltHdr, &GptAltEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT error: %r\n", res); + goto error; + } + + CryptoHeader = MEM_ALLOC(512); + if (CryptoHeader == NULL) { + ERR_PRINT(L"Can't alloc CryptoHeader\n"); + res = EFI_BUFFER_TOO_SMALL; + goto error; + } + + // Load disk IDs + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't MBR \n"); + goto error; + } + + SetMem(&DeDiskId, sizeof(DeDiskId), 0); + DeDiskId.Type = DE_DISKID; + CopyMem(&DeDiskId.MbrID, &CryptoHeader[0x1b8], sizeof(DiskIdMbr)); + CopyMem(&DeDiskId.GptID, &GptMainHdr->DiskGUID, sizeof(DiskIdGpt)); + + // Load crypto header + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 62, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read CryptoHeader\n"); + goto error; + } + + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + CHAR16* defExec = L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi"; + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + ZeroMem(DeExecParams, sizeof(*DeExecParams)); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + CopyMem(&DeExecParams->ExecCmd, defExec, (StrLen(defExec) + 1 ) * 2); + break; + } + } + return res; + +error: + MEM_FREE(GptMainHdr); + MEM_FREE(GptMainEntrys); + MEM_FREE(GptAltHdr); + MEM_FREE(GptAltEntrys); + MEM_FREE(CryptoHeader); + return res; +} + +VOID +DeListPrint() { + OUT_PRINT(L"Diskid %08x, %g\n", DeDiskId.MbrID, &DeDiskId.GptID); + if (DeExecParams != NULL) { + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + } + if (DePwdCache != NULL) { + OUT_PRINT(L"PwdCache %d\n", DePwdCache->Count); + } + if (DeRndSaved != NULL) { + OUT_PRINT(L"Rnd %d\n", DeRndSaved->Type); + } + GptPrint(GptMainHdr, GptMainEntrys); +} + +#define DeList_UPDATE_BEGIN(Data, DEType, Index, Len) \ + if (Data != NULL) { \ + DeData[Index] = Data; \ + DeList->DE[Index].Type = DEType; \ + DeList->DE[Index].Offset = Offset; \ + DeList->DE[Index].Length = Len; \ + Offset += ((Len + 511) >> 9) << 9; + +#define DeList_UPDATE_END \ + } + +VOID +DeListSaveToFile() { + EFI_STATUS res = EFI_SUCCESS; + UINT32 Offset; + VOID* DeData[DE_IDX_TOTAL]; + UINT8* pad512buf = NULL; + + ZeroMem(DeData, sizeof(DeData)); + + res = EFI_BUFFER_TOO_SMALL; + DeList = MEM_ALLOC(sizeof(*DeList)); + if (DeList == NULL) { + ERR_PRINT(L"Can't alloc DeList\n"); + goto error; + } + + pad512buf = MEM_ALLOC(512); + if (pad512buf == NULL) { + ERR_PRINT(L"No memory\n"); + goto error; + } + + DeList->Signature = DCS_DISK_ENTRY_LIST_HEADER_SIGN; + DeList->HeaderSize = sizeof(*DeList); + DeList->Count = DE_IDX_TOTAL; + Offset = 0; + + DeList_UPDATE_BEGIN(CryptoHeader, DE_Sectors, DE_IDX_CRYPTOHEADER, 512) + DeList->DE[DE_IDX_CRYPTOHEADER].Sectors.Start = 62 * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeList, DE_List, DE_IDX_LIST, 512) + DeList_UPDATE_END + + CopyMem(&DeList->DE[DE_IDX_DISKID], &DeDiskId, sizeof(DeDiskId)); + + DeList_UPDATE_BEGIN(GptMainHdr, DE_Sectors, DE_IDX_MAINGPTHDR, 512) + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start = GptMainHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptMainEntrys, DE_Sectors, DE_IDX_MAINGPTENTRYS, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Start = GptMainHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltHdr, DE_Sectors, DE_IDX_ALTGPTHDR, 512) + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start = GptAltHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltEntrys, DE_Sectors, DE_IDX_ALTGPTENTRYS, GptAltHdr->NumberOfPartitionEntries * GptAltHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Start = GptAltHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeExecParams, DE_ExecParams, DE_IDX_EXEC, sizeof(*DeExecParams)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DePwdCache, DE_PwdCache, DE_IDX_PWDCACHE, sizeof(*DePwdCache)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeRndSaved, DE_Rnd, DE_IDX_RND, sizeof(*DeRndSaved)) + DeList_UPDATE_END + + DeList->DataSize = Offset; + res = gBS->CalculateCrc32(DeList, 512, &DeList->CRC32); + if (EFI_ERROR(res)) { + ERR_PRINT(L"CRC: %r\n", res); + goto error; + } + { + EFI_FILE* file; + UINTN i; + + FileDelete(NULL, (CHAR16*)DcsDiskEntrysFileName); + res = FileOpen(NULL, (CHAR16*)DcsDiskEntrysFileName, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) { + ERR_PRINT(L"File: %r\n", res); + goto error; + } + for (i = 0; i < DeList->Count; ++i) { + if (DeData[i] != 0 && DeList->DE[i].Type != DE_DISKID) { + UINTN len; + UINTN pad; + len = (UINTN)DeList->DE[i].Length; + pad = (((len + 511) >> 9) << 9) - len; + res = FileWrite(file, DeData[i], &len, NULL); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + if (pad > 0) { + res = FileWrite(file, pad512buf, &pad, NULL); + } + } + } + FileClose(file); + } + +error: + MEM_FREE(DeList); + MEM_FREE(pad512buf); +} + +EFI_STATUS +DeListZero() { + if (DePwdCache != NULL) { + DePwdCache = AskConfirm("Remove passwords cache?", 1) ? NULL : DePwdCache; + } + if (DeExecParams != NULL) { + DeExecParams = AskConfirm("Remove exec?", 1) ? NULL : DeExecParams; + } + if (DeRndSaved != NULL) { + DeRndSaved = AskConfirm("Remove rnd?", 1) ? NULL : DeRndSaved; + } + if (GptMainHdr != NULL) { + if (AskConfirm("Remove GPT?", 1)) { + GptMainHdr = NULL; + GptMainEntrys = NULL; + GptAltHdr = NULL; + GptAltEntrys = NULL; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListParseSaved( + IN UINT8 *DeBuffer + ) +{ + EFI_STATUS res = EFI_SUCCESS; + CryptoHeader = DeBuffer; + DeList = (DCS_DISK_ENTRY_LIST*)(DeBuffer + 512); + CopyMem(&DeDiskId, &DeList->DE[DE_IDX_DISKID], sizeof(DeDiskId)); + + if (DeList->DE[DE_IDX_EXEC].Type == DE_ExecParams) { + DeExecParams = (DCS_DEP_EXEC *)(DeBuffer + DeList->DE[DE_IDX_EXEC].Offset); + } + + if (DeList->DE[DE_IDX_RND].Type == DE_Rnd) { + DeRndSaved = (DCS_RND_SAVED *)(DeBuffer + DeList->DE[DE_IDX_RND].Offset); + if ((UINTN)DeList->DE[DE_IDX_RND].Length != sizeof(*DeRndSaved)) { + return EFI_CRC_ERROR; + } + } + + if (DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { + UINT32 crc = 0; + UINT32 crcSaved = 0; + DePwdCache = (DCS_DEP_PWD_CACHE*)(DeBuffer + DeList->DE[DE_IDX_PWDCACHE].Offset); + if (DePwdCache->Sign != gDcsDiskEntryPwdCacheID) { + return EFI_CRC_ERROR; + } + crcSaved = DePwdCache->CRC; + DePwdCache->CRC = 0; + res = gBS->CalculateCrc32(DePwdCache, sizeof(*DePwdCache), &crc); + if (crc != crcSaved) { + ERR_PRINT(L"Pwd cache crc\n"); + return EFI_CRC_ERROR; + } + DePwdCache->CRC = crcSaved; + } + + if (DeList->DE[DE_IDX_MAINGPTHDR].Type == DE_Sectors) { + GptMainHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Offset); + if ((GptMainHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptMainHdr->Header) || + (DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start >> 9) != GptMainHdr->MyLBA || + (GptMainHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Main GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_MAINGPTENTRYS].Type == DE_Sectors) { + GptMainEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTHDR].Type == DE_Sectors) { + GptAltHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Offset); + if ((GptAltHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptAltHdr->Header) || + (DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start >> 9) != GptAltHdr->MyLBA || + (GptAltHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Alt GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTENTRYS].Type == DE_Sectors) { + GptAltEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT: %r\n", res); + return res; + } + } + + if (GptMainEntrys != NULL && GptAltEntrys != NULL && GptMainHdr != NULL) { + if (CompareMem(GptMainEntrys, GptAltEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) != 0) { + ERR_PRINT(L"Alt GPT != Main GPT\n", ); + return EFI_CRC_ERROR; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListLoadFromFile() +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len; + UINT8 *DeBuffer; + + InitFS(); + res = FileLoad(NULL, (CHAR16*)DcsDiskEntrysFileName, &DeBuffer, &len); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Load: %r\n", res); + return res; + } + return DeListParseSaved(DeBuffer); +} + +EFI_STATUS +DeListApplySectorsToDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + UINT8 *Mbr; + + InitBio(); + InitFS(); + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + // Compare MBR disk ID + Mbr = MEM_ALLOC(512); + if (Mbr == NULL) { + ERR_PRINT(L"Can't load MBR\n"); + return EFI_BUFFER_TOO_SMALL; + } + + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, Mbr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read MBR: %r\n", res); + MEM_FREE(Mbr); + return res; + } + + if (CompareMem(Mbr + 0x1b8, &DeDiskId.MbrID, sizeof(UINT32)) != 0) { + ERR_PRINT(L"Disk MBR ID %08x != %08x \n", *((UINT32*)(Mbr + 0x1b8)), DeDiskId.MbrID); + MEM_FREE(Mbr); + return res; + } + MEM_FREE(Mbr); + + // Save sectors + for (i = 0; i < DeList->Count; ++i) { + if (DeList->DE[i].Type == DE_Sectors) { + OUT_PRINT(L"%d Write: %lld, %lld\n", i, DeList->DE[i].Sectors.Start, DeList->DE[i].Sectors.Length); + res = BlockIo->WriteBlocks(BlockIo, BlockIo->Media->MediaId, + DeList->DE[i].Sectors.Start >> 9, + (UINTN)DeList->DE[i].Sectors.Length, + CryptoHeader + DeList->DE[i].Sectors.Offset); + } + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + return res; + } + } + return EFI_SUCCESS; +} + + +EFI_STATUS +GptSyncMainAlt() { + EFI_STATUS res = EFI_SUCCESS; + // Duplicate parts array + CopyMem(GptAltEntrys, GptMainEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry); + + res = GptUpdateCRC(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main CRC: %r\n", res); + return res; + } + GptUpdateCRC(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt CRC: %r\n", res); + return res; + } + return res; +} + +VOID +GptSqueze() { + UINTN i = 0; + UINTN emptyIdx = 0; + UINTN count; + count = GptMainHdr->NumberOfPartitionEntries; + while (i < count) { + if (CompareGuid(&GptMainEntrys[i].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + ++i; + continue; + } + else { + if (emptyIdx != i) { + CopyMem(&GptMainEntrys[emptyIdx], &GptMainEntrys[i], sizeof(*GptMainEntrys) * (count - i)); + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + } + ++emptyIdx; + i = emptyIdx; + } + } +} + +VOID +GptSort() { + UINTN i = 0; + UINTN j = 0; + UINTN n = 0; + UINTN count; + EFI_PARTITION_ENTRY tmp; + BOOLEAN swapped = TRUE; + count = GptMainHdr->NumberOfPartitionEntries; + + while (n < count) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + break; + } + ++n; + } + + while (swapped) { + swapped = FALSE; + j++; + for (i = 0; i < n - j; ++i) { + if (GptMainEntrys[i].StartingLBA > GptMainEntrys[i + 1].StartingLBA) { + CopyMem(&tmp, &GptMainEntrys[i], sizeof(tmp)); + CopyMem(&GptMainEntrys[i], &GptMainEntrys[i + 1], sizeof(tmp)); + CopyMem(&GptMainEntrys[i + 1], &tmp, sizeof(tmp)); + swapped = TRUE; + } + } + } +} + +// Checks if two regions overlap (borders are parts of regions) +BOOLEAN +IsRegionOverlap(UINT64 start1, UINT64 end1, UINT64 start2, UINT64 end2) { + return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); +} + +VOID +GptHideParts() { + UINTN count; + UINTN n; + BOOLEAN set = FALSE; + count = GptMainHdr->NumberOfPartitionEntries; + + for (n = 0; n < count; ++n) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + if (IsRegionOverlap( + GptMainEntrys[n].StartingLBA, GptMainEntrys[n].EndingLBA, + DcsHidePart.StartingLBA, DcsHidePart.EndingLBA)) { + if (set) { + SetMem(&GptMainEntrys[n], sizeof(*GptMainEntrys), 0); + } + else { + set = TRUE; + CopyMem(&GptMainEntrys[n], &DcsHidePart, sizeof(*GptMainEntrys)); + } + } + } + GptSqueze(); + GptSort(); + GptSyncMainAlt(); +} + +BOOLEAN +GptAskGUID( + IN char* prompt, + IN OUT EFI_GUID* guid) +{ + CHAR8 buf[128]; + UINTN len = 0; + EFI_GUID result; + BOOLEAN ok = TRUE; + OUT_PRINT(L"[%g] %a", guid, prompt); + + // (msr, data, oem, efi, del or guid) + GetLine(&len, NULL, buf, sizeof(buf), 1); + if (AsciiStrCmp(buf, "msr") == 0) { + CopyMem(guid, &gEfiPartTypeMsReservedPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "data") == 0) { + CopyMem(guid, &gEfiPartTypeBasicDataPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "wre") == 0) { + CopyMem(guid, &gEfiPartTypeMsRecoveryPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "efi") == 0) { + CopyMem(guid, &gEfiPartTypeSystemPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "del") == 0) { + CopyMem(guid, &gEfiPartTypeUnusedGuid, sizeof(EFI_GUID)); + } + else if (len == 0) { + ok = TRUE; + } + else { + ok = AsciiStrToGuid(&result, buf); + if (ok) { + CopyMem(guid, &result, sizeof(result)); + } + } + return ok; +} + +EFI_STATUS +DeListExecEdit() +{ + UINTN len; + UINTN i; + CHAR16 execCmd[FIELD_SIZEOF(DCS_DEP_EXEC, ExecCmd)]; + if (DeExecParams == NULL) { + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + } + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + if (GptMainHdr != NULL) { + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + if (CompareMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)) != 0) { + OUT_PRINT(L"EFI partition missmatched, updated"); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + } + break; + } + } + } + while (!GptAskGUID("\n\r:",(EFI_GUID*) &DeExecParams->ExecPartGuid)); + OUT_PRINT(L"[%s]\n\r:", &DeExecParams->ExecCmd); + GetLine(&len, execCmd, NULL, sizeof(execCmd) / 2 - 1, 1); + if (len != 0) { + CopyMem(&DeExecParams->ExecCmd, execCmd, sizeof(execCmd)); + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListPwdCacheEdit() +{ + UINTN count; + UINTN len; + UINTN i; + UINT32 crc = 0; + Password pwd; + UINTN pim; + EFI_STATUS res; + if (DePwdCache == NULL) { + DePwdCache = MEM_ALLOC(sizeof(*DePwdCache)); + DePwdCache->Sign = DCS_DEP_PWD_CACHE_SIGN; + } + OUT_PRINT(L"PwdCache\n"); + do { + count = (uint32)AskUINTN("Count[0-4]:", DePwdCache->Count); + } while (count > 4); + DePwdCache->Count = (uint32)count; + for (i = 0; i < 4; ++i) { + ZeroMem(&pwd, sizeof(pwd)); + pim = 0; + if (i < DePwdCache->Count) { + OUT_PRINT(L"%H%d%N [%a] [%d]\n:", i, DePwdCache->Pwd[i].Text, DePwdCache->Pim[i]); + GetLine(&len, NULL, pwd.Text, MAX_PASSWORD, 1); + if (len != 0) { + pwd.Length = (uint32)len; + pim = (uint32)AskUINTN("Pim:", DePwdCache->Pim[i]); + } + } + DePwdCache->Pim[i] = (uint32)pim; + CopyMem(&DePwdCache->Pwd[i], &pwd, sizeof(pwd)); + } + ZeroMem(&DePwdCache->pad, sizeof(DePwdCache->pad)); + DePwdCache->CRC = 0; + res =gBS->CalculateCrc32(DePwdCache, 512, &crc); + DePwdCache->CRC = crc; + return res; +} + +EFI_STATUS +DeListRndSave() +{ + EFI_STATUS res; + if (gRnd == NULL) { + DeRndSaved = NULL; + return EFI_SUCCESS; + } + res = RndSave(gRnd,&DeRndSaved); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", DeRndSaved->Type); + return res; +} + +EFI_STATUS +DeListRndLoad() +{ + EFI_STATUS res = EFI_NOT_FOUND; + if (DeRndSaved != NULL) { + res = RndLoad(DeRndSaved,&gRnd); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", gRnd->Type); + } + return res; +} -- cgit v1.2.3