File shim-merge-lf-loader-code.patch of Package shim

From 43a23fadf063d0644d123a8024f9a864ed32135f Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Sun, 19 May 2013 18:13:01 +0100
Subject: [PATCH] Port MokManager to Linux Foundation loader UI code

This is the first stage of porting the MokManager UI to the UI code used
by the Linux Foundation UEFI loader.
---
 Makefile                   |    9 +-
 MokManager.c               | 1220 +++++++++++++++-----------------------------
 include/PeImage.h          |  787 ++++++++++++++++++++++++++++
 include/configtable.h      |   68 +++
 include/console.h          |   21 +
 include/efiauthenticated.h |  222 ++++++++
 include/errors.h           |    9 +
 include/execute.h          |    5 +
 include/guid.h             |   18 +
 include/security_policy.h  |    6 +
 include/shell.h            |    2 +
 include/simple_file.h      |   21 +
 include/variables.h        |   59 +++
 include/version.h          |    8 +
 include/wincert.h          |   33 ++
 lib/Makefile               |   28 +
 lib/configtable.c          |  144 ++++++
 lib/console.c              |  402 +++++++++++++++
 lib/execute.c              |  127 +++++
 lib/guid.c                 |   47 ++
 lib/security_policy.c      |  391 ++++++++++++++
 lib/shell.c                |   57 +++
 lib/simple_file.c          |  501 ++++++++++++++++++
 lib/variables.c            |  340 ++++++++++++
 24 files changed, 3721 insertions(+), 804 deletions(-)
 create mode 100644 include/PeImage.h
 create mode 100644 include/configtable.h
 create mode 100644 include/console.h
 create mode 100644 include/efiauthenticated.h
 create mode 100644 include/errors.h
 create mode 100644 include/execute.h
 create mode 100644 include/guid.h
 create mode 100644 include/security_policy.h
 create mode 100644 include/shell.h
 create mode 100644 include/simple_file.h
 create mode 100644 include/variables.h
 create mode 100644 include/version.h
 create mode 100644 include/wincert.h
 create mode 100644 lib/Makefile
 create mode 100644 lib/configtable.c
 create mode 100644 lib/console.c
 create mode 100644 lib/execute.c
 create mode 100644 lib/guid.c
 create mode 100644 lib/security_policy.c
 create mode 100644 lib/shell.c
 create mode 100644 lib/simple_file.c
 create mode 100644 lib/variables.c

diff --git a/Makefile b/Makefile
index 287fbcf..b37ceb3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 ARCH		= $(shell uname -m | sed s,i[3456789]86,ia32,)
 
-SUBDIRS		= Cryptlib
+SUBDIRS		= Cryptlib lib
 
 LIB_PATH	= /usr/lib64
 
@@ -74,8 +74,8 @@ fallback.so: $(FALLBACK_OBJS)
 
 MokManager.o: $(SOURCES)
 
-MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a
-	$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
+MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a
+	$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a
 
 Cryptlib/libcryptlib.a:
 	$(MAKE) -C Cryptlib
@@ -83,6 +83,9 @@ Cryptlib/libcryptlib.a:
 Cryptlib/OpenSSL/libopenssl.a:
 	$(MAKE) -C Cryptlib/OpenSSL
 
+lib/lib.a:
+	$(MAKE) -C lib
+
 %.efi: %.so
 	objcopy -j .text -j .sdata -j .data \
 		-j .dynamic -j .dynsym  -j .rel \
diff --git a/MokManager.c b/MokManager.c
index 97588cb..60e799a 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -6,6 +6,9 @@
 #include "signature.h"
 #include "PeImage.h"
 
+#include "include/console.h"
+#include "include/simple_file.h"
+
 #define PASSWORD_MAX 16
 #define PASSWORD_MIN 8
 #define SB_PASSWORD_LEN 8
@@ -16,18 +19,6 @@
 
 #define EFI_VARIABLE_APPEND_WRITE 0x00000040
 
-#define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
-#define HASH_STRING L"Select a file to trust:\n\n"
-
-struct menu_item {
-	CHAR16 *text;
-	INTN (* callback)(void *data, void *data2, void *data3);
-	void *data;
-	void *data2;
-	void *data3;
-	UINTN colour;
-};
-
 typedef struct {
 	UINT32 MokSize;
 	UINT8 *Mok;
@@ -56,7 +47,7 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
 	*buffer = AllocatePool(*size);
 
 	if (!*buffer) {
-		Print(L"Unable to allocate variable buffer\n");
+		console_notify(L"Unable to allocate variable buffer");
 		return EFI_OUT_OF_RESOURCES;
 	}
 
@@ -88,24 +79,24 @@ static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash)
 	ctx = AllocatePool(ctxsize);
 
 	if (!ctx) {
-		Print(L"Unable to allocate memory for hash context\n");
+		console_notify(L"Unable to allocate memory for hash context");
 		return EFI_OUT_OF_RESOURCES;
 	}
 
 	if (!Sha1Init(ctx)) {
-		Print(L"Unable to initialise hash\n");
+		console_notify(L"Unable to initialise hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
 
 	if (!(Sha1Update(ctx, Data, DataSize))) {
-		Print(L"Unable to generate hash\n");
+		console_notify(L"Unable to generate hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
 
 	if (!(Sha1Final(ctx, hash))) {
-		Print(L"Unable to finalise hash\n");
+		console_notify(L"Unable to finalise hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
@@ -126,7 +117,7 @@ static UINT32 count_keys(void *Data, UINTN DataSize)
 	while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
 		if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
 		    (CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
-			Print(L"Doesn't look like a key or hash\n");
+			console_notify(L"Doesn't look like a key or hash");
 			dbsize -= CertList->SignatureListSize;
 			CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
 						  CertList->SignatureListSize);
@@ -135,7 +126,7 @@ static UINT32 count_keys(void *Data, UINTN DataSize)
 
 		if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
 		    (CertList->SignatureSize != 48)) {
-			Print(L"Doesn't look like a valid hash\n");
+			console_notify(L"Doesn't look like a valid hash");
 			dbsize -= CertList->SignatureListSize;
 			CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
 						  CertList->SignatureListSize);
@@ -163,7 +154,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
 	list = AllocatePool(sizeof(MokListNode) * num);
 
 	if (!list) {
-		Print(L"Unable to allocate MOK list\n");
+		console_notify(L"Unable to allocate MOK list");
 		return NULL;
 	}
 
@@ -200,15 +191,17 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
 	return list;
 }
 
-static void print_x509_name (X509_NAME *X509Name, CHAR16 *name)
+static CHAR16* get_x509_name (X509_NAME *X509Name, CHAR16 *name)
 {
 	char *str;
+	CHAR16 *ret = NULL;
 
 	str = X509_NAME_oneline(X509Name, NULL, 0);
 	if (str) {
-		Print(L"  %s:\n    %a\n", name, str);
+		ret = PoolPrint(L"%s: %a", name, str);
 		OPENSSL_free(str);
 	}
+	return ret;
 }
 
 static const char *mon[12]= {
@@ -315,7 +308,7 @@ error:
 	return;
 }
 
-static void print_x509_time (ASN1_TIME *time, CHAR16 *name)
+static CHAR16* get_x509_time (ASN1_TIME *time, CHAR16 *name)
 {
 	CHAR16 time_string[30];
 
@@ -327,48 +320,126 @@ static void print_x509_time (ASN1_TIME *time, CHAR16 *name)
 		time_string[0] = '\0';
 	}
 
-	Print(L"  %s:\n    %s\n", name, time_string);
+	return PoolPrint(L"%s: %s", name, time_string);
 }
 
-static void show_x509_info (X509 *X509Cert)
+static void show_x509_info (X509 *X509Cert, UINT8 *hash)
 {
 	ASN1_INTEGER *serial;
 	BIGNUM *bnser;
 	unsigned char hexbuf[30];
 	X509_NAME *X509Name;
 	ASN1_TIME *time;
+	CHAR16 *issuer = NULL;
+	CHAR16 *subject = NULL;
+	CHAR16 *from = NULL;
+	CHAR16 *until = NULL;
+	POOL_PRINT hash_string1;
+	POOL_PRINT hash_string2;
+	POOL_PRINT serial_string;
+	int fields = 0;
+	CHAR16 **text;
+	int i = 0;
+
+	ZeroMem(&hash_string1, sizeof(hash_string1));
+	ZeroMem(&hash_string2, sizeof(hash_string2));
+	ZeroMem(&serial_string, sizeof(serial_string));
 
 	serial = X509_get_serialNumber(X509Cert);
 	if (serial) {
 		int i, n;
 		bnser = ASN1_INTEGER_to_BN(serial, NULL);
 		n = BN_bn2bin(bnser, hexbuf);
-		Print(L"  Serial Number:\n    ");
-		for (i = 0; i < n-1; i++) {
-			Print(L"%02x:", hexbuf[i]);
+		CatPrint(&serial_string, L"Serial Number:");
+		for (i = 0; i < n; i++) {
+			CatPrint(&serial_string, L"%02x:", hexbuf[i]);
 		}
-		Print(L"%02x\n", hexbuf[n-1]);
 	}
 
+	if (serial_string.str)
+		fields++;
+
 	X509Name = X509_get_issuer_name(X509Cert);
 	if (X509Name) {
-		print_x509_name(X509Name, L"Issuer");
+		issuer = get_x509_name(X509Name, L"Issuer");
+		if (issuer)
+			fields++;
 	}
 
 	X509Name = X509_get_subject_name(X509Cert);
 	if (X509Name) {
-		print_x509_name(X509Name, L"Subject");
+		subject = get_x509_name(X509Name, L"Subject");
+		if (subject)
+			fields++;
 	}
 
 	time = X509_get_notBefore(X509Cert);
 	if (time) {
-		print_x509_time(time, L"Validity from");
+		from = get_x509_time(time, L"Validity from");
+		if (time)
+			fields++;
 	}
 
 	time = X509_get_notAfter(X509Cert);
 	if (time) {
-		print_x509_time(time, L"Validity till");
+		until = get_x509_time(time, L"Validity till");
+		if (until)
+			fields++;
+	}
+
+#if 0
+	CatPrint(&hash_string1, L"SHA1 Fingerprint: ");
+	for (i=0; i<10; i++)
+		CatPrint(&hash_string1, L"%02x ", hash[i]);
+	for (i=10; i<20; i++)
+		CatPrint(&hash_string2, L"%02x ", hash[i]);
+
+	if (hash_string1.str)
+		fields++;
+
+	if (hash_string2.str)
+		fields++;
+#endif
+	if (!fields)
+		return;
+
+	text = AllocateZeroPool(sizeof(CHAR16 *) * (fields + 1));
+	if (serial_string.str) {
+		text[i] = serial_string.str;
+		i++;
+	}
+	if (issuer) {
+		text[i] = issuer;
+		i++;
+	}
+	if (subject) {
+		text[i] = subject;
+		i++;
+	}
+	if (from) {
+		text[i] = from;
+		i++;
+	}
+	if (until) {
+		text[i] = until;
+		i++;
 	}
+	if (hash_string1.str) {
+		text[i] = hash_string1.str;
+		i++;
+	}
+	if (hash_string2.str) {
+		text[i] = hash_string2.str;
+		i++;
+	}
+	text[i] = NULL;
+
+	console_alertbox(text);
+
+	for (i=0; text[i] != NULL; i++)
+		FreePool(text[i]);
+
+	FreePool(text);
 }
 
 static void show_mok_info (void *Mok, UINTN MokSize)
@@ -382,28 +453,20 @@ static void show_mok_info (void *Mok, UINTN MokSize)
 		return;
 
 	if (MokSize != SHA256_DIGEST_SIZE) {
-		if (X509ConstructCertificate(Mok, MokSize,
-				 (UINT8 **) &X509Cert) && X509Cert != NULL) {
-			show_x509_info(X509Cert);
-			X509_free(X509Cert);
-		} else {
-			Print(L"  Not a valid X509 certificate: %x\n\n",
-			      ((UINT32 *)Mok)[0]);
-			return;
-		}
-
 		efi_status = get_sha1sum(Mok, MokSize, hash);
 
 		if (efi_status != EFI_SUCCESS) {
-			Print(L"Failed to compute MOK fingerprint\n");
+			console_notify(L"Failed to compute MOK fingerprint");
 			return;
 		}
 
-		Print(L"  Fingerprint (SHA1):\n    ");
-		for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
-			Print(L" %02x", hash[i]);
-			if (i % 10 == 9)
-				Print(L"\n    ");
+		if (X509ConstructCertificate(Mok, MokSize,
+				 (UINT8 **) &X509Cert) && X509Cert != NULL) {
+			show_x509_info(X509Cert, hash);
+			X509_free(X509Cert);
+		} else {
+			console_notify(L"Not a valid X509 certificate");
+			return;
 		}
 	} else {
 		Print(L"SHA256 hash:\n   ");
@@ -414,58 +477,19 @@ static void show_mok_info (void *Mok, UINTN MokSize)
 		}
 		Print(L"\n");
 	}
-
-	Print(L"\n");
-}
-
-static INTN get_number ()
-{
-	EFI_INPUT_KEY input_key;
-	CHAR16 input[10];
-	int count = 0;
-
-	do {
-		input_key = get_keystroke();
-
-		if ((input_key.UnicodeChar < '0' ||
-		     input_key.UnicodeChar > '9' ||
-		     count >= 10) &&
-		    input_key.UnicodeChar != CHAR_BACKSPACE) {
-			continue;
-		}
-
-		if (count == 0 && input_key.UnicodeChar == CHAR_BACKSPACE)
-			continue;
-
-		Print(L"%c", input_key.UnicodeChar);
-
-		if (input_key.UnicodeChar == CHAR_BACKSPACE) {
-			input[--count] = '\0';
-			continue;
-		}
-
-		input[count++] = input_key.UnicodeChar;
-	} while (input_key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
-	if (count == 0)
-		return -1;
-
-	input[count] = '\0';
-
-	return (INTN)Atoi(input);
 }
 
-static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
+static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
 {
 	UINT32 MokNum = 0;
 	MokListNode *keys = NULL;
 	INTN key_num = 0;
-	UINT8 initial = 1;
+	CHAR16 **menu_strings;
+	int i;
 
 	if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) +
 			   sizeof(EFI_SIGNATURE_DATA))) {
-		Print(L"No keys\n");
-		Pause();
+		console_notify(L"No MOK keys found");
 		return 0;
 	}
 
@@ -473,41 +497,38 @@ static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
 	keys = build_mok_list(MokNum, KeyList, KeyListSize);
 
 	if (!keys) {
-		Print(L"Failed to construct key list\n");
+		console_notify(L"Failed to construct key list");
 		return 0;
 	}
 
-	do {
-		uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-		if (title)
-			Print(L"%s\n", title);
-		Print(L"Input the key number to show the details of the key or\n"
-		      L"type \'0\' to continue\n\n");
-		Print(L"%d key(s) in the key list\n\n", MokNum);
-
-		if (key_num > MokNum) {
-			Print(L"[Key %d]\n", key_num);
-			Print(L"No such key\n\n");
-		} else if (initial != 1 && key_num > 0){
-			Print(L"[Key %d]\n", key_num);
-			show_mok_info(keys[key_num-1].Mok, keys[key_num-1].MokSize);
-		}
+	menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2));
+
+	if (!menu_strings)
+		return EFI_OUT_OF_RESOURCES;
 
-		Print(L"Key Number: ");
+	for (i=0; i<MokNum; i++) {
+		menu_strings[i] = PoolPrint(L"View key %d", i);
+	}
+	menu_strings[i] = StrDuplicate(L"Continue");
 
-		key_num = get_number();
+	menu_strings[i+1] = NULL;
 
-		Print(L"\n\n");
+	while (key_num < MokNum) {
+		key_num = console_select((CHAR16 *[]){ title, NULL },
+					 menu_strings, 0);
 
-		if (key_num == -1)
-			continue;
+		if (key_num < MokNum)
+			show_mok_info(keys[key_num].Mok, keys[key_num].MokSize);
+	}
+
+	for (i=0; menu_strings[i] != NULL; i++)
+		FreePool(menu_strings[i]);
 
-		initial = 0;
-	} while (key_num != 0);
+	FreePool(menu_strings);
 
 	FreePool(keys);
 
-	return 1;
+	return EFI_SUCCESS;
 }
 
 static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show)
@@ -561,32 +582,32 @@ static EFI_STATUS compute_pw_hash (void *MokNew, UINTN MokNewSize, CHAR16 *passw
 	ctx = AllocatePool(ctxsize);
 
 	if (!ctx) {
-		Print(L"Unable to allocate memory for hash context\n");
+		console_notify(L"Unable to allocate memory for hash context");
 		return EFI_OUT_OF_RESOURCES;
 	}
 
 	if (!Sha256Init(ctx)) {
-		Print(L"Unable to initialise hash\n");
+		console_notify(L"Unable to initialise hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
 
 	if (MokNew && MokNewSize) {
 		if (!(Sha256Update(ctx, MokNew, MokNewSize))) {
-			Print(L"Unable to generate hash\n");
+			console_notify(L"Unable to generate hash");
 			status = EFI_OUT_OF_RESOURCES;
 			goto done;
 		}
 	}
 
 	if (!(Sha256Update(ctx, password, pw_length * sizeof(CHAR16)))) {
-		Print(L"Unable to generate hash\n");
+		console_notify(L"Unable to generate hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
 
 	if (!(Sha256Final(ctx, hash))) {
-		Print(L"Unable to finalise hash\n");
+		console_notify(L"Unable to finalise hash");
 		status = EFI_OUT_OF_RESOURCES;
 		goto done;
 	}
@@ -660,7 +681,7 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
 
 
 		if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) {
-			Print(L"Failed to get MokAuth %d\n", efi_status);
+			console_error(L"Failed to get MokAuth", efi_status);
 			return efi_status;
 		}
 
@@ -687,7 +708,7 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
 	}
 
 	if (efi_status != EFI_SUCCESS) {
-		Print(L"Failed to set variable %d\n", efi_status);
+		console_error(L"Failed to set variable", efi_status);
 		return efi_status;
 	}
 
@@ -696,84 +717,60 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
 
 static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
-	CHAR16 line[1];
-	UINT32 length;
 	EFI_STATUS efi_status;
 
-	do {
-		if (!list_keys(MokNew, MokNewSize, L"[Enroll MOK]")) {
-			return 0;
-		}
-
-		Print(L"Enroll the key(s)? (y/n): ");
-
-		get_line (&length, line, 1, 1);
+	if (list_keys(MokNew, MokNewSize, L"[Enroll MOK]") != EFI_SUCCESS)
+		return 0;
 
-		if (line[0] == 'Y' || line[0] == 'y') {
-			efi_status = store_keys(MokNew, MokNewSize, auth);
+	if (console_yes_no((CHAR16 *[]){L"Enroll the key(s)?", NULL}) == 0)
+		return 0;
 
-			if (efi_status != EFI_SUCCESS) {
-				Print(L"Failed to enroll keys\n");
-				return -1;
-			}
+	efi_status = store_keys(MokNew, MokNewSize, auth);
 
-			if (auth) {
-				LibDeleteVariable(L"MokNew", &shim_lock_guid);
-				LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+	if (efi_status != EFI_SUCCESS) {
+		console_notify(L"Failed to enroll keys\n");
+		return -1;
+	}
 
-				Print(L"\nPress a key to reboot system\n");
-				Pause();
-				uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
-						  EFI_SUCCESS, 0, NULL);
-				Print(L"Failed to reboot\n");
-				return -1;
-			}
+	if (auth) {
+		LibDeleteVariable(L"MokNew", &shim_lock_guid);
+		LibDeleteVariable(L"MokAuth", &shim_lock_guid);
 
-			return 0;
-		}
-	} while (line[0] != 'N' && line[0] != 'n');
-	return -1;
-}
+		console_notify(L"The system must now be rebooted");
+		uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
+				  EFI_SUCCESS, 0, NULL);
+		console_notify(L"Failed to reboot");
+		return -1;
+	}
 
