VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/Library/DcsCfgLib
diff options
context:
space:
mode:
authorAlex <kavsrf@gmail.com>2016-08-15 17:11:31 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2016-08-15 17:14:26 +0200
commitb87fc6b140772ba3017de311c7063c259424264c (patch)
tree41ad139e7469380704361ae757a155464e8b68e3 /Library/DcsCfgLib
parent68ea2f72cfe6a9b34212ced97882e488c73c8f1d (diff)
downloadVeraCrypt-DCS-b87fc6b140772ba3017de311c7063c259424264c.tar.gz
VeraCrypt-DCS-b87fc6b140772ba3017de311c7063c259424264c.zip
First public release. Used by VeraCrypt 1.18.VeraCrypt_1.18_PreRelease
Diffstat (limited to 'Library/DcsCfgLib')
-rw-r--r--Library/DcsCfgLib/DcsCfgLib.inf80
-rw-r--r--Library/DcsCfgLib/DcsRandom.c460
-rw-r--r--Library/DcsCfgLib/GptEdit.c935
3 files changed, 1475 insertions, 0 deletions
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;
+}