-static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2,
-					    void *data3)
-{
-	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-	return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE);
+	return 0;
 }
 
-static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3)
+static INTN mok_reset_prompt ()
 {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
-	CHAR16 line[1];
-	UINT32 length;
 	EFI_STATUS efi_status;
 
 	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-	Print(L"Erase all stored keys? (y/N): ");
-
-	get_line (&length, line, 1, 1);
 
-	if (line[0] == 'Y' || line[0] == 'y') {
-		efi_status = store_keys(NULL, 0, TRUE);
+	if (console_yes_no((CHAR16 *[]){L"Erase all stored keys?", NULL }) == 0)
+		return 0;
 
-		if (efi_status != EFI_SUCCESS) {
-			Print(L"Failed to erase keys\n");
-			return -1;
-		}
+	efi_status = store_keys(NULL, 0, TRUE);
 
-		LibDeleteVariable(L"MokNew", &shim_lock_guid);
-		LibDeleteVariable(L"MokAuth", &shim_lock_guid);
-
-		Print(L"\nPress a key to reboot system\n");
-		Pause();
-		uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
-				  EFI_SUCCESS, 0, NULL);
-		Print(L"Failed to reboot\n");
+	if (efi_status != EFI_SUCCESS) {
+		console_notify(L"Failed to erase keys\n");
 		return -1;
 	}
 
-	return 0;
+	LibDeleteVariable(L"MokNew", &shim_lock_guid);
+	LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+
+	console_notify(L"The system must now be rebooted");
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
+			  EFI_SUCCESS, 0, NULL);
+	console_notify(L"Failed to reboot\n");
+	return -1;
 }
 
 static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
@@ -831,7 +828,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
 		FreePool(Data);
 
 	if (efi_status != EFI_SUCCESS) {
-		Print(L"Failed to set variable %d\n", efi_status);
+		console_error(L"Failed to set variable", efi_status);
 		return efi_status;
 	}
 
@@ -856,7 +853,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
 				       &attributes, &auth_size, auth);
 
 	if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) {
-		Print(L"Failed to get MokDelAuth %d\n", efi_status);
+		console_error(L"Failed to get MokDelAuth", efi_status);
 		return efi_status;
 	}
 
@@ -868,9 +865,11 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
 				  &MokListDataSize, &MokListData);
 
 	if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
-		Print(L"MokList is compromised!\nErase all keys in MokList!\n");
+		console_alertbox((CHAR16 *[]){L"MokList is compromised!",
+					L"Erase all keys in MokList!",
+					NULL});
 		if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
-			Print(L"Failed to erase MokList\n");
+			console_notify(L"Failed to erase MokList");
 		}
 		return EFI_ACCESS_DENIED;
 	}
@@ -911,59 +910,48 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
 	return efi_status;
 }
 
-static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3)
+static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize)
 {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
-	UINTN MokDelSize = (UINTN)data2;
-	CHAR16 line[1];
-	UINT32 length;
 	EFI_STATUS efi_status;
 
-	do {
-		if (!list_keys(MokDel, MokDelSize, L"[Delete MOK]")) {
-			return 0;
-		}
-
-		Print(L"Delete the key(s)? (y/n): ");
+	if (list_keys(MokDel, MokDelSize, L"[Delete MOK]") != EFI_SUCCESS) {
+		return 0;
+	}
 
-		get_line (&length, line, 1, 1);
+        if (console_yes_no((CHAR16 *[]){L"Delete the key(s)?", NULL}) == 0)
+                return 0;
 
-		if (line[0] == 'Y' || line[0] == 'y') {
-			efi_status = delete_keys(MokDel, MokDelSize);
+	efi_status = delete_keys(MokDel, MokDelSize);
 
-			if (efi_status != EFI_SUCCESS) {
-				Print(L"Failed to delete keys\n");
-				return -1;
-			}
+	if (efi_status != EFI_SUCCESS) {
+		console_notify(L"Failed to delete keys");
+		return -1;
+	}
 
-			LibDeleteVariable(L"MokDel", &shim_lock_guid);
-			LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
+	LibDeleteVariable(L"MokDel", &shim_lock_guid);
+	LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
 
-			Print(L"\nPress a key to reboot system\n");
-			Pause();
-			uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
-					  EFI_SUCCESS, 0, NULL);
-			Print(L"Failed to reboot\n");
-			return -1;
-		}
-	} while (line[0] != 'N' && line[0] != 'n');
+	console_notify(L"The system must now be rebooted");
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
+			  EFI_SUCCESS, 0, NULL);
+	console_notify(L"Failed to reboot");
 	return -1;
 }
 
-static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
+static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
 	EFI_STATUS efi_status;
-	UINTN MokSBSize = (UINTN)data2;
 	MokSBvar *var = MokSB;
 	CHAR16 pass1, pass2, pass3;
 	UINT8 fail_count = 0;
 	UINT32 length;
-	CHAR16 line[1];
 	UINT8 sbval = 1;
 	UINT8 pos1, pos2, pos3;
+	int ret;
 
 	if (MokSBSize != sizeof(MokSBvar)) {
-		Print(L"Invalid MokSB variable contents\n");
+		console_notify(L"Invalid MokSB variable contents");
 		return -1;
 	}
 
@@ -1003,61 +991,49 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
 	}
 
 	if (fail_count >= 3) {
-		Print(L"Password limit reached\n");
+		console_notify(L"Password limit reached");
 		return -1;
 	}
 
-	if (var->MokSBState == 0) {
-		Print(L"Disable Secure Boot? (y/n): ");
-	} else {
-		Print(L"Enable Secure Boot? (y/n): ");
-	}
+	if (var->MokSBState == 0)
+		ret = console_yes_no((CHAR16 *[]){L"Disable Secure Boot", NULL});
+	else
+		ret = console_yes_no((CHAR16 *[]){L"Enable Secure Boot", NULL});
 
-	do {
-		get_line (&length, line, 1, 1);
+	if (ret == 0) {
+		LibDeleteVariable(L"MokSB", &shim_lock_guid);
+		return -1;
+	}
 
-		if (line[0] == 'Y' || line[0] == 'y') {
-			if (var->MokSBState == 0) {
-				efi_status = uefi_call_wrapper(RT->SetVariable,
-							       5, L"MokSBState",
-							       &shim_lock_guid,
+	if (var->MokSBState == 0) {
+		efi_status = uefi_call_wrapper(RT->SetVariable,
+					       5, L"MokSBState",
+					       &shim_lock_guid,
 					       EFI_VARIABLE_NON_VOLATILE |
 					       EFI_VARIABLE_BOOTSERVICE_ACCESS,
-							       1, &sbval);
-				if (efi_status != EFI_SUCCESS) {
-					Print(L"Failed to set Secure Boot state\n");
-					return -1;
-				}
-			} else {
-				LibDeleteVariable(L"MokSBState",
-						  &shim_lock_guid);
-			}
-
-			LibDeleteVariable(L"MokSB", &shim_lock_guid);
-
-			Print(L"Press a key to reboot system\n");
-			Pause();
-			uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
-					  EFI_SUCCESS, 0, NULL);
-			Print(L"Failed to reboot\n");
+					       1, &sbval);
+		if (efi_status != EFI_SUCCESS) {
+			console_notify(L"Failed to set Secure Boot state");
 			return -1;
 		}
-	} while (line[0] != 'N' && line[0] != 'n');
+	} else {
+		LibDeleteVariable(L"MokSBState", &shim_lock_guid);
+	}
 
+	console_notify(L"The system must now be rebooted");
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
+			  EFI_SUCCESS, 0, NULL);
+	console_notify(L"Failed to reboot");
 	return -1;
 }
 
-
-static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) {
+static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
 	EFI_STATUS efi_status;
-	UINTN MokPWSize = (UINTN)data2;
 	UINT8 hash[SHA256_DIGEST_SIZE];
-	UINT32 length;
-	CHAR16 line[1];
 
 	if (MokPWSize != SHA256_DIGEST_SIZE) {
-		Print(L"Invalid MokPW variable contents\n");
+		console_notify(L"Invalid MokPW variable contents");
 		return -1;
 	}
 
@@ -1066,190 +1042,41 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) {
 	SetMem(hash, SHA256_DIGEST_SIZE, 0);
 
 	if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) {
-		Print(L"Clear MOK password? (y/n): ");
-
-		do {
-			get_line (&length, line, 1, 1);
-
-			if (line[0] == 'Y' || line[0] == 'y') {
-				LibDeleteVariable(L"MokPWStore", &shim_lock_guid);
-				LibDeleteVariable(L"MokPW", &shim_lock_guid);
-			}
-		} while (line[0] != 'N' && line[0] != 'n');
+		if (console_yes_no((CHAR16 *[]){L"Clear MOK password?", NULL}) == 0)
+			return 0;
 
+		LibDeleteVariable(L"MokPWStore", &shim_lock_guid);
+		LibDeleteVariable(L"MokPW", &shim_lock_guid);
 		return 0;
 	}
 
 	efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: ");
 	if (efi_status != EFI_SUCCESS) {
-		Print(L"Password limit reached\n");
+		console_notify(L"Password limit reached");
 		return -1;
 	}
 
-	Print(L"Set MOK password? (y/n): ");
-
-	do {
-		get_line (&length, line, 1, 1);
-
-		if (line[0] == 'Y' || line[0] == 'y') {
-			efi_status = uefi_call_wrapper(RT->SetVariable, 5,
-						       L"MokPWStore",
-						       &shim_lock_guid,
-					       EFI_VARIABLE_NON_VOLATILE |
-					       EFI_VARIABLE_BOOTSERVICE_ACCESS,
-						       MokPWSize, MokPW);
-			if (efi_status != EFI_SUCCESS) {
-				Print(L"Failed to set MOK password\n");
-				return -1;
-			}
-
-			LibDeleteVariable(L"MokPW", &shim_lock_guid);
-
-			Print(L"Press a key to reboot system\n");
-			Pause();
-			uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
-					  EFI_SUCCESS, 0, NULL);
-			Print(L"Failed to reboot\n");
-			return -1;
-		}
-	} while (line[0] != 'N' && line[0] != 'n');
-
-	return 0;
-}
-
-static UINTN draw_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
-			UINTN count) {
-	UINTN i;
-
-	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-
-	uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
-			  EFI_WHITE | EFI_BACKGROUND_BLACK);
-
-	Print(L"%s UEFI key management\n\n", SHIM_VENDOR);
-
-	if (header)
-		Print(L"%s", header);
-
-	for (i = 0; i < count; i++) {
-		uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
-				  items[i].colour | EFI_BACKGROUND_BLACK);
-		Print(L"  %s\n", items[i].text);
-	}
-
-	uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
-	uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
-
-	return 2 + lines;
-}
-
-static void free_menu (struct menu_item *items, UINTN count) {
-	UINTN i;
+	if (console_yes_no((CHAR16 *[]){L"Set MOK password?", NULL}) == 0)
+		return 0;
 
-	for (i=0; i<count; i++) {
-		if (items[i].text)
-			FreePool(items[i].text);
+	efi_status = uefi_call_wrapper(RT->SetVariable, 5,
+				       L"MokPWStore",
+				       &shim_lock_guid,
+				       EFI_VARIABLE_NON_VOLATILE |
+				       EFI_VARIABLE_BOOTSERVICE_ACCESS,
+				       MokPWSize, MokPW);
+	if (efi_status != EFI_SUCCESS) {
+		console_notify(L"Failed to set MOK password");
+		return -1;
 	}
 
-	FreePool(items);
-}
-
-static void update_time (UINTN position, UINTN timeout)
-{
-	uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
-			  position);
-
-	uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
-			  EFI_BLACK | EFI_BACKGROUND_BLACK);
-
-	Print(L"                       ", timeout);
-
-	uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
-			  position);
-
-	uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
-			  EFI_WHITE | EFI_BACKGROUND_BLACK);
-
-	if (timeout > 1)
-		Print(L"Booting in %d seconds\n", timeout);
-	else if (timeout)
-		Print(L"Booting in %d second\n", timeout);
-}
-
-static void run_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
-		      UINTN count, UINTN timeout) {
-	UINTN index, pos = 0, wait = 0, offset;
-	EFI_INPUT_KEY key;
-	EFI_STATUS status;
-	INTN ret;
-
-	if (timeout)
-		wait = 10000000;
-
-	offset = draw_menu (header, lines, items, count);
-
-	while (1) {
-		update_time(count + offset + 1, timeout);
-
-		uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut,
-				  0, pos + offset);
-		status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait);
-
-		if (status == EFI_TIMEOUT) {
-			timeout--;
-			if (!timeout) {
-				free_menu(items, count);
-				return;
-			}
-			continue;
-		}
-
-		wait = 0;
-		timeout = 0;
-
-		uefi_call_wrapper(BS->WaitForEvent, 3, 1,
-				  &ST->ConIn->WaitForKey, &index);
-		uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn,
-				  &key);
-
-		switch(key.ScanCode) {
-		case SCAN_UP:
-			if (pos == 0)
-				continue;
-			pos--;
-			continue;
-			break;
-		case SCAN_DOWN:
-			if (pos == (count - 1))
-				continue;
-			pos++;
-			continue;
-			break;
-		}
-
-		switch(key.UnicodeChar) {
-		case CHAR_LINEFEED:
-		case CHAR_CARRIAGE_RETURN:
-			if (items[pos].callback == NULL) {
-				free_menu(items, count);
-				return;
-			}
+	LibDeleteVariable(L"MokPW", &shim_lock_guid);
 
-			ret = items[pos].callback(items[pos].data,
-						  items[pos].data2,
-						  items[pos].data3);
-			if (ret < 0) {
-				Print(L"Press a key to continue\n");
-				Pause();
-				/* Clear the key in the queue */
-				uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2,
-						  ST->ConIn, &key);
-			}
-			draw_menu (header, lines, items, count);
-			pos = 0;
-			break;
-		}
-	}
+	console_notify(L"The system must now be rebooted");
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0,
+			  NULL);
+	console_notify(L"Failed to reboot");
+	return -1;
 }
 
 static UINTN verify_certificate(void *cert, UINTN size)
@@ -1260,8 +1087,7 @@ static UINTN verify_certificate(void *cert, UINTN size)
 
 	if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) ||
 	    X509Cert == NULL) {
-		Print(L"Invalid X509 certificate\n");
-		Pause();
+		console_notify(L"Invalid X509 certificate");
 		return FALSE;
 	}
 
@@ -1269,49 +1095,22 @@ static UINTN verify_certificate(void *cert, UINTN size)
 	return TRUE;
 }
 
-static INTN file_callback (void *data, void *data2, void *data3) {
-	EFI_FILE_INFO *buffer = NULL;
-	UINTN buffersize = 0, mokbuffersize;
-	EFI_STATUS status;
-	EFI_FILE *file;
-	CHAR16 *filename = data;
-	EFI_FILE *parent = data2;
-	BOOLEAN hash = !!data3;
-	EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
+static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash)
+{
+	EFI_STATUS status = EFI_SUCCESS;
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
 	EFI_SIGNATURE_LIST *CertList;
 	EFI_SIGNATURE_DATA *CertData;
+	UINTN mokbuffersize;
 	void *mokbuffer = NULL;
 
-	status = uefi_call_wrapper(parent->Open, 5, parent, &file, filename,
-				   EFI_FILE_MODE_READ, 0);
-
-	if (status != EFI_SUCCESS)
-		return 1;
-
-	status = uefi_call_wrapper(file->GetInfo, 4, file, &file_info_guid,
-				   &buffersize, buffer);
-
-	if (status == EFI_BUFFER_TOO_SMALL) {
-		buffer = AllocatePool(buffersize);
-		status = uefi_call_wrapper(file->GetInfo, 4, file,
-					   &file_info_guid, &buffersize,
-					   buffer);
-	}
-
-	if (!buffer)
-		return 0;
-
-	buffersize = buffer->FileSize;
-
 	if (hash) {
-		void *binary;
 		UINT8 sha256[SHA256_DIGEST_SIZE];
 		UINT8 sha1[SHA1_DIGEST_SIZE];
 		SHIM_LOCK *shim_lock;
 		EFI_GUID shim_guid = SHIM_LOCK_GUID;
 		PE_COFF_LOADER_IMAGE_CONTEXT context;
-
+	
 		status = LibLocateProtocol(&shim_guid, (VOID **)&shim_lock);
 
 		if (status != EFI_SUCCESS)
@@ -1325,20 +1124,12 @@ static INTN file_callback (void *data, void *data2, void *data3) {
 		if (!mokbuffer)
 			goto out;
 
-		binary = AllocatePool(buffersize);
-
-		status = uefi_call_wrapper(file->Read, 3, file, &buffersize,
-					   binary);
-
-		if (status != EFI_SUCCESS)
-			goto out;
-
-		status = shim_lock->Context(binary, buffersize, &context);
+		status = shim_lock->Context(data, datasize, &context);
 
 		if (status != EFI_SUCCESS)
 			goto out;
-
-		status = shim_lock->Hash(binary, buffersize, &context, sha256,
+	
+		status = shim_lock->Hash(data, datasize, &context, sha256,
 					 sha1);
 
 		if (status != EFI_SUCCESS)
@@ -1351,7 +1142,7 @@ static INTN file_callback (void *data, void *data2, void *data3) {
 						  sizeof(EFI_SIGNATURE_LIST));
 		CopyMem(CertData->SignatureData, sha256, SHA256_DIGEST_SIZE);
 	} else {
-		mokbuffersize = buffersize + sizeof(EFI_SIGNATURE_LIST) +
+		mokbuffersize = datasize + sizeof(EFI_SIGNATURE_LIST) +
 			sizeof(EFI_GUID);
 		mokbuffer = AllocatePool(mokbuffersize);
 
@@ -1360,12 +1151,11 @@ static INTN file_callback (void *data, void *data2, void *data3) {
 
 		CertList = mokbuffer;
 		CertList->SignatureType = EfiCertX509Guid;
-		CertList->SignatureSize = 16 + buffersize;
-		status = uefi_call_wrapper(file->Read, 3, file, &buffersize,
-				 mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16);
+		CertList->SignatureSize = 16 + datasize;
+
+		memcpy(mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16, data,
+		       datasize);
 
-		if (status != EFI_SUCCESS)
-			goto out;
 		CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) +
 						  sizeof(EFI_SIGNATURE_LIST));
 	}
@@ -1375,316 +1165,100 @@ static INTN file_callback (void *data, void *data2, void *data3) {
 	CertData->SignatureOwner = shim_lock_guid;
 
 	if (!hash) {
-		if (!verify_certificate(CertData->SignatureData, buffersize))
+		if (!verify_certificate(CertData->SignatureData, datasize))
 			goto out;
 	}
 
 	mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE);
 out:
-	if (buffer)
-		FreePool(buffer);
-
 	if (mokbuffer)
 		FreePool(mokbuffer);
 
-	return 0;
+	return status;
 }
 
-static INTN directory_callback (void *data, void *data2, void *data3) {
-	EFI_FILE_INFO *buffer = NULL;
-	UINTN buffersize = 0;
-	EFI_STATUS status;
-	UINTN dircount = 0, i = 0;
-	struct menu_item *dircontent;
-	EFI_FILE *dir;
-	CHAR16 *filename = data;
-	EFI_FILE *root = data2;
-	BOOLEAN hash = !!data3;
-
-	status = uefi_call_wrapper(root->Open, 5, root, &dir, filename,
-				   EFI_FILE_MODE_READ, 0);
-
-	if (status != EFI_SUCCESS)
-		return 1;
-
-	while (1) {
-		status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize,
-					   buffer);
-
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			buffer = AllocatePool(buffersize);
-			status = uefi_call_wrapper(dir->Read, 3, dir,
-						   &buffersize, buffer);
-		}
-
-		if (status != EFI_SUCCESS)
-			return 1;
-
-		if (!buffersize)
-			break;
-
-		if ((StrCmp(buffer->FileName, L".") == 0) ||
-		    (StrCmp(buffer->FileName, L"..") == 0))
-			continue;
-
-		dircount++;
-
-		FreePool(buffer);
-		buffersize = 0;
-	}
-
-	dircount++;
-
-	dircontent = AllocatePool(sizeof(struct menu_item) * dircount);
-
-	dircontent[0].text = StrDuplicate(L"..");
-	dircontent[0].callback = NULL;
-	dircontent[0].colour = EFI_YELLOW;
-	i++;
-
-	uefi_call_wrapper(dir->SetPosition, 2, dir, 0);
-
-	while (1) {
-		status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize,
-					   buffer);
-
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			buffer = AllocatePool(buffersize);
-			status = uefi_call_wrapper(dir->Read, 3, dir,
-						   &buffersize, buffer);
-		}
-
-		if (status != EFI_SUCCESS)
-			return 1;
+static void mok_hash_enroll(void)
+{
+	EFI_STATUS efi_status;
+        CHAR16 *file_name = NULL;
+	EFI_HANDLE im = NULL;
+	EFI_FILE *file = NULL;
+	UINTN filesize;
+	void *data;
 
-		if (!buffersize)
-			break;
+	simple_file_selector(&im, (CHAR16 *[]){
+      L"Select Binary",
+      L"",
+      L"The Selected Binary will have its hash Enrolled",
+      L"This means it will Subsequently Boot with no prompting",
+      L"Remember to make sure it is a genuine binary before Enroling its hash",
+      NULL
+	      }, L"\\", L"", &file_name);
 
-		if ((StrCmp(buffer->FileName, L".") == 0) ||
-		    (StrCmp(buffer->FileName, L"..") == 0))
-			continue;
+	if (!file_name)
+		return;
 
-		if (buffer->Attribute & EFI_FILE_DIRECTORY) {
-			dircontent[i].text = StrDuplicate(buffer->FileName);
-			dircontent[i].callback = directory_callback;
-			dircontent[i].data = dircontent[i].text;
-			dircontent[i].data2 = dir;
-			dircontent[i].data3 = data3;
-			dircontent[i].colour = EFI_YELLOW;
-		} else {
-			dircontent[i].text = StrDuplicate(buffer->FileName);
-			dircontent[i].callback = file_callback;
-			dircontent[i].data = dircontent[i].text;
-			dircontent[i].data2 = dir;
-			dircontent[i].data3 = data3;
-			dircontent[i].colour = EFI_WHITE;
-		}
+	efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ);
 
-		i++;
-		FreePool(buffer);
-		buffersize = 0;
-		buffer = NULL;
+	if (efi_status != EFI_SUCCESS) {
+		console_error(L"Unable to open file", efi_status);
+		return;
 	}
 
-	if (hash)
-		run_menu(HASH_STRING, 2, dircontent, dircount, 0);
-	else
-		run_menu(CERT_STRING, 2, dircontent, dircount, 0);
+	simple_file_read_all(file, &filesize, &data);
+	simple_file_close(file);
 
-	return 0;
-}
-
-static INTN filesystem_callback (void *data, void *data2, void *data3) {
-	EFI_FILE_INFO *buffer = NULL;
-	UINTN buffersize = 0;
-	EFI_STATUS status;
-	UINTN dircount = 0, i = 0;
-	struct menu_item *dircontent;
-	EFI_FILE *root = data;
-	BOOLEAN hash = !!data3;
-
-	uefi_call_wrapper(root->SetPosition, 2, root, 0);
-
-	while (1) {
-		status = uefi_call_wrapper(root->Read, 3, root, &buffersize,
-					   buffer);
-
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			buffer = AllocatePool(buffersize);
-			status = uefi_call_wrapper(root->Read, 3, root,
-						   &buffersize, buffer);
-		}
-
-		if (status != EFI_SUCCESS)
-			return 1;
-
-		if (!buffersize)
-			break;
-
-		if ((StrCmp(buffer->FileName, L".") == 0) ||
-		    (StrCmp(buffer->FileName, L"..") == 0))
-			continue;
-
-		dircount++;
-
-		FreePool(buffer);
-		buffersize = 0;
+	if (!filesize) {
+		console_error(L"Unable to read file", efi_status);
+		return;
 	}
 
-	dircount++;
-
-	dircontent = AllocatePool(sizeof(struct menu_item) * dircount);
-
-	dircontent[0].text = StrDuplicate(L"Return to filesystem list");
-	dircontent[0].callback = NULL;
-	dircontent[0].colour = EFI_YELLOW;
-	i++;
-
-	uefi_call_wrapper(root->SetPosition, 2, root, 0);
-
-	while (1) {
-		status = uefi_call_wrapper(root->Read, 3, root, &buffersize,
-					   buffer);
-
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			buffer = AllocatePool(buffersize);
-			status = uefi_call_wrapper(root->Read, 3, root,
-						   &buffersize, buffer);
-		}
-
-		if (status != EFI_SUCCESS)
-			return 1;
-
-		if (!buffersize)
-			break;
-
-		if ((StrCmp(buffer->FileName, L".") == 0) ||
-		    (StrCmp(buffer->FileName, L"..") == 0))
-			continue;
-
-		if (buffer->Attribute & EFI_FILE_DIRECTORY) {
-			dircontent[i].text = StrDuplicate(buffer->FileName);
-			dircontent[i].callback = directory_callback;
-			dircontent[i].data = dircontent[i].text;
-			dircontent[i].data2 = root;
-			dircontent[i].data3 = data3;
-			dircontent[i].colour = EFI_YELLOW;
-		} else {
-			dircontent[i].text = StrDuplicate(buffer->FileName);
-			dircontent[i].callback = file_callback;
-			dircontent[i].data = dircontent[i].text;
-			dircontent[i].data2 = root;
-			dircontent[i].data3 = data3;
-			dircontent[i].colour = EFI_WHITE;
-		}
-
-		i++;
-		FreePool(buffer);
-		buffer = NULL;
-		buffersize = 0;
-	}
+	efi_status = enroll_file(data, filesize, TRUE);
 
-	if (hash)
-		run_menu(HASH_STRING, 2, dircontent, dircount, 0);
-	else
-		run_menu(CERT_STRING, 2, dircontent, dircount, 0);
+	if (efi_status != EFI_SUCCESS)
+		console_error(L"Hash failed (did you select a valid EFI binary?)", efi_status);
 
-	return 0;
+	FreePool(data);
 }
 
-static INTN find_fs (void *data, void *data2, void *data3) {
-	EFI_GUID fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
-	UINTN count, i;
-	UINTN OldSize, NewSize;
-	EFI_HANDLE *filesystem_handles = NULL;
-	struct menu_item *filesystems;
-	BOOLEAN hash = !!data3;
-
-	uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &fs_guid,
-			  NULL, &count, &filesystem_handles);
-
-	if (!count || !filesystem_handles) {
-		Print(L"No filesystems?\n");
-		return 1;
-	}
-
-	count++;
-
-	filesystems = AllocatePool(sizeof(struct menu_item) * count);
-
-	filesystems[0].text = StrDuplicate(L"Exit");
-	filesystems[0].callback = NULL;
-	filesystems[0].colour = EFI_YELLOW;
-
-	for (i=1; i<count; i++) {
-		EFI_HANDLE fs = filesystem_handles[i-1];
-		EFI_FILE_IO_INTERFACE *fs_interface;
-		EFI_DEVICE_PATH *path;
-		EFI_FILE *root;
-		EFI_STATUS status;
-		CHAR16 *VolumeLabel = NULL;
-		EFI_FILE_SYSTEM_INFO *buffer = NULL;
-		UINTN buffersize = 0;
-		EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
-
-		status = uefi_call_wrapper(BS->HandleProtocol, 3, fs, &fs_guid,
-					   (void **)&fs_interface);
-
-		if (status != EFI_SUCCESS || !fs_interface)
-			continue;
-
-		path = DevicePathFromHandle(fs);
-
-		status = uefi_call_wrapper(fs_interface->OpenVolume, 2,
-					   fs_interface, &root);
-
-		if (status != EFI_SUCCESS || !root)
-			continue;
-
-		status = uefi_call_wrapper(root->GetInfo, 4, root,
-					   &file_info_guid, &buffersize,
-					   buffer);
+static void mok_key_enroll(void)
+{
+	EFI_STATUS efi_status;
+        CHAR16 *file_name = NULL;
+	EFI_HANDLE im = NULL;
+	EFI_FILE *file = NULL;
+	UINTN filesize;
+	void *data;
 
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			buffer = AllocatePool(buffersize);
-			status = uefi_call_wrapper(root->GetInfo, 4, root,
-						   &file_info_guid,
-						   &buffersize, buffer);
-		}
+	simple_file_selector(&im, (CHAR16 *[]){
+      L"Select Key",
+      L"",
+      L"The selected key will be enrolled into the MOK database",
+      L"This means any binaries signed with it will be run without prompting",
+      L"Remember to make sure it is a genuine key before Enroling it",
+      NULL
+	      }, L"\\", L"", &file_name);
 
-		if (status == EFI_SUCCESS)
-			VolumeLabel = buffer->VolumeLabel;
-
-		if (path)
-			filesystems[i].text = DevicePathToStr(path);
-		else
-			filesystems[i].text = StrDuplicate(L"Unknown device\n");
-		if (VolumeLabel) {
-			OldSize = (StrLen(filesystems[i].text) + 1) * sizeof(CHAR16);
-			NewSize = OldSize + StrLen(VolumeLabel) * sizeof(CHAR16);
-			filesystems[i].text = ReallocatePool(filesystems[i].text,
-							     OldSize, NewSize);
-			StrCat(filesystems[i].text, VolumeLabel);
-		}
+	if (!file_name)
+		return;
 
-		if (buffersize)
-			FreePool(buffer);
+	efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ);
 
-		filesystems[i].data = root;
-		filesystems[i].data2 = NULL;
-		filesystems[i].data3 = data3;
-		filesystems[i].callback = filesystem_callback;
-		filesystems[i].colour = EFI_YELLOW;
+	if (efi_status != EFI_SUCCESS) {
+		console_error(L"Unable to open file", efi_status);
+		return;
 	}
 
-	uefi_call_wrapper(BS->FreePool, 1, filesystem_handles);
+	simple_file_read_all(file, &filesize, &data);
+	simple_file_close(file);
 
-	if (hash)
-		run_menu(HASH_STRING, 2, filesystems, count, 0);
-	else
-		run_menu(CERT_STRING, 2, filesystems, count, 0);
+	if (!filesize) {
+		console_error(L"Unable to read file", efi_status);
+		return;
+	}
 
-	return 0;
+	enroll_file(data, filesize, FALSE);
+	FreePool(data);
 }
 
 static BOOLEAN verify_pw(void)
@@ -1714,20 +1288,33 @@ static BOOLEAN verify_pw(void)
 
 	efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: ");
 	if (efi_status != EFI_SUCCESS) {
-		Print(L"Password limit reached\n");
+		console_notify(L"Password limit reached");
 		return FALSE;
 	}
 
 	return TRUE;
 }
 
+typedef enum {
+	MOK_CONTINUE_BOOT,
+	MOK_RESET_MOK,
+	MOK_ENROLL_MOK,
+	MOK_DELETE_MOK,
+	MOK_CHANGE_SB,
+	MOK_SET_PW,
+	MOK_KEY_ENROLL,
+	MOK_HASH_ENROLL
+} mok_menu_item;
+
 static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 				 void *MokNew, UINTN MokNewSize,
 				 void *MokDel, UINTN MokDelSize,
 				 void *MokSB, UINTN MokSBSize,
 				 void *MokPW, UINTN MokPWSize)
 {
-	struct menu_item *menu_item;
+	CHAR16 **menu_strings;
+	mok_menu_item *menu_item;
+	int choice = 0;
 	UINT32 MokAuth = 0;
 	UINT32 MokDelAuth = 0;
 	UINTN menucount = 3, i = 0;
@@ -1736,10 +1323,11 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 	UINT8 auth[SHA256_DIGEST_SIZE];
 	UINTN auth_size = SHA256_DIGEST_SIZE;
 	UINT32 attributes;
+	EFI_STATUS ret = EFI_SUCCESS;
 
 	if (verify_pw() == FALSE)
 		return EFI_ACCESS_DENIED;
-
+	
 	efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
 					       &shim_lock_guid,
 					       &attributes, &auth_size, auth);
@@ -1766,78 +1354,108 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 	if (MokPW)
 		menucount++;
 
-	menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount);
+	menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1));
 
-	if (!menu_item)
+	if (!menu_strings)
 		return EFI_OUT_OF_RESOURCES;
 
-	menu_item[i].text = StrDuplicate(L"Continue boot");
-	menu_item[i].colour = EFI_WHITE;
-	menu_item[i].callback = NULL;
+	menu_item = AllocateZeroPool(sizeof(mok_menu_item) * menucount);
+
+	if (!menu_item) {
+		FreePool(menu_strings);
+		return EFI_OUT_OF_RESOURCES;
+	}
+
+	menu_strings[i] = StrDuplicate(L"Continue boot");
+	menu_item[i] = MOK_CONTINUE_BOOT;
 
 	i++;
 
 	if (MokNew || MokAuth) {
 		if (!MokNew) {
-			menu_item[i].text = StrDuplicate(L"Reset MOK");
-			menu_item[i].colour = EFI_WHITE;
-			menu_item[i].callback = mok_reset_prompt;
+			menu_strings[i] = StrDuplicate(L"Reset MOK");
+			menu_item[i] = MOK_RESET_MOK;
 		} else {
-			menu_item[i].text = StrDuplicate(L"Enroll MOK");
-			menu_item[i].colour = EFI_WHITE;
-			menu_item[i].data = MokNew;
-			menu_item[i].data2 = (void *)MokNewSize;
-			menu_item[i].callback = mok_enrollment_prompt_callback;
+			menu_strings[i] = StrDuplicate(L"Enroll MOK");
+			menu_item[i] = MOK_ENROLL_MOK;
 		}
 		i++;
 	}
 
-	if (MokDel || MokDelAuth) {
-		menu_item[i].text = StrDuplicate(L"Delete MOK");
-		menu_item[i].colour = EFI_WHITE;
-		menu_item[i].data = MokDel;
-		menu_item[i].data2 = (void *)MokDelSize;
-		menu_item[i].callback = mok_deletion_prompt;
+	if (MokDel || MokDelAuth) {		
+		menu_strings[i] = StrDuplicate(L"Delete MOK");
+		menu_item[i] = MOK_DELETE_MOK;
 		i++;
 	}
 
 	if (MokSB) {
-		menu_item[i].text = StrDuplicate(L"Change Secure Boot state");
-		menu_item[i].colour = EFI_WHITE;
-		menu_item[i].callback = mok_sb_prompt;
-		menu_item[i].data = MokSB;
-		menu_item[i].data2 = (void *)MokSBSize;
+		menu_strings[i] = StrDuplicate(L"Change Secure Boot state");
+		menu_item[i] = MOK_CHANGE_SB;
 		i++;
 	}
 
 	if (MokPW) {
-		menu_item[i].text = StrDuplicate(L"Set MOK password");
-		menu_item[i].colour = EFI_WHITE;
-		menu_item[i].callback = mok_pw_prompt;
-		menu_item[i].data = MokPW;
-		menu_item[i].data2 = (void *)MokPWSize;
+		menu_strings[i] = StrDuplicate(L"Set MOK password");
+		menu_item[i] = MOK_SET_PW;
 		i++;
 	}
 
-	menu_item[i].text = StrDuplicate(L"Enroll key from disk");
-	menu_item[i].colour = EFI_WHITE;
-	menu_item[i].callback = find_fs;
-	menu_item[i].data3 = (void *)FALSE;
+	menu_strings[i] = StrDuplicate(L"Enroll key from disk");
+	menu_item[i] = MOK_KEY_ENROLL;
+	i++;
 
+	menu_strings[i] = StrDuplicate(L"Enroll hash from disk");
+	menu_item[i] = MOK_HASH_ENROLL;
 	i++;
 
-	menu_item[i].text = StrDuplicate(L"Enroll hash from disk");
-	menu_item[i].colour = EFI_WHITE;
-	menu_item[i].callback = find_fs;
-	menu_item[i].data3 = (void *)TRUE;
+	menu_strings[i] = NULL;
 
-	i++;
+	while (choice >= 0) {
+		choice = console_select((CHAR16 *[]){ L"Perform MOK management", NULL },
+					menu_strings, 0);
 
-	run_menu(NULL, 0, menu_item, menucount, 10);
+		if (choice < 0)
+			goto out;
 
-	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+		switch (menu_item[choice]) {
+		case MOK_CONTINUE_BOOT:
+			goto out;
+		case MOK_RESET_MOK:
+			mok_reset_prompt();
+			break;
+		case MOK_ENROLL_MOK:
+			mok_enrollment_prompt(MokNew, MokNewSize, TRUE);
+			break;
+		case MOK_DELETE_MOK:
+			mok_deletion_prompt(MokDel, MokDelSize);
+			break;
+		case MOK_CHANGE_SB:
+			mok_sb_prompt(MokSB, MokSBSize);
+			break;
+		case MOK_SET_PW:
+			mok_pw_prompt(MokPW, MokPWSize);
+			break;
+		case MOK_KEY_ENROLL:
+			mok_key_enroll();
+			break;
+		case MOK_HASH_ENROLL:
+			mok_hash_enroll();
+			break;
+		}
+	}
 
-	return 0;
+out:
+	console_reset();
+
+	for (i=0; menu_strings[i] != NULL; i++)
+		FreePool(menu_strings[i]);
+
+	FreePool(menu_strings);
+
+	if (menu_item)
+		FreePool(menu_item);
+
+	return ret;
 }
 
 static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
@@ -1862,28 +1480,28 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 
 	if (MokNew) {
 		if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
-			Print(L"Failed to delete MokNew\n");
+			console_notify(L"Failed to delete MokNew");
 		}
 		FreePool (MokNew);
 	}
 
 	if (MokDel) {
 		if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) {
-			Print(L"Failed to delete MokDel\n");
+			console_notify(L"Failed to delete MokDel");
 		}
 		FreePool (MokDel);
 	}
 
 	if (MokSB) {
 		if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) {
-			Print(L"Failed to delete MokSB\n");
+			console_notify(L"Failed to delete MokSB");
 		}
 		FreePool (MokNew);
 	}
 
 	if (MokPW) {
 		if (LibDeleteVariable(L"MokPW", &shim_lock_guid) != EFI_SUCCESS) {
-			Print(L"Failed to delete MokPW\n");
+			console_notify(L"Failed to delete MokPW");
 		}
 		FreePool (MokNew);
 	}
diff --git a/include/PeImage.h b/include/PeImage.h
new file mode 100644
index 0000000..ec13404
--- /dev/null
+++ b/include/PeImage.h
@@ -0,0 +1,787 @@
+/** @file
+  EFI image format for PE32, PE32+ and TE. Please note some data structures are 
+  different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and 
+  EFI_IMAGE_NT_HEADERS64 is for PE32+. 
+
+  This file is coded to the Visual Studio, Microsoft Portable Executable and 
+  Common Object File Format Specification, Revision 8.0 - May 16, 2006. 
+  This file also includes some definitions in PI Specification, Revision 1.0.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution.  The full text of the license may be found at        
+http://opensource.org/licenses/bsd-license.php.                                           
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+**/
+
+#ifndef __PE_IMAGE_H__
+#define __PE_IMAGE_H__
+
+#include <wincert.h>
+
+#define SIGNATURE_16(A, B)        ((A) | (B << 8))
+#define SIGNATURE_32(A, B, C, D)  (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+	(SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
+
+#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
+#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment))))
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION         10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13 ///< defined PI Specification, 1.0
+
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386            0x014c
+#define IMAGE_FILE_MACHINE_IA64            0x0200
+#define IMAGE_FILE_MACHINE_EBC             0x0EBC
+#define IMAGE_FILE_MACHINE_X64             0x8664
+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED  0x01c2
+
+//
+// EXE file formats
+//
+#define EFI_IMAGE_DOS_SIGNATURE     SIGNATURE_16('M', 'Z')
+#define EFI_IMAGE_OS2_SIGNATURE     SIGNATURE_16('N', 'E')
+#define EFI_IMAGE_OS2_SIGNATURE_LE  SIGNATURE_16('L', 'E')
+#define EFI_IMAGE_NT_SIGNATURE      SIGNATURE_32('P', 'E', '\0', '\0')
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+  UINT16  e_magic;    ///< Magic number.
+  UINT16  e_cblp;     ///< Bytes on last page of file.
+  UINT16  e_cp;       ///< Pages in file.
+  UINT16  e_crlc;     ///< Relocations.
+  UINT16  e_cparhdr;  ///< Size of header in paragraphs.
+  UINT16  e_minalloc; ///< Minimum extra paragraphs needed.
+  UINT16  e_maxalloc; ///< Maximum extra paragraphs needed.
+  UINT16  e_ss;       ///< Initial (relative) SS value.
+  UINT16  e_sp;       ///< Initial SP value.
+  UINT16  e_csum;     ///< Checksum.
+  UINT16  e_ip;       ///< Initial IP value.
+  UINT16  e_cs;       ///< Initial (relative) CS value.
+  UINT16  e_lfarlc;   ///< File address of relocation table.
+  UINT16  e_ovno;     ///< Overlay number.
+  UINT16  e_res[4];   ///< Reserved words.
+  UINT16  e_oemid;    ///< OEM identifier (for e_oeminfo).
+  UINT16  e_oeminfo;  ///< OEM information; e_oemid specific.
+  UINT16  e_res2[10]; ///< Reserved words.
+  UINT32  e_lfanew;   ///< File address of new exe header.
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// COFF File Header (Object and Image).
+///
+typedef struct {
+  UINT16  Machine;
+  UINT16  NumberOfSections;
+  UINT32  TimeDateStamp;
+  UINT32  PointerToSymbolTable;
+  UINT32  NumberOfSymbols;
+  UINT16  SizeOfOptionalHeader;
+  UINT16  Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+///
+/// Size of EFI_IMAGE_FILE_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_FILE_HEADER        20
+
+//
+// Characteristics
+//
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED      (1 << 0)     ///< 0x0001  Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE     (1 << 1)     ///< 0x0002  File is executable  (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED   (1 << 2)     ///< 0x0004  Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED  (1 << 3)     ///< 0x0008  Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO    (1 << 7)     ///< 0x0080  Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE        (1 << 8)     ///< 0x0100  32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED       (1 << 9)     ///< 0x0200  Debugging info stripped from file in .DBG file.
+#define EFI_IMAGE_FILE_SYSTEM               (1 << 12)    ///< 0x1000  System File.
+#define EFI_IMAGE_FILE_DLL                  (1 << 13)    ///< 0x2000  File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI    (1 << 15)    ///< 0x8000  Bytes of machine word are reversed.
+
+///
+/// Header Data Directories.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT      0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT      1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE    2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION   3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY    4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC   5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG       6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT   7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR   8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS         9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and 
+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+          
+///
+/// Optional Header Standard Fields for PE32.
+///
+typedef struct {
+  ///
+  /// Standard fields.
+  ///
+  UINT16                    Magic;
+  UINT8                     MajorLinkerVersion;
+  UINT8                     MinorLinkerVersion;
+  UINT32                    SizeOfCode;
+  UINT32                    SizeOfInitializedData;
+  UINT32                    SizeOfUninitializedData;
+  UINT32                    AddressOfEntryPoint;
+  UINT32                    BaseOfCode;
+  UINT32                    BaseOfData;  ///< PE32 contains this additional field, which is absent in PE32+.
+  ///
+  /// Optional Header Windows-Specific Fields.
+  ///
+  UINT32                    ImageBase;
+  UINT32                    SectionAlignment;
+  UINT32                    FileAlignment;
+  UINT16                    MajorOperatingSystemVersion;
+  UINT16                    MinorOperatingSystemVersion;
+  UINT16                    MajorImageVersion;
+  UINT16                    MinorImageVersion;
+  UINT16                    MajorSubsystemVersion;
+  UINT16                    MinorSubsystemVersion;
+  UINT32                    Win32VersionValue;
+  UINT32                    SizeOfImage;
+  UINT32                    SizeOfHeaders;
+  UINT32                    CheckSum;
+  UINT16                    Subsystem;
+  UINT16                    DllCharacteristics;
+  UINT32                    SizeOfStackReserve;
+  UINT32                    SizeOfStackCommit;
+  UINT32                    SizeOfHeapReserve;
+  UINT32                    SizeOfHeapCommit;
+  UINT32                    LoaderFlags;
+  UINT32                    NumberOfRvaAndSizes;
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and 
+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+///
+/// Optional Header Standard Fields for PE32+.
+///
+typedef struct {
+  ///
+  /// Standard fields.
+  ///
+  UINT16                    Magic;
+  UINT8                     MajorLinkerVersion;
+  UINT8                     MinorLinkerVersion;
+  UINT32                    SizeOfCode;
+  UINT32                    SizeOfInitializedData;
+  UINT32                    SizeOfUninitializedData;
+  UINT32                    AddressOfEntryPoint;
+  UINT32                    BaseOfCode;
+  ///
+  /// Optional Header Windows-Specific Fields.
+  ///
+  UINT64                    ImageBase;
+  UINT32                    SectionAlignment;
+  UINT32                    FileAlignment;
+  UINT16                    MajorOperatingSystemVersion;
+  UINT16                    MinorOperatingSystemVersion;
+  UINT16                    MajorImageVersion;
+  UINT16                    MinorImageVersion;
+  UINT16                    MajorSubsystemVersion;
+  UINT16                    MinorSubsystemVersion;
+  UINT32                    Win32VersionValue;
+  UINT32                    SizeOfImage;
+  UINT32                    SizeOfHeaders;
+  UINT32                    CheckSum;
+  UINT16                    Subsystem;
+  UINT16                    DllCharacteristics;
+  UINT64                    SizeOfStackReserve;
+  UINT64                    SizeOfStackCommit;
+  UINT64                    SizeOfHeapReserve;
+  UINT64                    SizeOfHeapCommit;
+  UINT32                    LoaderFlags;
+  UINT32                    NumberOfRvaAndSizes;
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
+///
+typedef struct {
+  UINT32                      Signature;
+  EFI_IMAGE_FILE_HEADER       FileHeader;
+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+///
+/// @attention
+/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
+///
+typedef struct {
+  UINT32                      Signature;
+  EFI_IMAGE_FILE_HEADER       FileHeader;
+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Other Windows Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN     0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE      1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI     5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI   7
+
+///
+/// Length of ShortName.
+///
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+///
+/// Section Table. This table immediately follows the optional header.
+///
+typedef struct {
+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+  union {
+    UINT32  PhysicalAddress;
+    UINT32  VirtualSize;
+  } Misc;
+  UINT32  VirtualAddress;
+  UINT32  SizeOfRawData;
+  UINT32  PointerToRawData;
+  UINT32  PointerToRelocations;
+  UINT32  PointerToLinenumbers;
+  UINT16  NumberOfRelocations;
+  UINT16  NumberOfLinenumbers;
+  UINT32  Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+///
+/// Size of EFI_IMAGE_SECTION_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER       40
+         
+//
+// Section Flags Values
+//
+#define EFI_IMAGE_SCN_TYPE_NO_PAD                  BIT3   ///< 0x00000008  ///< Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE                     BIT5   ///< 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA         BIT6   ///< 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA       BIT7   ///< 0x00000080
+                                                   
+#define EFI_IMAGE_SCN_LNK_OTHER                    BIT8   ///< 0x00000100  ///< Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO                     BIT9   ///< 0x00000200  ///< Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE                   BIT11  ///< 0x00000800  ///< Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT                   BIT12  ///< 0x00001000
+                                                   
+#define EFI_IMAGE_SCN_ALIGN_1BYTES                 BIT20  ///< 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES                 BIT21  ///< 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES          (BIT20|BIT21) ///< 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES                 BIT22  ///< 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES         (BIT20|BIT22) ///< 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES         (BIT21|BIT22) ///< 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES   (BIT20|BIT21|BIT22) ///< 0x00700000
+                                              
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE              BIT25  ///< 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED               BIT26  ///< 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED                BIT27  ///< 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED                   BIT28  ///< 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE                  BIT29  ///< 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ                     BIT30  ///< 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE                    BIT31  ///< 0x80000000
+
+///
+/// Size of a Symbol Table Record.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0  ///< Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE  (UINT16) -1 ///< Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG     (UINT16) -2 ///< Symbol is a special debug item.
+
+//
+// Symbol Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL   0   ///< no type.
+#define EFI_IMAGE_SYM_TYPE_VOID   1   ///< no valid type.
+#define EFI_IMAGE_SYM_TYPE_CHAR   2   ///< type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT  3   ///< type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT    4
+#define EFI_IMAGE_SYM_TYPE_LONG   5
+#define EFI_IMAGE_SYM_TYPE_FLOAT  6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION  9
+#define EFI_IMAGE_SYM_TYPE_ENUM   10  ///< enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE    11  ///< member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE   12
+#define EFI_IMAGE_SYM_TYPE_WORD   13
+#define EFI_IMAGE_SYM_TYPE_UINT   14
+#define EFI_IMAGE_SYM_TYPE_DWORD  15
+
+//
+// Symbol Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL      0 ///< no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER   1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION  2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY     3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION   ((UINT8) -1)
+#define EFI_IMAGE_SYM_CLASS_NULL              0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC         1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL          2
+#define EFI_IMAGE_SYM_CLASS_STATIC            3
+#define EFI_IMAGE_SYM_CLASS_REGISTER          4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF      5
+#define EFI_IMAGE_SYM_CLASS_LABEL             6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL   7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT  8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT          9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG        10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION   11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG         12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION   13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC  14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG          15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM    16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM    17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD         18
+#define EFI_IMAGE_SYM_CLASS_BLOCK             100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION          101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT     102
+#define EFI_IMAGE_SYM_CLASS_FILE              103
+#define EFI_IMAGE_SYM_CLASS_SECTION           104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL     105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK  017
+#define EFI_IMAGE_N_TMASK   060
+#define EFI_IMAGE_N_TMASK1  0300
+#define EFI_IMAGE_N_TMASK2  0360
+#define EFI_IMAGE_N_BTSHFT  4
+#define EFI_IMAGE_N_TSHIFT  2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES    1
+#define EFI_IMAGE_COMDAT_SELECT_ANY             2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE       3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH     4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE     5
+                                       
+//
+// the following values only be referred in PeCoff, not defined in PECOFF.
+//
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3
+
+///
+/// Relocation format.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  SymbolTableIndex;
+  UINT16  Type;
+} EFI_IMAGE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_RELOCATION
+///
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000  ///< Reference is absolute, no relocation is necessary.
+#define EFI_IMAGE_REL_I386_DIR16    0x0001  ///< Direct 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_REL16    0x0002  ///< PC-relative 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32    0x0006  ///< Direct 32-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32NB  0x0007  ///< Direct 32-bit reference to the symbols virtual address, base not included.
+#define EFI_IMAGE_REL_I386_SEG12    0x0009  ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
+#define EFI_IMAGE_REL_I386_SECTION  0x000A
+#define EFI_IMAGE_REL_I386_SECREL   0x000B
+#define EFI_IMAGE_REL_I386_REL32    0x0014  ///< PC-relative 32-bit reference to the symbols virtual address.
+
+// 
+// x64 processor relocation types.
+// 
+#define IMAGE_REL_AMD64_ABSOLUTE  0x0000
+#define IMAGE_REL_AMD64_ADDR64    0x0001
+#define IMAGE_REL_AMD64_ADDR32    0x0002
+#define IMAGE_REL_AMD64_ADDR32NB  0x0003
+#define IMAGE_REL_AMD64_REL32     0x0004
+#define IMAGE_REL_AMD64_REL32_1   0x0005
+#define IMAGE_REL_AMD64_REL32_2   0x0006
+#define IMAGE_REL_AMD64_REL32_3   0x0007
+#define IMAGE_REL_AMD64_REL32_4   0x0008
+#define IMAGE_REL_AMD64_REL32_5   0x0009
+#define IMAGE_REL_AMD64_SECTION   0x000A
+#define IMAGE_REL_AMD64_SECREL    0x000B
+#define IMAGE_REL_AMD64_SECREL7   0x000C
+#define IMAGE_REL_AMD64_TOKEN     0x000D
+#define IMAGE_REL_AMD64_SREL32    0x000E
+#define IMAGE_REL_AMD64_PAIR      0x000F
+#define IMAGE_REL_AMD64_SSPAN32   0x0010
+
+///
+/// Based relocation format.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_BASE_RELOCATION.
+///
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION  8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE        0
+#define EFI_IMAGE_REL_BASED_HIGH            1
+#define EFI_IMAGE_REL_BASED_LOW             2
+#define EFI_IMAGE_REL_BASED_HIGHLOW         3
+#define EFI_IMAGE_REL_BASED_HIGHADJ         4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR    5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32A      5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32T      7
+#define EFI_IMAGE_REL_BASED_IA64_IMM64      9
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16  9
+#define EFI_IMAGE_REL_BASED_DIR64           10
+
+///
+/// Line number format.
+///
+typedef struct {
+  union {
+    UINT32  SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
+    UINT32  VirtualAddress;   ///< Virtual address of line number.
+  } Type;
+  UINT16  Linenumber;         ///< Line number.
+} EFI_IMAGE_LINENUMBER;
+
+///
+/// Size of EFI_IMAGE_LINENUMBER.
+///
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE        8
+#define EFI_IMAGE_ARCHIVE_START             "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END               "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD               "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER     "/               "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER  "//              "
+
+///
+/// Archive Member Headers
+///
+typedef struct {
+  UINT8 Name[16];     ///< File member name - `/' terminated.
+  UINT8 Date[12];     ///< File member date - decimal.
+  UINT8 UserID[6];    ///< File member user id - decimal.
+  UINT8 GroupID[6];   ///< File member group id - decimal.
+  UINT8 Mode[8];      ///< File member mode - octal.
+  UINT8 Size[10];     ///< File member size - decimal.
+  UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+///
+/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+
+//
+// DLL Support
+//
+
+///
+/// Export Directory Table.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT32  Name;
+  UINT32  Base;
+  UINT32  NumberOfFunctions;
+  UINT32  NumberOfNames;
+  UINT32  AddressOfFunctions;
+  UINT32  AddressOfNames;
+  UINT32  AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// Hint/Name Table.
+///
+typedef struct {
+  UINT16  Hint;
+  UINT8   Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+///
+/// Import Address Table RVA (Thunk Table).
+///
+typedef struct {
+  union {
+    UINT32                    Function;
+    UINT32                    Ordinal;
+    EFI_IMAGE_IMPORT_BY_NAME  *AddressOfData;
+  } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG              BIT31    ///< Flag for PE32.
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal)  ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal)          (Ordinal & 0xffff)
+
+///
+/// Import Directory Table
+///
+typedef struct {
+  UINT32                Characteristics;
+  UINT32                TimeDateStamp;
+  UINT32                ForwarderChain;
+  UINT32                Name;
+  EFI_IMAGE_THUNK_DATA  *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+
+///
+/// Debug Directory Format.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT32  Type;
+  UINT32  SizeOfData;
+  UINT32  RVA;           ///< The address of the debug data when loaded, relative to the image base.
+  UINT32  FileOffset;    ///< The file pointer to the debug data.
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2     ///< The Visual C++ debug information.
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_NB10  SIGNATURE_32('N', 'B', '1', '0')
+typedef struct {
+  UINT32  Signature;                        ///< "NB10"
+  UINT32  Unknown;
+  UINT32  Unknown2;
+  UINT32  Unknown3;
+  //
+  // Filename of .PDB goes here
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_RSDS  SIGNATURE_32('R', 'S', 'D', 'S')
+typedef struct {
+  UINT32  Signature;                        ///< "RSDS".
+  UINT32  Unknown;
+  UINT32  Unknown2;
+  UINT32  Unknown3;
+  UINT32  Unknown4;
+  UINT32  Unknown5;
+  //
+  // Filename of .PDB goes here
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+
+///
+/// Debug Data Structure defined by Apple Mach-O to Coff utility.
+///
+#define CODEVIEW_SIGNATURE_MTOC  SIGNATURE_32('M', 'T', 'O', 'C')
+typedef struct {
+  UINT32    Signature;                       ///< "MTOC".
+  EFI_GUID      MachOUuid;
+  //
+  //  Filename of .DLL (Mach-O with debug info) goes here
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
+
+///
+/// Resource format.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT16  NumberOfNamedEntries;
+  UINT16  NumberOfIdEntries;
+  //
+  // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
+  //
+} EFI_IMAGE_RESOURCE_DIRECTORY;
+
+///
+/// Resource directory entry format.
+///
+typedef struct {
+  union {
+    struct {
+      UINT32  NameOffset:31;
+      UINT32  NameIsString:1;
+    } s;
+    UINT32  Id;
+  } u1;
+  union {
+    UINT32  OffsetToData;
+    struct {
+      UINT32  OffsetToDirectory:31;
+      UINT32  DataIsDirectory:1;
+    } s;
+  } u2;
+} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+///
+/// Resource directory entry for string.
+///
+typedef struct {
+  UINT16  Length;
+  CHAR16  String[1];
+} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
+
+///
+/// Resource directory entry for data array.
+///
+typedef struct {
+  UINT32  OffsetToData;
+  UINT32  Size;
+  UINT32  CodePage;
+  UINT32  Reserved;
+} EFI_IMAGE_RESOURCE_DATA_ENTRY;
+
+///
+/// Header format for TE images, defined in the PI Specification, 1.0.
+///
+typedef struct {
+  UINT16                    Signature;            ///< The signature for TE format = "VZ".
+  UINT16                    Machine;              ///< From the original file header.
+  UINT8                     NumberOfSections;     ///< From the original file header.
+  UINT8                     Subsystem;            ///< From original optional header.
+  UINT16                    StrippedSize;         ///< Number of bytes we removed from the header.
+  UINT32                    AddressOfEntryPoint;  ///< Offset to entry point -- from original optional header.
+  UINT32                    BaseOfCode;           ///< From original image -- required for ITP debug.
+  UINT64                    ImageBase;            ///< From original file header.
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[2];     ///< Only base relocation and debug directory.
+} EFI_TE_IMAGE_HEADER;
+
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE  SIGNATURE_16('V', 'Z')
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1
+
+
+///
+/// Union of PE32, PE32+, and TE headers.
+///
+typedef union {
+  EFI_IMAGE_NT_HEADERS32   Pe32;
+  EFI_IMAGE_NT_HEADERS64   Pe32Plus;
+  EFI_TE_IMAGE_HEADER      Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+typedef union {
+  EFI_IMAGE_NT_HEADERS32            *Pe32;
+  EFI_IMAGE_NT_HEADERS64            *Pe32Plus;
+  EFI_TE_IMAGE_HEADER               *Te;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
+typedef struct {
+	WIN_CERTIFICATE Hdr;
+	UINT8           CertData[1];
+} WIN_CERTIFICATE_EFI_PKCS;
+
+#define SHA256_DIGEST_SIZE  32
+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
+
+typedef struct {
+	UINT64 ImageAddress;
+	UINT64 ImageSize;
+	UINT64 EntryPoint;
+	UINTN SizeOfHeaders;
+	UINT16 ImageType;
+	UINT16 NumberOfSections;
+	EFI_IMAGE_SECTION_HEADER *FirstSection;
+	EFI_IMAGE_DATA_DIRECTORY *RelocDir;
+	EFI_IMAGE_DATA_DIRECTORY *SecDir;
+	UINT64 NumberOfRvaAndSizes;
+	EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
+} PE_COFF_LOADER_IMAGE_CONTEXT;
+
+#endif
diff --git a/include/configtable.h b/include/configtable.h
new file mode 100644
index 0000000..fa2b505
--- /dev/null
+++ b/include/configtable.h
@@ -0,0 +1,68 @@
+/* definitions straight from TianoCore */
+
+typedef UINT32 EFI_IMAGE_EXECUTION_ACTION;
+
+#define EFI_IMAGE_EXECUTION_AUTHENTICATION      0x00000007 
+#define EFI_IMAGE_EXECUTION_AUTH_UNTESTED       0x00000000
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED     0x00000001
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED     0x00000002
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND  0x00000003
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND      0x00000004
+#define EFI_IMAGE_EXECUTION_POLICY_FAILED       0x00000005
+#define EFI_IMAGE_EXECUTION_INITIALIZED         0x00000008
+
+typedef struct {
+  ///
+  /// Describes the action taken by the firmware regarding this image.
+  ///
+  EFI_IMAGE_EXECUTION_ACTION    Action;
+  ///
+  /// Size of all of the entire structure.
+  ///
+  UINT32                        InfoSize;
+  ///
+  /// If this image was a UEFI device driver (for option ROM, for example) this is the 
+  /// null-terminated, user-friendly name for the device. If the image was for an application, 
+  /// then this is the name of the application. If this cannot be determined, then a simple 
+  /// NULL character should be put in this position.
+  /// CHAR16                    Name[];
+  ///
+
+  ///
+  /// For device drivers, this is the device path of the device for which this device driver 
+  /// was intended. In some cases, the driver itself may be stored as part of the system 
+  /// firmware, but this field should record the device's path, not the firmware path. For 
+  /// applications, this is the device path of the application. If this cannot be determined, 
+  /// a simple end-of-path device node should be put in this position.
+  /// EFI_DEVICE_PATH_PROTOCOL  DevicePath;
+  ///
+
+  ///
+  /// Zero or more image signatures. If the image contained no signatures, 
+  /// then this field is empty.
+  ///
+  ///EFI_SIGNATURE_LIST            Signature;
+  UINT8 Data[];
+} EFI_IMAGE_EXECUTION_INFO;
+
+typedef struct {
+  ///
+  /// Number of EFI_IMAGE_EXECUTION_INFO structures.
+  ///
+  UINTN                     NumberOfImages; 
+  ///
+  /// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures.
+  ///
+  EFI_IMAGE_EXECUTION_INFO  InformationInfo[];
+} EFI_IMAGE_EXECUTION_INFO_TABLE;
+
+
+void *
+configtable_get_table(EFI_GUID *guid);
+EFI_IMAGE_EXECUTION_INFO_TABLE *
+configtable_get_image_table(void);
+EFI_IMAGE_EXECUTION_INFO *
+configtable_find_image(const EFI_DEVICE_PATH *DevicePath);
+int
+configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath);
+
diff --git a/include/console.h b/include/console.h
new file mode 100644
index 0000000..7eb8a0b
--- /dev/null
+++ b/include/console.h
@@ -0,0 +1,21 @@
+EFI_INPUT_KEY
+console_get_keystroke(void);
+void
+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines);
+void
+console_print_box(CHAR16 *str_arr[], int highlight);
+int
+console_yes_no(CHAR16 *str_arr[]);
+int
+console_select(CHAR16 *title[], CHAR16* selectors[], int start);
+void
+console_errorbox(CHAR16 *err);
+void
+console_error(CHAR16 *err, EFI_STATUS);
+void
+console_alertbox(CHAR16 **title);
+void
+console_notify(CHAR16 *string);
+void
+console_reset(void);
+#define NOSEL 0x7fffffff
diff --git a/include/efiauthenticated.h b/include/efiauthenticated.h
new file mode 100644
index 0000000..f7d6bcb
--- /dev/null
+++ b/include/efiauthenticated.h
@@ -0,0 +1,222 @@
+#ifndef _INC_EFIAUTHENTICATED_H
+#define _INC_EFIAUTHENTICATED_H
+#include <wincert.h>
+//***********************************************************************
+// Signature Database
+//***********************************************************************
+///
+/// The format of a signature database. 
+///
+#pragma pack(1)
+
+typedef struct {
+  ///
+  /// An identifier which identifies the agent which added the signature to the list.
+  ///
+  EFI_GUID          SignatureOwner;
+  ///
+  /// The format of the signature is defined by the SignatureType.
+  ///
+  UINT8             SignatureData[1];
+} EFI_SIGNATURE_DATA;
+
+typedef struct {
+  ///
+  /// Type of the signature. GUID signature types are defined in below.
+  ///
+  EFI_GUID            SignatureType;
+  ///
+  /// Total size of the signature list, including this header.
+  ///
+  UINT32              SignatureListSize;
+  ///
+  /// Size of the signature header which precedes the array of signatures.
+  ///
+  UINT32              SignatureHeaderSize;
+  ///
+  /// Size of each signature.
+  ///
+  UINT32              SignatureSize; 
+  ///
+  /// Header before the array of signatures. The format of this header is specified 
+  /// by the SignatureType.
+  /// UINT8           SignatureHeader[SignatureHeaderSize];
+  ///
+  /// An array of signatures. Each signature is SignatureSize bytes in length. 
+  /// EFI_SIGNATURE_DATA Signatures[][SignatureSize];
+  ///
+} EFI_SIGNATURE_LIST;
+
+#pragma pack()
+
+//
+// _WIN_CERTIFICATE.wCertificateType
+// 
+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
+#define WIN_CERT_TYPE_EFI_PKCS115      0x0EF0
+#define WIN_CERT_TYPE_EFI_GUID         0x0EF1
+
+#define EFI_CERT_X509_GUID \
+  (EFI_GUID){								\
+    0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} \
+  }
+
+#define EFI_CERT_RSA2048_GUID \
+  (EFI_GUID){								\
+    0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \
+  }
+
+
+#define EFI_CERT_TYPE_PKCS7_GUID \
+  (EFI_GUID){								\
+    0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
+  }
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertType
+/// 
+#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \
+  {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertData
+/// 
+typedef struct {
+  EFI_GUID  HashType;
+  UINT8     PublicKey[256];
+  UINT8     Signature[256];
+} EFI_CERT_BLOCK_RSA_2048_SHA256;
+
+
+///
+/// Certificate which encapsulates a GUID-specific digital signature
+///
+typedef struct {
+  ///
+  /// This is the standard WIN_CERTIFICATE header, where
+  /// wCertificateType is set to WIN_CERT_TYPE_UEFI_GUID. 
+  ///                         
+  WIN_CERTIFICATE   Hdr;
+  ///
+  /// This is the unique id which determines the 
+  /// format of the CertData. .
+  ///
+  EFI_GUID          CertType;
+  /// 
+  /// The following is the certificate data. The format of
+  /// the data is determined by the CertType. 
+  /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
+  /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
+  ///
+  UINT8            CertData[1];
+} WIN_CERTIFICATE_UEFI_GUID;
+
+
+///   
+/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
+///  
+/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
+/// WIN_CERTIFICATE and encapsulate the information needed to  
+/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as  
+/// specified in RFC2437.  
+///  
+typedef struct {     
+  ///
+  /// This is the standard WIN_CERTIFICATE header, where 
+  /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.                       
+  ///
+  WIN_CERTIFICATE Hdr;
+  ///
+  /// This is the hashing algorithm which was performed on the
+  /// UEFI executable when creating the digital signature. 
+  ///
+  EFI_GUID        HashAlgorithm;
+  ///
+  /// The following is the actual digital signature. The   
+  /// size of the signature is the same size as the key 
+  /// (1024-bit key is 128 bytes) and can be determined by 
+  /// subtracting the length of the other parts of this header
+  /// from the total length of the certificate as found in 
+  /// Hdr.dwLength.                               
+  ///
+  /// UINT8 Signature[];
+  ///
+} WIN_CERTIFICATE_EFI_PKCS1_15;
+
+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
+
+///
+/// Attributes of Authenticated Variable
+///
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS              0x00000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS   0x00000020
+#define EFI_VARIABLE_APPEND_WRITE                            0x00000040
+
+///   
+/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
+/// WIN_CERTIFICATE_UEFI_GUID and the CertType
+/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies
+/// authenticated access, then the Data buffer should begin with an
+/// authentication descriptor prior to the data payload and DataSize
+/// should reflect the the data.and descriptor size. The caller
+/// shall digest the Monotonic Count value and the associated data
+/// for the variable update using the SHA-256 1-way hash algorithm.
+/// The ensuing the 32-byte digest will be signed using the private
+/// key associated w/ the public/private 2048-bit RSA key-pair. The
+/// WIN_CERTIFICATE shall be used to describe the signature of the
+/// Variable data *Data. In addition, the signature will also
+/// include the MonotonicCount value to guard against replay attacks.
+///  
+typedef struct {
+  ///
+  /// Included in the signature of        
+  /// AuthInfo.Used to ensure freshness/no
+  /// replay. Incremented during each     
+  /// "Write" access.   
+  ///                  
+  UINT64                      MonotonicCount;
+  ///
+  /// Provides the authorization for the variable 
+  /// access. It is a signature across the        
+  /// variable data and the  Monotonic Count      
+  /// value. Caller uses Private key that is      
+  /// associated with a public key that has been  
+  /// provisioned via the key exchange.           
+  ///
+  WIN_CERTIFICATE_UEFI_GUID   AuthInfo;
+} EFI_VARIABLE_AUTHENTICATION;
+
+///
+/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is 
+/// set, then the Data buffer shall begin with an instance of a complete (and serialized)
+/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new 
+/// variable value and DataSize shall reflect the combined size of the descriptor and the new 
+/// variable value. The authentication descriptor is not part of the variable data and is not 
+/// returned by subsequent calls to GetVariable().
+///
+typedef struct {
+  ///
+  /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and 
+  /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT.
+  ///
+  EFI_TIME                    TimeStamp;
+  /// 
+  /// Only a CertType of  EFI_CERT_TYPE_PKCS7_GUID is accepted.
+  ///
+  WIN_CERTIFICATE_UEFI_GUID   AuthInfo;
+ } EFI_VARIABLE_AUTHENTICATION_2;
+
+///
+/// Size of AuthInfo prior to the data payload.
+///
+#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
+                       (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
+                       sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
+
+#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
+                                  (UINTN) ((EFI_VARIABLE_AUTHENTICATION_2 *) (VarAuth2))->AuthInfo.Hdr.dwLength)
+
+#define OFFSET_OF_AUTHINFO2_CERT_DATA ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
+                                       (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)))
+
+#endif
diff --git a/include/errors.h b/include/errors.h
new file mode 100644
index 0000000..0da4bb5
--- /dev/null
+++ b/include/errors.h
@@ -0,0 +1,9 @@
+#include <efierr.h>
+
+#ifndef EFI_INCOMPATIBLE_VERSION
+#define EFI_INCOMPATIBLE_VERSION	EFIERR(25)
+#endif
+#ifndef EFI_SECURITY_VIOLATION
+#define EFI_SECURITY_VIOLATION		EFIERR(26)
+#endif
+
diff --git a/include/execute.h b/include/execute.h
new file mode 100644
index 0000000..9aecbff
--- /dev/null
+++ b/include/execute.h
@@ -0,0 +1,5 @@
+EFI_STATUS
+generate_path(CHAR16* name, EFI_LOADED_IMAGE *li,
+	      EFI_DEVICE_PATH **path, CHAR16 **PathName);
+EFI_STATUS
+execute(EFI_HANDLE image, CHAR16 *name);
diff --git a/include/guid.h b/include/guid.h
new file mode 100644
index 0000000..10f865a
--- /dev/null
+++ b/include/guid.h
@@ -0,0 +1,18 @@
+#include <efi.h>
+
+#ifndef BUILD_EFI
+const char *guid_to_str(EFI_GUID *guid);
+void str_to_guid(const char *str, EFI_GUID *guid);
+#endif
+
+extern EFI_GUID GV_GUID;
+extern EFI_GUID SIG_DB;
+extern EFI_GUID X509_GUID;
+extern EFI_GUID RSA2048_GUID;
+extern EFI_GUID PKCS7_GUID;
+extern EFI_GUID IMAGE_PROTOCOL;
+extern EFI_GUID SIMPLE_FS_PROTOCOL;
+extern EFI_GUID EFI_CERT_SHA256_GUID;
+extern EFI_GUID MOK_OWNER;
+extern EFI_GUID SECURITY_PROTOCOL_GUID;
+extern EFI_GUID SECURITY2_PROTOCOL_GUID;
diff --git a/include/security_policy.h b/include/security_policy.h
new file mode 100644
index 0000000..a1c1002
--- /dev/null
+++ b/include/security_policy.h
@@ -0,0 +1,6 @@
+EFI_STATUS
+security_policy_install(void);
+EFI_STATUS
+security_policy_uninstall(void);
+void
+security_protocol_set_hashes(unsigned char *esl, int len);
diff --git a/include/shell.h b/include/shell.h
new file mode 100644
index 0000000..9cb5d47
--- /dev/null
+++ b/include/shell.h
@@ -0,0 +1,2 @@
+EFI_STATUS
+argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV);
diff --git a/include/simple_file.h b/include/simple_file.h
new file mode 100644
index 0000000..fe4fd97
--- /dev/null
+++ b/include/simple_file.h
@@ -0,0 +1,21 @@
+EFI_STATUS
+simple_file_open (EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode);
+EFI_STATUS
+simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode);
+EFI_STATUS
+simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer);
+EFI_STATUS
+simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer);
+void
+simple_file_close(EFI_FILE *file);
+EFI_STATUS
+simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **Entries,
+		    int *count);
+EFI_STATUS
+simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
+		  CHAR16 ***result, int *count, EFI_FILE_INFO **entries);
+void
+simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
+		     CHAR16 *filter, CHAR16 **result);
+EFI_STATUS
+simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h);
diff --git a/include/variables.h b/include/variables.h
new file mode 100644
index 0000000..c171bd5
--- /dev/null
+++ b/include/variables.h
@@ -0,0 +1,59 @@
+#include <efiauthenticated.h>
+
+#include <sha256.h>		/* for SHA256_DIGEST_SIZE */
+
+#define certlist_for_each_certentry(cl, cl_init, s, s_init)		\
+	for (cl = (EFI_SIGNATURE_LIST *)(cl_init), s = (s_init);	\
+		s > 0 && s >= cl->SignatureListSize;			\
+		s -= cl->SignatureListSize,				\
+		cl = (EFI_SIGNATURE_LIST *) ((UINT8 *)cl + cl->SignatureListSize))
+
+/*
+ * Warning: this assumes (cl)->SignatureHeaderSize is zero.  It is for all
+ * the signatures we process (X509, RSA2048, SHA256)
+ */
+#define certentry_for_each_cert(c, cl)	\
+  for (c = (EFI_SIGNATURE_DATA *)((UINT8 *) (cl) + sizeof(EFI_SIGNATURE_LIST) + (cl)->SignatureHeaderSize); \
+	(UINT8 *)c < ((UINT8 *)(cl)) + (cl)->SignatureListSize; \
+	c = (EFI_SIGNATURE_DATA *)((UINT8 *)c + (cl)->SignatureSize))
+
+EFI_STATUS
+CreatePkX509SignatureList (
+  IN	UINT8			    *X509Data,
+  IN	UINTN			    X509DataSize,
+  IN	EFI_GUID		    owner,
+  OUT   EFI_SIGNATURE_LIST          **PkCert 
+			   );
+EFI_STATUS
+CreateTimeBasedPayload (
+  IN OUT UINTN            *DataSize,
+  IN OUT UINT8            **Data
+			);
+EFI_STATUS
+SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased);
+EFI_STATUS
+get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner);
+EFI_STATUS
+get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
+		  UINT32 *attributes);
+EFI_STATUS
+find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen);
+EFI_STATUS
+find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen);
+
+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
+
+UINT64
+GetOSIndications(void);
+EFI_STATUS
+SETOSIndicationsAndReboot(UINT64 indications);
+int
+variable_is_secureboot(void);
+int
+variable_is_setupmode(void);
+EFI_STATUS
+variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
+		     UINT8 hash[SHA256_DIGEST_SIZE]);
+EFI_STATUS
+variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
+		    void **out, int *outlen);
diff --git a/include/version.h b/include/version.h
new file mode 100644
index 0000000..09fd44a
--- /dev/null
+++ b/include/version.h
@@ -0,0 +1,8 @@
+#define VERSION "1.3.4"
+
+static void
+version(const char *progname)
+{
+	printf("%s " VERSION "\n", progname);
+}
+
diff --git a/include/wincert.h b/include/wincert.h
new file mode 100644
index 0000000..68d1974
--- /dev/null
+++ b/include/wincert.h
@@ -0,0 +1,33 @@
+#ifndef _INC_WINCERT_H
+#define _INC_WINCERT_H
+
+///
+/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
+///
+typedef struct {
+  ///
+  /// The length of the entire certificate,  
+  /// including the length of the header, in bytes.                                
+  ///
+  UINT32  dwLength;
+  ///
+  /// The revision level of the WIN_CERTIFICATE 
+  /// structure. The current revision level is 0x0200.                                   
+  ///
+  UINT16  wRevision;
+  ///
+  /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI      
+  /// certificate types. The UEFI specification reserves the range of 
+  /// certificate type values from 0x0EF0 to 0x0EFF.                          
+  ///
+  UINT16  wCertificateType;
+  ///
+  /// The following is the actual certificate. The format of   
+  /// the certificate depends on wCertificateType.
+  ///
+  /// UINT8 bCertificate[ANYSIZE_ARRAY];
+  ///
+} WIN_CERTIFICATE;
+
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..be5f354
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,28 @@
+TARGET = lib.a
+
+LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o
+
+ARCH            = $(shell uname -m | sed s,i[3456789]86,ia32,)
+
+EFI_INCLUDE     = /usr/include/efi
+EFI_INCLUDES    = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include
+EFI_PATH        = /usr/lib64/gnuefi
+
+EFI_CRT_OBJS    = $(EFI_PATH)/crt0-efi-$(ARCH).o
+EFI_LDS         = $(EFI_PATH)/elf_$(ARCH)_efi.lds
+
+CFLAGS          = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
+		  -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI $(EFI_INCLUDES)
+ifeq ($(ARCH),x86_64)
+        CFLAGS  += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI
+endif
+
+lib.a: $(LIBFILES)
+	ar rcs lib.a $(LIBFILES)
+
+all: $(TARGET)
+
+clean:
+	rm -f lib.a
+	rm -f $(LIBFILES)
+
diff --git a/lib/configtable.c b/lib/configtable.c
new file mode 100644
index 0000000..735ce8f
--- /dev/null
+++ b/lib/configtable.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2013 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * read some platform configuration tables
+ */
+#include <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <configtable.h>
+
+void *
+configtable_get_table(EFI_GUID *guid)
+{
+	int i;
+
+	for (i = 0; i < ST->NumberOfTableEntries; i++) {
+		EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i];
+
+		if (CompareGuid(guid, &CT->VendorGuid) == 0) {
+			return CT->VendorTable;
+		}
+	}
+	return NULL;
+}
+
+EFI_IMAGE_EXECUTION_INFO_TABLE *
+configtable_get_image_table(void)
+{
+	return configtable_get_table(&SIG_DB);
+}
+
+EFI_IMAGE_EXECUTION_INFO *
+configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
+{
+	EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table();
+
+	if (!t)
+		return NULL;
+
+	int entries = t->NumberOfImages;
+	EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo;
+
+	int i;
+	for (i = 0; i < entries; i++) {
+#ifdef DEBUG_CONFIG
+		Print(L"InfoSize = %d  Action = %d\n", e->InfoSize, e->Action);
+
+		/* print what we have for debugging */
+		UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+		d += 16;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+		d += 16;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+		d += 16;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+		d += 16;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+		d += 16;
+		Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 
+#endif
+		CHAR16 *name = (CHAR16 *)(e->Data);
+		int skip = 0;
+
+		/* There's a bug in a lot of EFI platforms and they forget to
+		 * put the name here.  The only real way of detecting it is to
+		 * look for either a UC16 NULL or ASCII as UC16 */
+		if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) {
+			skip = StrSize(name);
+#ifdef DEBUG_CONFIG
+			Print(L"FOUND NAME %s (%d)\n", name, skip);
+#endif
+		}
+		EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp;
+		if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0
+		    || (((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) {
+			/* Parse error, table corrupt, bail */
+			Print(L"Image Execution Information table corrupt\n");
+			break;
+		}
+
+		UINTN Size;
+		DevicePathInstance(&dpn, &Size);
+#ifdef DEBUG_CONFIG
+		Print(L"Path: %s\n", DevicePathToStr(dp));
+		Print(L"Device Path Size %d\n", Size);
+#endif
+		if (Size > e->InfoSize) {
+			/* parse error; the platform obviously has a 
+			 * corrupted image table; bail */
+			Print(L"Image Execution Information table corrupt\n");
+			break;
+		}
+		
+		if (CompareMem(dp, DevicePath, Size) == 0) {
+#ifdef DEBUG_CONFIG
+			Print(L"***FOUND\n");
+			console_get_keystroke();
+#endif
+			return e;
+		}
+		e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize);
+	}
+
+#ifdef DEBUG_CONFIG
+	Print(L"***NOT FOUND\n");
+	console_get_keystroke();
+#endif
+
+	return NULL;
+}
+
+int
+configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath)
+{
+	EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath);
+
+	/* Image may not be in DB if it gets executed successfully If it is,
+	 * and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image
+	 * isn't authenticated.  If there's no signature, usually
+	 * EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx,
+	 * EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is
+	 * in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/
+
+	if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
+		  || e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) {
+		/* this means the images signing key is in dbx */
+#ifdef DEBUG_CONFIG
+		Print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n");
+#endif
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/lib/console.c b/lib/console.c
new file mode 100644
index 0000000..af01f03
--- /dev/null
+++ b/lib/console.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+#include <efi/efi.h>
+#include <efi/efilib.h>
+
+#include <console.h>
+#include <errors.h>
+
+static int min(int a, int b)
+{
+	if (a < b)
+		return a;
+	return b;
+}
+
+static int
+count_lines(CHAR16 *str_arr[])
+{
+	int i = 0;
+
+	while (str_arr[i])
+		i++;
+	return i;
+}
+
+static void
+SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c)
+{
+	int i;
+
+	for (i = 0; i < n/2; i++) {
+		dst[i] = c;
+	}
+}
+
+EFI_INPUT_KEY
+console_get_keystroke(void)
+{
+	EFI_INPUT_KEY key;
+	UINTN EventIndex;
+
+	uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex);
+	uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key);
+
+	return key;
+}
+
+void
+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines)
+{
+	int i;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
+	UINTN rows, cols;
+	CHAR16 *Line;
+
+	if (lines == 0)
+		return;
+
+	uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
+
+	/* last row on screen is unusable without scrolling, so ignore it */
+	rows--;
+
+	if (size_rows < 0)
+		size_rows = rows + size_rows + 1;
+	if (size_cols < 0)
+		size_cols = cols + size_cols + 1;
+
+	if (start_col < 0)
+		start_col = (cols + start_col + 2)/2;
+	if (start_row < 0)
+		start_row = (rows + start_row + 2)/2;
+	if (start_col < 0)
+		start_col = 0;
+	if (start_row < 0)
+		start_row = 0;
+
+	if (start_col > cols || start_row > rows) {
+		Print(L"Starting Position (%d,%d) is off screen\n",
+		      start_col, start_row);
+		return;
+	}
+	if (size_cols + start_col > cols)
+		size_cols = cols - start_col;
+	if (size_rows + start_row > rows)
+		size_rows = rows - start_row;
+	       
+	if (lines > size_rows - 2)
+		lines = size_rows - 2;
+
+	Line = AllocatePool((size_cols+1)*sizeof(CHAR16));
+	if (!Line) {
+		Print(L"Failed Allocation\n");
+		return;
+	}
+
+	SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
+
+	Line[0] = BOXDRAW_DOWN_RIGHT;
+	Line[size_cols - 1] = BOXDRAW_DOWN_LEFT;
+	Line[size_cols] = L'\0';
+	uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row);
+	uefi_call_wrapper(co->OutputString, 2, co, Line);
+
+	int start;
+	if (offset == 0)
+		/* middle */
+		start = (size_rows - lines)/2 + start_row + offset;
+	else if (offset < 0)
+		/* from bottom */
+		start = start_row + size_rows - lines + offset - 1;
+	else
+		/* from top */
+		start = start_row + offset;
+		
+
+	for (i = start_row + 1; i < size_rows + start_row - 1; i++) {
+		int line = i - start;
+
+		SetMem16 (Line, size_cols*2, L' ');
+		Line[0] = BOXDRAW_VERTICAL;
+		Line[size_cols - 1] = BOXDRAW_VERTICAL;
+		Line[size_cols] = L'\0';
+		if (line >= 0 && line < lines) {
+			CHAR16 *s = str_arr[line];
+			int len = StrLen(s);
+			int col = (size_cols - 2 - len)/2;
+
+			if (col < 0)
+				col = 0;
+
+			CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2);
+		}
+		if (line >= 0 && line == highlight) 
+			uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+		uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
+		uefi_call_wrapper(co->OutputString, 2, co, Line);
+		if (line >= 0 && line == highlight) 
+			uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
+
+	}
+	SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
+	Line[0] = BOXDRAW_UP_RIGHT;
+	Line[size_cols - 1] = BOXDRAW_UP_LEFT;
+	Line[size_cols] = L'\0';
+	uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
+	uefi_call_wrapper(co->OutputString, 2, co, Line);
+
+	FreePool (Line);
+
+}
+
+void
+console_print_box(CHAR16 *str_arr[], int highlight)
+{
+	SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
+	CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode));
+	uefi_call_wrapper(co->EnableCursor, 2, co, FALSE);
+	uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
+
+	console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0,
+			     count_lines(str_arr));
+
+	console_get_keystroke();
+
+	uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
+
+	uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
+	uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);
+	uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute);
+}
+
+int
+console_select(CHAR16 *title[], CHAR16* selectors[], int start)
+{
+	SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
+	EFI_INPUT_KEY k;
+	int selector;
+	int selector_lines = count_lines(selectors);
+	int selector_max_cols = 0;
+	int i, offs_col, offs_row, size_cols, size_rows, lines;
+	int selector_offset;
+	UINTN cols, rows;
+
+	uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
+
+	for (i = 0; i < selector_lines; i++) {
+		int len = StrLen(selectors[i]);
+
+		if (len > selector_max_cols)
+			selector_max_cols = len;
+	}
+
+	if (start < 0)
+		start = 0;
+	if (start >= selector_lines)
+		start = selector_lines - 1;
+
+	offs_col = - selector_max_cols - 4;
+	size_cols = selector_max_cols + 4;
+
+	if (selector_lines > rows - 10) {
+		int title_lines = count_lines(title);
+		offs_row =  title_lines + 1;
+		size_rows = rows - 3 - title_lines;
+		lines = size_rows - 2;
+	} else {
+		offs_row = - selector_lines - 4;
+		size_rows = selector_lines + 2;
+		lines = selector_lines;
+	}
+
+	if (start > lines) {
+		selector = lines;
+		selector_offset = start - lines;
+	} else {
+		selector = start;
+		selector_offset = 0;
+	}
+
+	CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode));
+	uefi_call_wrapper(co->EnableCursor, 2, co, FALSE);
+	uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
+
+	console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title));
+
+	console_print_box_at(selectors, selector, offs_col, offs_row,
+			     size_cols, size_rows, 0, lines);
+
+	do {
+		k = console_get_keystroke();
+
+		if (k.ScanCode == SCAN_ESC) {
+			selector = -1;
+			break;
+		}
+
+		if (k.ScanCode == SCAN_UP) {
+			if (selector > 0)
+				selector--;
+			else if (selector_offset > 0)
+				selector_offset--;
+		} else if (k.ScanCode == SCAN_DOWN) {
+			if (selector < lines - 1)
+				selector++;
+			else if (selector_offset < (selector_lines - lines))
+				selector_offset++;
+		}
+
+		console_print_box_at(&selectors[selector_offset], selector,
+				     offs_col, offs_row,
+				     size_cols, size_rows, 0, lines);
+	} while (!(k.ScanCode == SCAN_NULL
+		   && k.UnicodeChar == CHAR_CARRIAGE_RETURN));
+
+	uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
+
+	uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
+	uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);
+	uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute);
+
+	if (selector < 0)
+		/* ESC pressed */
+		return selector;
+	return selector + selector_offset;
+}
+
+
+int
+console_yes_no(CHAR16 *str_arr[])
+{
+	return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0);
+}
+
+void
+console_alertbox(CHAR16 **title)
+{
+	console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0);
+}
+
+void
+console_errorbox(CHAR16 *err)
+{
+	CHAR16 **err_arr = (CHAR16 *[]){
+		L"ERROR",
+		L"",
+		0,
+		0,
+	};
+
+	err_arr[2] = err;
+
+	console_alertbox(err_arr);
+}
+
+void
+console_notify(CHAR16 *string)
+{
+	CHAR16 **str_arr = (CHAR16 *[]){
+		0,
+		0,
+	};
+
+	str_arr[0] = string;
+
+	console_alertbox(str_arr);
+}
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+/* Copy of gnu-efi-3.0 with the added secure boot strings */
+static struct {
+    EFI_STATUS      Code;
+    WCHAR	    *Desc;
+} error_table[] = {
+	{  EFI_SUCCESS,                L"Success"},
+	{  EFI_LOAD_ERROR,             L"Load Error"},
+	{  EFI_INVALID_PARAMETER,      L"Invalid Parameter"},
+	{  EFI_UNSUPPORTED,            L"Unsupported"},
+	{  EFI_BAD_BUFFER_SIZE,        L"Bad Buffer Size"},
+	{  EFI_BUFFER_TOO_SMALL,       L"Buffer Too Small"},
+	{  EFI_NOT_READY,              L"Not Ready"},
+	{  EFI_DEVICE_ERROR,           L"Device Error"},
+	{  EFI_WRITE_PROTECTED,        L"Write Protected"},
+	{  EFI_OUT_OF_RESOURCES,       L"Out of Resources"},
+	{  EFI_VOLUME_CORRUPTED,       L"Volume Corrupt"},
+	{  EFI_VOLUME_FULL,            L"Volume Full"},
+	{  EFI_NO_MEDIA,               L"No Media"},
+	{  EFI_MEDIA_CHANGED,          L"Media changed"},
+	{  EFI_NOT_FOUND,              L"Not Found"},
+	{  EFI_ACCESS_DENIED,          L"Access Denied"},
+	{  EFI_NO_RESPONSE,            L"No Response"},
+	{  EFI_NO_MAPPING,             L"No mapping"},
+	{  EFI_TIMEOUT,                L"Time out"},
+	{  EFI_NOT_STARTED,            L"Not started"},
+	{  EFI_ALREADY_STARTED,        L"Already started"},
+	{  EFI_ABORTED,                L"Aborted"},
+	{  EFI_ICMP_ERROR,             L"ICMP Error"},
+	{  EFI_TFTP_ERROR,             L"TFTP Error"},
+	{  EFI_PROTOCOL_ERROR,         L"Protocol Error"},
+	{  EFI_INCOMPATIBLE_VERSION,   L"Incompatible Version"},
+	{  EFI_SECURITY_VIOLATION,     L"Security Violation"},
+
+	// warnings
+	{  EFI_WARN_UNKOWN_GLYPH,      L"Warning Unknown Glyph"},
+	{  EFI_WARN_DELETE_FAILURE,    L"Warning Delete Failure"},
+	{  EFI_WARN_WRITE_FAILURE,     L"Warning Write Failure"},
+	{  EFI_WARN_BUFFER_TOO_SMALL,  L"Warning Buffer Too Small"},
+	{  0, NULL}
+} ;
+
+
+static CHAR16 *
+err_string (
+    IN EFI_STATUS       Status
+    )
+{
+	UINTN           Index;
+
+	for (Index = 0; error_table[Index].Desc; Index +=1) {
+		if (error_table[Index].Code == Status) {
+			return error_table[Index].Desc;
+		}
+	}
+
+	return L"";
+}
+	
+
+void
+console_error(CHAR16 *err, EFI_STATUS status)
+{
+	CHAR16 **err_arr = (CHAR16 *[]){
+		L"ERROR",
+		L"",
+		0,
+		0,
+	};
+	CHAR16 str[512];
+
+	SPrint(str, sizeof(str), L"%s: (%d) %s", err, status, err_string(status));
+
+	err_arr[2] = str;
+
+	console_alertbox(err_arr);
+}
+
+void
+console_reset(void)
+{
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
+
+	uefi_call_wrapper(co->Reset, 2, co, TRUE);
+	/* set mode 0 - required to be 80x25 */
+	uefi_call_wrapper(co->SetMode, 2, co, 0);
+	uefi_call_wrapper(co->ClearScreen, 1, co);
+}
diff --git a/lib/execute.c b/lib/execute.c
new file mode 100644
index 0000000..8d726eb
--- /dev/null
+++ b/lib/execute.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * --
+ *
+ * generate_path is a cut and paste from
+ *  
+ *   git://github.com/mjg59/shim.git
+ *
+ * Code Copyright 2012 Red Hat, Inc <mjg@redhat.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <execute.h>
+
+EFI_STATUS
+generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName)
+{
+	unsigned int pathlen;
+	EFI_STATUS efi_status = EFI_SUCCESS;
+	CHAR16 *devpathstr = DevicePathToStr(li->FilePath),
+		*found = NULL;
+	int i;
+
+	for (i = 0; i < StrLen(devpathstr); i++) {
+		if (devpathstr[i] == '/')
+			devpathstr[i] = '\\';
+		if (devpathstr[i] == '\\')
+			found = &devpathstr[i];
+	}
+	if (!found) {
+		pathlen = 0;
+	} else {
+		while (*(found - 1) == '\\')
+			--found;
+		*found = '\0';
+		pathlen = StrLen(devpathstr);
+	}
+
+	if (name[0] != '\\')
+		pathlen++;
+
+	*PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16));
+
+	if (!*PathName) {
+		Print(L"Failed to allocate path buffer\n");
+		efi_status = EFI_OUT_OF_RESOURCES;
+		goto error;
+	}
+
+	StrCpy(*PathName, devpathstr);
+
+	if (name[0] != '\\')
+		StrCat(*PathName, L"\\");
+	StrCat(*PathName, name);
+	
+	*path = FileDevicePath(li->DeviceHandle, *PathName);
+
+error:
+	FreePool(devpathstr);
+
+	return efi_status;
+}
+
+EFI_STATUS
+execute(EFI_HANDLE image, CHAR16 *name)
+{
+	EFI_STATUS status;
+	EFI_HANDLE h;
+	EFI_LOADED_IMAGE *li;
+	EFI_DEVICE_PATH *devpath;
+	CHAR16 *PathName;
+
+	status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
+				   &IMAGE_PROTOCOL, &li);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	
+	status = generate_path(name, li, &devpath, &PathName);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image,
+				   devpath, NULL, 0, &h);
+	if (status != EFI_SUCCESS)
+		goto out;
+	
+	status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL);
+	uefi_call_wrapper(BS->UnloadImage, 1, h);
+
+ out:
+	FreePool(PathName);
+	FreePool(devpath);
+	return status;
+}
diff --git a/lib/guid.c b/lib/guid.c
new file mode 100644
index 0000000..25db91a
--- /dev/null
+++ b/lib/guid.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include <guid.h>
+#include <stdio.h>
+
+#ifndef BUILD_EFI
+/* EFI has %g for this, so it's only needed in platform c */
+const char *guid_to_str(EFI_GUID *guid)
+{
+	static char str[256];
+
+	sprintf(str, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+		guid->Data1, guid->Data2, guid->Data3,
+		guid->Data4[0], guid->Data4[1], guid->Data4[2],
+		guid->Data4[3], guid->Data4[4], guid->Data4[5],
+		guid->Data4[6], guid->Data4[7]);
+
+	return str;
+}
+
+void str_to_guid(const char *str, EFI_GUID *guid)
+{
+  sscanf(str, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+	       &guid->Data1, &guid->Data2, &guid->Data3,
+	       guid->Data4, guid->Data4 + 1, guid->Data4 + 2,
+	       guid->Data4 + 3, guid->Data4 + 4, guid->Data4 + 5,
+	       guid->Data4 + 6, guid->Data4 + 7);
+}
+#endif
+
+/* all the necessary guids */
+EFI_GUID GV_GUID = EFI_GLOBAL_VARIABLE;
+EFI_GUID SIG_DB = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0,  0xe, 0x67, 0x65, 0x6f }};
+
+EFI_GUID X509_GUID =   { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} };
+EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} };
+EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} };
+EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
+EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
+EFI_GUID EFI_CERT_SHA256_GUID  = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } };
+EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
+EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } };
+EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
diff --git a/lib/security_policy.c b/lib/security_policy.c
new file mode 100644
index 0000000..e7becbf
--- /dev/null
+++ b/lib/security_policy.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * Install and remove a platform security2 override policy
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <sha256.h>
+#include <variables.h>
+#include <simple_file.h>
+#include <errors.h>
+
+#include <security_policy.h>
+
+/*
+ * See the UEFI Platform Initialization manual (Vol2: DXE) for this
+ */
+struct _EFI_SECURITY2_PROTOCOL;
+struct _EFI_SECURITY_PROTOCOL;
+typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
+typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
+typedef EFI_DEVICE_PATH EFI_DEVICE_PATH_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
+			const EFI_SECURITY_PROTOCOL *This,
+			UINT32 AuthenticationStatus,
+			const EFI_DEVICE_PATH_PROTOCOL *File
+								     );
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
+			const EFI_SECURITY2_PROTOCOL *This,
+			const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+			VOID *FileBuffer,
+			UINTN FileSize,
+			BOOLEAN	BootPolicy
+								     );
+
+struct _EFI_SECURITY2_PROTOCOL {
+	EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
+};
+
+struct _EFI_SECURITY_PROTOCOL {
+	EFI_SECURITY_FILE_AUTHENTICATION_STATE  FileAuthenticationState;
+};
+
+
+static UINT8 *security_policy_esl = NULL;
+static UINTN security_policy_esl_len;
+
+static EFI_STATUS
+security_policy_check_mok(void *data, UINTN len)
+{
+	EFI_STATUS status;
+	UINT8 hash[SHA256_DIGEST_SIZE];
+	UINT32 attr;
+	UINT8 *VarData;
+	UINTN VarLen;
+
+	/* first check is MokSBState.  If we're in insecure mode, boot
+	 * anyway regardless of dbx contents */
+	status = get_variable_attr(L"MokSBState", &VarData, &VarLen,
+				   MOK_OWNER, &attr);
+	if (status == EFI_SUCCESS) {
+		UINT8 MokSBState = VarData[0];
+
+		FreePool(VarData);
+		if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0
+		    && MokSBState)
+			return EFI_SUCCESS;
+	}
+
+	status = sha256_get_pecoff_digest_mem(data, len, hash);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE)
+	    == EFI_SUCCESS)
+		/* MOK list cannot override dbx */
+		return EFI_SECURITY_VIOLATION;
+
+	status = get_variable_attr(L"MokList", &VarData, &VarLen, MOK_OWNER,
+				   &attr);
+	if (status != EFI_SUCCESS)
+		goto check_tmplist;
+
+	FreePool(VarData);
+
+	if (attr & EFI_VARIABLE_RUNTIME_ACCESS)
+		goto check_tmplist;
+
+	if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS)
+		return EFI_SUCCESS;
+
+ check_tmplist:
+	if (security_policy_esl
+	    && find_in_esl(security_policy_esl, security_policy_esl_len, hash,
+			   SHA256_DIGEST_SIZE) == EFI_SUCCESS)
+		return EFI_SUCCESS;
+
+	return EFI_SECURITY_VIOLATION;
+}
+
+static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL;
+static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL;
+
+static EFI_STATUS thunk_security_policy_authentication(
+	const EFI_SECURITY_PROTOCOL *This,
+	UINT32 AuthenticationStatus,
+	const EFI_DEVICE_PATH_PROTOCOL *DevicePath
+						       ) 
+__attribute__((unused));
+
+static EFI_STATUS thunk_security2_policy_authentication(
+	const EFI_SECURITY2_PROTOCOL *This,
+	const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+	VOID *FileBuffer,
+	UINTN FileSize,
+	BOOLEAN	BootPolicy
+						       ) 
+__attribute__((unused));
+
+static __attribute__((used)) EFI_STATUS
+security2_policy_authentication (
+	const EFI_SECURITY2_PROTOCOL *This,
+	const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+	VOID *FileBuffer,
+	UINTN FileSize,
+	BOOLEAN	BootPolicy
+				 )
+{
+	EFI_STATUS status, auth;
+
+	/* Chain original security policy */
+
+	status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer,
+				   FileSize, BootPolicy);
+
+	/* if OK, don't bother with MOK check */
+	if (status == EFI_SUCCESS)
+		return status;
+
+	auth = security_policy_check_mok(FileBuffer, FileSize);
+
+	if (auth == EFI_SECURITY_VIOLATION || auth == EFI_ACCESS_DENIED)
+		/* return previous status, which is the correct one
+		 * for the platform: may be either EFI_ACCESS_DENIED
+		 * or EFI_SECURITY_VIOLATION */
+		return status;
+
+	return auth;
+}
+
+static __attribute__((used)) EFI_STATUS
+security_policy_authentication (
+	const EFI_SECURITY_PROTOCOL *This,
+	UINT32 AuthenticationStatus,
+	const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
+	)
+{
+	EFI_STATUS status, fail_status;
+	EFI_DEVICE_PATH *DevPath 
+		= DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst),
+		*OrigDevPath = DevPath;
+	EFI_HANDLE h;
+	EFI_FILE *f;
+	VOID *FileBuffer;
+	UINTN FileSize;
+	CHAR16* DevPathStr;
+
+	/* Chain original security policy */
+	status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus,
+				   DevicePathConst);
+
+	/* if OK avoid checking MOK: It's a bit expensive to
+	 * read the whole file in again (esfas already did this) */
+	if (status == EFI_SUCCESS)
+		goto out;
+
+	/* capture failure status: may be either EFI_ACCESS_DENIED or
+	 * EFI_SECURITY_VIOLATION */
+	fail_status = status;
+
+	status = uefi_call_wrapper(BS->LocateDevicePath, 3,
+				   &SIMPLE_FS_PROTOCOL, &DevPath, &h);
+	if (status != EFI_SUCCESS)
+		goto out;
+
+	DevPathStr = DevicePathToStr(DevPath);
+
+	status = simple_file_open_by_handle(h, DevPathStr, &f,
+					    EFI_FILE_MODE_READ);
+	FreePool(DevPathStr);
+	if (status != EFI_SUCCESS)
+		goto out;
+
+	status = simple_file_read_all(f, &FileSize, &FileBuffer);
+	simple_file_close(f);
+	if (status != EFI_SUCCESS)
+		goto out;
+
+	status = security_policy_check_mok(FileBuffer, FileSize);
+	FreePool(FileBuffer);
+
+	if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION)
+		/* return what the platform originally said */
+		status = fail_status;
+ out:
+	FreePool(OrigDevPath);
+	return status;
+}
+
+
+/* Nasty: ELF and EFI have different calling conventions.  Here is the map for
+ * calling ELF -> EFI
+ *
+ *   1) rdi -> rcx (32 saved)
+ *   2) rsi -> rdx (32 saved)
+ *   3) rdx -> r8 ( 32 saved)
+ *   4) rcx -> r9 (32 saved)
+ *   5) r8 -> 32(%rsp) (48 saved)
+ *   6) r9 -> 40(%rsp) (48 saved)
+ *   7) pad+0(%rsp) -> 48(%rsp) (64 saved)
+ *   8) pad+8(%rsp) -> 56(%rsp) (64 saved)
+ *   9) pad+16(%rsp) -> 64(%rsp) (80 saved)
+ *  10) pad+24(%rsp) -> 72(%rsp) (80 saved)
+ *  11) pad+32(%rsp) -> 80(%rsp) (96 saved)
+
+ *
+ * So for a five argument callback, the map is ignore the first two arguments
+ * and then map (EFI -> ELF) assuming pad = 0.
+ *
+ * ARG4  -> ARG1
+ * ARG3  -> ARG2
+ * ARG5  -> ARG3
+ * ARG6  -> ARG4
+ * ARG11 -> ARG5
+ *
+ * Calling conventions also differ over volatile and preserved registers in
+ * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile .
+ * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling
+ * function and the called function is required to preserve their values.
+ *
+ * This means when accepting a function callback from MS -> ELF, we have to do
+ * separate preservation on %rdi, %rsi before swizzling the arguments and
+ * handing off to the ELF function.
+ */
+
+asm (
+".type security2_policy_authentication,@function\n"
+"thunk_security2_policy_authentication:\n\t"
+	"mov	0x28(%rsp), %r10	# ARG5\n\t"
+	"push	%rdi\n\t"
+	"push	%rsi\n\t"
+	"mov	%r10, %rdi\n\t"
+	"subq	$8, %rsp	# space for storing stack pad\n\t"
+	"mov	$0x08, %rax\n\t"
+	"mov	$0x10, %r10\n\t"
+	"and	%rsp, %rax\n\t"
+	"cmovnz	%rax, %r11\n\t"
+	"cmovz	%r10, %r11\n\t"
+	"subq	%r11, %rsp\n\t"
+	"addq	$8, %r11\n\t"
+	"mov	%r11, (%rsp)\n\t"
+"# five argument swizzle\n\t"
+	"mov	%rdi, %r10\n\t"
+	"mov	%rcx, %rdi\n\t"
+	"mov	%rdx, %rsi\n\t"
+	"mov	%r8, %rdx\n\t"
+	"mov	%r9, %rcx\n\t"
+	"mov	%r10, %r8\n\t"
+	"callq	security2_policy_authentication@PLT\n\t"
+	"mov	(%rsp), %r11\n\t"
+	"addq	%r11, %rsp\n\t"
+	"pop	%rsi\n\t"
+	"pop	%rdi\n\t"
+	"ret\n"
+);
+
+asm (
+".type security_policy_authentication,@function\n"
+"thunk_security_policy_authentication:\n\t"
+	"push	%rdi\n\t"
+	"push	%rsi\n\t"
+	"subq	$8, %rsp	# space for storing stack pad\n\t"
+	"mov	$0x08, %rax\n\t"
+	"mov	$0x10, %r10\n\t"
+	"and	%rsp, %rax\n\t"
+	"cmovnz	%rax, %r11\n\t"
+	"cmovz	%r10, %r11\n\t"
+	"subq	%r11, %rsp\n\t"
+	"addq	$8, %r11\n\t"
+	"mov	%r11, (%rsp)\n\t"
+"# three argument swizzle\n\t"
+	"mov	%rcx, %rdi\n\t"
+	"mov	%rdx, %rsi\n\t"
+	"mov	%r8, %rdx\n\t"
+	"callq	security_policy_authentication@PLT\n\t"
+	"mov	(%rsp), %r11\n\t"
+	"addq	%r11, %rsp\n\t"
+	"pop	%rsi\n\t"
+	"pop	%rdi\n\t"
+	"ret\n"
+);
+
+EFI_STATUS
+security_policy_install(void)
+{
+	EFI_SECURITY_PROTOCOL *security_protocol;
+	EFI_SECURITY2_PROTOCOL *security2_protocol = NULL;
+	EFI_STATUS status;
+
+	if (esfas)
+		/* Already Installed */
+		return EFI_ALREADY_STARTED;
+
+	/* Don't bother with status here.  The call is allowed
+	 * to fail, since SECURITY2 was introduced in PI 1.2.1
+	 * If it fails, use security2_protocol == NULL as indicator */
+	uefi_call_wrapper(BS->LocateProtocol, 3,
+			  &SECURITY2_PROTOCOL_GUID, NULL,
+			  &security2_protocol);
+
+	status = uefi_call_wrapper(BS->LocateProtocol, 3,
+					   &SECURITY_PROTOCOL_GUID, NULL,
+					   &security_protocol);
+	if (status != EFI_SUCCESS)
+		/* This one is mandatory, so there's a serious problem */
+		return status;
+
+	if (security2_protocol) {
+		es2fa = security2_protocol->FileAuthentication;
+		security2_protocol->FileAuthentication = 
+			thunk_security2_policy_authentication;
+	}
+
+	esfas = security_protocol->FileAuthenticationState;
+	security_protocol->FileAuthenticationState =
+		thunk_security_policy_authentication;
+
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS
+security_policy_uninstall(void)
+{
+	EFI_STATUS status;
+
+	if (esfas) {
+		EFI_SECURITY_PROTOCOL *security_protocol;
+
+		status = uefi_call_wrapper(BS->LocateProtocol, 3,
+					   &SECURITY_PROTOCOL_GUID, NULL,
+					   &security_protocol);
+
+		if (status != EFI_SUCCESS)
+			return status;
+
+		security_protocol->FileAuthenticationState = esfas;
+		esfas = NULL;
+	} else {
+		/* nothing installed */
+		return EFI_NOT_STARTED;
+	}
+
+	if (es2fa) {
+		EFI_SECURITY2_PROTOCOL *security2_protocol;
+
+		status = uefi_call_wrapper(BS->LocateProtocol, 3,
+					   &SECURITY2_PROTOCOL_GUID, NULL,
+					   &security2_protocol);
+
+		if (status != EFI_SUCCESS)
+			return status;
+
+		security2_protocol->FileAuthentication = es2fa;
+		es2fa = NULL;
+	}
+
+	return EFI_SUCCESS;
+}
+
+void
+security_protocol_set_hashes(unsigned char *esl, int len)
+{
+	security_policy_esl = esl;
+	security_policy_esl_len = len;
+}
diff --git a/lib/shell.c b/lib/shell.c
new file mode 100644
index 0000000..51de4e0
--- /dev/null
+++ b/lib/shell.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * misc shell helper functions
+ */
+#include <efi.h>
+#include <efilib.h>
+
+#include <shell.h>
+
+EFI_STATUS
+argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV)
+{
+	int i, count = 1;
+	EFI_STATUS status;
+	EFI_LOADED_IMAGE *info;
+	CHAR16 *start;
+
+	*argc = 0;
+
+	status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info);
+	if (EFI_ERROR(status)) {
+		Print(L"Failed to get arguments\n");
+		return status;
+	}
+
+	for (i = 0; i < info->LoadOptionsSize; i += 2) {
+		CHAR16 *c = (CHAR16 *)(info->LoadOptions + i);
+		if (*c == L' ' && *(c+1) != '\0') {
+			(*argc)++;
+		}
+	}
+
+	(*argc)++;		/* we counted spaces, so add one for initial */
+
+	*ARGV = AllocatePool(*argc * sizeof(*ARGV));
+	if (!*ARGV) {
+		return EFI_OUT_OF_RESOURCES;
+	}
+	(*ARGV)[0] = (CHAR16 *)info->LoadOptions;
+	for (i = 0; i < info->LoadOptionsSize; i += 2) {
+		CHAR16 *c = (CHAR16 *)(info->LoadOptions + i);
+		if (*c == L' ') {
+			*c = L'\0';
+			if (*(c + 1) == '\0')
+				/* strip trailing space */
+				break;
+			start = c + 1;
+			(*ARGV)[count++] = start;
+		}
+	}
+
+	return EFI_SUCCESS;
+}
+
diff --git a/lib/simple_file.c b/lib/simple_file.c
new file mode 100644
index 0000000..0e5ecd2
--- /dev/null
+++ b/lib/simple_file.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <console.h>
+#include <simple_file.h>
+#include <efiauthenticated.h>
+#include <execute.h>		/* for generate_path() */
+
+static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
+static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
+static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID;
+static EFI_GUID FS_INFO = EFI_FILE_SYSTEM_INFO_ID;
+
+EFI_STATUS
+simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode)
+{
+	EFI_STATUS efi_status;
+	EFI_FILE_IO_INTERFACE *drive;
+	EFI_FILE *root;
+
+	efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
+				       &SIMPLE_FS_PROTOCOL, &drive);
+
+	if (efi_status != EFI_SUCCESS) {
+		Print(L"Unable to find simple file protocol (%d)\n", efi_status);
+		goto error;
+	}
+
+	efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
+
+	if (efi_status != EFI_SUCCESS) {
+		Print(L"Failed to open drive volume (%d)\n", efi_status);
+		goto error;
+	}
+
+	efi_status = uefi_call_wrapper(root->Open, 5, root, file, name,
+				       mode, 0);
+
+ error:
+	return efi_status;
+}
+
+EFI_STATUS
+simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode)
+{
+	EFI_STATUS efi_status;
+	EFI_HANDLE device;
+	EFI_LOADED_IMAGE *li;
+	EFI_DEVICE_PATH *loadpath = NULL;
+	CHAR16 *PathName = NULL;
+
+	efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
+				       &IMAGE_PROTOCOL, &li);
+
+	if (efi_status != EFI_SUCCESS)
+		return simple_file_open_by_handle(image, name, file, mode);
+
+	efi_status = generate_path(name, li, &loadpath, &PathName);
+
+	if (efi_status != EFI_SUCCESS) {
+		Print(L"Unable to generate load path for %s\n", name);
+		return efi_status;
+	}
+
+	device = li->DeviceHandle;
+
+	efi_status = simple_file_open_by_handle(device, PathName, file, mode);
+
+	FreePool(PathName);
+	FreePool(loadpath);
+
+	return efi_status;
+}
+
+EFI_STATUS
+simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EFI_FILE_INFO **entries,
+		    int *count)
+{
+	EFI_STATUS status;
+	char buf[4096];
+	UINTN size = sizeof(buf);
+	EFI_FILE_INFO *fi = (void *)buf;
+	
+	status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO,
+				   &size, fi);
+	if (status != EFI_SUCCESS) {
+		Print(L"Failed to get file info\n");
+		goto out;
+	}
+	if ((fi->Attribute & EFI_FILE_DIRECTORY) == 0) {
+		Print(L"Not a directory %s\n", name);
+		status = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	size = 0;
+	*count = 0;
+	for (;;) {
+		UINTN len = sizeof(buf);
+		status = uefi_call_wrapper(file->Read, 3, file, &len, buf);
+		if (status != EFI_SUCCESS || len == 0)
+			break;
+		(*count)++;
+		size += len;
+	}
+	uefi_call_wrapper(file->SetPosition, 2, file, 0);
+
+	char *ptr = AllocatePool(size);
+	*entries = (EFI_FILE_INFO *)ptr;
+	if (!*entries)
+		return EFI_OUT_OF_RESOURCES;
+	int i;
+	for (i = 0; i < *count; i++) {
+		int len = size;
+		uefi_call_wrapper(file->Read, 3, file, &len, ptr);
+		ptr += len;
+		size -= len;
+	}
+	status = EFI_SUCCESS;
+ out:
+	simple_file_close(file);
+	if (status != EFI_SUCCESS && *entries) {
+		FreePool(*entries);
+		*entries = NULL;
+	}
+	return status;
+}
+
+EFI_STATUS
+simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries,
+		    int *count)
+{
+	EFI_FILE *file;
+	EFI_STATUS status;
+
+	status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ);
+	if (status != EFI_SUCCESS) {
+		Print(L"failed to open file %s: %d\n", name, status);
+		return status;
+	}
+
+	return simple_dir_read_all_by_handle(image, file, name, entries, count);
+}
+
+EFI_STATUS
+simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
+{
+	EFI_STATUS efi_status;
+	EFI_FILE_INFO *fi;
+	char buf[1024];
+
+	*size = sizeof(buf);
+	fi = (void *)buf;
+	
+
+	efi_status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO,
+				       size, fi);
+	if (efi_status != EFI_SUCCESS) {
+		Print(L"Failed to get file info\n");
+		return efi_status;
+	}
+
+	*size = fi->FileSize;
+
+	*buffer = AllocatePool(*size);
+	if (!*buffer) {
+		Print(L"Failed to allocate buffer of size %d\n", *size);
+		return EFI_OUT_OF_RESOURCES;
+	}
+	efi_status = uefi_call_wrapper(file->Read, 3, file, size, *buffer);
+
+	return efi_status;
+}
+
+
+EFI_STATUS
+simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer)
+{
+	EFI_STATUS efi_status;
+
+	efi_status = uefi_call_wrapper(file->Write, 3, file, &size, buffer);
+
+	return efi_status;
+}
+
+void
+simple_file_close(EFI_FILE *file)
+{
+	uefi_call_wrapper(file->Close, 1, file);
+}
+
+EFI_STATUS
+simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h)
+{
+	UINTN count, i;
+	EFI_HANDLE *vol_handles = NULL;
+	EFI_STATUS status;
+	CHAR16 **entries;
+	int val;
+
+	uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol,
+			  &SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles);
+
+	if (!count || !vol_handles)
+		return EFI_NOT_FOUND;
+
+	entries = AllocatePool(sizeof(CHAR16 *) * (count+1));
+	if (!entries)
+		return EFI_OUT_OF_RESOURCES;
+
+	for (i = 0; i < count; i++) {
+		char buf[4096];
+		UINTN size = sizeof(buf);
+		EFI_FILE_SYSTEM_INFO *fi = (void *)buf;
+		EFI_FILE *root;
+		CHAR16 *name;
+		EFI_FILE_IO_INTERFACE *drive;
+
+		status = uefi_call_wrapper(BS->HandleProtocol, 3,
+					   vol_handles[i],
+					   &SIMPLE_FS_PROTOCOL, &drive);
+		if (status != EFI_SUCCESS || !drive)
+			continue;
+
+		status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
+		if (status != EFI_SUCCESS)
+			continue;
+
+		status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO,
+					   &size, fi);
+		if (status != EFI_SUCCESS)
+			continue;
+
+		name = fi->VolumeLabel;
+		
+		if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0) 
+			name = DevicePathToStr(DevicePathFromHandle(vol_handles[i]));
+
+		entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16));
+		if (!entries[i])
+			break;
+		StrCpy(entries[i], name);
+	}
+	entries[i] = NULL;
+
+	val = console_select(title, entries, 0);
+
+	if (val >= 0) {
+		*selected = AllocatePool((StrLen(entries[val]) + 1) * sizeof(CHAR16));
+		if (*selected) {
+			StrCpy(*selected , entries[val]);
+		}
+		*h = vol_handles[val];
+	} else {
+		*selected = NULL;
+		*h = 0;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (entries[i])
+			FreePool(entries[i]);
+	}
+	FreePool(entries);
+	FreePool(vol_handles);
+
+	
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS
+simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
+		  CHAR16 ***result, int *count, EFI_FILE_INFO **entries)
+{
+	EFI_STATUS status;
+	int tot, offs = StrLen(filter), i, c, filtercount = 1;
+	EFI_FILE_INFO *next;
+	void *ptr;
+	CHAR16 *newfilter = AllocatePool((StrLen(filter) + 1) * sizeof(CHAR16)),
+		**filterarr;
+
+	if (!newfilter)
+		return EFI_OUT_OF_RESOURCES;
+
+	/* just in case efi ever stops writeable strings */
+	StrCpy(newfilter, filter);
+
+	for (i = 0; i < offs; i++) {
+		if (filter[i] == '|')
+			filtercount++;
+	}
+	filterarr = AllocatePool(filtercount * sizeof(void *));
+	if (!filterarr)
+		return EFI_OUT_OF_RESOURCES;
+	c = 0;
+	filterarr[c++] = newfilter;
+	for (i = 0; i < offs; i++) {
+		if (filter[i] == '|') {
+			newfilter[i] = '\0';
+			filterarr[c++] = &newfilter[i+1];
+		}
+	}
+
+	*count = 0;
+
+	status = simple_dir_read_all(image, name, entries, &tot);
+		
+	if (status != EFI_SUCCESS)
+		goto out;
+	ptr = next = *entries;
+
+	for (i = 0; i < tot; i++) {
+		int len = StrLen(next->FileName);
+
+		for (c = 0; c < filtercount; c++) {
+			offs = StrLen(filterarr[c]);
+
+			if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0
+			    || (next->Attribute & EFI_FILE_DIRECTORY)) {
+				(*count)++;
+				break;
+			}
+		}
+		ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
+		next = ptr;
+	}
+	if (*count)
+		*result = AllocatePool(((*count) + 1) * sizeof(void *));
+	else
+		*result = AllocatePool(2 * sizeof(void *));
+
+	*count = 0;
+	ptr = next = *entries;
+
+	for (i = 0; i < tot; i++) {
+		int len = StrLen(next->FileName);
+
+		if (StrCmp(next->FileName, L".") == 0)
+			/* ignore . directory */
+			goto next;
+
+		if (next->Attribute & EFI_FILE_DIRECTORY) {
+				(*result)[(*count)] = next->FileName;
+				(*result)[(*count)][len] = '/';
+				(*result)[(*count)++][len + 1] = '\0';
+				goto next;
+		}
+
+		for (c = 0; c < filtercount; c++) {
+			offs = StrLen(filterarr[c]);
+
+			if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) {
+				(*result)[(*count)++] = next->FileName;
+			} else {
+				continue;
+			}
+			break;
+		}
+
+	next:		
+		if (StrCmp(next->FileName, L"../") == 0) {
+			/* place .. directory first */
+			CHAR16 *tmp = (*result)[(*count) - 1];
+
+			(*result)[(*count) - 1] = (*result)[0];
+			(*result)[0] = tmp;
+		}
+
+		ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
+		next = ptr;
+	}
+	if (*count == 0) {
+		/* no entries at all ... can happen because top level dir has no . or .. */
+		(*result)[(*count)++] = L"./";
+	}
+	(*result)[*count] = NULL;
+	status = EFI_SUCCESS;
+
+ out:
+	if (status != EFI_SUCCESS) {
+		if (*entries)
+			FreePool(*entries);
+		*entries = NULL;
+		if (*result)
+			FreePool(*result);
+		*result = NULL;
+	}
+	return status;
+}
+
+void
+simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
+		     CHAR16 *filter, CHAR16 **result)
+{
+	EFI_STATUS status;
+	CHAR16 **entries;
+	EFI_FILE_INFO *dmp;
+	int count, select, len;
+	CHAR16 *newname, *selected;
+
+	*result = NULL;
+	if (!name)
+		name = L"\\";
+	if (!filter)
+		filter = L"";
+	if (!*im) {
+		EFI_HANDLE h;
+		CHAR16 *volname;
+
+		simple_volume_selector(title, &volname, &h);
+		if (!volname)
+			return;
+		FreePool(volname);
+		*im = h;
+	}
+
+	newname = AllocatePool((StrLen(name) + 1)*sizeof(CHAR16));
+	if (!newname)
+		return;
+
+	StrCpy(newname, name);
+	name = newname;
+
+ redo:
+	status = simple_dir_filter(*im, name, filter, &entries, &count, &dmp);
+
+	if (status != EFI_SUCCESS)
+		goto out_free_name;
+
+	select = console_select(title, entries, 0);
+	if (select < 0)
+		/* ESC key */
+		goto out_free;
+	selected = entries[select];
+	FreePool(entries);
+	entries = NULL;
+	/* note that memory used by selected is valid until dmp is freed */
+	len = StrLen(selected);
+	if (selected[len - 1] == '/') {
+		CHAR16 *newname;
+
+		/* stay where we are */
+		if (StrCmp(selected, L"./") == 0) {
+			FreePool(dmp);
+			goto redo;
+		} else if (StrCmp(selected, L"../") == 0) {
+			int i;
+
+			i = StrLen(name) - 1;
+
+
+			for (i = StrLen(name); i > 0; --i) {
+				if (name[i] == '\\')
+					break;
+			}
+			if (i == 0)
+				i = 1;
+
+			if (StrCmp(name, L"\\") != 0
+			    && StrCmp(&name[i], L"..") != 0) {
+				name[i] = '\0';
+				FreePool(dmp);
+				goto redo;
+			}
+		}
+		newname = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16));
+		if (!newname)
+			goto out_free;
+		StrCpy(newname, name);
+			
+		if (name[StrLen(name) - 1] != '\\')
+			StrCat(newname, L"\\");
+		StrCat(newname, selected);
+		/* remove trailing / */
+		newname[StrLen(newname) - 1] = '\0';
+
+		FreePool(dmp);
+		FreePool(name);
+		name = newname;
+
+		goto redo;
+	}
+	*result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16));
+	if (*result) {
+		StrCpy(*result, name);
+		if (name[StrLen(name) - 1] != '\\')
+			StrCat(*result, L"\\");
+		StrCat(*result, selected);
+	}
+
+ out_free:
+	FreePool(dmp);
+	if (entries)
+		FreePool(entries);
+ out_free_name:
+	FreePool(name);
+}
diff --git a/lib/variables.c b/lib/variables.c
new file mode 100644
index 0000000..9db6480
--- /dev/null
+++ b/lib/variables.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * Portions of this file are a direct cut and paste from Tianocore
+ * (http://tianocore.sf.net)
+ *
+ *  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+ *
+ * Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution.  The full text of the license may be found 
+ * at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ * 
+ */
+#include <efi.h>
+#include <efilib.h>
+
+#include <efiauthenticated.h>
+
+#include <variables.h>
+#include <guid.h>
+#include <console.h>
+#include <sha256.h>
+#include <errors.h>
+
+EFI_STATUS
+variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
+		    void **out, int *outlen)
+{
+	*outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
+
+	*out = AllocateZeroPool(*outlen);
+	if (!*out)
+		return EFI_OUT_OF_RESOURCES;
+
+	EFI_SIGNATURE_LIST *sl = *out;
+
+	sl->SignatureHeaderSize = 0;
+	sl->SignatureType = *type;
+	sl->SignatureSize = cert_len + sizeof(EFI_GUID);
+	sl->SignatureListSize = *outlen;
+
+	EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST);
+
+	if (owner)
+		sd->SignatureOwner = *owner;
+
+	CopyMem(sd->SignatureData, cert, cert_len);
+
+	return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateTimeBasedPayload (
+  IN OUT UINTN            *DataSize,
+  IN OUT UINT8            **Data
+  )
+{
+  EFI_STATUS                       Status;
+  UINT8                            *NewData;
+  UINT8                            *Payload;
+  UINTN                            PayloadSize;
+  EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;
+  UINTN                            DescriptorSize;
+  EFI_TIME                         Time;
+  EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID;
+  
+  if (Data == NULL || DataSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  //
+  // In Setup mode or Custom mode, the variable does not need to be signed but the 
+  // parameters to the SetVariable() call still need to be prepared as authenticated
+  // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
+  // data in it.
+  //
+  Payload     = *Data;
+  PayloadSize = *DataSize;
+  
+  DescriptorSize    = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
+  NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
+  if (NewData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if ((Payload != NULL) && (PayloadSize != 0)) {
+    CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
+  }
+
+  DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
+
+  ZeroMem (&Time, sizeof (EFI_TIME));
+  Status = uefi_call_wrapper(RT->GetTime,2, &Time, NULL);
+  if (EFI_ERROR (Status)) {
+    FreePool(NewData);
+    return Status;
+  }
+  Time.Pad1       = 0;
+  Time.Nanosecond = 0;
+  Time.TimeZone   = 0;
+  Time.Daylight   = 0;
+  Time.Pad2       = 0;
+  CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
+ 
+  DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
+  DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
+  DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+  DescriptorData->AuthInfo.CertType =  efi_cert_type;
+ 
+  /* we're expecting an EFI signature list, so don't free the input since
+   * it might not be in a pool */
+#if 0
+  if (Payload != NULL) {
+    FreePool(Payload);
+  }
+#endif
+  
+  *DataSize = DescriptorSize + PayloadSize;
+  *Data     = NewData;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner,
+		  UINT32 options, int createtimebased)
+{
+	EFI_SIGNATURE_LIST *Cert;
+	UINTN DataSize;
+	EFI_STATUS efi_status;
+
+	/* Microsoft request: Bugs in some UEFI platforms mean that PK or any
+	 * other secure variable can be updated or deleted programmatically,
+	 * so prevent */
+	if (!variable_is_setupmode())
+		return EFI_SECURITY_VIOLATION;
+
+	if (createtimebased) {
+		int ds;
+		efi_status = variable_create_esl(Data, len, &X509_GUID, NULL,
+						 (void **)&Cert, &ds);
+		if (efi_status != EFI_SUCCESS) {
+			Print(L"Failed to create %s certificate %d\n", var, efi_status);
+			return efi_status;
+		}
+
+		DataSize = ds;
+	} else {
+		/* we expect an efi signature list rather than creating it */
+		Cert = (EFI_SIGNATURE_LIST *)Data;
+		DataSize = len;
+	}
+	efi_status = CreateTimeBasedPayload(&DataSize, (UINT8 **)&Cert);
+	if (efi_status != EFI_SUCCESS) {
+		Print(L"Failed to create time based payload %d\n", efi_status);
+		return efi_status;
+	}
+
+	efi_status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner,
+				       EFI_VARIABLE_NON_VOLATILE
+				       | EFI_VARIABLE_RUNTIME_ACCESS 
+				       | EFI_VARIABLE_BOOTSERVICE_ACCESS
+				       | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+				       | options,
+				       DataSize, Cert);
+
+	return efi_status;
+}
+
+UINT64
+GetOSIndications(void)
+{
+	UINT64 indications;
+	UINTN DataSize = sizeof(indications);
+	EFI_STATUS efi_status;
+
+	efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"OsIndicationsSupported", &GV_GUID, NULL, &DataSize, &indications);
+	if (efi_status != EFI_SUCCESS)
+		return 0;
+
+	return indications;
+}
+
+EFI_STATUS
+SETOSIndicationsAndReboot(UINT64 indications)
+{
+	UINTN DataSize = sizeof(indications);
+	EFI_STATUS efi_status;
+
+	efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"OsIndications",
+				       &GV_GUID,
+				       EFI_VARIABLE_NON_VOLATILE
+				       | EFI_VARIABLE_RUNTIME_ACCESS 
+				       | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+				       DataSize, &indications);
+
+	if (efi_status != EFI_SUCCESS)
+		return efi_status;
+
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL);
+	/* does not return */
+
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS
+get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
+		  UINT32 *attributes)
+{
+	EFI_STATUS efi_status;
+
+	*len = 0;
+
+	efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
+				       NULL, len, NULL);
+	if (efi_status != EFI_BUFFER_TOO_SMALL)
+		return efi_status;
+
+	*data = AllocateZeroPool(*len);
+	if (!data)
+		return EFI_OUT_OF_RESOURCES;
+	
+	efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
+				       attributes, len, *data);
+
+	if (efi_status != EFI_SUCCESS) {
+		FreePool(*data);
+		*data = NULL;
+	}
+	return efi_status;
+}
+
+EFI_STATUS
+get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner)
+{
+	return get_variable_attr(var, data, len, owner, NULL);
+}
+
+EFI_STATUS
+find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen)
+{
+	EFI_SIGNATURE_LIST *CertList;
+
+	certlist_for_each_certentry(CertList, Data, DataSize, DataSize) {
+		if (CertList->SignatureSize != keylen + sizeof(EFI_GUID))
+			continue;
+		EFI_SIGNATURE_DATA *Cert;
+
+		certentry_for_each_cert(Cert, CertList)
+			if (CompareMem (Cert->SignatureData, key, keylen) == 0)
+				return EFI_SUCCESS;
+	}
+	return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen)
+{
+	UINTN DataSize;
+	UINT8 *Data;
+	EFI_STATUS status;
+
+	status = get_variable(var, &Data, &DataSize, owner);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = find_in_esl(Data, DataSize, key, keylen);
+
+	FreePool(Data);
+
+	return status;
+}
+
+int
+variable_is_setupmode(void)
+{
+	/* set to 1 because we return true if SetupMode doesn't exist */
+	UINT8 SetupMode = 1;
+	UINTN DataSize = sizeof(SetupMode);
+
+	uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL,
+			  &DataSize, &SetupMode);
+
+	return SetupMode;
+}
+
+int
+variable_is_secureboot(void)
+{
+	/* return false if variable doesn't exist */
+	UINT8 SecureBoot = 0;
+	UINTN DataSize;
+
+	DataSize = sizeof(SecureBoot);
+	uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL,
+			  &DataSize, &SecureBoot);
+
+	return SecureBoot;
+}
+
+EFI_STATUS
+variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
+		     UINT8 hash[SHA256_DIGEST_SIZE])
+{
+	EFI_STATUS status;
+
+	if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE)
+	    == EFI_SUCCESS)
+		/* hash already present */
+		return EFI_ALREADY_STARTED;
+
+	UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE];
+	EFI_SIGNATURE_LIST *l = (void *)sig;
+	EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST);
+	SetMem(sig, 0, sizeof(sig));
+	l->SignatureType = EFI_CERT_SHA256_GUID;
+	l->SignatureListSize = sizeof(sig);
+	l->SignatureSize = 16 +32; /* UEFI defined */
+	CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE);
+	d->SignatureOwner = MOK_OWNER;
+
+	if (CompareGuid(&owner, &SIG_DB) == 0)
+		status = SetSecureVariable(var, sig, sizeof(sig), owner,
+					   EFI_VARIABLE_APPEND_WRITE, 0);
+	else
+		status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner,
+					   EFI_VARIABLE_NON_VOLATILE
+					   | EFI_VARIABLE_BOOTSERVICE_ACCESS
+					   | EFI_VARIABLE_APPEND_WRITE,
+					   sizeof(sig), sig);
+	return status;
+}
-- 
1.8.1.4

openSUSE Build Service is sponsored by