diff --git a/.gitignore b/.gitignore
index 6af0766..31e92a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
+SOURCES/db.x64.esl
 SOURCES/shim-15.tar.bz2
diff --git a/.shim.metadata b/.shim.metadata
index 5677fcd..65c5635 100644
--- a/.shim.metadata
+++ b/.shim.metadata
@@ -1 +1,2 @@
+8738baca71e73b7c27a65d6b01d804d5d42e9cef SOURCES/db.x64.esl
 2dc6308584187bf3ee88bf9b119938c72c5a5088 SOURCES/shim-15.tar.bz2
diff --git a/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch b/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch
new file mode 100644
index 0000000..7190954
--- /dev/null
+++ b/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch
@@ -0,0 +1,29 @@
+From 1d50318f448b73b072724eb6664d311e6084a446 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 10 Apr 2018 12:36:34 -0400
+Subject: [PATCH 01/62] Make some things dprint() instead of console_print()
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: dad59f8c0f36
+---
+ shim.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 00155346c12..ff0817009cd 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2087,8 +2087,8 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len)
+ 	if (!dppath)
+ 		return 0;
+ 
+-	console_print(L"dppath: %s\n", dppath);
+-	console_print(L"path:   %s\n", path);
++	dprint(L"dppath: %s\n", dppath);
++	dprint(L"path:   %s\n", path);
+ 	if (StrnCaseCmp(dppath, path, len))
+ 		ret = 0;
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch b/SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch
deleted file mode 100644
index 0779498..0000000
--- a/SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 9ab0d796bdc9cefdaa3b0df7434845d26c43d894 Mon Sep 17 00:00:00 2001
-From: Patrick Uiterwijk <patrick@puiterwijk.org>
-Date: Mon, 5 Nov 2018 14:51:16 +0100
-Subject: [PATCH 1/3] Make sure that MOK variables always get mirrored
-
-Without this, if a Mok variable doesn't exist in Boot Services, it will also
-not be copied to Runtime, even if we have data to be added to it (vendor cert).
-This patch makes sure that if we have extra data to append, we still mirror
-the variable.
-
-Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
----
- mok.c | 20 ++++++++++++++++----
- 1 file changed, 16 insertions(+), 4 deletions(-)
-
-diff --git a/mok.c b/mok.c
-index 38675211e0e..00dd1ad3034 100644
---- a/mok.c
-+++ b/mok.c
-@@ -223,11 +223,26 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 		UINT32 attrs = 0;
- 		BOOLEAN delete = FALSE, present, addend;
- 
-+		addend = (v->addend_source && v->addend_size &&
-+			  *v->addend_source && *v->addend_size)
-+			? TRUE : FALSE;
-+
- 		efi_status = get_variable_attr(v->name,
- 					       &v->data, &v->data_size,
- 					       *v->guid, &attrs);
--		if (efi_status == EFI_NOT_FOUND)
-+		if (efi_status == EFI_NOT_FOUND) {
-+			if (v->rtname && addend) {
-+				efi_status = mirror_one_mok_variable(v);
-+				if (EFI_ERROR(efi_status) &&
-+				    ret != EFI_SECURITY_VIOLATION)
-+					ret = efi_status;
-+			}
-+			/*
-+			 * after possibly adding, we can continue, no
-+			 * further checks to be done.
-+			 */
- 			continue;
-+		}
- 		if (EFI_ERROR(efi_status)) {
- 			perror(L"Could not verify %s: %r\n", v->name,
- 			       efi_status);
-@@ -272,9 +287,6 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 		}
- 
- 		present = (v->data && v->data_size) ? TRUE : FALSE;
--		addend = (v->addend_source && v->addend_size &&
--			  *v->addend_source && *v->addend_size)
--			? TRUE : FALSE;
- 
- 		if (v->flags & MOK_VARIABLE_MEASURE && present) {
- 			/*
--- 
-2.20.1
-
diff --git a/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch b/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch
new file mode 100644
index 0000000..94c0c73
--- /dev/null
+++ b/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch
@@ -0,0 +1,131 @@
+From 32f71225382ddb7dd1ad51f584bc3d42a7ee39d1 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 12 Apr 2018 13:24:48 -0400
+Subject: [PATCH 02/62] Makefiles: ensure -m32 gets propogated to our gcc
+ parameter queries
+
+'gcc -print-file-name=include' and 'gcc -print-libgcc-file-name' both
+need -m32 when we're building 32-on-64 on some distros, so ensure that
+gets propogated correctly.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 104d6e54ac7
+---
+ Make.defaults | 66 ++++++++++++++++++++++++++-------------------------
+ 1 file changed, 34 insertions(+), 32 deletions(-)
+
+diff --git a/Make.defaults b/Make.defaults
+index e11ab5a7f2c..bbfc1d7f77b 100644
+--- a/Make.defaults
++++ b/Make.defaults
+@@ -33,66 +33,46 @@ EFI_INCLUDES	= -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \
+ 		  -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \
+ 		  -I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd)
+ 
+-LIB_GCC		= $(shell $(CC) -print-libgcc-file-name)
+-EFI_LIBS	= -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC)
+-
+ EFI_CRT_OBJS 	= $(EFI_PATH)/crt0-efi-$(ARCH).o
+ EFI_LDS		= $(TOPDIR)/elf_$(ARCH)_efi.lds
+ 
+-CFLAGS		= -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
+-		  -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \
+-		  -Werror=sign-compare -ffreestanding -std=gnu89 \
+-		  -I$(shell $(CC) -print-file-name=include) \
+-		  "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \
+-		  "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \
+-		  $(EFI_INCLUDES)
+-
+ CLANG_BUGS	= $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,)
+ 
+ COMMIT_ID ?= $(shell if [ -e .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo master; fi)
+ 
+-ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
+-	CFLAGS	+= -DOVERRIDE_SECURITY_POLICY
+-endif
+-
+-ifneq ($(origin ENABLE_HTTPBOOT), undefined)
+-	CFLAGS	+= -DENABLE_HTTPBOOT
+-endif
+-
+-ifneq ($(origin REQUIRE_TPM), undefined)
+-	CFLAGS  += -DREQUIRE_TPM
+-endif
+-
+ ifeq ($(ARCH),x86_64)
+-	CFLAGS	+= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
+-		   $(CLANG_BUGS) -m64 \
+-		   -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
+-		   -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 -DPAGE_SIZE=4096
++	ARCH_CFLAGS		?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
++				   $(CLANG_BUGS) -m64 \
++				   -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
++				   -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 \
++				   -DPAGE_SIZE=4096
+ 	LIBDIR			?= $(prefix)/lib64
+ 	ARCH_SUFFIX		?= x64
+ 	ARCH_SUFFIX_UPPER	?= X64
+ 	ARCH_LDFLAGS		?=
+ endif
+ ifeq ($(ARCH),ia32)
+-	CFLAGS	+= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
+-		   $(CLANG_BUGS) -m32 \
+-		   -DMDE_CPU_IA32 -DPAGE_SIZE=4096
++	ARCH_CFLAGS		?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
++				   $(CLANG_BUGS) -m32 \
++				   -DMDE_CPU_IA32 -DPAGE_SIZE=4096
+ 	LIBDIR			?= $(prefix)/lib
+ 	ARCH_SUFFIX		?= ia32
+ 	ARCH_SUFFIX_UPPER	?= IA32
+ 	ARCH_LDFLAGS		?=
++	ARCH_CFLAGS		?= -m32
+ endif
+ ifeq ($(ARCH),aarch64)
+-	CFLAGS += -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
++	ARCH_CFLAGS		?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
+ 	LIBDIR			?= $(prefix)/lib64
+ 	ARCH_SUFFIX		?= aa64
+ 	ARCH_SUFFIX_UPPER	?= AA64
+ 	FORMAT			:= -O binary
+ 	SUBSYSTEM		:= 0xa
+ 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
++	ARCH_CFLAGS		?=
+ endif
+ ifeq ($(ARCH),arm)
+-	CFLAGS += -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
++	ARCH_CFLAGS		?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
+ 	LIBDIR			?= $(prefix)/lib
+ 	ARCH_SUFFIX		?= arm
+ 	ARCH_SUFFIX_UPPER	?= ARM
+@@ -101,6 +81,28 @@ ifeq ($(ARCH),arm)
+ 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
+ endif
+ 
++CFLAGS		= -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
++		  -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \
++		  -Werror=sign-compare -ffreestanding -std=gnu89 \
++		  -I$(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include) \
++		  "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \
++		  "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \
++		  $(EFI_INCLUDES) $(ARCH_CFLAGS)
++
++ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
++	CFLAGS	+= -DOVERRIDE_SECURITY_POLICY
++endif
++
++ifneq ($(origin ENABLE_HTTPBOOT), undefined)
++	CFLAGS	+= -DENABLE_HTTPBOOT
++endif
++
++ifneq ($(origin REQUIRE_TPM), undefined)
++	CFLAGS  += -DREQUIRE_TPM
++endif
++
++LIB_GCC		= $(shell $(CC) $(ARCH_CFLAGS) -print-libgcc-file-name)
++EFI_LIBS	= -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC)
+ FORMAT		?= --target efi-app-$(ARCH)
+ EFI_PATH	?= $(LIBDIR)/gnuefi
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch b/SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch
deleted file mode 100644
index fc2adbc..0000000
--- a/SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 4b27ae034ba9885960e72f77b3f687a9b7fea824 Mon Sep 17 00:00:00 2001
-From: Gary Lin <glin@suse.com>
-Date: Wed, 21 Nov 2018 12:47:43 +0800
-Subject: [PATCH 2/3] mok: fix the mirroring of RT variables
-
-When there is no key in MokList, import_mok_state() just skipped MokList
-even though it should always mirror the vendor cert. Besides, the faulty
-check of 'present' and 'addend' invalidates the mirroring of MokListXRT,
-MokSBStateRT, and MokIgnoreDB.
-
-https://github.com/rhboot/shim/issues/154
-
-Signed-off-by: Gary Lin <glin@suse.com>
----
- mok.c | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
-diff --git a/mok.c b/mok.c
-index 00dd1ad3034..41925abbb49 100644
---- a/mok.c
-+++ b/mok.c
-@@ -231,12 +231,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 					       &v->data, &v->data_size,
- 					       *v->guid, &attrs);
- 		if (efi_status == EFI_NOT_FOUND) {
--			if (v->rtname && addend) {
--				efi_status = mirror_one_mok_variable(v);
--				if (EFI_ERROR(efi_status) &&
--				    ret != EFI_SECURITY_VIOLATION)
--					ret = efi_status;
--			}
-+			if (addend)
-+				goto mirror_addend;
- 			/*
- 			 * after possibly adding, we can continue, no
- 			 * further checks to be done.
-@@ -316,7 +312,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 			}
- 		}
- 
--		if (v->rtname && present && addend) {
-+mirror_addend:
-+		if (v->rtname && (present || addend)) {
- 			if (v->flags & MOK_MIRROR_DELETE_FIRST)
- 				LibDeleteVariable(v->rtname, v->guid);
- 
--- 
-2.20.1
-
diff --git a/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch b/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch
new file mode 100644
index 0000000..9f6697a
--- /dev/null
+++ b/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch
@@ -0,0 +1,61 @@
+From 74718677945b1ab825130b317c63f5002876e772 Mon Sep 17 00:00:00 2001
+From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Date: Thu, 5 Jul 2018 11:28:12 -0400
+Subject: [PATCH 03/62] Let MokManager follow a MokTimeout var for timeout
+ length for the prompt
+
+This timeout can have the values [-1,0..0x7fff]; where -1 means "no timeout",
+with MokManager going directly to the menu, and is capped to 0x7fff to avoid
+unecessary long timeouts. The default remains 10, which will be used whenever
+the MokTimeout variable isn't set.
+
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Upstream-commit-id: 93708c11083
+---
+ MokManager.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index 7e40a38f1d1..0767e4a6cde 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -40,6 +40,10 @@ typedef struct {
+ 	CHAR16 Password[SB_PASSWORD_LEN];
+ } __attribute__ ((packed)) MokDBvar;
+ 
++typedef struct {
++	INT32 Timeout;
++} __attribute__ ((packed)) MokTimeoutvar;
++
+ static EFI_STATUS get_sha1sum(void *Data, int DataSize, UINT8 * hash)
+ {
+ 	EFI_STATUS efi_status;
+@@ -2041,7 +2045,24 @@ static int draw_countdown()
+ 	UINTN cols, rows;
+ 	CHAR16 *title[2];
+ 	CHAR16 *message = L"Press any key to perform MOK management";
+-	int timeout = 10, wait = 10000000;
++	void *MokTimeout = NULL;
++	MokTimeoutvar *var;
++	UINTN MokTimeoutSize = 0;
++	int timeout, wait = 10000000;
++
++	efi_status = get_variable(L"MokTimeout", (UINT8 **) &MokTimeout,
++				  &MokTimeoutSize, SHIM_LOCK_GUID);
++	if (EFI_ERROR(efi_status)) {
++		timeout = 10;
++	} else {
++		var = MokTimeout;
++		timeout = (int)var->Timeout;
++		FreePool(MokTimeout);
++		LibDeleteVariable(L"MokTimeout", &SHIM_LOCK_GUID);
++	}
++
++	if (timeout < 0)
++		return timeout;
+ 
+ 	console_save_and_set_mode(&SavedMode);
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch b/SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
deleted file mode 100644
index caded4e..0000000
--- a/SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From 29c11483101b460869a5e0dba1f425073862127d Mon Sep 17 00:00:00 2001
-From: Peter Jones <pjones@redhat.com>
-Date: Thu, 31 Jan 2019 13:45:30 -0500
-Subject: [PATCH 3/3] mok: consolidate mirroring code in a helper instead of
- using goto
-
-There's no reason to complicate the logic with a goto here, instead just
-pull the logic we're jumping to out to a helper function.
-
-Signed-off-by: Peter Jones <pjones@redhat.com>
----
- mok.c  | 41 ++++++++++++++++++++++++++++-------------
- shim.h |  2 ++
- 2 files changed, 30 insertions(+), 13 deletions(-)
-
-diff --git a/mok.c b/mok.c
-index 41925abbb49..2f495e6cf25 100644
---- a/mok.c
-+++ b/mok.c
-@@ -130,7 +130,8 @@ struct mok_state_variable mok_state_variables[] = {
- 	{ NULL, }
- };
- 
--static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
-+static EFI_STATUS nonnull(1)
-+mirror_one_mok_variable(struct mok_state_variable *v)
- {
- 	EFI_STATUS efi_status = EFI_SUCCESS;
- 	void *FullData = NULL;
-@@ -196,6 +197,29 @@ static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
- 	return efi_status;
- }
- 
-+/*
-+ * Mirror a variable if it has an rtname, and preserve any
-+ * EFI_SECURITY_VIOLATION status at the same time.
-+ */
-+static EFI_STATUS nonnull(1)
-+maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
-+{
-+	EFI_STATUS efi_status;
-+	if (v->rtname) {
-+		if (v->flags & MOK_MIRROR_DELETE_FIRST)
-+			LibDeleteVariable(v->rtname, v->guid);
-+
-+		efi_status = mirror_one_mok_variable(v);
-+		if (EFI_ERROR(efi_status)) {
-+			if (ret != EFI_SECURITY_VIOLATION)
-+				ret = efi_status;
-+			perror(L"Could not create %s: %r\n", v->rtname,
-+			       efi_status);
-+		}
-+	}
-+	return ret;
-+}
-+
- /*
-  * Verify our non-volatile MoK state.  This checks the variables above
-  * accessable and have valid attributes.  If they don't, it removes
-@@ -232,7 +256,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 					       *v->guid, &attrs);
- 		if (efi_status == EFI_NOT_FOUND) {
- 			if (addend)
--				goto mirror_addend;
-+				ret = maybe_mirror_one_mok_variable(v, ret);
- 			/*
- 			 * after possibly adding, we can continue, no
- 			 * further checks to be done.
-@@ -312,16 +336,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 			}
- 		}
- 
--mirror_addend:
--		if (v->rtname && (present || addend)) {
--			if (v->flags & MOK_MIRROR_DELETE_FIRST)
--				LibDeleteVariable(v->rtname, v->guid);
--
--			efi_status = mirror_one_mok_variable(v);
--			if (EFI_ERROR(efi_status) &&
--			    ret != EFI_SECURITY_VIOLATION)
--				ret = efi_status;
--		}
-+		if (present)
-+			ret = maybe_mirror_one_mok_variable(v, ret);
- 	}
- 
- 	/*
-@@ -340,4 +356,4 @@ mirror_addend:
- 	return ret;
- }
- 
--// vim:fenc=utf-8:tw=75
-+// vim:fenc=utf-8:tw=75:noet
-diff --git a/shim.h b/shim.h
-index 2b359d821e3..c26d5f06538 100644
---- a/shim.h
-+++ b/shim.h
-@@ -30,6 +30,8 @@
- 
- #include <stddef.h>
- 
-+#define nonnull(...) __attribute__((__nonnull__(__VA_ARGS__)))
-+
- #define min(a, b) ({(a) < (b) ? (a) : (b);})
- 
- #ifdef __x86_64__
--- 
-2.20.1
-
diff --git a/SOURCES/0004-Make-VLogError-behave-as-expected.patch b/SOURCES/0004-Make-VLogError-behave-as-expected.patch
deleted file mode 100644
index 2e5ca64..0000000
--- a/SOURCES/0004-Make-VLogError-behave-as-expected.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 0bff94b170116737e6e0838c35c0ac376542a5c0 Mon Sep 17 00:00:00 2001
-From: Peter Jones <pjones@redhat.com>
-Date: Tue, 12 Feb 2019 18:04:49 -0500
-Subject: [PATCH 4/4] Make VLogError() behave as expected.
-
-Signed-off-by: Peter Jones <pjones@redhat.com>
----
- errlog.c | 15 +++------------
- 1 file changed, 3 insertions(+), 12 deletions(-)
-
-diff --git a/errlog.c b/errlog.c
-index 18be4822d53..eebb266d396 100644
---- a/errlog.c
-+++ b/errlog.c
-@@ -14,29 +14,20 @@ EFI_STATUS
- VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args)
- {
- 	va_list args2;
--	UINTN size = 0, size2;
- 	CHAR16 **newerrs;
- 
--	size = SPrint(NULL, 0, L"%a:%d %a() ", file, line, func);
--	va_copy(args2, args);
--	size2 = VSPrint(NULL, 0, fmt, args2);
--	va_end(args2);
--
- 	newerrs = ReallocatePool(errs, (nerrs + 1) * sizeof(*errs),
- 				       (nerrs + 3) * sizeof(*errs));
- 	if (!newerrs)
- 		return EFI_OUT_OF_RESOURCES;
- 
--	newerrs[nerrs] = AllocatePool(size*2+2);
-+	newerrs[nerrs] = PoolPrint(L"%a:%d %a() ", file, line, func);
- 	if (!newerrs[nerrs])
- 		return EFI_OUT_OF_RESOURCES;
--	newerrs[nerrs+1] = AllocatePool(size2*2+2);
-+	va_copy(args2, args);
-+	newerrs[nerrs+1] = VPoolPrint(fmt, args2);
- 	if (!newerrs[nerrs+1])
- 		return EFI_OUT_OF_RESOURCES;
--
--	SPrint(newerrs[nerrs], size*2+2, L"%a:%d %a() ", file, line, func);
--	va_copy(args2, args);
--	VSPrint(newerrs[nerrs+1], size2*2+2, fmt, args2);
- 	va_end(args2);
- 
- 	nerrs += 2;
--- 
-2.20.1
-
diff --git a/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch b/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch
new file mode 100644
index 0000000..44de3b7
--- /dev/null
+++ b/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch
@@ -0,0 +1,30 @@
+From 8a66f5571bb059d2692e804f4ba9817e978dd103 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 28 May 2018 16:05:38 +0800
+Subject: [PATCH 04/62] httpboot: return EFI_NOT_FOUND when it fails to find
+ the NIC handle
+
+httpboot_fetch_buffer() should return EFI_NOT_FOUND to reflect the error
+status when get_nic_handle() returns NULL.
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 2be5c7dc4b0
+---
+ httpboot.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/httpboot.c b/httpboot.c
+index 4cfa3aab3b7..d656073c633 100644
+--- a/httpboot.c
++++ b/httpboot.c
+@@ -715,6 +715,7 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
+ 	   also supports the HTTP service binding protocol */
+ 	nic = get_nic_handle(&mac_addr);
+ 	if (!nic) {
++		efi_status = EFI_NOT_FOUND;
+ 		goto error;
+ 	}
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0005-Once-again-try-even-harder-to-get-binaries-without-t.patch b/SOURCES/0005-Once-again-try-even-harder-to-get-binaries-without-t.patch
deleted file mode 100644
index 8e3c47a..0000000
--- a/SOURCES/0005-Once-again-try-even-harder-to-get-binaries-without-t.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From fea3f2ec1936cfb9ed0b3ee62d9d23698097b814 Mon Sep 17 00:00:00 2001
-From: Peter Jones <pjones@redhat.com>
-Date: Fri, 15 Mar 2019 09:52:02 -0400
-Subject: [PATCH] Once again, try even harder to get binaries without
- timestamps in them.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-$ objdump -x /builddir/build/BUILDROOT/shim-*/usr/share/shim/*/shimx64.efi | grep 'Time/Date'
-Time/Date		Thu Jan  1 00:00:08 1970
-$ _
-
-"What is despair? I have known it—hear my song. Despair is when you’re
-debugging a kernel driver and you look at a memory dump and you see that
-a pointer has a value of 7."
- - http://scholar.harvard.edu/files/mickens/files/thenightwatch.pdf
-
-objcopy only knows about -D for some targets.
-ld only believes in --no-insert-timestamp in some versions.
-dd takes off and nukes the site from orbit.
-
-It's the only way to be sure.
-
-Signed-off-by: Peter Jones <pjones@redhat.com>
----
- Make.defaults | 4 ++++
- Makefile      | 6 ++++--
- 2 files changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/Make.defaults b/Make.defaults
-index e11ab5a7f2c..4c26c1adf1f 100644
---- a/Make.defaults
-+++ b/Make.defaults
-@@ -72,6 +72,7 @@ ifeq ($(ARCH),x86_64)
- 	ARCH_SUFFIX		?= x64
- 	ARCH_SUFFIX_UPPER	?= X64
- 	ARCH_LDFLAGS		?=
-+	TIMESTAMP_LOCATION	:= 136
- endif
- ifeq ($(ARCH),ia32)
- 	CFLAGS	+= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
-@@ -81,6 +82,7 @@ ifeq ($(ARCH),ia32)
- 	ARCH_SUFFIX		?= ia32
- 	ARCH_SUFFIX_UPPER	?= IA32
- 	ARCH_LDFLAGS		?=
-+	TIMESTAMP_LOCATION	:= 136
- endif
- ifeq ($(ARCH),aarch64)
- 	CFLAGS += -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
-@@ -90,6 +92,7 @@ ifeq ($(ARCH),aarch64)
- 	FORMAT			:= -O binary
- 	SUBSYSTEM		:= 0xa
- 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
-+	TIMESTAMP_LOCATION	:= 72
- endif
- ifeq ($(ARCH),arm)
- 	CFLAGS += -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
-@@ -99,6 +102,7 @@ ifeq ($(ARCH),arm)
- 	FORMAT			:= -O binary
- 	SUBSYSTEM		:= 0xa
- 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
-+	TIMESTAMP_LOCATION	:= 72
- endif
- 
- FORMAT		?= --target efi-app-$(ARCH)
-diff --git a/Makefile b/Makefile
-index 115e7f08c0f..a012c9f0d16 100644
---- a/Makefile
-+++ b/Makefile
-@@ -189,11 +189,13 @@ endif
- ifneq ($(OBJCOPY_GTE224),1)
- 	$(error objcopy >= 2.24 is required)
- endif
--	$(OBJCOPY) -j .text -j .sdata -j .data -j .data.ident \
-+	$(OBJCOPY) -D -j .text -j .sdata -j .data -j .data.ident \
- 		-j .dynamic -j .dynsym -j .rel* \
- 		-j .rela* -j .reloc -j .eh_frame \
- 		-j .vendor_cert \
- 		$(FORMAT) $^ $@
-+	# I am tired of wasting my time fighting binutils timestamp code.
-+	dd conv=notrunc bs=1 count=4 seek=$(TIMESTAMP_LOCATION) if=/dev/zero of=$@
- 
- ifneq ($(origin ENABLE_SHIM_HASH),undefined)
- %.hash : %.efi
-@@ -204,7 +206,7 @@ endif
- ifneq ($(OBJCOPY_GTE224),1)
- 	$(error objcopy >= 2.24 is required)
- endif
--	$(OBJCOPY) -j .text -j .sdata -j .data \
-+	$(OBJCOPY) -D -j .text -j .sdata -j .data \
- 		-j .dynamic -j .dynsym -j .rel* \
- 		-j .rela* -j .reloc -j .eh_frame \
- 		-j .debug_info -j .debug_abbrev -j .debug_aranges \
--- 
-2.20.1
-
diff --git a/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch b/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch
new file mode 100644
index 0000000..d64a381
--- /dev/null
+++ b/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch
@@ -0,0 +1,107 @@
+From 0ba6c87bdf55f749a0ec1c3b0fd24ebb8200d537 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 28 May 2018 17:24:30 +0800
+Subject: [PATCH 05/62] httpboot: print more messages when it fails to set IP
+
+We previously only print the return status and it may not be clear
+enough in some situations. Print the IP address and the gateway to help
+the user to identify the possible errors.
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 3abe94516c7
+---
+ httpboot.c | 45 +++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 41 insertions(+), 4 deletions(-)
+
+diff --git a/httpboot.c b/httpboot.c
+index d656073c633..6f27b01bf71 100644
+--- a/httpboot.c
++++ b/httpboot.c
+@@ -311,6 +311,20 @@ is_unspecified_addr (EFI_IPv6_ADDRESS ip6)
+ 	return TRUE;
+ }
+ 
++static inline void
++print_ip6_addr(EFI_IPv6_ADDRESS ip6addr)
++{
++	perror(L"%x:%x:%x:%x:%x:%x:%x:%x\n",
++	       ip6addr.Addr[0]  << 8 | ip6addr.Addr[1],
++	       ip6addr.Addr[2]  << 8 | ip6addr.Addr[3],
++	       ip6addr.Addr[4]  << 8 | ip6addr.Addr[5],
++	       ip6addr.Addr[6]  << 8 | ip6addr.Addr[7],
++	       ip6addr.Addr[8]  << 8 | ip6addr.Addr[9],
++	       ip6addr.Addr[10] << 8 | ip6addr.Addr[11],
++	       ip6addr.Addr[12] << 8 | ip6addr.Addr[13],
++	       ip6addr.Addr[14] << 8 | ip6addr.Addr[15]);
++}
++
+ static EFI_STATUS
+ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+ {
+@@ -329,8 +343,12 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+ 	ip6.IsAnycast = FALSE;
+ 	efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeManualAddress,
+ 				     sizeof(ip6), &ip6);
+-	if (EFI_ERROR(efi_status))
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to set IPv6 Address:\nIP: ");
++		print_ip6_addr(ip6.Address);
++		perror(L"Prefix Length: %u\n", ip6.PrefixLength);
+ 		return efi_status;
++	}
+ 
+ 	gateway = ip6node->GatewayIpAddress;
+ 	if (is_unspecified_addr(gateway))
+@@ -338,12 +356,23 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+ 
+ 	efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway,
+ 				     sizeof(gateway), &gateway);
+-	if (EFI_ERROR(efi_status))
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to set IPv6 Gateway:\nIP: ");
++		print_ip6_addr(gateway);
+ 		return efi_status;
++	}
+ 
+ 	return EFI_SUCCESS;
+ }
+ 
++static inline void
++print_ip4_addr(EFI_IPv4_ADDRESS ip4addr)
++{
++	perror(L"%u.%u.%u.%u\n",
++	       ip4addr.Addr[0], ip4addr.Addr[1],
++	       ip4addr.Addr[2], ip4addr.Addr[3]);
++}
++
+ static EFI_STATUS
+ set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node)
+ {
+@@ -361,14 +390,22 @@ set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node)
+ 	ip4.SubnetMask = ip4node->SubnetMask;
+ 	efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeManualAddress,
+ 				      sizeof(ip4), &ip4);
+-	if (EFI_ERROR(efi_status))
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to Set IPv4 Address:\nIP: ");
++		print_ip4_addr(ip4.Address);
++		perror(L"Mask: ");
++		print_ip4_addr(ip4.SubnetMask);
+ 		return efi_status;
++	}
+ 
+ 	gateway = ip4node->GatewayIpAddress;
+ 	efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway,
+ 				      sizeof(gateway), &gateway);
+-	if (EFI_ERROR(efi_status))
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to Set IPv4 Gateway:\nGateway: ");
++		print_ip4_addr(gateway);
+ 		return efi_status;
++	}
+ 
+ 	return EFI_SUCCESS;
+ }
+-- 
+2.26.2
+
diff --git a/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch b/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch
new file mode 100644
index 0000000..4b92fda
--- /dev/null
+++ b/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch
@@ -0,0 +1,68 @@
+From 80e52895f206fcb40a60f031e7b721627bb193ca Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 28 May 2018 17:42:56 +0800
+Subject: [PATCH 06/62] httpboot: allow the IPv4 gateway to be empty
+
+The gateway is not mandatory.
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 69089e9c678
+---
+ httpboot.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/httpboot.c b/httpboot.c
+index 6f27b01bf71..16dd6621f66 100644
+--- a/httpboot.c
++++ b/httpboot.c
+@@ -299,7 +299,7 @@ out:
+ }
+ 
+ static BOOLEAN
+-is_unspecified_addr (EFI_IPv6_ADDRESS ip6)
++is_unspecified_ip6addr (EFI_IPv6_ADDRESS ip6)
+ {
+ 	UINT8 i;
+ 
+@@ -351,7 +351,7 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+ 	}
+ 
+ 	gateway = ip6node->GatewayIpAddress;
+-	if (is_unspecified_addr(gateway))
++	if (is_unspecified_ip6addr(gateway))
+ 		return EFI_SUCCESS;
+ 
+ 	efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway,
+@@ -365,6 +365,19 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+ 	return EFI_SUCCESS;
+ }
+ 
++static BOOLEAN
++is_unspecified_ip4addr (EFI_IPv4_ADDRESS ip4)
++{
++	UINT8 i;
++
++	for (i = 0; i<4; i++) {
++		if (ip4.Addr[i] != 0)
++			return FALSE;
++	}
++
++	return TRUE;
++}
++
+ static inline void
+ print_ip4_addr(EFI_IPv4_ADDRESS ip4addr)
+ {
+@@ -399,6 +412,9 @@ set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node)
+ 	}
+ 
+ 	gateway = ip4node->GatewayIpAddress;
++	if (is_unspecified_ip4addr(gateway))
++		return EFI_SUCCESS;
++
+ 	efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway,
+ 				      sizeof(gateway), &gateway);
+ 	if (EFI_ERROR(efi_status)) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch b/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch
new file mode 100644
index 0000000..8d42888
--- /dev/null
+++ b/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch
@@ -0,0 +1,30 @@
+From c2f645c7cd9872585e7b4522b01c368bb545258b Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 28 May 2018 18:03:39 +0800
+Subject: [PATCH 07/62] httpboot: show the error message for the ChildHandle
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 0fd3c7e8518
+---
+ httpboot.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/httpboot.c b/httpboot.c
+index 16dd6621f66..3622e85867c 100644
+--- a/httpboot.c
++++ b/httpboot.c
+@@ -696,8 +696,10 @@ http_fetch (EFI_HANDLE image, EFI_HANDLE device,
+ 	/* Set the handle to NULL to request a new handle */
+ 	http_handle = NULL;
+ 	efi_status = service->CreateChild(service, &http_handle);
+-	if (EFI_ERROR(efi_status))
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to create the ChildHandle\n");
+ 		return efi_status;
++	}
+ 
+ 	/* Get the http protocol */
+ 	efi_status = gBS->HandleProtocol(http_handle, &EFI_HTTP_PROTOCOL_GUID,
+-- 
+2.26.2
+
diff --git a/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch b/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch
new file mode 100644
index 0000000..be22b83
--- /dev/null
+++ b/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch
@@ -0,0 +1,54 @@
+From 409b59af29b8749207a527c91dccba7eee98232b Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Wed, 23 May 2018 15:15:56 +0800
+Subject: [PATCH 08/62] Fix typo in debug path in shim.h
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: a98c20bbdbb
+---
+ shim.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/shim.h b/shim.h
+index a25a660df6a..2b359d821e3 100644
+--- a/shim.h
++++ b/shim.h
+@@ -43,7 +43,7 @@
+ #define EFI_ARCH L"x64"
+ #endif
+ #ifndef DEBUGDIR
+-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/x64/"
++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/x64/"
+ #endif
+ #endif
+ 
+@@ -58,7 +58,7 @@
+ #define EFI_ARCH L"ia32"
+ #endif
+ #ifndef DEBUGDIR
+-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/ia32/"
++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/ia32/"
+ #endif
+ #endif
+ 
+@@ -73,7 +73,7 @@
+ #define EFI_ARCH L"aa64"
+ #endif
+ #ifndef DEBUGDIR
+-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/aa64/"
++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/aa64/"
+ #endif
+ #endif
+ 
+@@ -88,7 +88,7 @@
+ #define EFI_ARCH L"arm"
+ #endif
+ #ifndef DEBUGDIR
+-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/arm/"
++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/arm/"
+ #endif
+ #endif
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch b/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch
new file mode 100644
index 0000000..1baa54b
--- /dev/null
+++ b/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch
@@ -0,0 +1,43 @@
+From 85c837d67fef9cd831a3126398ed8da1421f61c5 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 11 May 2018 16:59:03 +0800
+Subject: [PATCH 09/62] MokManager: Stop using EFI_VARIABLE_APPEND_WRITE
+
+When writing MokList with EFI_VARIABLE_APPEND_WRITE, some HP laptops
+may just return EFI_SUCCESS without writing the content into the flash,
+so we have no way to detect if MokList is updated or not. Now we always
+read MokList first and write it back with the new content.
+
+https://github.com/rhboot/shim/issues/105
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: f442c8424b4
+---
+ MokManager.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index 0767e4a6cde..df9b6fe6912 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -880,14 +880,9 @@ static EFI_STATUS write_db(CHAR16 * db_name, void *MokNew, UINTN MokNewSize)
+ 	UINTN old_size;
+ 	UINTN new_size;
+ 
+-	efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID,
+-				      EFI_VARIABLE_NON_VOLATILE |
+-				      EFI_VARIABLE_BOOTSERVICE_ACCESS |
+-				      EFI_VARIABLE_APPEND_WRITE,
+-				      MokNewSize, MokNew);
+-	if (!EFI_ERROR(efi_status) || efi_status != EFI_INVALID_PARAMETER) {
+-		return efi_status;
+-	}
++	/* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares.
++	 * ref: https://github.com/rhboot/shim/issues/55
++	 *      https://github.com/rhboot/shim/issues/105 */
+ 
+ 	efi_status = get_variable_attr(db_name, (UINT8 **)&old_data, &old_size,
+ 				       SHIM_LOCK_GUID, &attributes);
+-- 
+2.26.2
+
diff --git a/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch b/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch
new file mode 100644
index 0000000..76d26e8
--- /dev/null
+++ b/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch
@@ -0,0 +1,40 @@
+From 956717e2b375d7c7f0faafec8f12a7692708eb9a Mon Sep 17 00:00:00 2001
+From: Paul Menzel <pmenzel@molgen.mpg.de>
+Date: Wed, 23 May 2018 12:32:37 +0200
+Subject: [PATCH 10/62] shim: Extend invalid reloc size warning message
+
+Knowing the value of the reloc directory size is helpful for debugging,
+cf. issue #131 [1],
+
+[1]: https://github.com/rhboot/shim/issues/131
+
+Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Upstream-commit-id: dd3230d07f3
+---
+ shim.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index ff0817009cd..05fc65005d1 100644
+--- a/shim.c
++++ b/shim.c
+@@ -280,8 +280,14 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
+ 	while (RelocBase < RelocBaseEnd) {
+ 		Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
+ 
+-		if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > context->RelocDir->Size)) {
+-			perror(L"Reloc %d block size %d is invalid\n", n, RelocBase->SizeOfBlock);
++		if (RelocBase->SizeOfBlock == 0) {
++			perror(L"Reloc %d block size 0 is invalid\n", n);
++			return EFI_UNSUPPORTED;
++		} else if (RelocBase->SizeOfBlock > context->RelocDir->Size) {
++			perror(L"Reloc %d block size %d greater than reloc dir"
++					"size %d, which is invalid\n", n,
++					RelocBase->SizeOfBlock,
++					context->RelocDir->Size);
+ 			return EFI_UNSUPPORTED;
+ 		}
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch b/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch
new file mode 100644
index 0000000..25197e0
--- /dev/null
+++ b/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch
@@ -0,0 +1,34 @@
+From bd97e72f0490b2be766949f448bf6ea3ec2bba1a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 1 Aug 2018 09:58:09 -0500
+Subject: [PATCH 11/62] Add GRUB's PCR Usage to README.tpm
+
+This didn't seem to get documented anywhere, and this is as good a place as any.
+Upstream-commit-id: 4fab7281a8c
+---
+ README.tpm | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/README.tpm b/README.tpm
+index b7314f12d57..d9c7c53483b 100644
+--- a/README.tpm
++++ b/README.tpm
+@@ -19,6 +19,15 @@ PCR7:
+ - MokSBState will be extended into PCR7 if it is set, logged as
+   "MokSBState".
+ 
++PCR8:
++- If you're using the grub2 TPM patchset we cary in Fedora, the kernel command
++  line and all grub commands (including all of grub.cfg that gets run) are
++  measured into PCR8.
++  
++PCR9:
++- If you're using the grub2 TPM patchset we cary in Fedora, the kernel,
++  initramfs, and any multiboot modules loaded are measured into PCR9.
++
+ PCR14:
+ - MokList, MokListX, and MokSBState will be extended into PCR14 if they are
+   set.
+-- 
+2.26.2
+
diff --git a/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch b/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch
new file mode 100644
index 0000000..a71436e
--- /dev/null
+++ b/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch
@@ -0,0 +1,36 @@
+From c4e3516e303daa42b3381ddd889a90641717f720 Mon Sep 17 00:00:00 2001
+From: TanMing <tanminger@TanMing-WorkPC.sh.intel.com>
+Date: Tue, 21 Aug 2018 02:25:52 -0400
+Subject: [PATCH 12/62] Fix the compile error of mkdir wrong directory.
+
+In Ubuntu 14.04, the following code in old Makefile:
+  mkdir -p Cryptlib/{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall}
+will create a directory named "{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall}".
+
+Signed-off-by: Ming Tan <ming.tan@intel.com>
+Upstream-commit-id: 39b83455d68
+---
+ Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 115e7f08c0f..3f2105595a6 100644
+--- a/Makefile
++++ b/Makefile
+@@ -102,11 +102,11 @@ $(MMSONAME): $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a li
+ 	$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a
+ 
+ Cryptlib/libcryptlib.a:
+-	mkdir -p Cryptlib/{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall}
++	for i in Hash Hmac Cipher Rand Pk Pem SysCall; do mkdir -p Cryptlib/$$i; done
+ 	$(MAKE) VPATH=$(TOPDIR)/Cryptlib TOPDIR=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile
+ 
+ Cryptlib/OpenSSL/libopenssl.a:
+-	mkdir -p Cryptlib/OpenSSL/crypto/{x509v3,x509,txt_db,stack,sha,rsa,rc4,rand,pkcs7,pkcs12,pem,ocsp,objects,modes,md5,lhash,kdf,hmac,evp,err,dso,dh,conf,comp,cmac,buffer,bn,bio,async{,/arch},asn1,aes}/
++	for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done
+ 	$(MAKE) VPATH=$(TOPDIR)/Cryptlib/OpenSSL TOPDIR=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile
+ 
+ lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch])
+-- 
+2.26.2
+
diff --git a/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch b/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch
new file mode 100644
index 0000000..00dfaeb
--- /dev/null
+++ b/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch
@@ -0,0 +1,52 @@
+From 79be2af5260b1f2e2a4680e74e14da0fdb42b570 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri, 7 Sep 2018 14:11:02 +0200
+Subject: [PATCH 13/62] shim: Properly generate absolute paths from relative
+ image paths
+
+The generate_path_from_image_path() doesn't properly handle the case when
+shim is invoked using a relative path (e.g: from the EFI shell). In that
+function, always the last component is stripped from absolute file path
+to calculate the dirname, and this is concatenated with the image path.
+
+But if the path is a relative one, the function will wrongly concatenate
+the dirname with the relative image path, i.e:
+
+ Shell> FS0:
+ FS0:\> cd EFI
+ FS0:\EFI\> BOOT\BOOTX64.EFI
+ Failed to open \EFI\BOOT\BOOT\BOOTX64.EFI - Not found
+ Failed to load image \EFI\BOOT\BOOT\BOOTX64.EFI: Not found
+ start_image() returned Not found
+
+Calculate the image path basename and concatenate that with the dirname.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Reviewed-by: Maran Wilson maran.wilson@oracle.com
+Tested-by: Maran Wilson maran.wilson@oracle.com
+Upstream-commit-id: a625fa5096c
+---
+ shim.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 05fc65005d1..5ab23d03db4 100644
+--- a/shim.c
++++ b/shim.c
+@@ -1610,9 +1610,11 @@ static EFI_STATUS generate_path_from_image_path(EFI_LOADED_IMAGE *li,
+ 		bootpath[j] = '\0';
+ 	}
+ 
+-	while (*ImagePath == '\\')
+-		ImagePath++;
++	for (i = 0, last = 0; i < StrLen(ImagePath); i++)
++		if (ImagePath[i] == '\\')
++			last = i + 1;
+ 
++	ImagePath = ImagePath + last;
+ 	*PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
+ 
+ 	if (!*PathName) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch b/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch
new file mode 100644
index 0000000..34b9896
--- /dev/null
+++ b/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch
@@ -0,0 +1,77 @@
+From 818a0dbd247f7c83d844febfa0a037b396d22701 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri, 7 Sep 2018 15:10:51 +0200
+Subject: [PATCH 14/62] shim: Prevent shim to set itself as a second stage
+ loader
+
+When shim is invoked from a relative path (e.g: from the UEFI shell), the
+Loaded Image handle LoadOptions can be set to the binary relative path.
+
+But the is_our_path() function only checks if LoadOptions is set to the
+absolute path of shim to ignore it. So if a relative path is there, shim
+would set itself as the secondary loader and invoke itself in a loop.
+
+To prevent that, use the path in LoadOptions to calculate the absolute
+path and compare it with the one in the Loader Image handle FilePath.
+
+Resolves: bz#1622485
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Reviewed-by: Maran Wilson maran.wilson@oracle.com
+Tested-by: Maran Wilson maran.wilson@oracle.com
+Upstream-commit-id: e563bc3dcd1
+---
+ shim.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 5ab23d03db4..ae03da7eddf 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2086,21 +2086,32 @@ get_load_option_optional_data(UINT8 *data, UINTN data_size,
+ 	return EFI_SUCCESS;
+ }
+ 
+-static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len)
++static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path)
+ {
+ 	CHAR16 *dppath = NULL;
++	CHAR16 *PathName = NULL;
++	EFI_STATUS efi_status;
+ 	int ret = 1;
+ 
+ 	dppath = DevicePathToStr(li->FilePath);
+ 	if (!dppath)
+ 		return 0;
+ 
++	efi_status = generate_path_from_image_path(li, path, &PathName);
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Unable to generate path %s: %r\n", path,
++		       efi_status);
++		goto done;
++	}
++
+ 	dprint(L"dppath: %s\n", dppath);
+ 	dprint(L"path:   %s\n", path);
+-	if (StrnCaseCmp(dppath, path, len))
++	if (StrnCaseCmp(dppath, PathName, strlen(dppath)))
+ 		ret = 0;
+ 
++done:
+ 	FreePool(dppath);
++	FreePool(PathName);
+ 	return ret;
+ }
+ 
+@@ -2289,7 +2300,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
+ 
+ 	 * which is just cruel... So yeah, just don't use it.
+ 	 */
+-	if (strings == 1 && is_our_path(li, start, loader_len))
++	if (strings == 1 && is_our_path(li, start))
+ 		return EFI_SUCCESS;
+ 
+ 	/*
+-- 
+2.26.2
+
diff --git a/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch b/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch
new file mode 100644
index 0000000..419d841
--- /dev/null
+++ b/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch
@@ -0,0 +1,121 @@
+From 3d04aef8d80293d701f7efee6b5300f9f528ddfc Mon Sep 17 00:00:00 2001
+From: Maran Wilson <maran.wilson@oracle.com>
+Date: Tue, 7 Aug 2018 15:32:29 -0700
+Subject: [PATCH 15/62] Fix for "Section 0 has negative size" error when
+ loading fbaa64.efi
+
+The current code is incorrectly failing to load the fbaa64.efi image found
+in Arm servers even though the UEFI shell code is able to properly load
+and execute the same image.
+
+The problem is due to the presence of a section header that has zero size
+and address and marked "discardable" in the fbaa64.efi image.
+
+Although there is already a check further down in the code to look for
+the discardable bit and skip further verification checks if set, we never
+get to that point due to the "end < base" check at the start of the loop.
+
+Here is a dump of the fbaa64.efi image as compiled on an Arm machine
+from the latest code in this repo:
+
+% # First I used hexedit to change header byte from 'AA' to '86'
+% # so that objdump was able to correctly parse the file:
+% objdump -x -m aarch64 fbaa64.efi
+
+fbaa64.efi:     file format pei-x86-64
+fbaa64.efi
+architecture: i386:x86-64, flags 0x00000103:
+HAS_RELOC, EXEC_P, D_PAGED
+start address 0x0000000000000148
+
+Characteristics 0x20e
+        executable
+        line numbers stripped
+        symbols stripped
+        debugging information removed
+
+Time/Date               Wed Dec 31 16:00:00 1969
+Magic                   020b    (PE32+)
+MajorLinkerVersion      2
+MinorLinkerVersion      20
+SizeOfCode              000b15d0
+SizeOfInitializedData   00000000
+SizeOfUninitializedData 00000000
+AddressOfEntryPoint     0000000000000148
+BaseOfCode              0000000000000148
+ImageBase               0000000000000000
+SectionAlignment        0000000000000020
+FileAlignment           0000000000000008
+MajorOSystemVersion     0
+MinorOSystemVersion     0
+MajorImageVersion       0
+MinorImageVersion       0
+MajorSubsystemVersion   0
+MinorSubsystemVersion   0
+Win32Version            00000000
+SizeOfImage             000b1718
+SizeOfHeaders           00000148
+CheckSum                00000000
+Subsystem               0000000a        (EFI application)
+DllCharacteristics      00000000
+SizeOfStackReserve      0000000000000000
+SizeOfStackCommit       0000000000000000
+SizeOfHeapReserve       0000000000000000
+SizeOfHeapCommit        0000000000000000
+LoaderFlags             00000000
+NumberOfRvaAndSizes     00000006
+
+The Data Directory
+Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
+Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
+Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]
+Entry 3 0000000000000000 00000000 Exception Directory [.pdata]
+Entry 4 0000000000000000 00000000 Security Directory
+Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc]
+Entry 6 0000000000000000 00000000 Debug Directory
+Entry 7 0000000000000000 00000000 Description Directory
+Entry 8 0000000000000000 00000000 Special Directory
+Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
+Entry a 0000000000000000 00000000 Load Configuration Directory
+Entry b 0000000000000000 00000000 Bound Import Directory
+Entry c 0000000000000000 00000000 Import Address Table Directory
+Entry d 0000000000000000 00000000 Delay Import Directory
+Entry e 0000000000000000 00000000 CLR Runtime Header
+Entry f 0000000000000000 00000000 Reserved
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 .reloc        00000000  0000000000000000  0000000000000000  00000000  2**0
+                  ALLOC, LOAD, READONLY, DATA
+  1 .text         000b15d0  0000000000000148  0000000000000148  00000148  2**4
+                  CONTENTS, ALLOC, LOAD, CODE
+SYMBOL TABLE:
+no symbols
+
+Signed-off-by: Maran Wilson <maran.wilson@oracle.com>
+Reviewed-by: Aaron Young <aaron.young@oracle.com>
+Reviewed-by: Jack Schwartz <jack.schwartz@oracle.com>
+Upstream-commit-id: 6df7a8f5609
+---
+ shim.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/shim.c b/shim.c
+index ae03da7eddf..d980cadacfc 100644
+--- a/shim.c
++++ b/shim.c
+@@ -1347,6 +1347,11 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
+ 	 */
+ 	Section = context.FirstSection;
+ 	for (i = 0; i < context.NumberOfSections; i++, Section++) {
++		/* Don't try to copy discardable sections with zero size */
++		if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) &&
++		    !Section->Misc.VirtualSize)
++			continue;
++
+ 		base = ImageAddress (buffer, context.ImageSize,
+ 				     Section->VirtualAddress);
+ 		end = ImageAddress (buffer, context.ImageSize,
+-- 
+2.26.2
+
diff --git a/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch b/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch
new file mode 100644
index 0000000..6163a19
--- /dev/null
+++ b/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch
@@ -0,0 +1,30 @@
+From d5b72b322d5b7c6c115833c518e1aa5798076309 Mon Sep 17 00:00:00 2001
+From: dann frazier <dann.frazier@canonical.com>
+Date: Mon, 14 Jan 2019 15:25:11 -0700
+Subject: [PATCH 16/62] Fix apparent typo in ARM 32-on-64 code
+
+The architecture is aarch64, not arch64.
+
+Fixes: 750584c20775 ("Make 64-on-32 maybe work on x86_64.")
+Signed-off-by: dann frazier <dann.frazier@canonical.com>
+Upstream-commit-id: e9f67aaa75a
+---
+ shim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/shim.c b/shim.c
+index d980cadacfc..e4d4fea226d 100644
+--- a/shim.c
++++ b/shim.c
+@@ -150,7 +150,7 @@ allow_32_bit(void)
+ #endif
+ #elif defined(__i386__) || defined(__i686__)
+ 	return 1;
+-#elif defined(__arch64__)
++#elif defined(__aarch64__)
+ 	return 0;
+ #else /* assuming everything else is 32-bit... */
+ 	return 1;
+-- 
+2.26.2
+
diff --git a/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch b/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch
new file mode 100644
index 0000000..961e531
--- /dev/null
+++ b/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch
@@ -0,0 +1,32 @@
+From 8544018093b8aa4311b1e970f8396140c22ede0b Mon Sep 17 00:00:00 2001
+From: Luca Boccassi <bluca@debian.org>
+Date: Mon, 14 Jan 2019 19:29:34 +0000
+Subject: [PATCH 17/62] Makefile: do not run git on clean if there's no .git
+ directory
+
+When building in minimal chroot on build workers, like in Debian (where
+make clean is called at the beginning of the build process), git will
+not be available. Skip the git clean.
+
+Signed-off-by: Luca Boccassi <bluca@debian.org>
+Upstream-commit-id: be352762a01
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 3f2105595a6..fd7e83dc764 100644
+--- a/Makefile
++++ b/Makefile
+@@ -225,7 +225,7 @@ clean-shim-objs:
+ 	@rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME)
+ 	@rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid
+ 	@rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa]
+-	@git clean -f -d -e 'Cryptlib/OpenSSL/*'
++	@if [ -d .git ] ; then git clean -f -d -e 'Cryptlib/OpenSSL/*'; fi
+ 
+ clean: clean-shim-objs
+ 	$(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean
+-- 
+2.26.2
+
diff --git a/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch b/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch
new file mode 100644
index 0000000..e934fa7
--- /dev/null
+++ b/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch
@@ -0,0 +1,40 @@
+From 7f080b30f3c3718d6b2533f62a50f373fd2cda21 Mon Sep 17 00:00:00 2001
+From: Peter Korsgaard <peter@korsgaard.com>
+Date: Thu, 10 Jan 2019 23:34:11 +0100
+Subject: [PATCH 18/62] Make.default: use correct flags to disable unaligned
+ access for 32 bit ARM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The GCC flag to disable unaligned access on 32bit ARM is
+-mno-unaligned-access, not -mstrict-align (which is used on aarch64):
+
+https://lkml.org/lkml/2018/8/3/294
+
+Otherwise build dies with:
+arm-linux-gnueabihf-gcc: error: unrecognized command line option
+   ‘-mstrict-align’; did you mean ‘-Wstrict-aliasing’?
+
+Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
+Upstream-commit-id: 41b93358e8c
+---
+ Make.defaults | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Make.defaults b/Make.defaults
+index bbfc1d7f77b..09807bd8108 100644
+--- a/Make.defaults
++++ b/Make.defaults
+@@ -72,7 +72,7 @@ ifeq ($(ARCH),aarch64)
+ 	ARCH_CFLAGS		?=
+ endif
+ ifeq ($(ARCH),arm)
+-	ARCH_CFLAGS		?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
++	ARCH_CFLAGS		?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mno-unaligned-access
+ 	LIBDIR			?= $(prefix)/lib
+ 	ARCH_SUFFIX		?= arm
+ 	ARCH_SUFFIX_UPPER	?= ARM
+-- 
+2.26.2
+
diff --git a/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch b/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch
new file mode 100644
index 0000000..9ef4f67
--- /dev/null
+++ b/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch
@@ -0,0 +1,34 @@
+From ee832f21c6706d6b3890d82f9d8bcb2bd249ee04 Mon Sep 17 00:00:00 2001
+From: Peter Korsgaard <peter@korsgaard.com>
+Date: Fri, 11 Jan 2019 09:17:42 +0100
+Subject: [PATCH 19/62] Cryptlib: fix build on 32bit ARM
+
+Pass MDE_CPU_ARM, similar to how it is done for the other supported
+architectures, otherwise the build fails in:
+
+Cryptlib/Include/OpenSslSupport.h:55:2: error:
+ #error Unknown target architecture
+
+Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
+Upstream-commit-id: cb83c14628b
+---
+ Cryptlib/Makefile | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile
+index 2aa569594a0..5c098f34cec 100644
+--- a/Cryptlib/Makefile
++++ b/Cryptlib/Makefile
+@@ -19,6 +19,9 @@ endif
+ ifeq ($(ARCH),aarch64)
+ 	CFLAGS	+= -DMDE_CPU_AARCH64
+ endif
++ifeq ($(ARCH),arm)
++	CFLAGS	+= -DMDE_CPU_ARM
++endif
+ LDFLAGS		= -nostdlib -znocombreloc
+ 
+ TARGET		= libcryptlib.a
+-- 
+2.26.2
+
diff --git a/SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch b/SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch
new file mode 100644
index 0000000..ca6f732
--- /dev/null
+++ b/SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch
@@ -0,0 +1,61 @@
+From ac0400b20264ef67b67891d2216edd3fe20e5571 Mon Sep 17 00:00:00 2001
+From: Patrick Uiterwijk <patrick@puiterwijk.org>
+Date: Mon, 5 Nov 2018 14:51:16 +0100
+Subject: [PATCH 20/62] Make sure that MOK variables always get mirrored
+
+Without this, if a Mok variable doesn't exist in Boot Services, it will also
+not be copied to Runtime, even if we have data to be added to it (vendor cert).
+This patch makes sure that if we have extra data to append, we still mirror
+the variable.
+
+Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
+Upstream-commit-id: 9ab0d796bdc
+---
+ mok.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 38675211e0e..00dd1ad3034 100644
+--- a/mok.c
++++ b/mok.c
+@@ -223,11 +223,26 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		UINT32 attrs = 0;
+ 		BOOLEAN delete = FALSE, present, addend;
+ 
++		addend = (v->addend_source && v->addend_size &&
++			  *v->addend_source && *v->addend_size)
++			? TRUE : FALSE;
++
+ 		efi_status = get_variable_attr(v->name,
+ 					       &v->data, &v->data_size,
+ 					       *v->guid, &attrs);
+-		if (efi_status == EFI_NOT_FOUND)
++		if (efi_status == EFI_NOT_FOUND) {
++			if (v->rtname && addend) {
++				efi_status = mirror_one_mok_variable(v);
++				if (EFI_ERROR(efi_status) &&
++				    ret != EFI_SECURITY_VIOLATION)
++					ret = efi_status;
++			}
++			/*
++			 * after possibly adding, we can continue, no
++			 * further checks to be done.
++			 */
+ 			continue;
++		}
+ 		if (EFI_ERROR(efi_status)) {
+ 			perror(L"Could not verify %s: %r\n", v->name,
+ 			       efi_status);
+@@ -272,9 +287,6 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		}
+ 
+ 		present = (v->data && v->data_size) ? TRUE : FALSE;
+-		addend = (v->addend_source && v->addend_size &&
+-			  *v->addend_source && *v->addend_size)
+-			? TRUE : FALSE;
+ 
+ 		if (v->flags & MOK_VARIABLE_MEASURE && present) {
+ 			/*
+-- 
+2.26.2
+
diff --git a/SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch b/SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch
new file mode 100644
index 0000000..135788e
--- /dev/null
+++ b/SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch
@@ -0,0 +1,50 @@
+From f748139695384fb4e09833898f0b8cb3ab85d810 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Wed, 21 Nov 2018 12:47:43 +0800
+Subject: [PATCH 21/62] mok: fix the mirroring of RT variables
+
+When there is no key in MokList, import_mok_state() just skipped MokList
+even though it should always mirror the vendor cert. Besides, the faulty
+check of 'present' and 'addend' invalidates the mirroring of MokListXRT,
+MokSBStateRT, and MokIgnoreDB.
+
+https://github.com/rhboot/shim/issues/154
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 4b27ae034ba
+---
+ mok.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 00dd1ad3034..41925abbb49 100644
+--- a/mok.c
++++ b/mok.c
+@@ -231,12 +231,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 					       &v->data, &v->data_size,
+ 					       *v->guid, &attrs);
+ 		if (efi_status == EFI_NOT_FOUND) {
+-			if (v->rtname && addend) {
+-				efi_status = mirror_one_mok_variable(v);
+-				if (EFI_ERROR(efi_status) &&
+-				    ret != EFI_SECURITY_VIOLATION)
+-					ret = efi_status;
+-			}
++			if (addend)
++				goto mirror_addend;
+ 			/*
+ 			 * after possibly adding, we can continue, no
+ 			 * further checks to be done.
+@@ -316,7 +312,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 			}
+ 		}
+ 
+-		if (v->rtname && present && addend) {
++mirror_addend:
++		if (v->rtname && (present || addend)) {
+ 			if (v->flags & MOK_MIRROR_DELETE_FIRST)
+ 				LibDeleteVariable(v->rtname, v->guid);
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch b/SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
new file mode 100644
index 0000000..bd8d9cf
--- /dev/null
+++ b/SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
@@ -0,0 +1,110 @@
+From ff6e5cda136c8fd637d3d6b8334f4f221ba2b1ee Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 31 Jan 2019 13:45:30 -0500
+Subject: [PATCH 22/62] mok: consolidate mirroring code in a helper instead of
+ using goto
+
+There's no reason to complicate the logic with a goto here, instead just
+pull the logic we're jumping to out to a helper function.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 29c11483101
+---
+ mok.c  | 42 +++++++++++++++++++++++++++++-------------
+ shim.h |  2 ++
+ 2 files changed, 31 insertions(+), 13 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 41925abbb49..2b9d796a0e8 100644
+--- a/mok.c
++++ b/mok.c
+@@ -130,7 +130,8 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{ NULL, }
+ };
+ 
+-static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
++static EFI_STATUS nonnull(1)
++mirror_one_mok_variable(struct mok_state_variable *v)
+ {
+ 	EFI_STATUS efi_status = EFI_SUCCESS;
+ 	void *FullData = NULL;
+@@ -196,6 +197,29 @@ static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
+ 	return efi_status;
+ }
+ 
++/*
++ * Mirror a variable if it has an rtname, and preserve any
++ * EFI_SECURITY_VIOLATION status at the same time.
++ */
++static EFI_STATUS nonnull(1)
++maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
++{
++	EFI_STATUS efi_status;
++	if (v->rtname) {
++		if (v->flags & MOK_MIRROR_DELETE_FIRST)
++			LibDeleteVariable(v->rtname, v->guid);
++
++		efi_status = mirror_one_mok_variable(v);
++		if (EFI_ERROR(efi_status)) {
++			if (ret != EFI_SECURITY_VIOLATION)
++				ret = efi_status;
++			perror(L"Could not create %s: %r\n", v->rtname,
++			       efi_status);
++		}
++	}
++	return ret;
++}
++
+ /*
+  * Verify our non-volatile MoK state.  This checks the variables above
+  * accessable and have valid attributes.  If they don't, it removes
+@@ -232,7 +256,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 					       *v->guid, &attrs);
+ 		if (efi_status == EFI_NOT_FOUND) {
+ 			if (addend)
+-				goto mirror_addend;
++				ret = maybe_mirror_one_mok_variable(v, ret);
+ 			/*
+ 			 * after possibly adding, we can continue, no
+ 			 * further checks to be done.
+@@ -312,16 +336,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 			}
+ 		}
+ 
+-mirror_addend:
+-		if (v->rtname && (present || addend)) {
+-			if (v->flags & MOK_MIRROR_DELETE_FIRST)
+-				LibDeleteVariable(v->rtname, v->guid);
+-
+-			efi_status = mirror_one_mok_variable(v);
+-			if (EFI_ERROR(efi_status) &&
+-			    ret != EFI_SECURITY_VIOLATION)
+-				ret = efi_status;
+-		}
++		if (present)
++			ret = maybe_mirror_one_mok_variable(v, ret);
+ 	}
+ 
+ 	/*
+@@ -340,4 +356,4 @@ mirror_addend:
+ 	return ret;
+ }
+ 
+-// vim:fenc=utf-8:tw=75
++// vim:fenc=utf-8:tw=75:noet
+diff --git a/shim.h b/shim.h
+index 2b359d821e3..c26d5f06538 100644
+--- a/shim.h
++++ b/shim.h
+@@ -30,6 +30,8 @@
+ 
+ #include <stddef.h>
+ 
++#define nonnull(...) __attribute__((__nonnull__(__VA_ARGS__)))
++
+ #define min(a, b) ({(a) < (b) ? (a) : (b);})
+ 
+ #ifdef __x86_64__
+-- 
+2.26.2
+
diff --git a/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch b/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch
new file mode 100644
index 0000000..fce8963
--- /dev/null
+++ b/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch
@@ -0,0 +1,82 @@
+From 7a3638173e406ce7cbd682213606e3152244fcb2 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Wed, 19 Dec 2018 11:27:42 +0800
+Subject: [PATCH 23/62] shim: only include shim_cert.h in shim.c
+
+The shim_cert array was declared as a static array, and every user of
+shim_cert.h would create a shim_cert array for its own and grow the file
+size. To remove the unnecessary duplicate shim_cert arrays, this commit
+declares shim_cert in shim.c while other users still can access the
+array through the external variables: build_cert and build_cert_size.
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: 4e2d62f0f4e
+---
+ shim.c | 11 +++++++++++
+ shim.h |  7 ++++---
+ 2 files changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index e4d4fea226d..0a95f94b360 100644
+--- a/shim.c
++++ b/shim.c
+@@ -34,6 +34,9 @@
+  */
+ 
+ #include "shim.h"
++#if defined(ENABLE_SHIM_CERT)
++#include "shim_cert.h"
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 
+ #include <openssl/err.h>
+ #include <openssl/bn.h>
+@@ -75,6 +78,10 @@ UINT32 vendor_cert_size;
+ UINT32 vendor_dbx_size;
+ UINT8 *vendor_cert;
+ UINT8 *vendor_dbx;
++#if defined(ENABLE_SHIM_CERT)
++UINT32 build_cert_size;
++UINT8 *build_cert;
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 
+ /*
+  * indicator of how an image has been verified
+@@ -2562,6 +2569,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 	vendor_dbx_size = cert_table.vendor_dbx_size;
+ 	vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
+ 	vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
++#if defined(ENABLE_SHIM_CERT)
++	build_cert_size = sizeof(shim_cert);
++	build_cert = shim_cert;
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 	CHAR16 *msgs[] = {
+ 		L"import_mok_state() failed\n",
+ 		L"shim_int() failed\n",
+diff --git a/shim.h b/shim.h
+index c26d5f06538..e4d40505f09 100644
+--- a/shim.h
++++ b/shim.h
+@@ -122,9 +122,6 @@
+ #include "include/variables.h"
+ 
+ #include "version.h"
+-#ifdef ENABLE_SHIM_CERT
+-#include "shim_cert.h"
+-#endif
+ 
+ INTERFACE_DECL(_SHIM_LOCK);
+ 
+@@ -172,6 +169,10 @@ extern UINT32 vendor_cert_size;
+ extern UINT32 vendor_dbx_size;
+ extern UINT8 *vendor_cert;
+ extern UINT8 *vendor_dbx;
++#if defined(ENABLE_SHIM_CERT)
++extern UINT32 build_cert_size;
++extern UINT8 *build_cert;
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 
+ extern UINT8 user_insecure_mode;
+ extern UINT8 ignore_db;
+-- 
+2.26.2
+
diff --git a/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch b/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch
new file mode 100644
index 0000000..d331df4
--- /dev/null
+++ b/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch
@@ -0,0 +1,153 @@
+From 3d62232feb296b238ca5d7963ba40a2c346767e7 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Wed, 19 Dec 2018 12:40:02 +0800
+Subject: [PATCH 24/62] mok: also mirror the build cert to MokListRT
+
+If the build cert is enabled, we should also mirror it to MokListRT.
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: aecbe1f99b6
+---
+ mok.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 72 insertions(+), 6 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 2b9d796a0e8..6150d8c8868 100644
+--- a/mok.c
++++ b/mok.c
+@@ -68,6 +68,10 @@ struct mok_state_variable {
+ 	 */
+ 	UINT8 **addend_source;
+ 	UINT32 *addend_size;
++#if defined(ENABLE_SHIM_CERT)
++	UINT8 **build_cert;
++	UINT32 *build_cert_size;
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 	UINT32 yes_attr;
+ 	UINT32 no_attr;
+ 	UINT32 flags;
+@@ -90,6 +94,10 @@ struct mok_state_variable mok_state_variables[] = {
+ 	 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
+ 	 .addend_source = &vendor_cert,
+ 	 .addend_size = &vendor_cert_size,
++#if defined(ENABLE_SHIM_CERT)
++	 .build_cert = &build_cert,
++	 .build_cert_size = &build_cert_size,
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 	 .flags = MOK_MIRROR_KEYDB |
+ 		  MOK_VARIABLE_LOG,
+ 	 .pcr = 14,
+@@ -130,6 +138,22 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{ NULL, }
+ };
+ 
++inline BOOLEAN check_vendor_cert(struct mok_state_variable *v)
++{
++	return (v->addend_source && v->addend_size &&
++		*v->addend_source && *v->addend_size) ? TRUE : FALSE;
++}
++#if defined(ENABLE_SHIM_CERT)
++inline BOOLEAN check_build_cert(struct mok_state_variable *v)
++{
++	return (v->build_cert && v->build_cert_size &&
++		*v->build_cert && *v->build_cert_size) ? TRUE : FALSE;
++}
++#define check_addend(v) (check_vendor_cert(v) || check_build_cert(v))
++#else
++#define check_addend(v) check_vendor_cert(v)
++#endif /* defined(ENABLE_SHIM_CERT) */
++
+ static EFI_STATUS nonnull(1)
+ mirror_one_mok_variable(struct mok_state_variable *v)
+ {
+@@ -138,15 +162,27 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 	UINTN FullDataSize = 0;
+ 	uint8_t *p = NULL;
+ 
+-	if ((v->flags & MOK_MIRROR_KEYDB) &&
+-	    v->addend_source && *v->addend_source &&
+-	    v->addend_size && *v->addend_size) {
++	if ((v->flags & MOK_MIRROR_KEYDB) && check_addend(v)) {
+ 		EFI_SIGNATURE_LIST *CertList = NULL;
+ 		EFI_SIGNATURE_DATA *CertData = NULL;
++#if defined(ENABLE_SHIM_CERT)
++		FullDataSize = v->data_size;
++		if (check_build_cert(v)) {
++			FullDataSize += sizeof (*CertList)
++					+ sizeof (EFI_GUID)
++					+ *v->build_cert_size;
++		}
++		if (check_vendor_cert(v)) {
++			FullDataSize += sizeof (*CertList)
++					+ sizeof (EFI_GUID)
++					+ *v->addend_size;
++		}
++#else
+ 		FullDataSize = v->data_size
+ 			     + sizeof (*CertList)
+ 			     + sizeof (EFI_GUID)
+ 			     + *v->addend_size;
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 		FullData = AllocatePool(FullDataSize);
+ 		if (!FullData) {
+ 			perror(L"Failed to allocate space for MokListRT\n");
+@@ -158,6 +194,35 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 			CopyMem(p, v->data, v->data_size);
+ 			p += v->data_size;
+ 		}
++
++#if defined(ENABLE_SHIM_CERT)
++		if (check_build_cert(v) == FALSE)
++			goto skip_build_cert;
++
++		CertList = (EFI_SIGNATURE_LIST *)p;
++		p += sizeof (*CertList);
++		CertData = (EFI_SIGNATURE_DATA *)p;
++		p += sizeof (EFI_GUID);
++
++		CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
++		CertList->SignatureListSize = *v->build_cert_size
++					      + sizeof (*CertList)
++					      + sizeof (*CertData)
++					      -1;
++		CertList->SignatureHeaderSize = 0;
++		CertList->SignatureSize = *v->build_cert_size +
++					  sizeof (EFI_GUID);
++
++		CertData->SignatureOwner = SHIM_LOCK_GUID;
++		CopyMem(p, *v->build_cert, *v->build_cert_size);
++
++		p += *v->build_cert_size;
++
++		if (check_vendor_cert(v) == FALSE)
++			goto skip_vendor_cert;
++skip_build_cert:
++#endif /* defined(ENABLE_SHIM_CERT) */
++
+ 		CertList = (EFI_SIGNATURE_LIST *)p;
+ 		p += sizeof (*CertList);
+ 		CertData = (EFI_SIGNATURE_DATA *)p;
+@@ -174,6 +239,9 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 		CertData->SignatureOwner = SHIM_LOCK_GUID;
+ 		CopyMem(p, *v->addend_source, *v->addend_size);
+ 
++#if defined(ENABLE_SHIM_CERT)
++skip_vendor_cert:
++#endif /* defined(ENABLE_SHIM_CERT) */
+ 		if (v->data && v->data_size)
+ 			FreePool(v->data);
+ 		v->data = FullData;
+@@ -247,9 +315,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		UINT32 attrs = 0;
+ 		BOOLEAN delete = FALSE, present, addend;
+ 
+-		addend = (v->addend_source && v->addend_size &&
+-			  *v->addend_source && *v->addend_size)
+-			? TRUE : FALSE;
++		addend = check_addend(v);
+ 
+ 		efi_status = get_variable_attr(v->name,
+ 					       &v->data, &v->data_size,
+-- 
+2.26.2
+
diff --git a/SOURCES/0025-mok-minor-cleanups.patch b/SOURCES/0025-mok-minor-cleanups.patch
new file mode 100644
index 0000000..98120d3
--- /dev/null
+++ b/SOURCES/0025-mok-minor-cleanups.patch
@@ -0,0 +1,37 @@
+From ff890cf45224926574eee93b0ea1494468870bd3 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 31 Jan 2019 14:04:57 -0500
+Subject: [PATCH 25/62] mok: minor cleanups
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 617b9007668
+---
+ mok.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 6150d8c8868..59630e74425 100644
+--- a/mok.c
++++ b/mok.c
+@@ -138,13 +138,16 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{ NULL, }
+ };
+ 
+-inline BOOLEAN check_vendor_cert(struct mok_state_variable *v)
++static inline BOOLEAN nonnull(1)
++check_vendor_cert(struct mok_state_variable *v)
+ {
+ 	return (v->addend_source && v->addend_size &&
+ 		*v->addend_source && *v->addend_size) ? TRUE : FALSE;
+ }
++
+ #if defined(ENABLE_SHIM_CERT)
+-inline BOOLEAN check_build_cert(struct mok_state_variable *v)
++static inline BOOLEAN nonnull(1)
++check_build_cert(struct mok_state_variable *v)
+ {
+ 	return (v->build_cert && v->build_cert_size &&
+ 		*v->build_cert && *v->build_cert_size) ? TRUE : FALSE;
+-- 
+2.26.2
+
diff --git a/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch b/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch
new file mode 100644
index 0000000..30b8374
--- /dev/null
+++ b/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch
@@ -0,0 +1,91 @@
+From cf3f99c3b1e11c8c83938784975331db5efb410f Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg59@google.com>
+Date: Tue, 11 Dec 2018 15:25:44 -0800
+Subject: [PATCH 26/62] Remove call to TPM2 get_event_log()
+
+Calling the TPM2 get_event_log causes the firmware to start logging
+events to the final events table, but implementations may also continue
+logging to the boot services event log. Any OS that wishes to
+reconstruct the full PCR state must already look at both the final
+events log and the boot services event log, so if this call is made
+anywhere other than immediately before ExitBootServices() then the OS
+must deduplicate events that occur in both, complicating things
+immensely.
+
+Linux already has support for copying up the boot services event log
+across the ExitBootServices() boundary, so there's no reason to make
+this call. Remove it.
+
+Signed-off-by: Matthew Garrett <mjg59@google.com>
+Upstream-commit-id: fd7c3bd920b
+---
+ tpm.c | 46 ----------------------------------------------
+ 1 file changed, 46 deletions(-)
+
+diff --git a/tpm.c b/tpm.c
+index 674e69b715f..f07362c70bb 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -70,41 +70,6 @@ static BOOLEAN tpm2_present(EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
+ 	return FALSE;
+ }
+ 
+-static inline EFI_TCG2_EVENT_LOG_BITMAP
+-tpm2_get_supported_logs(efi_tpm2_protocol_t *tpm,
+-			EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
+-			BOOLEAN old_caps)
+-{
+-	if (old_caps)
+-		return ((TREE_BOOT_SERVICE_CAPABILITY *)caps)->SupportedEventLogs;
+-
+-	return caps->SupportedEventLogs;
+-}
+-
+-/*
+- * According to TCG EFI Protocol Specification for TPM 2.0 family,
+- * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
+- * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
+- * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
+- * internal switch through calling get_event_log() in order to allow
+- * to retrieve the logs from OS runtime.
+- */
+-static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2,
+-						  EFI_TCG2_EVENT_LOG_BITMAP supported_logs)
+-{
+-	EFI_TCG2_EVENT_LOG_FORMAT log_fmt;
+-	EFI_PHYSICAL_ADDRESS start;
+-	EFI_PHYSICAL_ADDRESS end;
+-	BOOLEAN truncated;
+-
+-	if (supported_logs & EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+-		log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+-	else
+-		log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+-
+-	return tpm2->get_event_log(tpm2, log_fmt, &start, &end, &truncated);
+-}
+-
+ static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm,
+ 				      efi_tpm2_protocol_t **tpm2,
+ 				      BOOLEAN *old_caps_p,
+@@ -166,17 +131,6 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+ #endif
+ 	} else if (tpm2) {
+ 		EFI_TCG2_EVENT *event;
+-		EFI_TCG2_EVENT_LOG_BITMAP supported_logs;
+-
+-		supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps);
+-
+-		efi_status = trigger_tcg2_final_events_table(tpm2,
+-							     supported_logs);
+-		if (EFI_ERROR(efi_status)) {
+-			perror(L"Unable to trigger tcg2 final events table: %r\n",
+-			       efi_status);
+-			return efi_status;
+-		}
+ 
+ 		event = AllocatePool(sizeof(*event) + logsize);
+ 		if (!event) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch b/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch
new file mode 100644
index 0000000..d07e6e2
--- /dev/null
+++ b/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch
@@ -0,0 +1,48 @@
+From 95bd1d88003a9a7c2732472b061ad2a9c7140419 Mon Sep 17 00:00:00 2001
+From: Patrick Uiterwijk <patrick@puiterwijk.org>
+Date: Thu, 6 Dec 2018 10:08:45 +0100
+Subject: [PATCH 27/62] Make EFI variable copying fatal only on secureboot
+ enabled systems
+
+I have come across systems that are unwilling to reserve enough memory for
+a MokListRT big enough for big certificates.
+This seems to be the case with firmware implementations that do not support
+secureboot, which is probably the reason they went with much lower variable
+storage.
+
+This patch set makes sure we can still boot on those systems, by only
+making the copy action fatal if the system has secure boot enabled, or if
+the error was anything other than EFI_INVALID_PARAMETER.
+
+Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
+Upstream-commit-id: 741c61abba7
+---
+ shim.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/shim.c b/shim.c
+index 0a95f94b360..d4ed332f901 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2609,7 +2609,17 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 	 * boot-services-only state variables are what we think they are.
+ 	 */
+ 	efi_status = import_mok_state(image_handle);
+-	if (EFI_ERROR(efi_status)) {
++	if (!secure_mode() && efi_status == EFI_INVALID_PARAMETER) {
++		/*
++		 * Make copy failures fatal only if secure_mode is enabled, or
++		 * the error was anything else than EFI_INVALID_PARAMETER.
++		 * There are non-secureboot firmware implementations that don't
++		 * reserve enough EFI variable memory to fit the variable.
++		 */
++		console_print(L"Importing MOK states has failed: %s: %r\n",
++			      msgs[msg], efi_status);
++		console_print(L"Continuing boot since secure mode is disabled");
++	} else if (EFI_ERROR(efi_status)) {
+ die:
+ 		console_print(L"Something has gone seriously wrong: %s: %r\n",
+ 			      msgs[msg], efi_status);
+-- 
+2.26.2
+
diff --git a/SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch b/SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch
new file mode 100644
index 0000000..c671a9a
--- /dev/null
+++ b/SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch
@@ -0,0 +1,66 @@
+From 344a8364cb05cdaafc43231d0f73d5217c4e118c Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 12 Feb 2019 18:04:49 -0500
+Subject: [PATCH 28/62] VLogError(): Avoid NULL pointer dereferences in
+ (V)Sprint calls
+
+VLogError() calculates the size of format strings by using calls to
+SPrint and VSPrint with a StrSize of 0 and NULL for an output buffer.
+Unfortunately, this is an incorrect usage of (V)Sprint. A StrSize
+of "0" is special-cased to mean "there is no limit". So, we end up
+writing our string to address 0x0. This was discovered because it
+causes a crash on ARM where, unlike x86, it does not necessarily
+have memory mapped at 0x0.
+
+Avoid the (V)Sprint calls altogether by using (V)PoolPrint, which
+handles the size calculation and allocation for us.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Fixes: 25f6fd08cd26 ("try to show errors more usefully.")
+[dannf: commit message ]
+Signed-off-by: dann frazier <dann.frazier@canonical.com>
+Upstream-commit-id: 20e731f423a
+---
+ errlog.c | 15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/errlog.c b/errlog.c
+index 18be4822d53..eebb266d396 100644
+--- a/errlog.c
++++ b/errlog.c
+@@ -14,29 +14,20 @@ EFI_STATUS
+ VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args)
+ {
+ 	va_list args2;
+-	UINTN size = 0, size2;
+ 	CHAR16 **newerrs;
+ 
+-	size = SPrint(NULL, 0, L"%a:%d %a() ", file, line, func);
+-	va_copy(args2, args);
+-	size2 = VSPrint(NULL, 0, fmt, args2);
+-	va_end(args2);
+-
+ 	newerrs = ReallocatePool(errs, (nerrs + 1) * sizeof(*errs),
+ 				       (nerrs + 3) * sizeof(*errs));
+ 	if (!newerrs)
+ 		return EFI_OUT_OF_RESOURCES;
+ 
+-	newerrs[nerrs] = AllocatePool(size*2+2);
++	newerrs[nerrs] = PoolPrint(L"%a:%d %a() ", file, line, func);
+ 	if (!newerrs[nerrs])
+ 		return EFI_OUT_OF_RESOURCES;
+-	newerrs[nerrs+1] = AllocatePool(size2*2+2);
++	va_copy(args2, args);
++	newerrs[nerrs+1] = VPoolPrint(fmt, args2);
+ 	if (!newerrs[nerrs+1])
+ 		return EFI_OUT_OF_RESOURCES;
+-
+-	SPrint(newerrs[nerrs], size*2+2, L"%a:%d %a() ", file, line, func);
+-	va_copy(args2, args);
+-	VSPrint(newerrs[nerrs+1], size2*2+2, fmt, args2);
+ 	va_end(args2);
+ 
+ 	nerrs += 2;
+-- 
+2.26.2
+
diff --git a/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch b/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch
new file mode 100644
index 0000000..617ae6a
--- /dev/null
+++ b/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch
@@ -0,0 +1,98 @@
+From 10d6e3d90f1ea504a1dedaea50478c444e92951c Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 15 Mar 2019 09:52:02 -0400
+Subject: [PATCH 29/62] Once again, try even harder to get binaries without
+ timestamps in them.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+$ objdump -x /builddir/build/BUILDROOT/shim-*/usr/share/shim/*/shimx64.efi | grep 'Time/Date'
+Time/Date		Thu Jan  1 00:00:08 1970
+$ _
+
+"What is despair? I have known it—hear my song. Despair is when you’re
+debugging a kernel driver and you look at a memory dump and you see that
+a pointer has a value of 7."
+ - http://scholar.harvard.edu/files/mickens/files/thenightwatch.pdf
+
+objcopy only knows about -D for some targets.
+ld only believes in --no-insert-timestamp in some versions.
+dd takes off and nukes the site from orbit.
+
+It's the only way to be sure.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: a4a1fbe728c
+---
+ Make.defaults | 4 ++++
+ Makefile      | 6 ++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/Make.defaults b/Make.defaults
+index 09807bd8108..f0bfa9fd573 100644
+--- a/Make.defaults
++++ b/Make.defaults
+@@ -50,6 +50,7 @@ ifeq ($(ARCH),x86_64)
+ 	ARCH_SUFFIX		?= x64
+ 	ARCH_SUFFIX_UPPER	?= X64
+ 	ARCH_LDFLAGS		?=
++	TIMESTAMP_LOCATION	:= 136
+ endif
+ ifeq ($(ARCH),ia32)
+ 	ARCH_CFLAGS		?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
+@@ -60,6 +61,7 @@ ifeq ($(ARCH),ia32)
+ 	ARCH_SUFFIX_UPPER	?= IA32
+ 	ARCH_LDFLAGS		?=
+ 	ARCH_CFLAGS		?= -m32
++	TIMESTAMP_LOCATION	:= 136
+ endif
+ ifeq ($(ARCH),aarch64)
+ 	ARCH_CFLAGS		?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
+@@ -70,6 +72,7 @@ ifeq ($(ARCH),aarch64)
+ 	SUBSYSTEM		:= 0xa
+ 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
+ 	ARCH_CFLAGS		?=
++	TIMESTAMP_LOCATION	:= 72
+ endif
+ ifeq ($(ARCH),arm)
+ 	ARCH_CFLAGS		?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mno-unaligned-access
+@@ -79,6 +82,7 @@ ifeq ($(ARCH),arm)
+ 	FORMAT			:= -O binary
+ 	SUBSYSTEM		:= 0xa
+ 	ARCH_LDFLAGS		+= --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
++	TIMESTAMP_LOCATION	:= 72
+ endif
+ 
+ CFLAGS		= -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
+diff --git a/Makefile b/Makefile
+index fd7e83dc764..49e14a26521 100644
+--- a/Makefile
++++ b/Makefile
+@@ -189,11 +189,13 @@ endif
+ ifneq ($(OBJCOPY_GTE224),1)
+ 	$(error objcopy >= 2.24 is required)
+ endif
+-	$(OBJCOPY) -j .text -j .sdata -j .data -j .data.ident \
++	$(OBJCOPY) -D -j .text -j .sdata -j .data -j .data.ident \
+ 		-j .dynamic -j .dynsym -j .rel* \
+ 		-j .rela* -j .reloc -j .eh_frame \
+ 		-j .vendor_cert \
+ 		$(FORMAT) $^ $@
++	# I am tired of wasting my time fighting binutils timestamp code.
++	dd conv=notrunc bs=1 count=4 seek=$(TIMESTAMP_LOCATION) if=/dev/zero of=$@
+ 
+ ifneq ($(origin ENABLE_SHIM_HASH),undefined)
+ %.hash : %.efi
+@@ -204,7 +206,7 @@ endif
+ ifneq ($(OBJCOPY_GTE224),1)
+ 	$(error objcopy >= 2.24 is required)
+ endif
+-	$(OBJCOPY) -j .text -j .sdata -j .data \
++	$(OBJCOPY) -D -j .text -j .sdata -j .data \
+ 		-j .dynamic -j .dynsym -j .rel* \
+ 		-j .rela* -j .reloc -j .eh_frame \
+ 		-j .debug_info -j .debug_abbrev -j .debug_aranges \
+-- 
+2.26.2
+
diff --git a/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch b/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch
new file mode 100644
index 0000000..ba8c278
--- /dev/null
+++ b/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch
@@ -0,0 +1,280 @@
+From 1b382ef850de5a6c59b192c146a0e8d898d2d961 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 23 Oct 2018 18:17:57 -0400
+Subject: [PATCH 30/62] shim: Rework pause functions and add read_counter()
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: fc6b0bca84e
+---
+ shim.c             |   4 +-
+ include/asm.h      |  59 +++++++++++++++++
+ include/compiler.h | 156 +++++++++++++++++++++++++++++++++++++++++++++
+ shim.h             |   1 +
+ 4 files changed, 217 insertions(+), 3 deletions(-)
+ create mode 100644 include/asm.h
+ create mode 100644 include/compiler.h
+
+diff --git a/shim.c b/shim.c
+index d4ed332f901..f69e69487fc 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2543,16 +2543,14 @@ debug_hook(void)
+ #if defined(__x86_64__) || defined(__i386__) || defined(__i686__)
+ 		if (x > 4294967294ULL)
+ 			break;
+-		__asm__ __volatile__("pause");
+ #elif defined(__aarch64__)
+ 		if (x > 1000)
+ 			break;
+-		__asm__ __volatile__("wfi");
+ #else
+ 		if (x > 12000)
+ 			break;
+-		msleep(5000);
+ #endif
++		pause();
+ 	}
+ 	x = 1;
+ }
+diff --git a/include/asm.h b/include/asm.h
+new file mode 100644
+index 00000000000..5e8f9ed9d7c
+--- /dev/null
++++ b/include/asm.h
+@@ -0,0 +1,59 @@
++/*
++ * asm.h
++ * Copyright 2018 Peter Jones <pjones@redhat.com>
++ */
++
++#ifndef SHIM_ASM_H_
++#define SHIM_ASM_H_
++
++#define __stringify_1(x...)     #x
++#define __stringify(x...)       __stringify_1(x)
++
++static inline uint64_t read_counter(void)
++{
++        uint64_t val;
++#if defined (__x86_64__)
++        unsigned long low, high;
++        __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
++        val = (low) | (high) << 32;
++#elif defined(__i386__) || defined(__i686__)
++        __asm__ __volatile__("rdtsc" : "=A" (val));
++#elif defined(__aarch64__)
++        __asm__ __volatile__ ("mrs %0, pmccntr_el0" : "=r" (val));
++#elif defined(__arm__)
++        __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
++#else
++#error unsupported arch
++#endif
++        return val;
++}
++
++#if defined(__x86_64__) || defined(__i386__) || defined(__i686__)
++static inline void pause(void)
++{
++	__asm__ __volatile__("pause");
++}
++#elif defined(__aarch64__)
++static inline void pause(void)
++{
++		__asm__ __volatile__("wfi");
++}
++#else
++static inline void pause(void)
++{
++        uint64_t a, b;
++        int x;
++        extern void msleep(unsigned long msecs);
++
++        a = read_counter();
++        for (x = 0; x < 1000; x++) {
++                msleep(1000);
++                b = read_counter();
++                if (a != b)
++                        break;
++        }
++}
++#endif
++
++#endif /* !SHIM_ASM_H_ */
++// vim:fenc=utf-8:tw=75:et
+diff --git a/include/compiler.h b/include/compiler.h
+new file mode 100644
+index 00000000000..a2a0859379f
+--- /dev/null
++++ b/include/compiler.h
+@@ -0,0 +1,156 @@
++/*
++ * compiler.h
++ * Copyright 2019 Peter Jones <pjones@redhat.com>
++ */
++
++#ifndef COMPILER_H_
++#define COMPILER_H_
++
++#ifndef UNUSED
++#define UNUSED __attribute__((__unused__))
++#endif
++#ifndef HIDDEN
++#define HIDDEN __attribute__((__visibility__ ("hidden")))
++#endif
++#ifndef PUBLIC
++#define PUBLIC __attribute__((__visibility__ ("default")))
++#endif
++#ifndef DESTRUCTOR
++#define DESTRUCTOR __attribute__((destructor))
++#endif
++#ifndef CONSTRUCTOR
++#define CONSTRUCTOR __attribute__((constructor))
++#endif
++#ifndef ALIAS
++#define ALIAS(x) __attribute__((weak, alias (#x)))
++#endif
++#ifndef NONNULL
++#endif
++#define NONNULL(first, args...) __attribute__((__nonnull__(first, ## args)))
++#ifndef PRINTF
++#define PRINTF(first, args...) __attribute__((__format__(printf, first, ## args)))
++#endif
++#ifndef FLATTEN
++#define FLATTEN __attribute__((__flatten__))
++#endif
++#ifndef PACKED
++#define PACKED __attribute__((__packed__))
++#endif
++#ifndef VERSION
++#define VERSION(sym, ver) __asm__(".symver " # sym "," # ver)
++#endif
++#ifndef NORETURN
++#define NORETURN __attribute__((__noreturn__))
++#endif
++#ifndef ALIGNED
++#define ALIGNED(n) __attribute__((__aligned__(n)))
++#endif
++#ifndef CLEANUP_FUNC
++#define CLEANUP_FUNC(x) __attribute__((__cleanup__(x)))
++#endif
++#ifndef USED
++#define USED __attribute__((__used__))
++#endif
++#ifndef SECTION
++#define SECTION(x) __attribute__((__section__(x)))
++#endif
++#ifndef OPTIMIZE
++#define OPTIMIZE(x) __attribute__((__optimize__(x)))
++#endif
++
++#ifndef __CONCAT
++#define __CONCAT3(a, b, c) a ## b ## c
++#endif
++#ifndef CAT
++#define CAT(a, b) __CONCAT(a, b)
++#endif
++#ifndef CAT3
++#define CAT3(a, b, c) __CONCAT3(a, b, c)
++#endif
++#ifndef STRING
++#define STRING(x) __STRING(x)
++#endif
++
++#ifndef WRITE_ONCE
++#define WRITE_ONCE(var, val) \
++        (*((volatile typeof(val) *)(&(var))) = (val))
++#endif
++
++#ifndef READ_ONCE
++#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
++#endif
++
++#ifndef likely
++#define likely(x)	__builtin_expect(!!(x), 1)
++#endif
++
++#ifndef unlikely
++#define unlikely(x)	__builtin_expect(!!(x), 0)
++#endif
++
++/* Are two types/vars the same type (ignoring qualifiers)? */
++#ifndef __same_type
++#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
++#endif
++
++/* Compile time object size, -1 for unknown */
++#ifndef __compiletime_object_size
++# define __compiletime_object_size(obj) -1
++#endif
++#ifndef __compiletime_warning
++# define __compiletime_warning(message)
++#endif
++#ifndef __compiletime_error
++# define __compiletime_error(message)
++#endif
++
++#ifndef __compiletime_assert
++#define __compiletime_assert(condition, msg, prefix, suffix)		\
++	do {								\
++		extern void prefix ## suffix(void) __compiletime_error(msg); \
++		if (!(condition))					\
++			prefix ## suffix();				\
++	} while (0)
++#endif
++
++#ifndef _compiletime_assert
++#define _compiletime_assert(condition, msg, prefix, suffix) \
++	__compiletime_assert(condition, msg, prefix, suffix)
++#endif
++
++/**
++ * compiletime_assert - break build and emit msg if condition is false
++ * @condition: a compile-time constant condition to check
++ * @msg:       a message to emit if condition is false
++ *
++ * In tradition of POSIX assert, this macro will break the build if the
++ * supplied condition is *false*, emitting the supplied error message if the
++ * compiler has support to do so.
++ */
++#ifndef compiletime_assert
++#define compiletime_assert(condition, msg) \
++	_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
++#endif
++
++/**
++ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied
++ *		      error message.
++ * @condition: the condition which the compiler should know is false.
++ *
++ * See BUILD_BUG_ON for description.
++ */
++#ifndef BUILD_BUG_ON_MSG
++#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
++#endif
++
++#ifndef ALIGN
++#define __ALIGN_MASK(x, mask)   (((x) + (mask)) & ~(mask))
++#define __ALIGN(x, a)           __ALIGN_MASK(x, (typeof(x))(a) - 1)
++#define ALIGN(x, a)             __ALIGN((x), (a))
++#endif
++#ifndef ALIGN_DOWN
++#define ALIGN_DOWN(x, a)        __ALIGN((x) - ((a) - 1), (a))
++#endif
++
++#endif /* !COMPILER_H_ */
++// vim:fenc=utf-8:tw=75:et
+diff --git a/shim.h b/shim.h
+index e4d40505f09..a0fa5a75e7e 100644
+--- a/shim.h
++++ b/shim.h
+@@ -97,6 +97,7 @@
+ #define FALLBACK L"\\fb" EFI_ARCH L".efi"
+ #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
+ 
++#include "include/asm.h"
+ #include "include/configtable.h"
+ #include "include/console.h"
+ #include "include/crypt_blowfish.h"
+-- 
+2.26.2
+
diff --git a/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch b/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch
new file mode 100644
index 0000000..16f472f
--- /dev/null
+++ b/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch
@@ -0,0 +1,49 @@
+From b5e10f70c7a495dc1788e3604803ee633f1e5f76 Mon Sep 17 00:00:00 2001
+From: Stuart Hayes <stuart.w.hayes@gmail.com>
+Date: Fri, 8 Feb 2019 15:48:20 -0500
+Subject: [PATCH 31/62] Hook exit when shim_lock protocol installed
+
+A recent commit moved where the shim_lock protocol is loaded and
+unloaded, but did not move where exit was hooked and unhooked.  Exit
+needs to be hooked when the protocol is installed, so that the protocol
+will be uninstalled on exit.  Otherwise, the system can crash if, for
+example, shim loads grub, the user exits grub, shim is run again, which
+installs a second instance of the protocol, and then grub tries to use
+the shim_lock protocol that was installed by the first instance of shim.
+
+Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com>
+Upstream-commit-id: 06c92591e94
+---
+ shim.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index f69e69487fc..16911a37b17 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2474,9 +2474,9 @@ shim_init(void)
+ 			loader_is_participating = 0;
+ 		}
+ 
+-		hook_exit(systab);
+ 	}
+ 
++	hook_exit(systab);
+ 	return install_shim_protocols();
+ }
+ 
+@@ -2494,9 +2494,10 @@ shim_fini(void)
+ 		 * Remove our hooks from system services.
+ 		 */
+ 		unhook_system_services();
+-		unhook_exit();
+ 	}
+ 
++	unhook_exit();
++
+ 	/*
+ 	 * Free the space allocated for the alternative 2nd stage loader
+ 	 */
+-- 
+2.26.2
+
diff --git a/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch b/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch
new file mode 100644
index 0000000..f7696a3
--- /dev/null
+++ b/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch
@@ -0,0 +1,89 @@
+From 2cbf56b82a5102777b37c4f7f47c8cf058cea027 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 13 May 2019 16:34:35 -0400
+Subject: [PATCH 32/62] Work around stuff -Waddress-of-packed-member finds.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In MokManager we get a lot of these:
+
+../src/MokManager.c:1063:19: error: taking address of packed member of ‘struct <anonymous>’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
+ 1063 |   if (CompareGuid(&(list[i].Type), &X509_GUID) == 0)
+      |                   ^~~~~~~~~~~~~~~
+
+The reason for this is that gnu-efi takes EFI_GUID * as its argument
+instead of VOID *, and there's nothing telling the compiler that it
+doesn't have alignment constraints on the input, so the compiler wants
+it to have 16-byte alignment.
+
+Just use CompareMem() for these, as that's all CompareGuid is calling
+anyway.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 08c14376b59
+---
+ MokManager.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index df9b6fe6912..a1bd39a68e2 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -22,6 +22,8 @@
+ #define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
+ #define HASH_STRING L"Select a file to trust:\n\n"
+ 
++#define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID))
++
+ typedef struct {
+ 	UINT32 MokSize;
+ 	UINT8 *Mok;
+@@ -1077,7 +1079,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 			continue;
+ 
+ 		DataSize += sizeof(EFI_SIGNATURE_LIST);
+-		if (CompareGuid(&(list[i].Type), &X509_GUID) == 0)
++		if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0)
+ 			DataSize += sizeof(EFI_GUID);
+ 		DataSize += list[i].MokSize;
+ 	}
+@@ -1099,7 +1101,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 		CertList->SignatureType = list[i].Type;
+ 		CertList->SignatureHeaderSize = 0;
+ 
+-		if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) {
++		if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) {
+ 			CertList->SignatureListSize = list[i].MokSize +
+ 			    sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
+ 			CertList->SignatureSize =
+@@ -1140,7 +1142,7 @@ static void delete_cert(void *key, UINT32 key_size,
+ 	int i;
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if (CompareGuid(&(mok[i].Type), &X509_GUID) != 0)
++		if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0)
+ 			continue;
+ 
+ 		if (mok[i].MokSize == key_size &&
+@@ -1191,7 +1193,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size,
+ 	sig_size = hash_size + sizeof(EFI_GUID);
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if ((CompareGuid(&(mok[i].Type), &Type) != 0) ||
++		if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) ||
+ 		    (mok[i].MokSize < sig_size))
+ 			continue;
+ 
+@@ -1355,7 +1357,7 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
+ 
+ 	/* Search and destroy */
+ 	for (i = 0; i < del_num; i++) {
+-		if (CompareGuid(&(del_key[i].Type), &X509_GUID) == 0) {
++		if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) {
+ 			delete_cert(del_key[i].Mok, del_key[i].MokSize,
+ 				    mok, mok_num);
+ 		} else if (is_sha2_hash(del_key[i].Type)) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch b/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch
new file mode 100644
index 0000000..e79afa1
--- /dev/null
+++ b/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch
@@ -0,0 +1,27 @@
+From c372ec7a254147f70d62c1f72da5806d42df6994 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 5 Sep 2019 10:36:23 -0400
+Subject: [PATCH 33/62] Fix a use of strlen() instead of Strlen()
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 1870bae7960
+---
+ shim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/shim.c b/shim.c
+index 16911a37b17..a0eb19b91fe 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2118,7 +2118,7 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path)
+ 
+ 	dprint(L"dppath: %s\n", dppath);
+ 	dprint(L"path:   %s\n", path);
+-	if (StrnCaseCmp(dppath, PathName, strlen(dppath)))
++	if (StrnCaseCmp(dppath, PathName, StrLen(dppath)))
+ 		ret = 0;
+ 
+ done:
+-- 
+2.26.2
+
diff --git a/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch b/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch
new file mode 100644
index 0000000..43a2c6e
--- /dev/null
+++ b/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch
@@ -0,0 +1,72 @@
+From 5d30a31fef4eb7e773da24c5e6c20576282a9c3a Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Tue, 26 Feb 2019 11:33:53 +0800
+Subject: [PATCH 34/62] MokManager: Use CompareMem on MokListNode.Type instead
+ of CompareGuid
+
+Fix the errors from gcc9 '-Werror=address-of-packed-member'
+
+https://github.com/rhboot/shim/issues/161
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Upstream-commit-id: aaa09b35e73
+---
+ MokManager.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index a1bd39a68e2..30192c16789 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -1079,7 +1079,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 			continue;
+ 
+ 		DataSize += sizeof(EFI_SIGNATURE_LIST);
+-		if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0)
++		if (CompareMem(&(list[i].Type), &X509_GUID,
++			       sizeof(EFI_GUID)) == 0)
+ 			DataSize += sizeof(EFI_GUID);
+ 		DataSize += list[i].MokSize;
+ 	}
+@@ -1101,7 +1102,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 		CertList->SignatureType = list[i].Type;
+ 		CertList->SignatureHeaderSize = 0;
+ 
+-		if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) {
++		if (CompareMem(&(list[i].Type), &X509_GUID,
++			       sizeof(EFI_GUID)) == 0) {
+ 			CertList->SignatureListSize = list[i].MokSize +
+ 			    sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
+ 			CertList->SignatureSize =
+@@ -1142,7 +1144,8 @@ static void delete_cert(void *key, UINT32 key_size,
+ 	int i;
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0)
++		if (CompareMem(&(mok[i].Type), &X509_GUID,
++			       sizeof(EFI_GUID)) != 0)
+ 			continue;
+ 
+ 		if (mok[i].MokSize == key_size &&
+@@ -1193,7 +1196,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size,
+ 	sig_size = hash_size + sizeof(EFI_GUID);
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) ||
++		if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) ||
+ 		    (mok[i].MokSize < sig_size))
+ 			continue;
+ 
+@@ -1357,7 +1360,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
+ 
+ 	/* Search and destroy */
+ 	for (i = 0; i < del_num; i++) {
+-		if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) {
++		if (CompareMem(&(del_key[i].Type), &X509_GUID,
++			       sizeof(EFI_GUID)) == 0) {
+ 			delete_cert(del_key[i].Mok, del_key[i].MokSize,
+ 				    mok, mok_num);
+ 		} else if (is_sha2_hash(del_key[i].Type)) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch b/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch
new file mode 100644
index 0000000..0efaac9
--- /dev/null
+++ b/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch
@@ -0,0 +1,32 @@
+From 44b211bcf7ad58ff29e6495e1c3978e4660cb7d1 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 15 Jan 2019 18:04:34 -0500
+Subject: [PATCH 35/62] OpenSSL: always provide OBJ_create() with name strings.
+
+Some versions of OpenSSL seem to go back and forth as to whether NULL
+for these names are okay.  Don't risk it.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 46b76a01717
+---
+ shim.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/shim.c b/shim.c
+index a0eb19b91fe..d7ee2b6de6f 100644
+--- a/shim.c
++++ b/shim.c
+@@ -388,7 +388,9 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
+ 	EXTENDED_KEY_USAGE *eku;
+ 	ASN1_OBJECT *module_signing;
+ 
+-	module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN, NULL, NULL));
++        module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN,
++                                                "modsign-eku",
++                                                "modsign-eku"));
+ 
+ 	x509 = d2i_X509 (NULL, &Temp, (long) CertSize);
+ 	if (x509 != NULL) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch b/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch
new file mode 100644
index 0000000..6ba6995
--- /dev/null
+++ b/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch
@@ -0,0 +1,42 @@
+From 07de085dabab8daaea589b597e3915893cc98445 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Forsman?= <bjorn.forsman@gmail.com>
+Date: Fri, 26 Apr 2019 11:41:02 +0200
+Subject: [PATCH 36/62] Use portable shebangs: /bin/bash -> /usr/bin/env bash
+
+Upstream-commit-id: 6a73ca814af
+---
+ Cryptlib/update.sh | 2 +-
+ make-certs         | 4 +++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/Cryptlib/update.sh b/Cryptlib/update.sh
+index 31a082d4db6..7ea59831a06 100755
+--- a/Cryptlib/update.sh
++++ b/Cryptlib/update.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ 
+ DIR=$1
+ OPENSSL_VERSION="1.0.2k"
+diff --git a/make-certs b/make-certs
+index 3e9293b2497..6f40b234d6a 100755
+--- a/make-certs
++++ b/make-certs
+@@ -1,10 +1,12 @@
+-#!/bin/bash -e
++#!/usr/bin/env bash
+ #
+ #  Generate a root CA cert for signing, and then a subject cert.
+ #  Usage: make-certs.sh hostname [user[@domain]] [more ...]
+ #  For testing only, probably still has some bugs in it.
+ #
+ 
++set -e
++
+ DOMAIN=xn--u4h.net
+ DAYS=365
+ KEYTYPE=RSA
+-- 
+2.26.2
+
diff --git a/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch b/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch
new file mode 100644
index 0000000..a2619ab
--- /dev/null
+++ b/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch
@@ -0,0 +1,44 @@
+From 6fd8db6bb3b23b9e41f109135253f77263071f46 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Sat, 22 Jun 2019 15:33:03 +0100
+Subject: [PATCH 37/62] tpm: Fix off-by-one error when calculating event size
+
+tpm_log_event_raw() allocates a buffer for the EFI_TCG2_EVENT structure
+that is one byte larger than necessary, and sets event->Size accordingly.
+The result of this is that the event data recorded in the log differs
+from the data that is measured to the TPM (it has an extra zero byte
+at the end).
+
+Upstream-commit-id: 8a27a4809a6
+---
+ tpm.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/tpm.c b/tpm.c
+index f07362c70bb..516fb876caa 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -131,8 +131,10 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+ #endif
+ 	} else if (tpm2) {
+ 		EFI_TCG2_EVENT *event;
++		UINTN event_size = sizeof(*event) - sizeof(event->Event) +
++			logsize;
+ 
+-		event = AllocatePool(sizeof(*event) + logsize);
++		event = AllocatePool(event_size);
+ 		if (!event) {
+ 			perror(L"Unable to allocate event structure\n");
+ 			return EFI_OUT_OF_RESOURCES;
+@@ -142,7 +144,7 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+ 		event->Header.HeaderVersion = 1;
+ 		event->Header.PCRIndex = pcr;
+ 		event->Header.EventType = type;
+-		event->Size = sizeof(*event) - sizeof(event->Event) + logsize + 1;
++		event->Size = event_size;
+ 		CopyMem(event->Event, (VOID *)log, logsize);
+ 		if (hash) {
+ 			/* TPM 2 systems will generate the appropriate hash
+-- 
+2.26.2
+
diff --git a/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch b/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch
new file mode 100644
index 0000000..71b98a9
--- /dev/null
+++ b/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch
@@ -0,0 +1,36 @@
+From 9f80be9f16a854e3946568fa92edebe26eb79e78 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Sat, 22 Jun 2019 15:37:29 +0100
+Subject: [PATCH 38/62] tpm: Define EFI_VARIABLE_DATA_TREE as packed
+
+tpm_measure_variable() calculates VarLogSize by adding the size of VarName
+and VarData to the size of EFI_VARIABLE_DATA_TREE, and then subtracting
+the size of the UnicodeName and VariableData members. This results in a
+calculation that is 5 bytes larger than necessary because it doesn't take
+in to account the padding of these members. The effect of this is that
+shim measures an additional 5 zero bytes when measuring UEFI variables
+(at least on 64-bit architectures).
+
+Byte packing EFI_VARIABLE_DATA_TREE fixes this.
+
+Upstream-commit-id: 7e4d3f1c8c7
+---
+ tpm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tpm.c b/tpm.c
+index 516fb876caa..c0617bb479e 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -233,7 +233,7 @@ typedef struct {
+ 	UINT64 VariableDataLength;
+ 	CHAR16 UnicodeName[1];
+ 	INT8 VariableData[1];
+-} EFI_VARIABLE_DATA_TREE;
++} __attribute__ ((packed)) EFI_VARIABLE_DATA_TREE;
+ 
+ static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData)
+ {
+-- 
+2.26.2
+
diff --git a/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch b/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch
new file mode 100644
index 0000000..a71b643
--- /dev/null
+++ b/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch
@@ -0,0 +1,223 @@
+From 55163bc82c5179adb109c3d8b982c2689d68b4c9 Mon Sep 17 00:00:00 2001
+From: Ivan Hu <ivan.hu@canonical.com>
+Date: Fri, 10 May 2019 17:50:12 +0800
+Subject: [PATCH 39/62] MokManager: console mode modification for hi-dpi screen
+ devices
+
+There are lots of hi-dpi laptops nowadays, as doing mok enrollment, the font
+is too small to see.
+https://bugs.launchpad.net/ubuntu/+source/shim/+bug/1822043
+
+This patch checks if the resolution is larger than Full HD (1920x1080) and
+current console output columns and rows is in a good mode. Then swith the
+console output to a better mode.
+
+Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
+Upstream-commit-id: cf05af6d899
+---
+ MokManager.c      |   2 +
+ lib/console.c     | 161 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/console.h |   2 +
+ 3 files changed, 164 insertions(+), 1 deletion(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index 30192c16789..78da9fd95ee 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -2560,6 +2560,8 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab)
+ 
+ 	setup_rand();
+ 
++	console_mode_handle();
++
+ 	efi_status = check_mok_request(image_handle);
+ 
+ 	console_fini();
+diff --git a/lib/console.c b/lib/console.c
+index 3aee41cd276..c92d27f3c86 100644
+--- a/lib/console.c
++++ b/lib/console.c
+@@ -409,7 +409,166 @@ console_notify(CHAR16 *string)
+ 	console_alertbox(str_arr);
+ }
+ 
+-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
++void
++console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode)
++{
++	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
++
++	if (!SavedMode) {
++		console_print(L"Invalid parameter: SavedMode\n");
++		return;
++	}
++
++	CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE));
++	co->EnableCursor(co, FALSE);
++	co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
++}
++
++void
++console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode)
++{
++	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
++
++	co->EnableCursor(co, SavedMode->CursorVisible);
++	co->SetCursorPosition(co, SavedMode->CursorColumn,
++				SavedMode->CursorRow);
++	co->SetAttribute(co, SavedMode->Attribute);
++}
++
++int
++console_countdown(CHAR16* title, const CHAR16* message, int timeout)
++{
++	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
++	SIMPLE_INPUT_INTERFACE *ci = ST->ConIn;
++	SIMPLE_TEXT_OUTPUT_MODE SavedMode;
++	EFI_INPUT_KEY key;
++	EFI_STATUS efi_status;
++	UINTN cols, rows;
++	CHAR16 *titles[2];
++	int wait = 10000000;
++
++	console_save_and_set_mode(&SavedMode);
++
++	titles[0] = title;
++	titles[1] = NULL;
++
++	console_print_box_at(titles, -1, 0, 0, -1, -1, 1, 1);
++
++	co->QueryMode(co, co->Mode->Mode, &cols, &rows);
++
++	console_print_at((cols - StrLen(message)) / 2, rows / 2, message);
++	while (1) {
++		if (timeout > 1)
++			console_print_at(2, rows - 3,
++					 L"Booting in %d seconds  ",
++					 timeout);
++		else if (timeout)
++			console_print_at(2, rows - 3,
++					 L"Booting in %d second   ",
++					 timeout);
++
++		efi_status = WaitForSingleEvent(ci->WaitForKey, wait);
++		if (efi_status != EFI_TIMEOUT) {
++			/* Clear the key in the queue */
++			ci->ReadKeyStroke(ci, &key);
++			break;
++		}
++
++		timeout--;
++		if (!timeout)
++			break;
++	}
++
++	console_restore_mode(&SavedMode);
++
++	return timeout;
++}
++
++#define HORIZONTAL_MAX_OK 1920
++#define VERTICAL_MAX_OK 1080
++#define COLUMNS_MAX_OK 200
++#define ROWS_MAX_OK 100
++
++void
++console_mode_handle(VOID)
++{
++	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
++	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
++	EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
++	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
++
++	UINTN mode_set;
++	UINTN rows = 0, columns = 0;
++	EFI_STATUS efi_status = EFI_SUCCESS;
++
++	efi_status = gBS->LocateProtocol(&gop_guid, NULL, (void **)&gop);
++	if (EFI_ERROR(efi_status)) {
++		console_error(L"Locate graphic output protocol fail", efi_status);
++		return;
++	}
++
++	Info = gop->Mode->Info;
++
++	/*
++	 * Start verifying if we are in a resolution larger than Full HD
++	 * (1920x1080). If we're not, assume we're in a good mode and do not
++	 * try to change it.
++	 */
++	if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK &&
++	    Info->VerticalResolution <= VERTICAL_MAX_OK) {
++		/* keep original mode and return */
++		return;
++	}
++
++        efi_status = co->QueryMode(co, co->Mode->Mode, &columns, &rows);
++	if (EFI_ERROR(efi_status)) {
++		console_error(L"Console query mode fail", efi_status);
++		return;
++	}
++
++	/*
++	 * Verify current console output to check if the character columns and
++	 * rows in a good mode.
++	 */
++	if (columns <= COLUMNS_MAX_OK && rows <= ROWS_MAX_OK) {
++		/* keep original mode and return */
++		return;
++	}
++
++	if (!console_text_mode)
++		setup_console(1);
++
++	co->Reset(co, TRUE);
++
++	/*
++	 * If we reached here, then we have a high resolution screen and the
++	 * text too small. Try to switch to a better mode. Mode number 2 is
++	 * first non standard mode, which is provided by the device
++	 * manufacturer, so it should be a good mode.
++	 */
++	if (co->Mode->MaxMode > 2)
++		mode_set = 2;
++	else
++		mode_set = 0;
++
++	efi_status = co->SetMode(co, mode_set);
++	if (EFI_ERROR(efi_status) && mode_set != 0) {
++		/*
++		 * Set to 0 mode which is required that all output devices
++		 * support at least 80x25 text mode.
++		 */
++		mode_set = 0;
++		efi_status = co->SetMode(co, mode_set);
++	}
++
++	co->ClearScreen(co);
++
++	if (EFI_ERROR(efi_status)) {
++		console_error(L"Console set mode fail", efi_status);
++	}
++
++	return;
++}
+ 
+ /* Copy of gnu-efi-3.0 with the added secure boot strings */
+ static struct {
+diff --git a/include/console.h b/include/console.h
+index deb4fa3db23..9f259c71b72 100644
+--- a/include/console.h
++++ b/include/console.h
+@@ -34,6 +34,8 @@ void
+ console_notify(CHAR16 *string);
+ void
+ console_reset(void);
++void
++console_mode_handle(void);
+ #define NOSEL 0x7fffffff
+ 
+ typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL   EFI_CONSOLE_CONTROL_PROTOCOL;
+-- 
+2.26.2
+
diff --git a/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch b/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch
new file mode 100644
index 0000000..ac8814e
--- /dev/null
+++ b/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch
@@ -0,0 +1,111 @@
+From d57e53f3bddc4bc7299b3d5efd5ba8c547e8dfa5 Mon Sep 17 00:00:00 2001
+From: Jonas Witschel <diabonas@gmx.de>
+Date: Thu, 5 Sep 2019 10:39:37 +0200
+Subject: [PATCH 40/62] MokManager: avoid -Werror=address-of-packed-member
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When compiling with GCC 9, there are a couple of errors of the form
+
+MokManager.c: In function ‘write_back_mok_list’:
+MokManager.c:1056:19: error: taking address of packed member of ‘struct <anonymous>’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
+ 1056 |   if (CompareGuid(&(list[i].Type), &X509_GUID) == 0)
+      |                   ^~~~~~~~~~~~~~~
+
+Copying the member of the packed struct to a temporary variable and
+pointing to that variable solves the problem.
+
+Upstream-commit-id: 58532e12e9a
+---
+ MokManager.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index 78da9fd95ee..fa73e2fd865 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -1064,6 +1064,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 	EFI_STATUS efi_status;
+ 	EFI_SIGNATURE_LIST *CertList;
+ 	EFI_SIGNATURE_DATA *CertData;
++	EFI_GUID type;
+ 	void *Data = NULL, *ptr;
+ 	INTN DataSize = 0;
+ 	int i;
+@@ -1079,8 +1080,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 			continue;
+ 
+ 		DataSize += sizeof(EFI_SIGNATURE_LIST);
+-		if (CompareMem(&(list[i].Type), &X509_GUID,
+-			       sizeof(EFI_GUID)) == 0)
++		type = list[i].Type; /* avoid -Werror=address-of-packed-member */
++		if (CompareGuid(&type, &X509_GUID) == 0)
+ 			DataSize += sizeof(EFI_GUID);
+ 		DataSize += list[i].MokSize;
+ 	}
+@@ -1102,8 +1103,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 		CertList->SignatureType = list[i].Type;
+ 		CertList->SignatureHeaderSize = 0;
+ 
+-		if (CompareMem(&(list[i].Type), &X509_GUID,
+-			       sizeof(EFI_GUID)) == 0) {
++		if (CompareGuid(&(CertList->SignatureType), &X509_GUID) == 0) {
+ 			CertList->SignatureListSize = list[i].MokSize +
+ 			    sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
+ 			CertList->SignatureSize =
+@@ -1141,11 +1141,12 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ static void delete_cert(void *key, UINT32 key_size,
+ 			MokListNode * mok, INTN mok_num)
+ {
++	EFI_GUID type;
+ 	int i;
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if (CompareMem(&(mok[i].Type), &X509_GUID,
+-			       sizeof(EFI_GUID)) != 0)
++		type = mok[i].Type; /* avoid -Werror=address-of-packed-member */
++		if (CompareGuid(&type, &X509_GUID) != 0)
+ 			continue;
+ 
+ 		if (mok[i].MokSize == key_size &&
+@@ -1187,6 +1188,7 @@ static void mem_move(void *dest, void *src, UINTN size)
+ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size,
+ 				MokListNode * mok, INTN mok_num)
+ {
++	EFI_GUID type;
+ 	UINT32 sig_size;
+ 	UINT32 list_num;
+ 	int i, del_ind;
+@@ -1196,7 +1198,8 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size,
+ 	sig_size = hash_size + sizeof(EFI_GUID);
+ 
+ 	for (i = 0; i < mok_num; i++) {
+-		if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) ||
++		type = mok[i].Type; /* avoid -Werror=address-of-packed-member */
++		if ((CompareGuid(&type, &Type) != 0) ||
+ 		    (mok[i].MokSize < sig_size))
+ 			continue;
+ 
+@@ -1252,6 +1255,7 @@ static void delete_hash_list(EFI_GUID Type, void *hash_list, UINT32 list_size,
+ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
+ {
+ 	EFI_STATUS efi_status;
++	EFI_GUID type;
+ 	CHAR16 *db_name;
+ 	CHAR16 *auth_name;
+ 	CHAR16 *err_strs[] = { NULL, NULL, NULL };
+@@ -1360,8 +1364,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
+ 
+ 	/* Search and destroy */
+ 	for (i = 0; i < del_num; i++) {
+-		if (CompareMem(&(del_key[i].Type), &X509_GUID,
+-			       sizeof(EFI_GUID)) == 0) {
++		type = del_key[i].Type; /* avoid -Werror=address-of-packed-member */
++		if (CompareGuid(&type, &X509_GUID) == 0) {
+ 			delete_cert(del_key[i].Mok, del_key[i].MokSize,
+ 				    mok, mok_num);
+ 		} else if (is_sha2_hash(del_key[i].Type)) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch b/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch
new file mode 100644
index 0000000..3a282e4
--- /dev/null
+++ b/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch
@@ -0,0 +1,31 @@
+From 58df8d745c6516818ba6ebfa8fe826702c1621a0 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Thu, 26 Sep 2019 20:01:01 +0100
+Subject: [PATCH 41/62] tpm: Don't log duplicate identical events
+
+According to the comment in tpm_measure_variable ("Don't measure something that we've already measured"), shim
+shouldn't measure duplicate events if they are identical, which also aligns with section 2.3.4.8 of the TCG PC
+Client Platform Firmware Profile Specification ("If it has been measured previously, it MUST NOT be measured
+again"). This is currently broken because tpm_data_measured() uses the return value of CompareGuid() incorrectly.
+
+Upstream-commit-id: 103adc89ce5
+---
+ tpm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tpm.c b/tpm.c
+index c0617bb479e..196b93c30f6 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -241,7 +241,7 @@ static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN Var
+ 
+ 	for (i=0; i<measuredcount; i++) {
+ 		if ((StrCmp (VarName, measureddata[i].VariableName) == 0) &&
+-		    (CompareGuid (&VendorGuid, measureddata[i].VendorGuid)) &&
++		    (CompareGuid (&VendorGuid, measureddata[i].VendorGuid) == 0) &&
+ 		    (VarSize == measureddata[i].Size) &&
+ 		    (CompareMem (VarData, measureddata[i].Data, VarSize) == 0)) {
+ 			return TRUE;
+-- 
+2.26.2
+
diff --git a/SOURCES/0042-Slightly-better-debugging-messages.patch b/SOURCES/0042-Slightly-better-debugging-messages.patch
new file mode 100644
index 0000000..2e49a66
--- /dev/null
+++ b/SOURCES/0042-Slightly-better-debugging-messages.patch
@@ -0,0 +1,57 @@
+From 5e6e0792cedb3b71cbe061ae56e96906cf710579 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 18 Nov 2019 13:59:14 -0500
+Subject: [PATCH 42/62] Slightly better debugging messages
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 173d35fe8f5
+---
+ shim.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index d7ee2b6de6f..2f7aba07421 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2459,6 +2459,8 @@ uninstall_shim_protocols(void)
+ EFI_STATUS
+ shim_init(void)
+ {
++	EFI_STATUS efi_status;
++
+ 	setup_verbosity();
+ 	dprint(L"%a", shim_version);
+ 
+@@ -2479,7 +2481,12 @@ shim_init(void)
+ 	}
+ 
+ 	hook_exit(systab);
+-	return install_shim_protocols();
++
++	efi_status = install_shim_protocols();
++	if (EFI_ERROR(efi_status))
++		perror(L"install_shim_protocols() failed: %r\n", efi_status);
++
++	return efi_status;
+ }
+ 
+ void
+@@ -2575,13 +2582,12 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 	build_cert = shim_cert;
+ #endif /* defined(ENABLE_SHIM_CERT) */
+ 	CHAR16 *msgs[] = {
+-		L"import_mok_state() failed\n",
+-		L"shim_int() failed\n",
++		L"import_mok_state() failed",
++		L"shim_init() failed",
+ 		NULL
+ 	};
+ 	int msg = 0;
+ 
+-
+ 	/*
+ 	 * Set up the shim lock protocol so that grub and MokManager can
+ 	 * call back in and use shim functions
+-- 
+2.26.2
+
diff --git a/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch b/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch
new file mode 100644
index 0000000..255f47f
--- /dev/null
+++ b/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch
@@ -0,0 +1,69 @@
+From 959f5e4e993a82020fef48c7e7c012a44074645c Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 18 Nov 2019 13:58:46 -0500
+Subject: [PATCH 43/62] Actually check for errors from set_second_stage()
+
+This changes shim_init() to check for errors from set_second_stage().
+In order to make that work, it also does the following:
+
+- correctly /always/ allocate second_stage, not sometimes allocate and
+  sometimes point at .data
+- test for LoadOptionSize == 0 and return success
+- print an error message for the failure so we can see it.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 354bd9b1931
+---
+ shim.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 2f7aba07421..5329795c333 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2141,8 +2141,15 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
+ 	CHAR16 *loader_str = NULL;
+ 	UINTN loader_len = 0;
+ 	unsigned int i;
++	UINTN second_stage_len;
+ 
+-	second_stage = DEFAULT_LOADER;
++	second_stage_len = StrLen(DEFAULT_LOADER) + 1;
++	second_stage = AllocatePool(second_stage_len);
++	if (!second_stage) {
++		perror(L"Could not allocate %lu bytes\n", second_stage_len);
++		return EFI_OUT_OF_RESOURCES;
++	}
++	StrCpy(second_stage, DEFAULT_LOADER);
+ 	load_options = NULL;
+ 	load_options_size = 0;
+ 
+@@ -2199,6 +2206,12 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
+ 	* BDS will add that, but we ignore that here.
+ 	*/
+ 
++	/*
++	 * Maybe there just aren't any options...
++	 */
++	if (li->LoadOptionsSize == 0)
++		return EFI_SUCCESS;
++
+ 	/*
+ 	 * In either case, we've got to have at least a UCS2 NUL...
+ 	 */
+@@ -2465,7 +2478,11 @@ shim_init(void)
+ 	dprint(L"%a", shim_version);
+ 
+ 	/* Set the second stage loader */
+-	set_second_stage (global_image_handle);
++	efi_status = set_second_stage(global_image_handle);
++	if (EFI_ERROR(efi_status)) {
++		perror(L"set_second_stage() failed: %r\n", efi_status);
++		return efi_status;
++	}
+ 
+ 	if (secure_mode()) {
+ 		if (vendor_cert_size || vendor_dbx_size) {
+-- 
+2.26.2
+
diff --git a/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch b/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch
new file mode 100644
index 0000000..f69b22e
--- /dev/null
+++ b/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch
@@ -0,0 +1,140 @@
+From c6bedd5b83529925c3ec08f96a3bf61c81bff0ae Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Tue, 28 Jan 2020 23:33:46 +0100
+Subject: [PATCH 44/62] translate_slashes(): don't write to string literals
+
+Currently, all three invocations of the translate_slashes() function may
+lead to writes to the string literal that is #defined with the
+DEFAULT_LOADER_CHAR macro. According to ISO C99 6.4.5p6, this is undefined
+behavior ("If the program attempts to modify such an array, the behavior
+is undefined").
+
+This bug crashes shim on e.g. the 64-bit ArmVirtQemu platform ("Data
+abort: Permission fault"), where the platform firmware maps the .text
+section (which contains the string literal) read-only.
+
+Modify translate_slashes() so that it copies and translates characters
+from an input array of "char" to an output array of "CHAR8".
+
+While at it, fix another bug. Before this patch, if translate_slashes()
+ever encountered a double backslash (translating it to a single forward
+slash), then the output would end up shorter than the input. However, the
+output was not NUL-terminated in-place, therefore the original string
+length (and according trailing garbage) would be preserved. After this
+patch, the NUL-termination on contraction is automatic, as the output
+array's contents are indeterminate when entering the function, and so we
+must NUL-terminate it anyway.
+
+Fixes: 8e9124227d18475d3bc634c33518963fc8db7c98
+Fixes: e62b69a5b0b87c6df7a4fc23906134945309e927
+Fixes: 3d79bcb2651b9eae809b975b3e03e2f96c067072
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795654
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Upstream-commit-id: 9813e8bc8b3
+---
+ httpboot.c    |  4 ++--
+ netboot.c     | 16 +++++++++++-----
+ include/str.h | 14 ++++++++------
+ 3 files changed, 21 insertions(+), 13 deletions(-)
+
+diff --git a/httpboot.c b/httpboot.c
+index 3622e85867c..2d27e8ed993 100644
+--- a/httpboot.c
++++ b/httpboot.c
+@@ -743,14 +743,14 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
+ {
+ 	EFI_STATUS efi_status;
+ 	EFI_HANDLE nic;
+-	CHAR8 *next_loader = NULL;
++	CHAR8 next_loader[sizeof DEFAULT_LOADER_CHAR];
+ 	CHAR8 *next_uri = NULL;
+ 	CHAR8 *hostname = NULL;
+ 
+ 	if (!uri)
+ 		return EFI_NOT_READY;
+ 
+-	next_loader = translate_slashes(DEFAULT_LOADER_CHAR);
++	translate_slashes(next_loader, DEFAULT_LOADER_CHAR);
+ 
+ 	/* Create the URI for the next loader based on the original URI */
+ 	efi_status = generate_next_uri(uri, next_loader, &next_uri);
+diff --git a/netboot.c b/netboot.c
+index 58babfb4d2e..4922ef284b1 100644
+--- a/netboot.c
++++ b/netboot.c
+@@ -189,7 +189,9 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
+ 	CHAR8 *start, *end;
+ 	CHAR8 ip6str[40];
+ 	CHAR8 ip6inv[16];
+-	CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
++	CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
++
++	translate_slashes(template, DEFAULT_LOADER_CHAR);
+ 
+ 	// to check against str2ip6() errors
+ 	memset(ip6inv, 0, sizeof(ip6inv));
+@@ -254,10 +256,14 @@ static EFI_STATUS parseDhcp6()
+ 
+ static EFI_STATUS parseDhcp4()
+ {
+-	CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
+-	INTN template_len = strlen(template) + 1;
++	CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
++	INTN template_len;
++	UINTN template_ofs = 0;
+ 	EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4;
+ 
++	translate_slashes(template, DEFAULT_LOADER_CHAR);
++	template_len = strlen(template) + 1;
++
+ 	if(pxe->Mode->ProxyOfferReceived) {
+ 		/*
+ 		 * Proxy should not have precedence.  Check if DhcpAck
+@@ -288,8 +294,8 @@ static EFI_STATUS parseDhcp4()
+ 			full_path[dir_len-1] = '\0';
+ 	}
+ 	if (dir_len == 0 && dir[0] != '/' && template[0] == '/')
+-		template++;
+-	strcata(full_path, template);
++		template_ofs++;
++	strcata(full_path, template + template_ofs);
+ 	memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
+ 
+ 	return EFI_SUCCESS;
+diff --git a/include/str.h b/include/str.h
+index 9a748366bd1..f73c6212cd9 100644
+--- a/include/str.h
++++ b/include/str.h
+@@ -45,21 +45,23 @@ strcata(CHAR8 *dest, const CHAR8 *src)
+ static inline
+ __attribute__((unused))
+ CHAR8 *
+-translate_slashes(char *str)
++translate_slashes(CHAR8 *out, const char *str)
+ {
+ 	int i;
+ 	int j;
+-	if (str == NULL)
+-		return (CHAR8 *)str;
++	if (str == NULL || out == NULL)
++		return NULL;
+ 
+ 	for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
+ 		if (str[i] == '\\') {
+-			str[j] = '/';
++			out[j] = '/';
+ 			if (str[i+1] == '\\')
+ 				i++;
+-		}
++		} else
++			out[j] = str[i];
+ 	}
+-	return (CHAR8 *)str;
++	out[j] = '\0';
++	return out;
+ }
+ 
+ #endif /* SHIM_STR_H */
+-- 
+2.26.2
+
diff --git a/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch b/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch
new file mode 100644
index 0000000..2203e48
--- /dev/null
+++ b/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch
@@ -0,0 +1,93 @@
+From 89d72301aa67c82f00fe7fa4f42d7f6eb6045538 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Tue, 18 Feb 2020 12:03:28 +0100
+Subject: [PATCH 45/62] shim: Update EFI_LOADED_IMAGE with the second stage
+ loader file path
+
+When shim loads the second stage loader (e.g: GRUB) the FilePath field of
+the EFI_LOADED_IMAGE structure isn't updated with the path of the loaded
+binary. So it still contains the file path of the shim binary.
+
+This isn't a problem since the file path is currently not used. But should
+be used to set the DevicePath field of the EFI_IMAGE_LOAD_EVENT structure
+that is logged when measuring the PE/COFF binaries. In that case the TPM
+Event Log will have an incorrect file path for the measured binary, i.e:
+
+$ hexdump -Cv /sys/kernel/security/tpm0/binary_bios_measurements
+...
+00000a50  00 00 00 00 00 00 04 04  34 00 5c 00 45 00 46 00  |........4.\.E.F.|
+00000a60  49 00 5c 00 72 00 65 00  64 00 68 00 61 00 74 00  |I.\.r.e.d.h.a.t.|
+00000a70  5c 00 73 00 68 00 69 00  6d 00 78 00 36 00 34 00  |\.s.h.i.m.x.6.4.|
+00000a80  2e 00 65 00 66 00 69 00  00 00 7f ff 04 00 00 00  |..e.f.i.........|
+00000a90  00 00 00 00 00 00 af 08  00 00 00 0d 00 00 00 b5  |................|
+00000aa0  cd d0 8f bb 16 31 e2 80  8b e8 58 75 c9 89 18 95  |.....1....Xu....|
+00000ab0  d2 de 15 15 00 00 00 67  72 75 62 5f 63 6d 64 20  |.......grub_cmd |
+00000ac0  73 65 74 20 70 61 67 65  72 3d 31 00 08 00 00 00  |set pager=1.....|
+...
+
+So update the EFI_LOADED_IMAGE structure with the second stage loader file
+path to have the correct value in the log, i.e:
+
+$ hexdump -Cv /sys/kernel/security/tpm0/binary_bios_measurements
+...
+00000a50  00 00 00 00 00 00 04 04  34 00 5c 00 45 00 46 00  |........4.\.E.F.|
+00000a60  49 00 5c 00 72 00 65 00  64 00 68 00 61 00 74 00  |I.\.r.e.d.h.a.t.|
+00000a70  5c 00 67 00 72 00 75 00  62 00 78 00 36 00 34 00  |\.g.r.u.b.x.6.4.|
+00000a80  2e 00 65 00 66 00 69 00  00 00 7f ff 04 00 00 00  |..e.f.i.........|
+00000a90  00 00 00 00 00 00 af 08  00 00 00 0d 00 00 00 b5  |................|
+00000aa0  cd d0 8f bb 16 31 e2 80  8b e8 58 75 c9 89 18 95  |.....1....Xu....|
+00000ab0  d2 de 15 15 00 00 00 67  72 75 62 5f 63 6d 64 20  |.......grub_cmd |
+00000ac0  73 65 74 20 70 61 67 65  72 3d 31 00 08 00 00 00  |set pager=1.....|
+...
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Upstream-commit-id: cd7d42d493d
+---
+ shim.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 5329795c333..a4f7769b38b 100644
+--- a/shim.c
++++ b/shim.c
+@@ -1925,6 +1925,16 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
+ 	 */
+ 	CopyMem(&li_bak, li, sizeof(li_bak));
+ 
++	/*
++	 * Update the loaded image with the second stage loader file path
++	 */
++	li->FilePath = FileDevicePath(NULL, PathName);
++	if (!li->FilePath) {
++		perror(L"Unable to update loaded image file path\n");
++		efi_status = EFI_OUT_OF_RESOURCES;
++		goto restore;
++	}
++
+ 	/*
+ 	 * Verify and, if appropriate, relocate and execute the executable
+ 	 */
+@@ -1934,8 +1944,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
+ 		perror(L"Failed to load image: %r\n", efi_status);
+ 		PrintErrors();
+ 		ClearErrors();
+-		CopyMem(li, &li_bak, sizeof(li_bak));
+-		goto done;
++		goto restore;
+ 	}
+ 
+ 	loader_is_participating = 0;
+@@ -1945,6 +1954,10 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
+ 	 */
+ 	efi_status = entry_point(image_handle, systab);
+ 
++restore:
++	if (li->FilePath)
++		FreePool(li->FilePath);
++
+ 	/*
+ 	 * Restore our original loaded image values
+ 	 */
+-- 
+2.26.2
+
diff --git a/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch b/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch
new file mode 100644
index 0000000..90a6b52
--- /dev/null
+++ b/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch
@@ -0,0 +1,124 @@
+From 0a8f7ade76ff3eede486027eaa638181e6bed3b8 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Tue, 18 Feb 2020 12:03:17 +0100
+Subject: [PATCH 46/62] tpm: Include information about PE/COFF images in the
+ TPM Event Log
+
+The "TCG PC Client Specific Platform Firmware Profile Specification" says
+that when measuring a PE/COFF image, the TCG_PCR_EVENT2 structure Event
+field MUST contain a UEFI_IMAGE_LOAD_EVENT structure.
+
+Currently an empty UEFI_IMAGE_LOAD_EVENT structure is passed so users only
+have the hash of the PE/COFF image, but not information such the file path
+of the binary.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Upstream-commit-id: c252b9ee94c
+---
+ shim.c        |  7 +++++--
+ tpm.c         | 46 ++++++++++++++++++++++++++++++++--------------
+ include/tpm.h |  5 +++--
+ 3 files changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index a4f7769b38b..b35b0ad90cc 100644
+--- a/shim.c
++++ b/shim.c
+@@ -1274,7 +1274,9 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
+ #ifdef REQUIRE_TPM
+ 	efi_status =
+ #endif
+-	tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4);
++	tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize,
++		   (EFI_PHYSICAL_ADDRESS)(UINTN)context.ImageAddress,
++		   li->FilePath, sha1hash, 4);
+ #ifdef REQUIRE_TPM
+ 	if (efi_status != EFI_SUCCESS) {
+ 		return efi_status;
+@@ -1788,7 +1790,8 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size)
+ #ifdef REQUIRE_TPM
+ 	efi_status =
+ #endif
+-	tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)buffer, size, sha1hash, 4);
++	tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)buffer, size, 0, NULL,
++		   sha1hash, 4);
+ #ifdef REQUIRE_TPM
+ 	if (EFI_ERROR(efi_status))
+ 		goto done;
+diff --git a/tpm.c b/tpm.c
+index 196b93c30f6..22ad148b35a 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -210,21 +210,39 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
+ 				 strlen(description) + 1, 0xd, NULL);
+ }
+ 
+-EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash,
+-		      UINT8 pcr)
++EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size,
++		      EFI_PHYSICAL_ADDRESS addr, EFI_DEVICE_PATH *path,
++		      UINT8 *sha1hash, UINT8 pcr)
+ {
+-	EFI_IMAGE_LOAD_EVENT ImageLoad;
+-
+-	// All of this is informational and forces us to do more parsing before
+-	// we can generate it, so let's just leave it out for now
+-	ImageLoad.ImageLocationInMemory = 0;
+-	ImageLoad.ImageLengthInMemory = 0;
+-	ImageLoad.ImageLinkTimeAddress = 0;
+-	ImageLoad.LengthOfDevicePath = 0;
+-
+-	return tpm_log_event_raw(buf, size, pcr, (CHAR8 *)&ImageLoad,
+-				 sizeof(ImageLoad),
+-				 EV_EFI_BOOT_SERVICES_APPLICATION, sha1hash);
++	EFI_IMAGE_LOAD_EVENT *ImageLoad = NULL;
++	EFI_STATUS efi_status;
++	UINTN path_size = 0;
++
++	if (path)
++		path_size = DevicePathSize(path);
++
++	ImageLoad = AllocateZeroPool(sizeof(*ImageLoad) + path_size);
++	if (!ImageLoad) {
++		perror(L"Unable to allocate image load event structure\n");
++		return EFI_OUT_OF_RESOURCES;
++	}
++
++	ImageLoad->ImageLocationInMemory = buf;
++	ImageLoad->ImageLengthInMemory = size;
++	ImageLoad->ImageLinkTimeAddress = addr;
++
++	if (path_size > 0) {
++		CopyMem(ImageLoad->DevicePath, path, path_size);
++		ImageLoad->LengthOfDevicePath = path_size;
++	}
++
++	efi_status = tpm_log_event_raw(buf, size, pcr, (CHAR8 *)ImageLoad,
++				       sizeof(*ImageLoad) + path_size,
++				       EV_EFI_BOOT_SERVICES_APPLICATION,
++				       sha1hash);
++	FreePool(ImageLoad);
++
++	return efi_status;
+ }
+ 
+ typedef struct {
+diff --git a/include/tpm.h b/include/tpm.h
+index 746e871ff22..a05c24949e5 100644
+--- a/include/tpm.h
++++ b/include/tpm.h
+@@ -10,8 +10,9 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
+ 			 const CHAR8 *description);
+ EFI_STATUS fallback_should_prefer_reset(void);
+ 
+-EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash,
+-		      UINT8 pcr);
++EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size,
++		      EFI_PHYSICAL_ADDRESS addr, EFI_DEVICE_PATH *path,
++		      UINT8 *sha1hash, UINT8 pcr);
+ 
+ EFI_STATUS tpm_measure_variable(CHAR16 *dbname, EFI_GUID guid, UINTN size, void *data);
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch b/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch
new file mode 100644
index 0000000..b62628d
--- /dev/null
+++ b/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch
@@ -0,0 +1,27 @@
+From dce3659ac3d14ed338cdb37798a429751898c078 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Apr 2020 18:55:34 -0400
+Subject: [PATCH 47/62] Fix the license on our buildid extractor.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 71439f848f6
+---
+ buildid.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/buildid.c b/buildid.c
+index f213f3bc921..6b414cdcffb 100644
+--- a/buildid.c
++++ b/buildid.c
+@@ -1,8 +1,6 @@
+ /*
+  * Walk a list of input files, printing the name and buildid of any file
+  * that has one.
+- *
+- * This program is licensed under the GNU Public License version 2.
+  */
+ 
+ #include <err.h>
+-- 
+2.26.2
+
diff --git a/SOURCES/0048-Update-README.tpm.patch b/SOURCES/0048-Update-README.tpm.patch
new file mode 100644
index 0000000..b5cd08d
--- /dev/null
+++ b/SOURCES/0048-Update-README.tpm.patch
@@ -0,0 +1,27 @@
+From 633169fe3291c832236ca1074fc679852f9caee1 Mon Sep 17 00:00:00 2001
+From: noahbliss <noah@superuser.sh>
+Date: Wed, 4 Mar 2020 19:46:28 -0500
+Subject: [PATCH 48/62] Update README.tpm
+
+typo
+Upstream-commit-id: bc24c9eb1d4
+---
+ README.tpm | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/README.tpm b/README.tpm
+index d9c7c53483b..c060dbe22db 100644
+--- a/README.tpm
++++ b/README.tpm
+@@ -25,7 +25,7 @@ PCR8:
+   measured into PCR8.
+   
+ PCR9:
+-- If you're using the grub2 TPM patchset we cary in Fedora, the kernel,
++- If you're using the grub2 TPM patchset we carry in Fedora, the kernel,
+   initramfs, and any multiboot modules loaded are measured into PCR9.
+ 
+ PCR14:
+-- 
+2.26.2
+
diff --git a/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch b/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch
new file mode 100644
index 0000000..dd9eea9
--- /dev/null
+++ b/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch
@@ -0,0 +1,61 @@
+From 9a209af5d84f4015ec399e1d1fa9dab31ef4d2b7 Mon Sep 17 00:00:00 2001
+From: Thomas Frauendorfer | Miray Software <tf@miray.de>
+Date: Wed, 25 Mar 2020 09:19:19 +0100
+Subject: [PATCH 49/62] Check PxeReplyReceived as fallback in netboot
+
+Some mainboards do not update the ProxyOffset dhcp information when using
+proxy dhcp and boot menus.
+This adds a fallback to check the PxeReply field if no boot information is
+found in the v4 dhcp or proxy dhcp information
+
+Upstream-commit-id: cc7ebe0f9f4
+---
+ netboot.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+ mode change 100644 => 100755 netboot.c
+
+diff --git a/netboot.c b/netboot.c
+old mode 100644
+new mode 100755
+index 4922ef284b1..047dad3a760
+--- a/netboot.c
++++ b/netboot.c
+@@ -273,7 +273,16 @@ static EFI_STATUS parseDhcp4()
+ 			pkt_v4 = &pxe->Mode->ProxyOffer.Dhcpv4;
+ 	}
+ 
+-	INTN dir_len = strnlena(pkt_v4->BootpBootFile, 127);
++	if(pxe->Mode->PxeReplyReceived) {
++		/*
++		 * If we have no bootinfo yet search for it in the PxeReply.
++		 * Some mainboards run into this when the server uses boot menus
++		 */
++		if(pkt_v4->BootpBootFile[0] == '\0' && pxe->Mode->PxeReply.Dhcpv4.BootpBootFile[0] != '\0')
++			pkt_v4 = &pxe->Mode->PxeReply.Dhcpv4;
++	}
++
++	INTN dir_len = strnlena((CHAR8 *)pkt_v4->BootpBootFile, 127);
+ 	INTN i;
+ 	UINT8 *dir = pkt_v4->BootpBootFile;
+ 
+@@ -289,7 +298,7 @@ static EFI_STATUS parseDhcp4()
+ 		return EFI_OUT_OF_RESOURCES;
+ 
+ 	if (dir_len > 0) {
+-		strncpya(full_path, dir, dir_len);
++		strncpya(full_path, (CHAR8 *)dir, dir_len);
+ 		if (full_path[dir_len-1] == '/' && template[0] == '/')
+ 			full_path[dir_len-1] = '\0';
+ 	}
+@@ -340,7 +349,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *buf
+ 
+ try_again:
+ 	efi_status = pxe->Mtftp(pxe, read, *buffer, overwrite, bufsiz, &blksz,
+-			      &tftp_addr, full_path, NULL, nobuffer);
++			      &tftp_addr, (UINT8 *)full_path, NULL, nobuffer);
+ 	if (efi_status == EFI_BUFFER_TOO_SMALL) {
+ 		/* try again, doubling buf size */
+ 		*bufsiz *= 2;
+-- 
+2.26.2
+
diff --git a/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch b/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch
new file mode 100644
index 0000000..1fda36c
--- /dev/null
+++ b/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch
@@ -0,0 +1,46 @@
+From e8a04c1d84d2ebd0dbdf7bda26d7a22017100586 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 9 Jul 2020 00:24:57 -0400
+Subject: [PATCH 50/62] Remove a couple of incorrect license claims.
+
+A certain someone's default editor template leaked in to a couple of
+source files, and claims they're GPL licensed.  They're not.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream-commit-id: 476cbff1110
+---
+ errlog.c | 3 ---
+ mok.c    | 2 --
+ 2 files changed, 5 deletions(-)
+
+diff --git a/errlog.c b/errlog.c
+index eebb266d396..6669c800233 100644
+--- a/errlog.c
++++ b/errlog.c
+@@ -1,10 +1,7 @@
+ /*
+  * errlog.c
+  * Copyright 2017 Peter Jones <pjones@redhat.com>
+- *
+- * Distributed under terms of the GPLv3 license.
+  */
+-
+ #include "shim.h"
+ 
+ static CHAR16 **errs = NULL;
+diff --git a/mok.c b/mok.c
+index 59630e74425..089ea6bfc9a 100644
+--- a/mok.c
++++ b/mok.c
+@@ -1,8 +1,6 @@
+ /*
+  * mok.c
+  * Copyright 2017 Peter Jones <pjones@redhat.com>
+- *
+- * Distributed under terms of the GPLv3 license.
+  */
+ 
+ #include "shim.h"
+-- 
+2.26.2
+
diff --git a/SOURCES/0051-MokManager-fix-uninitialized-value.patch b/SOURCES/0051-MokManager-fix-uninitialized-value.patch
new file mode 100644
index 0000000..808d11f
--- /dev/null
+++ b/SOURCES/0051-MokManager-fix-uninitialized-value.patch
@@ -0,0 +1,27 @@
+From 7b77bee7966a1aa5f00a9b34aeb7e550bfa47be1 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 22 Jul 2020 23:53:09 -0400
+Subject: [PATCH 51/62] MokManager: fix uninitialized value
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#212
+---
+ MokManager.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index fa73e2fd865..654a115033c 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -1431,7 +1431,7 @@ static CHAR16 get_password_charater(CHAR16 * prompt)
+ 	SIMPLE_TEXT_OUTPUT_MODE SavedMode;
+ 	EFI_STATUS efi_status;
+ 	CHAR16 *message[2];
+-	CHAR16 character;
++	CHAR16 character = 0;
+ 	UINTN length;
+ 	UINT32 pw_length;
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch b/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch
new file mode 100644
index 0000000..4f3d2d6
--- /dev/null
+++ b/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch
@@ -0,0 +1,41 @@
+From d3b7dc54cdac474a57b67cf9bcdb15bcb131d06c Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 16:18:52 -0400
+Subject: [PATCH 52/62] Fix some volatile usage gcc whines about.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#212
+---
+ fallback.c | 2 +-
+ shim.c     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fallback.c b/fallback.c
+index c3f5583c626..5a4bfff0793 100644
+--- a/fallback.c
++++ b/fallback.c
+@@ -983,7 +983,7 @@ debug_hook(void)
+ 	UINT8 *data = NULL;
+ 	UINTN dataSize = 0;
+ 	EFI_STATUS efi_status;
+-	volatile register int x = 0;
++	register volatile int x = 0;
+ 	extern char _etext, _edata;
+ 
+ 	efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize,
+diff --git a/shim.c b/shim.c
+index b35b0ad90cc..0e7e784b4c8 100644
+--- a/shim.c
++++ b/shim.c
+@@ -2559,7 +2559,7 @@ debug_hook(void)
+ 	UINT8 *data = NULL;
+ 	UINTN dataSize = 0;
+ 	EFI_STATUS efi_status;
+-	volatile register UINTN x = 0;
++	register volatile UINTN x = 0;
+ 	extern char _text, _data;
+ 
+ 	if (x)
+-- 
+2.26.2
+
diff --git a/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch b/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch
new file mode 100644
index 0000000..cd20cb4
--- /dev/null
+++ b/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch
@@ -0,0 +1,31 @@
+From 6df96cdb20b84b33027d2e40bc0dbe0676d31282 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 19:01:27 -0400
+Subject: [PATCH 53/62] MokManager: fix a wrong allocation failure check.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#212
+---
+ MokManager.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/MokManager.c b/MokManager.c
+index 654a115033c..c9949e33bcf 100644
+--- a/MokManager.c
++++ b/MokManager.c
+@@ -1085,9 +1085,11 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
+ 			DataSize += sizeof(EFI_GUID);
+ 		DataSize += list[i].MokSize;
+ 	}
++	if (DataSize == 0)
++		return EFI_SUCCESS;
+ 
+ 	Data = AllocatePool(DataSize);
+-	if (Data == NULL && DataSize != 0)
++	if (Data == NULL)
+ 		return EFI_OUT_OF_RESOURCES;
+ 
+ 	ptr = Data;
+-- 
+2.26.2
+
diff --git a/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch b/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch
new file mode 100644
index 0000000..8749432
--- /dev/null
+++ b/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch
@@ -0,0 +1,33 @@
+From c186bdddaa7b103aef9d4a164ac0a07499dba112 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 22 Jul 2020 23:55:44 -0400
+Subject: [PATCH 54/62] simple_file: fix uninitialized variable/unchecked
+ return
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#212
+---
+ lib/simple_file.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/lib/simple_file.c b/lib/simple_file.c
+index 3bf92ed8e0f..6ad31b4dc04 100644
+--- a/lib/simple_file.c
++++ b/lib/simple_file.c
+@@ -403,10 +403,10 @@ simple_file_selector(EFI_HANDLE * im, CHAR16 ** title, CHAR16 * name,
+ 		filter = L"";
+ 	if (!*im) {
+ 		EFI_HANDLE h;
+-		CHAR16 *volname;
++		CHAR16 *volname = NULL;
+ 
+-		simple_volume_selector(title, &volname, &h);
+-		if (!volname)
++		efi_status = simple_volume_selector(title, &volname, &h);
++		if (EFI_ERROR(efi_status) || !volname)
+ 			return;
+ 		FreePool(volname);
+ 		*im = h;
+-- 
+2.26.2
+
diff --git a/SOURCES/0055-Fix-a-broken-tpm-type.patch b/SOURCES/0055-Fix-a-broken-tpm-type.patch
new file mode 100644
index 0000000..06b1201
--- /dev/null
+++ b/SOURCES/0055-Fix-a-broken-tpm-type.patch
@@ -0,0 +1,27 @@
+From a7f9911b776f3cdc12e42bf5990ddef0b08d3701 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 20:35:56 -0400
+Subject: [PATCH 55/62] Fix a broken tpm type
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#212
+---
+ tpm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tpm.c b/tpm.c
+index 22ad148b35a..03cf3a1f60e 100644
+--- a/tpm.c
++++ b/tpm.c
+@@ -239,7 +239,7 @@ EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+ 	efi_status = tpm_log_event_raw(buf, size, pcr, (CHAR8 *)ImageLoad,
+ 				       sizeof(*ImageLoad) + path_size,
+ 				       EV_EFI_BOOT_SERVICES_APPLICATION,
+-				       sha1hash);
++				       (CHAR8 *)sha1hash);
+ 	FreePool(ImageLoad);
+ 
+ 	return efi_status;
+-- 
+2.26.2
+
diff --git a/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch b/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch
new file mode 100644
index 0000000..c8068ef
--- /dev/null
+++ b/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch
@@ -0,0 +1,279 @@
+From 7d542805ba5c48185128a2351bb315a5648fe3d7 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 00:08:30 -0400
+Subject: [PATCH 56/62] Make cert.S not impossible to read.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#206
+---
+ shim.c | 47 +++++++++++++++++--------------
+ shim.h | 28 +++++++++++++++---
+ cert.S | 89 ++++++++++++++++++++++------------------------------------
+ 3 files changed, 84 insertions(+), 80 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index 0e7e784b4c8..888ee6e8d7b 100644
+--- a/shim.c
++++ b/shim.c
+@@ -68,16 +68,18 @@ static UINT32 load_options_size;
+  * The vendor certificate used for validating the second stage loader
+  */
+ extern struct {
+-	UINT32 vendor_cert_size;
+-	UINT32 vendor_dbx_size;
+-	UINT32 vendor_cert_offset;
+-	UINT32 vendor_dbx_offset;
++	UINT32 vendor_authorized_size;
++	UINT32 vendor_deauthorized_size;
++	UINT32 vendor_authorized_offset;
++	UINT32 vendor_deauthorized_offset;
+ } cert_table;
+ 
+-UINT32 vendor_cert_size;
+-UINT32 vendor_dbx_size;
+-UINT8 *vendor_cert;
+-UINT8 *vendor_dbx;
++UINT32 vendor_authorized_size = 0;
++UINT8 *vendor_authorized = NULL;
++
++UINT32 vendor_deauthorized_size = 0;
++UINT8 *vendor_deauthorized = NULL;
++
+ #if defined(ENABLE_SHIM_CERT)
+ UINT32 build_cert_size;
+ UINT8 *build_cert;
+@@ -554,22 +556,22 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
+ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 				   UINT8 *sha256hash, UINT8 *sha1hash)
+ {
+-	EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
++	EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_deauthorized;
+ 
+-	if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
++	if (check_db_hash_in_ram(dbx, vendor_deauthorized_size, sha256hash,
+ 			SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID, L"dbx",
+ 			EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) {
+ 		LogError(L"binary sha256hash found in vendor dbx\n");
+ 		return EFI_SECURITY_VIOLATION;
+ 	}
+-	if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
++	if (check_db_hash_in_ram(dbx, vendor_deauthorized_size, sha1hash,
+ 				 SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID, L"dbx",
+ 				 EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) {
+ 		LogError(L"binary sha1hash found in vendor dbx\n");
+ 		return EFI_SECURITY_VIOLATION;
+ 	}
+ 	if (cert &&
+-	    check_db_cert_in_ram(dbx, vendor_dbx_size, cert, sha256hash, L"dbx",
++	    check_db_cert_in_ram(dbx, vendor_deauthorized_size, cert, sha256hash, L"dbx",
+ 				 EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) {
+ 		LogError(L"cert sha256hash found in vendor dbx\n");
+ 		return EFI_SECURITY_VIOLATION;
+@@ -1077,19 +1079,19 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 		/*
+ 		 * And finally, check against shim's built-in key
+ 		 */
+-		if (vendor_cert_size &&
++		if (vendor_authorized_size &&
+ 		    AuthenticodeVerify(cert->CertData,
+ 				       cert->Hdr.dwLength - sizeof(cert->Hdr),
+-				       vendor_cert, vendor_cert_size,
++				       vendor_authorized, vendor_authorized_size,
+ 				       sha256hash, SHA256_DIGEST_SIZE)) {
+ 			update_verification_method(VERIFIED_BY_CERT);
+ 			tpm_measure_variable(L"Shim", SHIM_LOCK_GUID,
+-					     vendor_cert_size, vendor_cert);
++					     vendor_authorized_size, vendor_authorized);
+ 			efi_status = EFI_SUCCESS;
+ 			drain_openssl_errors();
+ 			return efi_status;
+ 		} else {
+-			LogError(L"AuthenticodeVerify(vendor_cert) failed\n");
++			LogError(L"AuthenticodeVerify(vendor_authorized) failed\n");
+ 		}
+ 	}
+ 
+@@ -2501,7 +2503,7 @@ shim_init(void)
+ 	}
+ 
+ 	if (secure_mode()) {
+-		if (vendor_cert_size || vendor_dbx_size) {
++		if (vendor_authorized_size || vendor_deauthorized_size) {
+ 			/*
+ 			 * If shim includes its own certificates then ensure
+ 			 * that anything it boots has performed some
+@@ -2606,14 +2608,17 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 
+ 	verification_method = VERIFIED_BY_NOTHING;
+ 
+-	vendor_cert_size = cert_table.vendor_cert_size;
+-	vendor_dbx_size = cert_table.vendor_dbx_size;
+-	vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
+-	vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
++	vendor_authorized_size = cert_table.vendor_authorized_size;
++	vendor_authorized = (UINT8 *)&cert_table + cert_table.vendor_authorized_offset;
++
++	vendor_deauthorized_size = cert_table.vendor_deauthorized_size;
++	vendor_deauthorized = (UINT8 *)&cert_table + cert_table.vendor_deauthorized_offset;
++
+ #if defined(ENABLE_SHIM_CERT)
+ 	build_cert_size = sizeof(shim_cert);
+ 	build_cert = shim_cert;
+ #endif /* defined(ENABLE_SHIM_CERT) */
++
+ 	CHAR16 *msgs[] = {
+ 		L"import_mok_state() failed",
+ 		L"shim_init() failed",
+diff --git a/shim.h b/shim.h
+index a0fa5a75e7e..555498c6673 100644
+--- a/shim.h
++++ b/shim.h
+@@ -97,6 +97,24 @@
+ #define FALLBACK L"\\fb" EFI_ARCH L".efi"
+ #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
+ 
++#if defined(VENDOR_CERT_FILE)
++# define vendor_authorized vendor_cert
++# define vendor_authorized_size vendor_cert_size
++# define vendor_authorized_category VENDOR_ADDEND_X509
++#else
++# define vendor_authorized vendor_null
++# define vendor_authorized_size vendor_null_size
++# define vendor_authorized_category VENDOR_ADDEND_NONE
++#endif
++
++#if defined(VENDOR_DBX_FILE)
++# define vendor_deauthorized vendor_dbx
++# define vendor_deauthorized_size vendor_dbx_size
++#else
++# define vendor_deauthorized vendor_deauthorized_null
++# define vendor_deauthorized_size vendor_deauthorized_null_size
++#endif
++
+ #include "include/asm.h"
+ #include "include/configtable.h"
+ #include "include/console.h"
+@@ -166,10 +184,12 @@ extern VOID ClearErrors(VOID);
+ extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath);
+ extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle);
+ 
+-extern UINT32 vendor_cert_size;
+-extern UINT32 vendor_dbx_size;
+-extern UINT8 *vendor_cert;
+-extern UINT8 *vendor_dbx;
++extern UINT32 vendor_authorized_size;
++extern UINT8 *vendor_authorized;
++
++extern UINT32 vendor_deauthorized_size;
++extern UINT8 *vendor_deauthorized;
++
+ #if defined(ENABLE_SHIM_CERT)
+ extern UINT32 build_cert_size;
+ extern UINT8 *build_cert;
+diff --git a/cert.S b/cert.S
+index cfc4525b44c..520caaef3af 100644
+--- a/cert.S
++++ b/cert.S
+@@ -1,65 +1,44 @@
++
++#if defined(VENDOR_CERT_FILE)
++# define vendor_authorized vendor_cert
++# define vendor_authorized_end vendor_cert_end
++# define vendor_authorized_size vendor_cert_size
++# define vendor_authorized_size_end vendor_cert_size_end
++#endif
++
++#if defined(VENDOR_DBX_FILE)
++# define vendor_deauthorized vendor_dbx
++# define vendor_deauthorized_end vendor_dbx_end
++# define vendor_deauthorized_size vendor_dbx_size
++# define vendor_deauthorized_size_end vendor_dbx_size_end
++#endif
++
+ 	.globl cert_table
+ 	.type	cert_table, %object
+-	.size	cert_table, 4
++	.size	cert_table, .Lcert_table_end - cert_table
+ 	.section .vendor_cert, "a", %progbits
++	.balignl 4, 0
+ cert_table:
+-#if defined(VENDOR_CERT_FILE)
+-	.long	vendor_cert_priv_end - vendor_cert_priv
+-#else
+-	.long	0
+-#endif
+-#if defined(VENDOR_DBX_FILE)
+-	.long	vendor_dbx_priv_end - vendor_dbx_priv
+-#else
+-	.long	0
+-#endif
+-	.long	vendor_cert_priv - cert_table
+-	.long	vendor_dbx_priv - cert_table
+-#if defined(VENDOR_CERT_FILE)
+-	.data
+-	.align	1
+-	.type	vendor_cert_priv, %object
+-	.size	vendor_cert_priv, vendor_cert_priv_end-vendor_cert_priv
++	.4byte	.Lvendor_authorized_end - vendor_authorized
++	.4byte	.Lvendor_deauthorized_end - vendor_deauthorized
++	.4byte	vendor_authorized - cert_table
++	.4byte	vendor_deauthorized - cert_table
++	.balign	1, 0
++	.type	vendor_authorized, %object
++	.size	vendor_authorized, .Lvendor_authorized_end - vendor_authorized
+ 	.section .vendor_cert, "a", %progbits
+-vendor_cert_priv:
++vendor_authorized:
++#if defined(VENDOR_CERT_FILE)
+ .incbin VENDOR_CERT_FILE
+-vendor_cert_priv_end:
+-#else
+-	.bss
+-	.type	vendor_cert_priv, %object
+-	.size	vendor_cert_priv, 1
+-	.section .vendor_cert, "a", %progbits
+-vendor_cert_priv:
+-	.zero	1
+-
+-	.data
+-	.align 4
+-	.type	vendor_cert_size_priv, %object
+-	.size	vendor_cert_size_priv, 4
+-	.section .vendor_cert, "a", %progbits
+-vendor_cert_priv_end:
+ #endif
++.Lvendor_authorized_end:
++	.balign	1, 0
++	.type	vendor_deauthorized, %object
++	.size	vendor_deauthorized, .Lvendor_deauthorized_end - vendor_deauthorized
++	.section .vendor_cert, "a", %progbits
++vendor_deauthorized:
+ #if defined(VENDOR_DBX_FILE)
+-	.data
+-	.align	1
+-	.type	vendor_dbx_priv, %object
+-	.size	vendor_dbx_priv, vendor_dbx_priv_end-vendor_dbx_priv
+-	.section .vendor_cert, "a", %progbits
+-vendor_dbx_priv:
+ .incbin VENDOR_DBX_FILE
+-vendor_dbx_priv_end:
+-#else
+-	.bss
+-	.type	vendor_dbx_priv, %object
+-	.size	vendor_dbx_priv, 1
+-	.section .vendor_cert, "a", %progbits
+-vendor_dbx_priv:
+-	.zero	1
+-
+-	.data
+-	.align 4
+-	.type	vendor_dbx_size_priv, %object
+-	.size	vendor_dbx_size_priv, 4
+-	.section .vendor_cert, "a", %progbits
+-vendor_dbx_priv_end:
+ #endif
++.Lvendor_deauthorized_end:
++.Lcert_table_end:
+-- 
+2.26.2
+
diff --git a/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch b/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch
new file mode 100644
index 0000000..13a25e8
--- /dev/null
+++ b/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch
@@ -0,0 +1,943 @@
+From dd3a5d71252a1f94e37f1a4c8841d253630b305a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 12:36:56 -0400
+Subject: [PATCH 57/62] Add support for vendor_db built-in shim authorized
+ list.
+
+Potential new signing strategies ( for example signing grub, fwupdate
+and vmlinuz with separate certificates ) require shim to support a
+vendor provided bundle of trusted certificates and hashes, which allows
+shim to trust EFI binaries matching either certificate by signature or
+hash in the vendor_db.  Functionality is similar to vendor_dbx.
+
+This also improves the mirroring quite a bit.
+Upstream: pr#206
+---
+ lib/variables.c     |  55 +++--
+ mok.c               | 502 ++++++++++++++++++++++++++++++--------------
+ shim.c              |  27 +++
+ include/console.h   |   3 +-
+ include/variables.h |   9 +-
+ shim.h              |   7 +-
+ cert.S              |  13 +-
+ Make.defaults       |   3 +
+ README.tpm          |   1 +
+ 9 files changed, 437 insertions(+), 183 deletions(-)
+
+diff --git a/lib/variables.c b/lib/variables.c
+index 9c2e7d0ac2d..8123ae60fc9 100644
+--- a/lib/variables.c
++++ b/lib/variables.c
+@@ -25,32 +25,59 @@
+ #include "shim.h"
+ 
+ EFI_STATUS
+-variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
+-		    void **out, int *outlen)
++fill_esl(const uint8_t *data, const size_t data_len,
++	 const EFI_GUID *type, const EFI_GUID *owner,
++	 uint8_t *out, size_t *outlen)
+ {
+-	*outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
++	EFI_SIGNATURE_LIST *sl;
++	EFI_SIGNATURE_DATA *sd;
++	size_t needed = 0;
+ 
+-	*out = AllocateZeroPool(*outlen);
+-	if (!*out)
+-		return EFI_OUT_OF_RESOURCES;
++	if (!data || !data_len || !type || !outlen)
++		return EFI_INVALID_PARAMETER;
+ 
+-	EFI_SIGNATURE_LIST *sl = *out;
++	needed = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) + data_len;
++	if (!out || *outlen < needed) {
++		*outlen = needed;
++		return EFI_BUFFER_TOO_SMALL;
++	}
++
++	*outlen = needed;
++	sl = (EFI_SIGNATURE_LIST *)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);
++	sl->SignatureSize = sizeof(EFI_GUID) + data_len;
++	sl->SignatureListSize = needed;
+ 
++	sd = (EFI_SIGNATURE_DATA *)(out + sizeof(EFI_SIGNATURE_LIST));
+ 	if (owner)
+ 		sd->SignatureOwner = *owner;
+ 
+-	CopyMem(sd->SignatureData, cert, cert_len);
++	CopyMem(sd->SignatureData, data, data_len);
+ 
+ 	return EFI_SUCCESS;
+ }
+ 
++EFI_STATUS
++variable_create_esl(const uint8_t *data, const size_t data_len,
++		    const EFI_GUID *type, const EFI_GUID *owner,
++		    uint8_t **out, size_t *outlen)
++{
++	EFI_STATUS efi_status;
++
++	*outlen = 0;
++	efi_status = fill_esl(data, data_len, type, owner, NULL, outlen);
++	if (efi_status != EFI_BUFFER_TOO_SMALL)
++		return efi_status;
++
++	*out = AllocateZeroPool(*outlen);
++	if (!*out)
++		return EFI_OUT_OF_RESOURCES;
++
++	return fill_esl(data, data_len, type, owner, *out, outlen);
++}
++
+ EFI_STATUS
+ CreateTimeBasedPayload(IN OUT UINTN * DataSize, IN OUT UINT8 ** Data)
+ {
+@@ -137,9 +164,9 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner,
+ 		return EFI_SECURITY_VIOLATION;
+ 
+ 	if (createtimebased) {
+-		int ds;
++		size_t ds;
+ 		efi_status = variable_create_esl(Data, len, &X509_GUID, NULL,
+-						 (void **)&Cert, &ds);
++						 (uint8_t **)&Cert, &ds);
+ 		if (EFI_ERROR(efi_status)) {
+ 			console_print(L"Failed to create %s certificate %d\n",
+ 				      var, efi_status);
+diff --git a/mok.c b/mok.c
+index 089ea6bfc9a..e69857f3c37 100644
+--- a/mok.c
++++ b/mok.c
+@@ -5,6 +5,8 @@
+ 
+ #include "shim.h"
+ 
++#include <stdint.h>
++
+ /*
+  * Check if a variable exists
+  */
+@@ -47,6 +49,15 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
+ 	return EFI_SUCCESS;
+ }
+ 
++typedef enum {
++	VENDOR_ADDEND_DB,
++	VENDOR_ADDEND_X509,
++	VENDOR_ADDEND_NONE,
++} vendor_addend_category_t;
++
++struct mok_state_variable;
++typedef vendor_addend_category_t (vendor_addend_categorizer_t)(struct mok_state_variable *);
++
+ /*
+  * MoK variables that need to have their storage validated.
+  *
+@@ -58,18 +69,20 @@ struct mok_state_variable {
+ 	char *name8;
+ 	CHAR16 *rtname;
+ 	EFI_GUID *guid;
++
+ 	UINT8 *data;
+ 	UINTN data_size;
++
+ 	/*
+-	 * These two are indirect pointers just to make initialization
+-	 * saner...
++	 * These are indirect pointers just to make initialization saner...
+ 	 */
+-	UINT8 **addend_source;
++	vendor_addend_categorizer_t *categorize_addend;
++	UINT8 **addend;
+ 	UINT32 *addend_size;
+-#if defined(ENABLE_SHIM_CERT)
++
+ 	UINT8 **build_cert;
+ 	UINT32 *build_cert_size;
+-#endif /* defined(ENABLE_SHIM_CERT) */
++
+ 	UINT32 yes_attr;
+ 	UINT32 no_attr;
+ 	UINT32 flags;
+@@ -77,6 +90,28 @@ struct mok_state_variable {
+ 	UINT8 *state;
+ };
+ 
++static vendor_addend_category_t
++categorize_authorized(struct mok_state_variable *v)
++{
++	if (!(v->addend && v->addend_size &&
++	      *v->addend && *v->addend_size)) {
++		return VENDOR_ADDEND_NONE;
++	}
++
++	return vendor_authorized_category;
++}
++
++static vendor_addend_category_t
++categorize_deauthorized(struct mok_state_variable *v)
++{
++	if (!(v->addend && v->addend_size &&
++	      *v->addend && *v->addend_size)) {
++		return VENDOR_ADDEND_NONE;
++	}
++
++	return VENDOR_ADDEND_DB;
++}
++
+ #define MOK_MIRROR_KEYDB	0x01
+ #define MOK_MIRROR_DELETE_FIRST	0x02
+ #define MOK_VARIABLE_MEASURE	0x04
+@@ -90,8 +125,9 @@ struct mok_state_variable mok_state_variables[] = {
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+ 	 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
+-	 .addend_source = &vendor_cert,
+-	 .addend_size = &vendor_cert_size,
++	 .categorize_addend = categorize_authorized,
++	 .addend = &vendor_authorized,
++	 .addend_size = &vendor_authorized_size,
+ #if defined(ENABLE_SHIM_CERT)
+ 	 .build_cert = &build_cert,
+ 	 .build_cert_size = &build_cert_size,
+@@ -107,6 +143,9 @@ struct mok_state_variable mok_state_variables[] = {
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+ 	 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
++	 .categorize_addend = categorize_deauthorized,
++	 .addend = &vendor_deauthorized,
++	 .addend_size = &vendor_deauthorized_size,
+ 	 .flags = MOK_MIRROR_KEYDB |
+ 		  MOK_VARIABLE_LOG,
+ 	 .pcr = 14,
+@@ -136,123 +175,253 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{ NULL, }
+ };
+ 
+-static inline BOOLEAN nonnull(1)
+-check_vendor_cert(struct mok_state_variable *v)
+-{
+-	return (v->addend_source && v->addend_size &&
+-		*v->addend_source && *v->addend_size) ? TRUE : FALSE;
+-}
++#define should_mirror_addend(v) (((v)->categorize_addend) && ((v)->categorize_addend(v) != VENDOR_ADDEND_NONE))
+ 
+-#if defined(ENABLE_SHIM_CERT)
+ static inline BOOLEAN nonnull(1)
+-check_build_cert(struct mok_state_variable *v)
++should_mirror_build_cert(struct mok_state_variable *v)
+ {
+ 	return (v->build_cert && v->build_cert_size &&
+ 		*v->build_cert && *v->build_cert_size) ? TRUE : FALSE;
+ }
+-#define check_addend(v) (check_vendor_cert(v) || check_build_cert(v))
+-#else
+-#define check_addend(v) check_vendor_cert(v)
+-#endif /* defined(ENABLE_SHIM_CERT) */
++
++static const uint8_t null_sha256[32] = { 0, };
+ 
+ static EFI_STATUS nonnull(1)
+ mirror_one_mok_variable(struct mok_state_variable *v)
+ {
+ 	EFI_STATUS efi_status = EFI_SUCCESS;
+-	void *FullData = NULL;
+-	UINTN FullDataSize = 0;
++	uint8_t *FullData = NULL;
++	size_t FullDataSize = 0;
++	vendor_addend_category_t addend_category = VENDOR_ADDEND_NONE;
+ 	uint8_t *p = NULL;
+ 
+-	if ((v->flags & MOK_MIRROR_KEYDB) && check_addend(v)) {
+-		EFI_SIGNATURE_LIST *CertList = NULL;
+-		EFI_SIGNATURE_DATA *CertData = NULL;
+-#if defined(ENABLE_SHIM_CERT)
+-		FullDataSize = v->data_size;
+-		if (check_build_cert(v)) {
+-			FullDataSize += sizeof (*CertList)
+-					+ sizeof (EFI_GUID)
+-					+ *v->build_cert_size;
+-		}
+-		if (check_vendor_cert(v)) {
+-			FullDataSize += sizeof (*CertList)
+-					+ sizeof (EFI_GUID)
+-					+ *v->addend_size;
+-		}
+-#else
+-		FullDataSize = v->data_size
+-			     + sizeof (*CertList)
+-			     + sizeof (EFI_GUID)
+-			     + *v->addend_size;
+-#endif /* defined(ENABLE_SHIM_CERT) */
+-		FullData = AllocatePool(FullDataSize);
+-		if (!FullData) {
+-			perror(L"Failed to allocate space for MokListRT\n");
+-			return EFI_OUT_OF_RESOURCES;
+-		}
+-		p = FullData;
++	size_t build_cert_esl_sz = 0, addend_esl_sz = 0;
+ 
+-		if (!EFI_ERROR(efi_status) && v->data_size > 0) {
+-			CopyMem(p, v->data, v->data_size);
+-			p += v->data_size;
+-		}
++	if (v->categorize_addend)
++		addend_category = v->categorize_addend(v);
+ 
+-#if defined(ENABLE_SHIM_CERT)
+-		if (check_build_cert(v) == FALSE)
+-			goto skip_build_cert;
++	/*
++	 * we're always mirroring the original data, whether this is an efi
++	 * security database or not
++	 */
++	dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data);
++	dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData);
++	if (v->data_size) {
++		FullDataSize = v->data_size;
++		dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++		       FullDataSize, FullData);
++	}
+ 
+-		CertList = (EFI_SIGNATURE_LIST *)p;
+-		p += sizeof (*CertList);
+-		CertData = (EFI_SIGNATURE_DATA *)p;
+-		p += sizeof (EFI_GUID);
++	/*
++	 * if it is, there's more data
++	 */
++	if (v->flags & MOK_MIRROR_KEYDB) {
+ 
+-		CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
+-		CertList->SignatureListSize = *v->build_cert_size
+-					      + sizeof (*CertList)
+-					      + sizeof (*CertData)
+-					      -1;
+-		CertList->SignatureHeaderSize = 0;
+-		CertList->SignatureSize = *v->build_cert_size +
+-					  sizeof (EFI_GUID);
++		/*
++		 * We're mirroring (into) an efi security database, aka an
++		 * array of efi_signature_list_t.  Its layout goes like:
++		 *
++		 *   existing_variable_data
++		 *   existing_variable_data_size
++		 *   if flags & MOK_MIRROR_KEYDB
++		 *     if build_cert
++		 *       build_cert_esl
++		 *       build_cert_header (always sz=0)
++		 *       build_cert_esd[0] { owner, data }
++		 *     if addend==vendor_db
++		 *       for n=[1..N]
++		 *         vendor_db_esl_n
++		 *           vendor_db_header_n (always sz=0)
++		 *           vendor_db_esd_n[m] {{ owner, data }, ... }
++		 *     elif addend==vendor_cert
++		 *       vendor_cert_esl
++		 *         vendor_cert_header (always sz=0)
++		 *         vendor_cert_esd[1] { owner, data }
++		 *
++		 * first we determine the size of the variable, then alloc
++		 * and add the data.
++		 */
+ 
+-		CertData->SignatureOwner = SHIM_LOCK_GUID;
+-		CopyMem(p, *v->build_cert, *v->build_cert_size);
++		/*
++		 * first bit is existing data, but we added that above
++		 */
+ 
+-		p += *v->build_cert_size;
++		/*
++		 * then the build cert if it's there
++		 */
++		if (should_mirror_build_cert(v)) {
++			efi_status = fill_esl(*v->build_cert,
++					      *v->build_cert_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      NULL, &build_cert_esl_sz);
++			if (efi_status != EFI_BUFFER_TOO_SMALL) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			FullDataSize += build_cert_esl_sz;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++			       FullDataSize, FullData);
++		}
+ 
+-		if (check_vendor_cert(v) == FALSE)
+-			goto skip_vendor_cert;
+-skip_build_cert:
+-#endif /* defined(ENABLE_SHIM_CERT) */
++		/*
++		 * then the addend data
++		 */
++		switch (addend_category) {
++		case VENDOR_ADDEND_DB:
++			/*
++			 * if it's an ESL already, we use it wholesale
++			 */
++			FullDataSize += *v->addend_size;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++			       FullDataSize, FullData);
++			break;
++		case VENDOR_ADDEND_X509:
++			efi_status = fill_esl(*v->addend, *v->addend_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      NULL, &addend_esl_sz);
++			if (efi_status != EFI_BUFFER_TOO_SMALL) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			FullDataSize += addend_esl_sz;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++				      FullDataSize, FullData);
++			break;
++		default:
++		case VENDOR_ADDEND_NONE:
++			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++				      FullDataSize, FullData);
++			break;
++		}
++	}
+ 
+-		CertList = (EFI_SIGNATURE_LIST *)p;
+-		p += sizeof (*CertList);
+-		CertData = (EFI_SIGNATURE_DATA *)p;
+-		p += sizeof (EFI_GUID);
++	/*
++	 * Now we have the full size
++	 */
++	if (FullDataSize) {
++		/*
++		 * allocate the buffer, or use the old one if it's just the
++		 * existing data.
++		 */
++		if (FullDataSize != v->data_size) {
++			dprint(L"FullDataSize:%lu FullData:0x%08llx allocating FullData\n",
++			       FullDataSize, FullData);
++			FullData = AllocatePool(FullDataSize);
++			if (!FullData) {
++				FreePool(v->data);
++				v->data = NULL;
++				v->data_size = 0;
++				perror(L"Failed to allocate %lu bytes for %s\n",
++				       FullDataSize, v->name);
++				return EFI_OUT_OF_RESOURCES;
++			}
++			p = FullData;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			if (v->data && v->data_size) {
++				CopyMem(p, v->data, v->data_size);
++				p += v->data_size;
++			}
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		} else {
++			FullData = v->data;
++			FullDataSize = v->data_size;
++			p = FullData + FullDataSize;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			v->data = NULL;
++			v->data_size = 0;
++		}
++	}
++	dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++	       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 
+-		CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
+-		CertList->SignatureListSize = *v->addend_size
+-					      + sizeof (*CertList)
+-					      + sizeof (*CertData)
+-					      -1;
+-		CertList->SignatureHeaderSize = 0;
+-		CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID);
++	/*
++	 * Now fill it.
++	 */
++	if (v->flags & MOK_MIRROR_KEYDB) {
++		/*
++		 * first bit is existing data, but again, we added that above
++		 */
+ 
+-		CertData->SignatureOwner = SHIM_LOCK_GUID;
+-		CopyMem(p, *v->addend_source, *v->addend_size);
++		/*
++		 * second is the build cert
++		 */
++		dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		if (should_mirror_build_cert(v)) {
++			efi_status = fill_esl(*v->build_cert,
++					      *v->build_cert_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      p, &build_cert_esl_sz);
++			if (EFI_ERROR(efi_status)) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			p += build_cert_esl_sz;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		}
+ 
+-#if defined(ENABLE_SHIM_CERT)
+-skip_vendor_cert:
+-#endif /* defined(ENABLE_SHIM_CERT) */
+-		if (v->data && v->data_size)
+-			FreePool(v->data);
+-		v->data = FullData;
+-		v->data_size = FullDataSize;
+-	} else {
+-		FullDataSize = v->data_size;
+-		FullData = v->data;
++		switch (addend_category) {
++		case VENDOR_ADDEND_DB:
++			CopyMem(p, *v->addend, *v->addend_size);
++			p += *v->addend_size;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			break;
++		case VENDOR_ADDEND_X509:
++			efi_status = fill_esl(*v->addend, *v->addend_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      p, &addend_esl_sz);
++			if (EFI_ERROR(efi_status)) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			p += addend_esl_sz;
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			break;
++		default:
++		case VENDOR_ADDEND_NONE:
++			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			break;
++		}
++	}
++	/*
++	 * We always want to create our key databases, so in this case we
++	 * need a dummy entry
++	 */
++	if ((v->flags & MOK_MIRROR_KEYDB) && FullDataSize == 0) {
++		efi_status = variable_create_esl(
++				null_sha256, sizeof(null_sha256),
++				&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
++				&FullData, &FullDataSize);
++		if (EFI_ERROR(efi_status)) {
++			perror(L"Failed to allocate %lu bytes for %s\n",
++			       FullDataSize, v->name);
++			return efi_status;
++		}
++		p = FullData + FullDataSize;
++		dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 	}
+ 
++	dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++	       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 	if (FullDataSize) {
++		dprint(L"Setting %s with %lu bytes of data\n",
++		       v->rtname, FullDataSize);
+ 		efi_status = gRT->SetVariable(v->rtname, v->guid,
+ 					      EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 					      EFI_VARIABLE_RUNTIME_ACCESS,
+@@ -262,7 +431,15 @@ skip_vendor_cert:
+ 			       v->rtname, efi_status);
+ 		}
+ 	}
+-
++	if (v->data && v->data_size) {
++		FreePool(v->data);
++		v->data = NULL;
++		v->data_size = 0;
++	}
++	if (FullData && FullDataSize) {
++		FreePool(FullData);
++	}
++	dprint(L"returning %r\n", efi_status);
+ 	return efi_status;
+ }
+ 
+@@ -274,6 +451,8 @@ static EFI_STATUS nonnull(1)
+ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
+ {
+ 	EFI_STATUS efi_status;
++	BOOLEAN present = FALSE;
++
+ 	if (v->rtname) {
+ 		if (v->flags & MOK_MIRROR_DELETE_FIRST)
+ 			LibDeleteVariable(v->rtname, v->guid);
+@@ -286,6 +465,43 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
+ 			       efi_status);
+ 		}
+ 	}
++
++	present = (v->data && v->data_size) ? TRUE : FALSE;
++	if (!present)
++		return ret;
++
++	if (v->data_size == sizeof(UINT8) && v->state) {
++		*v->state = v->data[0];
++	}
++
++	if (v->flags & MOK_VARIABLE_MEASURE) {
++		/*
++		 * Measure this into PCR 7 in the Microsoft format
++		 */
++		efi_status = tpm_measure_variable(v->name, *v->guid,
++						  v->data_size,
++						  v->data);
++		if (EFI_ERROR(efi_status)) {
++			if (ret != EFI_SECURITY_VIOLATION)
++				ret = efi_status;
++		}
++	}
++
++	if (v->flags & MOK_VARIABLE_LOG) {
++		/*
++		 * Log this variable into whichever PCR the table
++		 * says.
++		 */
++		EFI_PHYSICAL_ADDRESS datap =
++				(EFI_PHYSICAL_ADDRESS)(UINTN)v->data,
++		efi_status = tpm_log_event(datap, v->data_size,
++					   v->pcr, (CHAR8 *)v->name8);
++		if (EFI_ERROR(efi_status)) {
++			if (ret != EFI_SECURITY_VIOLATION)
++				ret = efi_status;
++		}
++	}
++
+ 	return ret;
+ }
+ 
+@@ -311,26 +527,20 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 	user_insecure_mode = 0;
+ 	ignore_db = 0;
+ 
++	dprint(L"importing mok state\n");
+ 	for (i = 0; mok_state_variables[i].name != NULL; i++) {
+ 		struct mok_state_variable *v = &mok_state_variables[i];
+ 		UINT32 attrs = 0;
+-		BOOLEAN delete = FALSE, present, addend;
+-
+-		addend = check_addend(v);
++		BOOLEAN delete = FALSE;
+ 
+ 		efi_status = get_variable_attr(v->name,
+ 					       &v->data, &v->data_size,
+ 					       *v->guid, &attrs);
++		dprint(L"maybe mirroring %s\n", v->name);
+ 		if (efi_status == EFI_NOT_FOUND) {
+-			if (addend)
+-				ret = maybe_mirror_one_mok_variable(v, ret);
+-			/*
+-			 * after possibly adding, we can continue, no
+-			 * further checks to be done.
+-			 */
+-			continue;
+-		}
+-		if (EFI_ERROR(efi_status)) {
++			v->data = NULL;
++			v->data_size = 0;
++		} else if (EFI_ERROR(efi_status)) {
+ 			perror(L"Could not verify %s: %r\n", v->name,
+ 			       efi_status);
+ 			/*
+@@ -339,22 +549,22 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 			 */
+ 			if (ret != EFI_SECURITY_VIOLATION)
+ 				ret = efi_status;
+-			continue;
+-		}
+-
+-		if (!(attrs & v->yes_attr)) {
+-			perror(L"Variable %s is missing attributes:\n",
+-			       v->name);
+-			perror(L"  0x%08x should have 0x%08x set.\n",
+-			       attrs, v->yes_attr);
+-			delete = TRUE;
+-		}
+-		if (attrs & v->no_attr) {
+-			perror(L"Variable %s has incorrect attribute:\n",
+-			       v->name);
+-			perror(L"  0x%08x should not have 0x%08x set.\n",
+-			       attrs, v->no_attr);
+ 			delete = TRUE;
++		} else {
++			if (!(attrs & v->yes_attr)) {
++				perror(L"Variable %s is missing attributes:\n",
++				       v->name);
++				perror(L"  0x%08x should have 0x%08x set.\n",
++				       attrs, v->yes_attr);
++				delete = TRUE;
++			}
++			if (attrs & v->no_attr) {
++				perror(L"Variable %s has incorrect attribute:\n",
++				       v->name);
++				perror(L"  0x%08x should not have 0x%08x set.\n",
++				       attrs, v->no_attr);
++				delete = TRUE;
++			}
+ 		}
+ 		if (delete == TRUE) {
+ 			perror(L"Deleting bad variable %s\n", v->name);
+@@ -366,45 +576,9 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 			FreePool(v->data);
+ 			v->data = NULL;
+ 			v->data_size = 0;
+-			continue;
+ 		}
+ 
+-		if (v->data && v->data_size == sizeof(UINT8) && v->state) {
+-			*v->state = v->data[0];
+-		}
+-
+-		present = (v->data && v->data_size) ? TRUE : FALSE;
+-
+-		if (v->flags & MOK_VARIABLE_MEASURE && present) {
+-			/*
+-			 * Measure this into PCR 7 in the Microsoft format
+-			 */
+-			efi_status = tpm_measure_variable(v->name, *v->guid,
+-							  v->data_size,
+-							  v->data);
+-			if (EFI_ERROR(efi_status)) {
+-				if (ret != EFI_SECURITY_VIOLATION)
+-					ret = efi_status;
+-			}
+-		}
+-
+-		if (v->flags & MOK_VARIABLE_LOG && present) {
+-			/*
+-			 * Log this variable into whichever PCR the table
+-			 * says.
+-			 */
+-			EFI_PHYSICAL_ADDRESS datap =
+-					(EFI_PHYSICAL_ADDRESS)(UINTN)v->data,
+-			efi_status = tpm_log_event(datap, v->data_size,
+-						   v->pcr, (CHAR8 *)v->name8);
+-			if (EFI_ERROR(efi_status)) {
+-				if (ret != EFI_SECURITY_VIOLATION)
+-					ret = efi_status;
+-			}
+-		}
+-
+-		if (present)
+-			ret = maybe_mirror_one_mok_variable(v, ret);
++		ret = maybe_mirror_one_mok_variable(v, ret);
+ 	}
+ 
+ 	/*
+@@ -412,14 +586,16 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 	 * cause MokManager to demand a machine reboot, so this is safe to
+ 	 * have after the entire loop.
+ 	 */
++	dprint(L"checking mok request\n");
+ 	efi_status = check_mok_request(image_handle);
++	dprint(L"mok returned %r\n", efi_status);
+ 	if (EFI_ERROR(efi_status)) {
+ 		if (ret != EFI_SECURITY_VIOLATION)
+ 			ret = efi_status;
+ 		return ret;
+ 	}
+ 
+-
++	dprint(L"returning %r\n", ret);
+ 	return ret;
+ }
+ 
+diff --git a/shim.c b/shim.c
+index 888ee6e8d7b..ee62248ca4e 100644
+--- a/shim.c
++++ b/shim.c
+@@ -646,6 +646,31 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 		}
+ 	}
+ 
++#if defined(VENDOR_DB_FILE)
++	EFI_SIGNATURE_LIST *db = (EFI_SIGNATURE_LIST *)vendor_db;
++
++	if (check_db_hash_in_ram(db, vendor_db_size,
++				 sha256hash, SHA256_DIGEST_SIZE,
++				 EFI_CERT_SHA256_GUID, L"vendor_db",
++				 EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) {
++		verification_method = VERIFIED_BY_HASH;
++		update_verification_method(VERIFIED_BY_HASH);
++		return EFI_SUCCESS;
++	} else {
++		LogError(L"check_db_hash(vendor_db, sha256hash) != DATA_FOUND\n");
++	}
++	if (cert &&
++	    check_db_cert_in_ram(db, vendor_db_size,
++				 cert, sha256hash, L"vendor_db",
++				 EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) {
++		verification_method = VERIFIED_BY_CERT;
++		update_verification_method(VERIFIED_BY_CERT);
++		return EFI_SUCCESS;
++	} else {
++		LogError(L"check_db_cert(vendor_db, sha256hash) != DATA_FOUND\n");
++	}
++#endif
++
+ 	if (check_db_hash(L"MokList", SHIM_LOCK_GUID, sha256hash,
+ 			  SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID)
+ 				== DATA_FOUND) {
+@@ -1076,6 +1101,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 		}
+ #endif /* defined(ENABLE_SHIM_CERT) */
+ 
++#if defined(VENDOR_CERT_FILE)
+ 		/*
+ 		 * And finally, check against shim's built-in key
+ 		 */
+@@ -1093,6 +1119,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 		} else {
+ 			LogError(L"AuthenticodeVerify(vendor_authorized) failed\n");
+ 		}
++#endif /* defined(VENDOR_CERT_FILE) */
+ 	}
+ 
+ 	LogError(L"Binary is not whitelisted\n");
+diff --git a/include/console.h b/include/console.h
+index 9f259c71b72..810bf13a1f1 100644
+--- a/include/console.h
++++ b/include/console.h
+@@ -78,12 +78,13 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL {
+ extern VOID console_fini(VOID);
+ extern VOID setup_verbosity(VOID);
+ extern UINT32 verbose;
+-#define dprint(fmt, ...) ({							\
++#define dprint_(fmt, ...) ({							\
+ 		UINTN __dprint_ret = 0;						\
+ 		if (verbose)							\
+ 			__dprint_ret = console_print((fmt), ##__VA_ARGS__);	\
+ 		__dprint_ret;							\
+ 	})
++#define dprint(fmt, ...) dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
+ 
+ extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line);
+ #define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__)
+diff --git a/include/variables.h b/include/variables.h
+index 8566a1a4746..436adb46e16 100644
+--- a/include/variables.h
++++ b/include/variables.h
+@@ -57,7 +57,12 @@ 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);
++variable_create_esl(const uint8_t *cert, const size_t cert_len,
++		    const EFI_GUID *type, const EFI_GUID *owner,
++		    uint8_t **out, size_t *outlen);
++EFI_STATUS
++fill_esl(const uint8_t *data, const size_t data_len,
++	 const EFI_GUID *type, const EFI_GUID *owner,
++	 uint8_t *out, size_t *outlen);
+ 
+ #endif /* SHIM_VARIABLES_H */
+diff --git a/shim.h b/shim.h
+index 555498c6673..c1d7e7c7197 100644
+--- a/shim.h
++++ b/shim.h
+@@ -97,7 +97,11 @@
+ #define FALLBACK L"\\fb" EFI_ARCH L".efi"
+ #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
+ 
+-#if defined(VENDOR_CERT_FILE)
++#if defined(VENDOR_DB_FILE)
++# define vendor_authorized vendor_db
++# define vendor_authorized_size vendor_db_size
++# define vendor_authorized_category VENDOR_ADDEND_DB
++#elif defined(VENDOR_CERT_FILE)
+ # define vendor_authorized vendor_cert
+ # define vendor_authorized_size vendor_cert_size
+ # define vendor_authorized_category VENDOR_ADDEND_X509
+@@ -116,6 +120,7 @@
+ #endif
+ 
+ #include "include/asm.h"
++#include "include/compiler.h"
+ #include "include/configtable.h"
+ #include "include/console.h"
+ #include "include/crypt_blowfish.h"
+diff --git a/cert.S b/cert.S
+index 520caaef3af..e636fcbbf2d 100644
+--- a/cert.S
++++ b/cert.S
+@@ -1,5 +1,12 @@
+ 
+-#if defined(VENDOR_CERT_FILE)
++#if defined(VENDOR_DB_FILE) && defined(VENDOR_CERT_FILE)
++# error both VENDOR_DB_FILE and VENDOR_CERT_FILE have been configured
++#elif defined(VENDOR_DB_FILE)
++# define vendor_authorized vendor_db
++# define vendor_authorized_end vendor_db_end
++# define vendor_authorized_size vendor_db_size
++# define vendor_authorized_size_end vendor_db_size_end
++#elif defined(VENDOR_CERT_FILE)
+ # define vendor_authorized vendor_cert
+ # define vendor_authorized_end vendor_cert_end
+ # define vendor_authorized_size vendor_cert_size
+@@ -28,7 +35,9 @@ cert_table:
+ 	.size	vendor_authorized, .Lvendor_authorized_end - vendor_authorized
+ 	.section .vendor_cert, "a", %progbits
+ vendor_authorized:
+-#if defined(VENDOR_CERT_FILE)
++#if defined(VENDOR_DB_FILE)
++.incbin VENDOR_DB_FILE
++#elif defined(VENDOR_CERT_FILE)
+ .incbin VENDOR_CERT_FILE
+ #endif
+ .Lvendor_authorized_end:
+diff --git a/Make.defaults b/Make.defaults
+index f0bfa9fd573..2e01646a35d 100644
+--- a/Make.defaults
++++ b/Make.defaults
+@@ -125,6 +125,9 @@ BOOTCSVNAME	?= BOOT$(ARCH_SUFFIX_UPPER).CSV
+ 
+ CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\""
+ 
++ifneq ($(origin VENDOR_DB_FILE), undefined)
++	CFLAGS += -DVENDOR_DB_FILE=\"$(VENDOR_DB_FILE)\"
++endif
+ ifneq ($(origin VENDOR_CERT_FILE), undefined)
+ 	CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\"
+ endif
+diff --git a/README.tpm b/README.tpm
+index c060dbe22db..62308d5c71a 100644
+--- a/README.tpm
++++ b/README.tpm
+@@ -13,6 +13,7 @@ PCR7:
+   - MokListX - the Mok blacklist, logged as "MokListX"
+   - vendor_dbx - shim's built-in vendor blacklist, logged as "dbx"
+   - DB - the system whitelist, logged as "db"
++  - vendor_db - shim's built-in vendor whitelist, logged as "db"
+   - MokList the Mok whitelist, logged as "MokList"
+   - vendor_cert - shim's built-in vendor whitelist, logged as "Shim"
+   - shim_cert - shim's build-time generated whitelist, logged as "Shim"
+-- 
+2.26.2
+
diff --git a/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch b/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch
new file mode 100644
index 0000000..84482de
--- /dev/null
+++ b/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch
@@ -0,0 +1,366 @@
+From 76c0447e204c7e4ce918c4887ce8aae0e0816271 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 16:32:05 -0400
+Subject: [PATCH 58/62] Handle binaries with multiple signatures.
+
+This adds support for multiple signatures.  It first tries validating
+the binary by hash, first against our dbx lists, then against our db
+lists.  If it isn't allowed or rejected at that step, it continues to
+the normal routine of checking all the signatures.
+
+At this point it does *not* reject a binary just because a signature is
+by a cert on a dbx list, though that will override any db list that
+certificate is listed on.  If at any point any assertion about the
+binary or signature list being well-formed fails, the binary is
+immediately rejected, though we do allow skipping over signatures
+which have an unsupported sig->Hdr.wCertificateType.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#210
+---
+ shim.c | 287 +++++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 198 insertions(+), 89 deletions(-)
+
+diff --git a/shim.c b/shim.c
+index ee62248ca4e..d10a1ba1cac 100644
+--- a/shim.c
++++ b/shim.c
+@@ -690,7 +690,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 	}
+ 
+ 	update_verification_method(VERIFIED_BY_NOTHING);
+-	return EFI_SECURITY_VIOLATION;
++	return EFI_NOT_FOUND;
+ }
+ 
+ /*
+@@ -1004,6 +1004,103 @@ done:
+ 	return efi_status;
+ }
+ 
++static EFI_STATUS
++verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig,
++		     UINT8 *sha256hash, UINT8 *sha1hash)
++{
++	EFI_STATUS efi_status;
++
++	/*
++	 * Ensure that the binary isn't blacklisted
++	 */
++	drain_openssl_errors();
++	efi_status = check_blacklist(sig, sha256hash, sha1hash);
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Binary is blacklisted: %r\n", efi_status);
++		PrintErrors();
++		ClearErrors();
++		crypterr(efi_status);
++		return efi_status;
++	}
++
++	/*
++	 * Check whether the binary is whitelisted in any of the firmware
++	 * databases
++	 */
++	drain_openssl_errors();
++	efi_status = check_whitelist(sig, sha256hash, sha1hash);
++	if (EFI_ERROR(efi_status)) {
++		if (efi_status != EFI_NOT_FOUND) {
++			dprint(L"check_whitelist(): %r\n", efi_status);
++			PrintErrors();
++			ClearErrors();
++			crypterr(efi_status);
++		}
++	} else {
++		drain_openssl_errors();
++		return efi_status;
++	}
++
++	efi_status = EFI_NOT_FOUND;
++#if defined(ENABLE_SHIM_CERT)
++	/*
++	 * Check against the shim build key
++	 */
++	drain_openssl_errors();
++	if (build_cert && build_cert_size) {
++		dprint("verifying against shim cert\n");
++	}
++	if (build_cert && build_cert_size &&
++	    AuthenticodeVerify(sig->CertData,
++		       sig->Hdr.dwLength - sizeof(sig->Hdr),
++		       build_cert, build_cert_size, sha256hash,
++		       SHA256_DIGEST_SIZE)) {
++		dprint(L"AuthenticodeVerify(shim_cert) succeeded\n");
++		update_verification_method(VERIFIED_BY_CERT);
++		tpm_measure_variable(L"Shim", SHIM_LOCK_GUID,
++				     build_cert_size, build_cert);
++		efi_status = EFI_SUCCESS;
++		drain_openssl_errors();
++		return efi_status;
++	} else {
++		dprint(L"AuthenticodeVerify(shim_cert) failed\n");
++		PrintErrors();
++		ClearErrors();
++		crypterr(EFI_NOT_FOUND);
++	}
++#endif /* defined(ENABLE_SHIM_CERT) */
++
++#if defined(VENDOR_CERT_FILE)
++	/*
++	 * And finally, check against shim's built-in key
++	 */
++	drain_openssl_errors();
++	if (vendor_cert_size) {
++		dprint("verifying against vendor_cert\n");
++	}
++	if (vendor_cert_size &&
++	    AuthenticodeVerify(sig->CertData,
++			       sig->Hdr.dwLength - sizeof(sig->Hdr),
++			       vendor_cert, vendor_cert_size,
++			       sha256hash, SHA256_DIGEST_SIZE)) {
++		dprint(L"AuthenticodeVerify(vendor_cert) succeeded\n");
++		update_verification_method(VERIFIED_BY_CERT);
++		tpm_measure_variable(L"Shim", SHIM_LOCK_GUID,
++				     vendor_cert_size, vendor_cert);
++		efi_status = EFI_SUCCESS;
++		drain_openssl_errors();
++		return efi_status;
++	} else {
++		dprint(L"AuthenticodeVerify(vendor_cert) failed\n");
++		PrintErrors();
++		ClearErrors();
++		crypterr(EFI_NOT_FOUND);
++	}
++#endif /* defined(VENDOR_CERT_FILE) */
++
++	return efi_status;
++}
++
+ /*
+  * Check that the signature is valid and matches the binary
+  */
+@@ -1011,40 +1108,14 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 				 PE_COFF_LOADER_IMAGE_CONTEXT *context,
+ 				 UINT8 *sha256hash, UINT8 *sha1hash)
+ {
+-	EFI_STATUS efi_status = EFI_SECURITY_VIOLATION;
+-	WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
+-	unsigned int size = datasize;
++	EFI_STATUS ret_efi_status;
++	size_t size = datasize;
++	size_t offset = 0;
++	unsigned int i = 0;
+ 
+ 	if (datasize < 0)
+ 		return EFI_INVALID_PARAMETER;
+ 
+-	if (context->SecDir->Size != 0) {
+-		if (context->SecDir->Size >= size) {
+-			perror(L"Certificate Database size is too large\n");
+-			return EFI_INVALID_PARAMETER;
+-		}
+-
+-		cert = ImageAddress (data, size,
+-				     context->SecDir->VirtualAddress);
+-
+-		if (!cert) {
+-			perror(L"Certificate located outside the image\n");
+-			return EFI_INVALID_PARAMETER;
+-		}
+-
+-		if (cert->Hdr.dwLength > context->SecDir->Size) {
+-			perror(L"Certificate list size is inconsistent with PE headers");
+-			return EFI_INVALID_PARAMETER;
+-		}
+-
+-		if (cert->Hdr.wCertificateType !=
+-		    WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+-			perror(L"Unsupported certificate type %x\n",
+-				cert->Hdr.wCertificateType);
+-			return EFI_UNSUPPORTED;
+-		}
+-	}
+-
+ 	/*
+ 	 * Clear OpenSSL's error log, because we get some DSO unimplemented
+ 	 * errors during its intialization, and we don't want those to look
+@@ -1052,81 +1123,119 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 	 */
+ 	drain_openssl_errors();
+ 
+-	efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash);
+-	if (EFI_ERROR(efi_status)) {
+-		LogError(L"generate_hash: %r\n", efi_status);
+-		return efi_status;
++	ret_efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash);
++	if (EFI_ERROR(ret_efi_status)) {
++		dprint(L"generate_hash: %r\n", ret_efi_status);
++		PrintErrors();
++		ClearErrors();
++		crypterr(ret_efi_status);
++		return ret_efi_status;
+ 	}
+ 
+ 	/*
+-	 * Ensure that the binary isn't blacklisted
++	 * Ensure that the binary isn't blacklisted by hash
+ 	 */
+-	efi_status = check_blacklist(cert, sha256hash, sha1hash);
+-	if (EFI_ERROR(efi_status)) {
++	drain_openssl_errors();
++	ret_efi_status = check_blacklist(NULL, sha256hash, sha1hash);
++	if (EFI_ERROR(ret_efi_status)) {
+ 		perror(L"Binary is blacklisted\n");
+-		LogError(L"Binary is blacklisted: %r\n", efi_status);
+-		return efi_status;
++		dprint(L"Binary is blacklisted: %r\n", ret_efi_status);
++		PrintErrors();
++		ClearErrors();
++		crypterr(ret_efi_status);
++		return ret_efi_status;
+ 	}
+ 
+ 	/*
+-	 * Check whether the binary is whitelisted in any of the firmware
+-	 * databases
++	 * Check whether the binary is whitelisted by hash in any of the
++	 * firmware databases
+ 	 */
+-	efi_status = check_whitelist(cert, sha256hash, sha1hash);
+-	if (EFI_ERROR(efi_status)) {
+-		LogError(L"check_whitelist(): %r\n", efi_status);
++	drain_openssl_errors();
++	ret_efi_status = check_whitelist(NULL, sha256hash, sha1hash);
++	if (EFI_ERROR(ret_efi_status)) {
++		dprint(L"check_whitelist: %r\n", ret_efi_status);
++		if (ret_efi_status != EFI_NOT_FOUND) {
++			PrintErrors();
++			ClearErrors();
++			crypterr(ret_efi_status);
++			return ret_efi_status;
++		}
+ 	} else {
+ 		drain_openssl_errors();
+-		return efi_status;
++		return ret_efi_status;
+ 	}
+ 
+-	if (cert) {
+-#if defined(ENABLE_SHIM_CERT)
+-		/*
+-		 * Check against the shim build key
+-		 */
+-		if (sizeof(shim_cert) &&
+-		    AuthenticodeVerify(cert->CertData,
+-			       cert->Hdr.dwLength - sizeof(cert->Hdr),
+-			       shim_cert, sizeof(shim_cert), sha256hash,
+-			       SHA256_DIGEST_SIZE)) {
+-			update_verification_method(VERIFIED_BY_CERT);
+-			tpm_measure_variable(L"Shim", SHIM_LOCK_GUID,
+-					     sizeof(shim_cert), shim_cert);
+-			efi_status = EFI_SUCCESS;
+-			drain_openssl_errors();
+-			return efi_status;
+-		} else {
+-			LogError(L"AuthenticodeVerify(shim_cert) failed\n");
++	if (context->SecDir->Size == 0) {
++		dprint(L"No signatures found\n");
++		return EFI_SECURITY_VIOLATION;
++	}
++
++	if (context->SecDir->Size >= size) {
++		perror(L"Certificate Database size is too large\n");
++		return EFI_INVALID_PARAMETER;
++	}
++
++	ret_efi_status = EFI_NOT_FOUND;
++	do {
++		WIN_CERTIFICATE_EFI_PKCS *sig = NULL;
++		size_t sz;
++
++		sig = ImageAddress(data, size,
++				   context->SecDir->VirtualAddress + offset);
++		if (!sig)
++			break;
++
++		sz = offset + offsetof(WIN_CERTIFICATE_EFI_PKCS, Hdr.dwLength)
++		     + sizeof(sig->Hdr.dwLength);
++		if (sz > context->SecDir->Size) {
++			perror(L"Certificate size is too large for secruity database");
++			return EFI_INVALID_PARAMETER;
++		}
++
++		sz = sig->Hdr.dwLength;
++		if (sz > context->SecDir->Size - offset) {
++			perror(L"Certificate size is too large for secruity database");
++			return EFI_INVALID_PARAMETER;
+ 		}
+-#endif /* defined(ENABLE_SHIM_CERT) */
+-
+-#if defined(VENDOR_CERT_FILE)
+-		/*
+-		 * And finally, check against shim's built-in key
+-		 */
+-		if (vendor_authorized_size &&
+-		    AuthenticodeVerify(cert->CertData,
+-				       cert->Hdr.dwLength - sizeof(cert->Hdr),
+-				       vendor_authorized, vendor_authorized_size,
+-				       sha256hash, SHA256_DIGEST_SIZE)) {
+-			update_verification_method(VERIFIED_BY_CERT);
+-			tpm_measure_variable(L"Shim", SHIM_LOCK_GUID,
+-					     vendor_authorized_size, vendor_authorized);
+-			efi_status = EFI_SUCCESS;
+-			drain_openssl_errors();
+-			return efi_status;
++
++		if (sz < sizeof(sig->Hdr)) {
++			perror(L"Certificate size is too small for certificate data");
++			return EFI_INVALID_PARAMETER;
++		}
++
++		if (sig->Hdr.wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
++			EFI_STATUS efi_status;
++
++			dprint(L"Attempting to verify signature %d:\n", i++);
++
++			efi_status = verify_one_signature(sig, sha256hash, sha1hash);
++
++			/*
++			 * If we didn't get EFI_SECURITY_VIOLATION from
++			 * checking the hashes above, then any dbx entries are
++			 * for a certificate, not this individual binary.
++			 *
++			 * So don't clobber successes with security violation
++			 * here; that just means it isn't a success.
++			 */
++			if (ret_efi_status != EFI_SUCCESS)
++				ret_efi_status = efi_status;
+ 		} else {
+-			LogError(L"AuthenticodeVerify(vendor_authorized) failed\n");
++			perror(L"Unsupported certificate type %x\n",
++				sig->Hdr.wCertificateType);
+ 		}
+-#endif /* defined(VENDOR_CERT_FILE) */
+-	}
++		offset = ALIGN_VALUE(offset + sz, 8);
++	} while (offset < context->SecDir->Size);
+ 
+-	LogError(L"Binary is not whitelisted\n");
+-	crypterr(EFI_SECURITY_VIOLATION);
+-	PrintErrors();
+-	efi_status = EFI_SECURITY_VIOLATION;
+-	return efi_status;
++	if (ret_efi_status != EFI_SUCCESS) {
++		dprint(L"Binary is not whitelisted\n");
++		PrintErrors();
++		ClearErrors();
++		crypterr(EFI_SECURITY_VIOLATION);
++		ret_efi_status = EFI_SECURITY_VIOLATION;
++	}
++	drain_openssl_errors();
++	return ret_efi_status;
+ }
+ 
+ /*
+-- 
+2.26.2
+
diff --git a/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch b/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch
new file mode 100644
index 0000000..87d6f0c
--- /dev/null
+++ b/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch
@@ -0,0 +1,119 @@
+From 705d47ac2c90b8de07a4ef3e1930de6c4b8fece0 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 22 Jul 2020 19:54:58 -0400
+Subject: [PATCH 59/62] Make openssl accept the right set of KU/EKUs
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#211
+---
+ Cryptlib/Pk/CryptPkcs7Verify.c | 87 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 87 insertions(+)
+
+diff --git a/Cryptlib/Pk/CryptPkcs7Verify.c b/Cryptlib/Pk/CryptPkcs7Verify.c
+index dcaba436797..09895d8c66a 100644
+--- a/Cryptlib/Pk/CryptPkcs7Verify.c
++++ b/Cryptlib/Pk/CryptPkcs7Verify.c
+@@ -30,6 +30,91 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ 
+ UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
+ 
++#if 1
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#define X509_OBJECT_get0_X509(obj) ((obj)->data.x509)
++#define X509_OBJECT_get_type(obj) ((obj)->type)
++#define X509_STORE_CTX_get0_cert(ctx) ((ctx)->cert)
++#define X509_STORE_get0_objects(certs) ((certs)->objs)
++#define X509_get_extended_key_usage(cert) ((cert)->ex_xkusage)
++#if OPENSSL_VERSION_NUMBER < 0x10020000L
++#define X509_STORE_CTX_get0_store(ctx) ((ctx)->ctx)
++#endif
++#endif
++
++static int cert_in_store(X509 *cert, X509_STORE_CTX *ctx)
++{
++  X509_OBJECT obj;
++  obj.type = X509_LU_X509;
++  obj.data.x509 = cert;
++  return X509_OBJECT_retrieve_match(ctx->ctx->objs, &obj) != NULL;
++}
++#else
++/*
++ * Later versions of openssl will need this instead.
++ */
++static int cert_in_store(X509 *cert, X509_STORE_CTX *ctx)
++{
++  STACK_OF(X509_OBJECT) *objs;
++  X509_OBJECT *obj;
++  int i;
++
++  objs = X509_STORE_get0_objects(X509_STORE_CTX_get0_store(ctx));
++
++  for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
++    obj = sk_X509_OBJECT_value(objs, i);
++
++    if (X509_OBJECT_get_type(obj) == X509_LU_X509 &&
++	!X509_cmp(X509_OBJECT_get0_X509(obj), cert))
++      return 1;
++  }
++
++  return 0;
++}
++#endif
++
++int
++X509VerifyCb (
++  IN int            Status,
++  IN X509_STORE_CTX *Context
++  )
++{
++  INTN         Error;
++
++  Error = (INTN) X509_STORE_CTX_get_error (Context);
++
++  /* Accept code-signing keys */
++  if (Error == X509_V_ERR_INVALID_PURPOSE &&
++      X509_get_extended_key_usage(X509_STORE_CTX_get0_cert(Context)) == XKU_CODE_SIGN) {
++    Status = 1;
++  } else if (Error == X509_V_ERR_CERT_UNTRUSTED ||
++	     Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT ||
++	     Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
++	     Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) {
++    /* all certs in our cert database are explicitly trusted */
++
++    if (cert_in_store(X509_STORE_CTX_get_current_cert(Context), Context))
++      Status = 1;
++  } else if (Error == X509_V_ERR_CERT_HAS_EXPIRED ||
++	     Error == X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD ||
++	     Error == X509_V_ERR_CERT_NOT_YET_VALID ||
++	     Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
++	     Error == X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD) {
++    /* UEFI explicitly allows expired certificates */
++    Status = 1;
++#if 0
++  } else if (Error == X509_V_ERR_INVALID_CA) {
++    /* Due to the historical reason, we have to relax the the x509 v3 extension
++     * check to allow the CA certificates without the CA flag in the basic
++     * constraints or KeyCertSign in the key usage to be loaded. In the future,
++     * this callback should be removed to enforce the proper check. */
++    Status = 1;
++#endif
++  }
++
++  return Status;
++}
++
+ /**
+   Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+   a new structure to wrap P7Data.
+@@ -844,6 +929,8 @@ Pkcs7Verify (
+     goto _Exit;
+   }
+ 
++  X509_STORE_set_verify_cb (CertStore, X509VerifyCb);
++
+   //
+   // For generic PKCS#7 handling, InData may be NULL if the content is present
+   // in PKCS#7 structure. So ignore NULL checking here.
+-- 
+2.26.2
+
diff --git a/SOURCES/0060-Improve-debug-output-some.patch b/SOURCES/0060-Improve-debug-output-some.patch
new file mode 100644
index 0000000..b48e54b
--- /dev/null
+++ b/SOURCES/0060-Improve-debug-output-some.patch
@@ -0,0 +1,451 @@
+From fc4368fed53837e00d303600d8b628cb0392b629 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 20:29:52 -0400
+Subject: [PATCH 60/62] Improve debug output some
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: pr#213
+---
+ errlog.c          |  26 ++++++-
+ shim.c            |  36 ++++++++--
+ include/console.h |   3 +
+ include/hexdump.h | 172 ++++++++++++++++++++++++++++------------------
+ shim.h            |   5 +-
+ 5 files changed, 164 insertions(+), 78 deletions(-)
+
+diff --git a/errlog.c b/errlog.c
+index 6669c800233..08f7a82a6b2 100644
+--- a/errlog.c
++++ b/errlog.c
+@@ -3,12 +3,28 @@
+  * Copyright 2017 Peter Jones <pjones@redhat.com>
+  */
+ #include "shim.h"
++#include "hexdump.h"
+ 
+ static CHAR16 **errs = NULL;
+ static UINTN nerrs = 0;
+ 
+ EFI_STATUS
+-VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args)
++vdprint_(const CHAR16 *fmt, const char *file, int line, const char *func, va_list args)
++{
++	va_list args2;
++	EFI_STATUS efi_status = EFI_SUCCESS;
++
++	if (verbose) {
++		va_copy(args2, args);
++		console_print(L"%a:%d:%a() ", file, line, func);
++		efi_status = VPrint(fmt, args2);
++		va_end(args2);
++	}
++	return efi_status;
++}
++
++EFI_STATUS
++VLogError(const char *file, int line, const char *func, const CHAR16 *fmt, va_list args)
+ {
+ 	va_list args2;
+ 	CHAR16 **newerrs;
+@@ -35,7 +51,7 @@ VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list arg
+ }
+ 
+ EFI_STATUS
+-LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...)
++LogError_(const char *file, int line, const char *func, const CHAR16 *fmt, ...)
+ {
+ 	va_list args;
+ 	EFI_STATUS efi_status;
+@@ -47,6 +63,12 @@ LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...)
+ 	return efi_status;
+ }
+ 
++VOID
++LogHexdump_(const char *file, int line, const char *func, const void *data, size_t sz)
++{
++	hexdumpat(file, line, func, data, sz, 0);
++}
++
+ VOID
+ PrintErrors(VOID)
+ {
+diff --git a/shim.c b/shim.c
+index d10a1ba1cac..9248642bd57 100644
+--- a/shim.c
++++ b/shim.c
+@@ -34,6 +34,7 @@
+  */
+ 
+ #include "shim.h"
++#include "hexdump.h"
+ #if defined(ENABLE_SHIM_CERT)
+ #include "shim_cert.h"
+ #endif /* defined(ENABLE_SHIM_CERT) */
+@@ -373,12 +374,18 @@ static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize)
+ 	 * and 64KB. For convenience, assume the number of value bytes
+ 	 * is 2, i.e. the second byte is 0x82.
+ 	 */
+-	if (Cert[0] != 0x30 || Cert[1] != 0x82)
++	if (Cert[0] != 0x30 || Cert[1] != 0x82) {
++		dprint(L"cert[0:1] is [%02x%02x], should be [%02x%02x]\n",
++		       Cert[0], Cert[1], 0x30, 0x82);
+ 		return FALSE;
++	}
+ 
+ 	length = Cert[2]<<8 | Cert[3];
+-	if (length != (CertSize - 4))
++	if (length != (CertSize - 4)) {
++		dprint(L"Cert length is %ld, expecting %ld\n",
++		       length, CertSize);
+ 		return FALSE;
++	}
+ 
+ 	return TRUE;
+ }
+@@ -426,19 +433,23 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
+ 	EFI_SIGNATURE_DATA *Cert;
+ 	UINTN CertSize;
+ 	BOOLEAN IsFound = FALSE;
++	int i = 0;
+ 
+ 	while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
+ 		if (CompareGuid (&CertList->SignatureType, &EFI_CERT_TYPE_X509_GUID) == 0) {
+ 			Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ 			CertSize = CertList->SignatureSize - sizeof(EFI_GUID);
++			dprint(L"trying to verify cert %d (%s)\n", i++, dbname);
+ 			if (verify_x509(Cert->SignatureData, CertSize)) {
+ 				if (verify_eku(Cert->SignatureData, CertSize)) {
++					drain_openssl_errors();
+ 					IsFound = AuthenticodeVerify (data->CertData,
+ 								      data->Hdr.dwLength - sizeof(data->Hdr),
+ 								      Cert->SignatureData,
+ 								      CertSize,
+ 								      hash, SHA256_DIGEST_SIZE);
+ 					if (IsFound) {
++						dprint(L"AuthenticodeVerify() succeeded: %d\n", IsFound);
+ 						tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData);
+ 						drain_openssl_errors();
+ 						return DATA_FOUND;
+@@ -447,7 +458,9 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
+ 					}
+ 				}
+ 			} else if (verbose) {
+-				console_notify(L"Not a DER encoding x.509 Certificate");
++				console_print(L"Not a DER encoded x.509 Certificate");
++				dprint(L"cert:\n");
++				dhexdumpat(Cert->SignatureData, CertSize, 0);
+ 			}
+ 		}
+ 
+@@ -641,7 +654,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 			verification_method = VERIFIED_BY_CERT;
+ 			update_verification_method(VERIFIED_BY_CERT);
+ 			return EFI_SUCCESS;
+-		} else {
++		} else if (cert) {
+ 			LogError(L"check_db_cert(db, sha256hash) != DATA_FOUND\n");
+ 		}
+ 	}
+@@ -666,7 +679,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 		verification_method = VERIFIED_BY_CERT;
+ 		update_verification_method(VERIFIED_BY_CERT);
+ 		return EFI_SUCCESS;
+-	} else {
++	} else if (cert) {
+ 		LogError(L"check_db_cert(vendor_db, sha256hash) != DATA_FOUND\n");
+ 	}
+ #endif
+@@ -685,7 +698,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
+ 		verification_method = VERIFIED_BY_CERT;
+ 		update_verification_method(VERIFIED_BY_CERT);
+ 		return EFI_SUCCESS;
+-	} else {
++	} else if (cert) {
+ 		LogError(L"check_db_cert(MokList, sha256hash) != DATA_FOUND\n");
+ 	}
+ 
+@@ -993,6 +1006,11 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in,
+ 		goto done;
+ 	}
+ 
++	dprint(L"sha1 authenticode hash:\n");
++	dhexdumpat(sha1hash, SHA1_DIGEST_SIZE, 0);
++	dprint(L"sha256 authenticode hash:\n");
++	dhexdumpat(sha256hash, SHA256_DIGEST_SIZE, 0);
++
+ done:
+ 	if (SectionHeader)
+ 		FreePool(SectionHeader);
+@@ -1155,6 +1173,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
+ 	if (EFI_ERROR(ret_efi_status)) {
+ 		dprint(L"check_whitelist: %r\n", ret_efi_status);
+ 		if (ret_efi_status != EFI_NOT_FOUND) {
++			dprint(L"check_whitelist(): %r\n", ret_efi_status);
+ 			PrintErrors();
+ 			ClearErrors();
+ 			crypterr(ret_efi_status);
+@@ -1803,6 +1822,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
+ 
+ 	device = li->DeviceHandle;
+ 
++	dprint(L"attempting to load %s\n", PathName);
+ 	/*
+ 	 * Open the device
+ 	 */
+@@ -2778,6 +2798,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 	 */
+ 	InitializeLib(image_handle, systab);
+ 
++	dprint(L"vendor_authorized:0x%08lx vendor_authorized_size:%lu\n",
++		      __FILE__, __LINE__, __func__, vendor_authorized, vendor_authorized_size);
++	dprint(L"vendor_deauthorized:0x%08lx vendor_deauthorized_size:%lu\n",
++		      __FILE__, __LINE__, __func__, vendor_deauthorized, vendor_deauthorized_size);
+ 	init_openssl();
+ 
+ 	/*
+diff --git a/include/console.h b/include/console.h
+index 810bf13a1f1..ac6fdf61d18 100644
+--- a/include/console.h
++++ b/include/console.h
+@@ -85,6 +85,9 @@ extern UINT32 verbose;
+ 		__dprint_ret;							\
+ 	})
+ #define dprint(fmt, ...) dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
++extern EFI_STATUS
++vdprint_(const CHAR16 *fmt, const char *file, int line, const char *func, va_list args);
++#define vdprint(fmt, ...) vdprint_(fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
+ 
+ extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line);
+ #define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__)
+diff --git a/include/hexdump.h b/include/hexdump.h
+index d337b571d8d..f3f3ac284a3 100644
+--- a/include/hexdump.h
++++ b/include/hexdump.h
+@@ -1,104 +1,140 @@
+ #ifndef STATIC_HEXDUMP_H
+ #define STATIC_HEXDUMP_H
+ 
+-static int
+-__attribute__((__unused__))
+-isprint(char c)
+-{
+-	if (c < 0x20)
+-		return 0;
+-	if (c > 0x7e)
+-		return 0;
+-	return 1;
+-}
++#include <stdint.h>
+ 
+-static UINTN
+-__attribute__((__unused__))
+-format_hex(UINT8 *data, UINTN size, CHAR16 *buf)
++static inline unsigned long UNUSED
++prepare_hex(const void *data, size_t size, char *buf, int position)
+ {
+-	UINTN sz = (UINTN)data % 16;
+-	CHAR16 hexchars[] = L"0123456789abcdef";
++	char hexchars[] = "0123456789abcdef";
+ 	int offset = 0;
+-	UINTN i;
+-	UINTN j;
++	unsigned long i;
++	unsigned long j;
++	unsigned long ret;
+ 
+-	for (i = 0; i < sz; i++) {
+-		buf[offset++] = L' ';
+-		buf[offset++] = L' ';
+-		buf[offset++] = L' ';
++	unsigned long before = (position % 16);
++	unsigned long after = (before+size >= 16) ? 0 : 16 - (before+size);
++
++	for (i = 0; i < before; i++) {
++		buf[offset++] = 'X';
++		buf[offset++] = 'X';
++		buf[offset++] = ' ';
+ 		if (i == 7)
+-			buf[offset++] = L' ';
++			buf[offset++] = ' ';
+ 	}
+-	for (j = sz; j < 16 && j < size; j++) {
+-		UINT8 d = data[j-sz];
++	for (j = 0; j < 16 - after - before; j++) {
++		uint8_t d = ((uint8_t *)data)[j];
+ 		buf[offset++] = hexchars[(d & 0xf0) >> 4];
+ 		buf[offset++] = hexchars[(d & 0x0f)];
+-		if (j != 15)
+-			buf[offset++] = L' ';
+-		if (j == 7)
+-			buf[offset++] = L' ';
++		if (i+j != 15)
++			buf[offset++] = ' ';
++		if (i+j == 7)
++			buf[offset++] = ' ';
+ 	}
+-	for (i = j; i < 16; i++) {
+-		buf[offset++] = L' ';
+-		buf[offset++] = L' ';
+-		if (i != 15)
+-			buf[offset++] = L' ';
+-		if (i == 7)
+-			buf[offset++] = L' ';
++	ret = 16 - after - before;
++	j += i;
++	for (i = 0; i < after; i++) {
++		buf[offset++] = 'X';
++		buf[offset++] = 'X';
++		if (i+j != 15)
++			buf[offset++] = ' ';
++		if (i+j == 7)
++			buf[offset++] = ' ';
+ 	}
+-	buf[offset] = L'\0';
+-	return j - sz;
++	buf[offset] = '\0';
++	return ret;
+ }
+ 
+-static void
+-__attribute__((__unused__))
+-format_text(UINT8 *data, UINTN size, CHAR16 *buf)
++#define isprint(c) ((c) >= 0x20 && (c) <= 0x7e)
++
++static inline void UNUSED
++prepare_text(const void *data, size_t size, char *buf, int position)
+ {
+-	UINTN sz = (UINTN)data % 16;
+ 	int offset = 0;
+-	UINTN i;
+-	UINTN j;
++	unsigned long i;
++	unsigned long j;
+ 
+-	for (i = 0; i < sz; i++)
+-		buf[offset++] = L' ';
+-	buf[offset++] = L'|';
+-	for (j = sz; j < 16 && j < size; j++) {
+-		if (isprint(data[j-sz]))
+-			buf[offset++] = data[j-sz];
++	unsigned long before = position % 16;
++	unsigned long after = (before+size > 16) ? 0 : 16 - (before+size);
++
++	if (size == 0) {
++		buf[0] = '\0';
++		return;
++	}
++	for (i = 0; i < before; i++)
++		buf[offset++] = 'X';
++	buf[offset++] = '|';
++	for (j = 0; j < 16 - after - before; j++) {
++		if (isprint(((uint8_t *)data)[j]))
++			buf[offset++] = ((uint8_t *)data)[j];
+ 		else
+-			buf[offset++] = L'.';
++			buf[offset++] = '.';
+ 	}
+-	buf[offset++] = L'|';
+-	for (i = j; i < 16; i++)
+-		buf[offset++] = L' ';
+-	buf[offset] = L'\0';
++	buf[offset++] = size > 0 ? '|' : 'X';
++	buf[offset] = '\0';
+ }
+ 
+-static void
+-__attribute__((__unused__))
+-hexdump(UINT8 *data, UINTN size)
++/*
++ * variadic hexdump formatted
++ * think of it as: printf("%s%s\n", vformat(fmt, ap), hexdump(data,size));
++ */
++static inline void UNUSED
++vhexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, va_list ap)
+ {
+-	UINTN display_offset = (UINTN)data & 0xffffffff;
+-	UINTN offset = 0;
+-	//console_print(L"hexdump: data=0x%016x size=0x%x\n", data, size);
++	unsigned long display_offset = at;
++	unsigned long offset = 0;
+ 
+ 	while (offset < size) {
+-		CHAR16 hexbuf[49];
+-		CHAR16 txtbuf[19];
+-		UINTN sz;
++		char hexbuf[49];
++		char txtbuf[19];
++		unsigned long sz;
+ 
+-		sz = format_hex(data+offset, size-offset, hexbuf);
++		sz = prepare_hex(data+offset, size-offset, hexbuf,
++				 (unsigned long)data+offset);
+ 		if (sz == 0)
+ 			return;
+-		msleep(200000);
+ 
+-		format_text(data+offset, size-offset, txtbuf);
+-		console_print(L"%08x  %s  %s\n", display_offset, hexbuf, txtbuf);
+-		msleep(200000);
++		prepare_text(data+offset, size-offset, txtbuf,
++			     (unsigned long)data+offset);
++		if (fmt && fmt[0] != 0)
++			vdprint_(fmt, file, line, func, ap);
++		dprint_(L"%a:%d:%a() %08lx  %a  %a\n", file, line, func, display_offset, hexbuf, txtbuf);
+ 
+ 		display_offset += sz;
+ 		offset += sz;
+ 	}
+ }
+ 
++/*
++ * hexdump formatted
++ * think of it as: printf("%s%s", format(fmt, ...), hexdump(data,size)[lineN]);
++ */
++static inline void UNUSED
++hexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, ...)
++{
++	va_list ap;
++
++	va_start(ap, at);
++	vhexdumpf(file, line, func, fmt, data, size, at, ap);
++	va_end(ap);
++}
++
++static inline void UNUSED
++hexdump(const char *file, int line, const char *func, const void *data, unsigned long size)
++{
++	hexdumpf(file, line, func, L"", data, size, (intptr_t)data);
++}
++
++static inline void UNUSED
++hexdumpat(const char *file, int line, const char *func, const void *data, unsigned long size, size_t at)
++{
++	hexdumpf(file, line, func, L"", data, size, at);
++}
++
++#define LogHexdump(data, sz) LogHexdump_(__FILE__, __LINE__, __func__, data, sz)
++#define dhexdump(data, sz) hexdump(__FILE__, __LINE__, __func__, data, sz)
++#define dhexdumpat(data, sz, at) hexdumpat(__FILE__, __LINE__, __func__, data, sz, at)
++#define dhexdumpf(fmt, data, sz, at, ...) hexdumpf(__FILE__, __LINE__, __func__, fmt, data, sz, at, ##__VA_ARGS__)
++
+ #endif /* STATIC_HEXDUMP_H */
++// vim:fenc=utf-8:tw=75:noet
+diff --git a/shim.h b/shim.h
+index c1d7e7c7197..0b3ad4f2d20 100644
+--- a/shim.h
++++ b/shim.h
+@@ -182,8 +182,9 @@ typedef struct _SHIM_LOCK {
+ 
+ extern EFI_STATUS shim_init(void);
+ extern void shim_fini(void);
+-extern EFI_STATUS LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...);
+-extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args);
++extern EFI_STATUS LogError_(const char *file, int line, const char *func, const CHAR16 *fmt, ...);
++extern EFI_STATUS VLogError(const char *file, int line, const char *func, const CHAR16 *fmt, va_list args);
++extern VOID LogHexdump_(const char *file, int line, const char *func, const void *data, size_t sz);
+ extern VOID PrintErrors(VOID);
+ extern VOID ClearErrors(VOID);
+ extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath);
+-- 
+2.26.2
+
diff --git a/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch b/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch
new file mode 100644
index 0000000..a2095b1
--- /dev/null
+++ b/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch
@@ -0,0 +1,352 @@
+From fecc2dfb8e408526221091923d9345796b8e294e Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jul 2020 22:09:03 -0400
+Subject: [PATCH 61/62] Also use a config table to mirror mok variables.
+
+Everything was going just fine until I made a vendor_db with 17kB of
+sha256 sums in it.  And then the same source tree that had worked fine
+without that threw errors and failed all over the place.  I wrote some
+code to diagnose the problem, and of course it was a failure in
+mirroring MokList to MokListRT.
+
+As Patrick noted in 741c61abba7, some systems have obnoxiously low
+amounts of variable storage available:
+
+mok.c:550:import_mok_state() BS+RT variable info:
+		     MaximumVariableStorageSize:0x000000000000DFE4
+		     RemainingVariableStorageSize:0x000000000000D21C
+		     MaximumVariableSize:0x0000000000001FC4
+
+The most annoying part is that on at least this edk2 build,
+SetVariable() /does actually appear to set the variable/, but it returns
+EFI_INVALID_PARAMETER.  I'm not planning on relying on that behavior.
+
+So... yeah, the largest *volatile* (i.e. RAM only) variable this edk2
+build will let you create is less than two pages.  It's only got 7.9G
+free, so I guess it's feeling like space is a little tight.
+
+We're also not quite preserving that return code well enough for his
+workaround to work.
+
+New plan.  We try to create variables the normal way, but we don't
+consider not having enough space to be fatal.  In that case, we create
+an EFI_SECURITY_LIST with one sha256sum in it, with a value of all 0,
+and try to add that so we're sure there's /something/ there that's
+innocuous.  On systems where the first SetVariable() /
+QueryVariableInfo() lied to us, the correct variable should be there,
+otherwise the one with the zero-hash will be.
+
+We then also build a config table to hold this info and install that.
+
+The config table is a packed array of this struct:
+
+struct mok_variable_config_entry {
+       CHAR8 name[256];
+       UINT64 data_size;
+       UINT8 data[];
+};
+
+There will be N+1 entries, and the last entry is all 0 for name and
+data_size.  The total allocation size will always be a multiple of 4096.
+In the typical RHEL 7.9 case that means it'll be around 5 pages.
+
+It's installed with this guid:
+
+c451ed2b-9694-45d3-baba-ed9f8988a389
+
+Anything that can go wrong will.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Upstream: not yet, I don't want people to read this before Wednesday.
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ lib/guid.c     |   2 +
+ mok.c          | 150 ++++++++++++++++++++++++++++++++++++++++++++-----
+ include/guid.h |   2 +
+ 3 files changed, 140 insertions(+), 14 deletions(-)
+
+diff --git a/lib/guid.c b/lib/guid.c
+index 57c02fbeecd..99ff400a0ab 100644
+--- a/lib/guid.c
++++ b/lib/guid.c
+@@ -36,4 +36,6 @@ EFI_GUID EFI_SECURE_BOOT_DB_GUID =  { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc,
+ EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
+ 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 } };
++
+ EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } };
++EFI_GUID MOK_VARIABLE_STORE = {0xc451ed2b, 0x9694, 0x45d3, {0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89} };
+diff --git a/mok.c b/mok.c
+index e69857f3c37..4e141fb21fc 100644
+--- a/mok.c
++++ b/mok.c
+@@ -68,6 +68,7 @@ struct mok_state_variable {
+ 	CHAR16 *name;
+ 	char *name8;
+ 	CHAR16 *rtname;
++	char *rtname8;
+ 	EFI_GUID *guid;
+ 
+ 	UINT8 *data;
+@@ -121,6 +122,7 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{.name = L"MokList",
+ 	 .name8 = "MokList",
+ 	 .rtname = L"MokListRT",
++	 .rtname8 = "MokListRT",
+ 	 .guid = &SHIM_LOCK_GUID,
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+@@ -133,12 +135,14 @@ struct mok_state_variable mok_state_variables[] = {
+ 	 .build_cert_size = &build_cert_size,
+ #endif /* defined(ENABLE_SHIM_CERT) */
+ 	 .flags = MOK_MIRROR_KEYDB |
++		  MOK_MIRROR_DELETE_FIRST |
+ 		  MOK_VARIABLE_LOG,
+ 	 .pcr = 14,
+ 	},
+ 	{.name = L"MokListX",
+ 	 .name8 = "MokListX",
+ 	 .rtname = L"MokListXRT",
++	 .rtname8 = "MokListXRT",
+ 	 .guid = &SHIM_LOCK_GUID,
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+@@ -147,12 +151,14 @@ struct mok_state_variable mok_state_variables[] = {
+ 	 .addend = &vendor_deauthorized,
+ 	 .addend_size = &vendor_deauthorized_size,
+ 	 .flags = MOK_MIRROR_KEYDB |
++		  MOK_MIRROR_DELETE_FIRST |
+ 		  MOK_VARIABLE_LOG,
+ 	 .pcr = 14,
+ 	},
+ 	{.name = L"MokSBState",
+ 	 .name8 = "MokSBState",
+ 	 .rtname = L"MokSBStateRT",
++	 .rtname8 = "MokSBStateRT",
+ 	 .guid = &SHIM_LOCK_GUID,
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+@@ -166,6 +172,7 @@ struct mok_state_variable mok_state_variables[] = {
+ 	{.name = L"MokDBState",
+ 	 .name8 = "MokDBState",
+ 	 .rtname = L"MokIgnoreDB",
++	 .rtname8 = "MokIgnoreDB",
+ 	 .guid = &SHIM_LOCK_GUID,
+ 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ 		     EFI_VARIABLE_NON_VOLATILE,
+@@ -204,6 +211,7 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 	 * we're always mirroring the original data, whether this is an efi
+ 	 * security database or not
+ 	 */
++	dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname);
+ 	dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data);
+ 	dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData);
+ 	if (v->data_size) {
+@@ -299,6 +307,7 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 		}
+ 	}
+ 
++
+ 	/*
+ 	 * Now we have the full size
+ 	 */
+@@ -417,28 +426,72 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 	}
+ 
+-	dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++	dprint(L"FullDataSize:%lu FullData:0x%016llx p:0x%016llx pos:%lld\n",
+ 	       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 	if (FullDataSize) {
+-		dprint(L"Setting %s with %lu bytes of data\n",
+-		       v->rtname, FullDataSize);
++		uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
++				 EFI_VARIABLE_RUNTIME_ACCESS;
++		uint64_t max_storage_sz = 0;
++		uint64_t remaining_sz = 0;
++		uint64_t max_var_sz = 0;
++		UINT8 *tmp = NULL;
++		UINTN tmpsz = 0;
++
++		efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz,
++						    &remaining_sz, &max_var_sz);
++		if (EFI_ERROR(efi_status)) {
++			perror(L"Could not get variable storage info: %r\n", efi_status);
++			return efi_status;
++		}
++		dprint(L"calling SetVariable(\"%s\", 0x%016llx, 0x%08lx, %lu, 0x%016llx)\n",
++		       v->rtname, v->guid,
++		       EFI_VARIABLE_BOOTSERVICE_ACCESS
++		       | EFI_VARIABLE_RUNTIME_ACCESS,
++		       FullDataSize, FullData);
+ 		efi_status = gRT->SetVariable(v->rtname, v->guid,
+-					      EFI_VARIABLE_BOOTSERVICE_ACCESS |
+-					      EFI_VARIABLE_RUNTIME_ACCESS,
++					      EFI_VARIABLE_BOOTSERVICE_ACCESS
++					      | EFI_VARIABLE_RUNTIME_ACCESS,
+ 					      FullDataSize, FullData);
+-		if (EFI_ERROR(efi_status)) {
+-			perror(L"Failed to set %s: %r\n",
+-			       v->rtname, efi_status);
++		if (efi_status == EFI_INVALID_PARAMETER && max_var_sz < FullDataSize) {
++			/*
++			 * In this case we're going to try to create a
++			 * dummy variable so that there's one there.  It
++			 * may or may not work, because on some firmware
++			 * builds when the SetVariable call above fails it
++			 * does actually set the variable(!), so aside from
++			 * not using the allocation if it doesn't work, we
++			 * don't care about failures here.
++			 */
++			console_print(L"WARNING: Maximum volatile variable size is %lu.\n", max_var_sz);
++			console_print(L"WARNING: Cannot set %s (%lu bytes)\n", v->rtname, FullDataSize);
++			perror(L"Failed to set %s: %r\n", v->rtname, efi_status);
++			efi_status = variable_create_esl(
++					null_sha256, sizeof(null_sha256),
++					&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
++					&tmp, &tmpsz);
++			/*
++			 * from here we don't really care if it works or
++			 * doens't.
++			 */
++			if (!EFI_ERROR(efi_status) && tmp && tmpsz) {
++				gRT->SetVariable(v->rtname, v->guid,
++						 EFI_VARIABLE_BOOTSERVICE_ACCESS
++						 | EFI_VARIABLE_RUNTIME_ACCESS,
++						 tmpsz, tmp);
++				FreePool(tmp);
++			}
++			efi_status = EFI_INVALID_PARAMETER;
++		} else if (EFI_ERROR(efi_status)) {
++			perror(L"Failed to set %s: %r\n", v->rtname, efi_status);
+ 		}
+ 	}
+-	if (v->data && v->data_size) {
++	if (v->data && v->data_size && v->data != FullData) {
+ 		FreePool(v->data);
+ 		v->data = NULL;
+ 		v->data_size = 0;
+ 	}
+-	if (FullData && FullDataSize) {
+-		FreePool(FullData);
+-	}
++	v->data = FullData;
++	v->data_size = FullDataSize;
+ 	dprint(L"returning %r\n", efi_status);
+ 	return efi_status;
+ }
+@@ -454,8 +507,11 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
+ 	BOOLEAN present = FALSE;
+ 
+ 	if (v->rtname) {
+-		if (v->flags & MOK_MIRROR_DELETE_FIRST)
+-			LibDeleteVariable(v->rtname, v->guid);
++		if (v->flags & MOK_MIRROR_DELETE_FIRST) {
++			dprint(L"deleting \"%s\"\n", v->rtname);
++			efi_status = LibDeleteVariable(v->rtname, v->guid);
++			dprint(L"LibDeleteVariable(\"%s\",...) => %r\n", v->rtname, efi_status);
++		}
+ 
+ 		efi_status = mirror_one_mok_variable(v);
+ 		if (EFI_ERROR(efi_status)) {
+@@ -505,6 +561,12 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
+ 	return ret;
+ }
+ 
++struct mok_variable_config_entry {
++	CHAR8 name[256];
++	UINT64 data_size;
++	UINT8 data[];
++};
++
+ /*
+  * Verify our non-volatile MoK state.  This checks the variables above
+  * accessable and have valid attributes.  If they don't, it removes
+@@ -527,6 +589,11 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 	user_insecure_mode = 0;
+ 	ignore_db = 0;
+ 
++	UINT64 config_sz = 0;
++	UINT8 *config_table = NULL;
++	size_t npages = 0;
++	struct mok_variable_config_entry config_template;
++
+ 	dprint(L"importing mok state\n");
+ 	for (i = 0; mok_state_variables[i].name != NULL; i++) {
+ 		struct mok_state_variable *v = &mok_state_variables[i];
+@@ -579,6 +646,61 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		}
+ 
+ 		ret = maybe_mirror_one_mok_variable(v, ret);
++		if (v->data && v->data_size) {
++			config_sz += v->data_size;
++			config_sz += sizeof(config_template);
++		}
++	}
++
++	/*
++	 * Alright, so we're going to copy these to a config table.  The
++	 * table is a packed array of N+1 struct mok_variable_config_entry
++	 * items, with the last item having all zero's in name and
++	 * data_size.
++	 */
++	if (config_sz) {
++		config_sz += sizeof(config_template);
++		npages = ALIGN_VALUE(config_sz, PAGE_SIZE) >> EFI_PAGE_SHIFT;
++		config_table = NULL;
++		efi_status = gBS->AllocatePages(AllocateAnyPages,
++						EfiRuntimeServicesData,
++						npages,
++						(EFI_PHYSICAL_ADDRESS *)&config_table);
++		if (EFI_ERROR(efi_status) || !config_table) {
++			console_print(L"Allocating %lu pages for mok config table failed: %r\n",
++				      npages, efi_status);
++			if (ret != EFI_SECURITY_VIOLATION)
++				ret = efi_status;
++			config_table = NULL;
++		} else {
++			ZeroMem(config_table, npages << EFI_PAGE_SHIFT);
++		}
++	}
++
++	UINT8 *p = (UINT8 *)config_table;
++	for (i = 0; p && mok_state_variables[i].name != NULL; i++) {
++		struct mok_state_variable *v = &mok_state_variables[i];
++
++		ZeroMem(&config_template, sizeof(config_template));
++		strncpya(config_template.name, (CHAR8 *)v->rtname8, 255);
++		config_template.name[255] = '\0';
++
++		config_template.data_size = v->data_size;
++
++		CopyMem(p, &config_template, sizeof(config_template));
++		p += sizeof(config_template);
++		CopyMem(p, v->data, v->data_size);
++		p += v->data_size;
++	}
++	if (p) {
++		ZeroMem(&config_template, sizeof(config_template));
++		CopyMem(p, &config_template, sizeof(config_template));
++
++		efi_status = gBS->InstallConfigurationTable(&MOK_VARIABLE_STORE,
++							    config_table);
++		if (EFI_ERROR(efi_status)) {
++			console_print(L"Couldn't install MoK configuration table\n");
++		}
+ 	}
+ 
+ 	/*
+diff --git a/include/guid.h b/include/guid.h
+index 81689d6cc1a..91b14d96146 100644
+--- a/include/guid.h
++++ b/include/guid.h
+@@ -35,4 +35,6 @@ extern EFI_GUID SECURITY_PROTOCOL_GUID;
+ extern EFI_GUID SECURITY2_PROTOCOL_GUID;
+ extern EFI_GUID SHIM_LOCK_GUID;
+ 
++extern EFI_GUID MOK_VARIABLE_STORE;
++
+ #endif /* SHIM_GUID_H */
+-- 
+2.26.2
+
diff --git a/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch b/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch
new file mode 100644
index 0000000..86467e3
--- /dev/null
+++ b/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch
@@ -0,0 +1,991 @@
+From 65be350308783a8ef537246c8ad0545b4e6ad069 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Sat, 25 Jul 2020 22:13:57 -0400
+Subject: [PATCH 62/62] Implement lennysz's suggestions for MokListRT
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ mok.c             | 726 ++++++++++++++++++++++++++++++++--------------
+ shim.c            |   7 +-
+ include/PeImage.h |   3 +-
+ 3 files changed, 515 insertions(+), 221 deletions(-)
+
+diff --git a/mok.c b/mok.c
+index 4e141fb21fc..3e6c7e43025 100644
+--- a/mok.c
++++ b/mok.c
+@@ -7,6 +7,8 @@
+ 
+ #include <stdint.h>
+ 
++#include "hexdump.h"
++
+ /*
+  * Check if a variable exists
+  */
+@@ -25,6 +27,15 @@ static BOOLEAN check_var(CHAR16 *varname)
+ 	return FALSE;
+ }
+ 
++#define SetVariable(name, guid, attrs, varsz, var) ({			\
++	EFI_STATUS efi_status_;						\
++	efi_status_ = gRT->SetVariable(name, guid, attrs, varsz, var);	\
++	dprint_(L"%a:%d:%a() SetVariable(\"%s\", ... varsz=0x%llx) = %r\n",\
++		 __FILE__, __LINE__, __func__,				\
++		name, varsz, efi_status_);				\
++	efi_status_;							\
++})
++
+ /*
+  * If the OS has set any of these variables we need to drop into MOK and
+  * handle them appropriately
+@@ -193,33 +204,296 @@ should_mirror_build_cert(struct mok_state_variable *v)
+ 
+ static const uint8_t null_sha256[32] = { 0, };
+ 
++typedef UINTN SIZE_T;
++
++static EFI_STATUS
++get_max_var_sz(UINT32 attrs, SIZE_T *max_var_szp)
++{
++	EFI_STATUS efi_status;
++	uint64_t max_storage_sz = 0;
++	uint64_t remaining_sz = 0;
++	uint64_t max_var_sz = 0;
++
++	*max_var_szp = 0;
++	efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz,
++					    &remaining_sz, &max_var_sz);
++	if (EFI_ERROR(efi_status)) {
++		perror(L"Could not get variable storage info: %r\n", efi_status);
++		return efi_status;
++	}
++
++	/*
++	 * I just don't trust implementations to not be showing static data
++	 * for max_var_sz
++	 */
++	*max_var_szp = (max_var_sz < remaining_sz) ? max_var_sz : remaining_sz;
++	dprint("max_var_sz:%lx remaining_sz:%lx max_storage_sz:%lx\n",
++		max_var_sz, remaining_sz, max_storage_sz);
++	return efi_status;
++}
++
++/*
++ * If any entries fit in < maxsz, and nothing goes wrong, create a variable
++ * of the given name and guid with as many esd entries as possible in it,
++ * and updates *esdp with what would be the next entry (even if makes *esdp
++ * > esl+esl->SignatureListSize), and returns whatever SetVariable()
++ * returns
++ *
++ * If no entries fit (i.e. sizeof(esl) + esl->SignatureSize > maxsz),
++ * returns EFI_BUFFER_TOO_SMALL;
++ */
++static EFI_STATUS
++mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
++	       EFI_SIGNATURE_LIST *esl, EFI_SIGNATURE_DATA *esd,
++	       UINTN *newsz, SIZE_T maxsz)
++{
++	EFI_STATUS efi_status;
++	SIZE_T howmany, varsz = 0, esdsz;
++	UINT8 *var, *data;
++
++	howmany = min((maxsz - sizeof(*esl)) / esl->SignatureSize,
++		      (esl->SignatureListSize - sizeof(*esl)) / esl->SignatureSize);
++	if (howmany < 1) {
++		return EFI_BUFFER_TOO_SMALL;
++	}
++
++	/*
++	 * We always assume esl->SignatureHeaderSize is 0 (and so far,
++	 * that's true as per UEFI 2.8)
++	 */
++	esdsz = howmany * esl->SignatureSize;
++	data = (UINT8 *)esd;
++	dprint(L"Trying to add %lx signatures to \"%s\" of size %lx\n",
++	       howmany, name, esl->SignatureSize);
++
++	/*
++	 * Because of the semantics of variable_create_esl(), the first
++	 * owner guid from the data is not part of esdsz, or the data.
++	 *
++	 * Compensate here.
++	 */
++	efi_status = variable_create_esl(data + sizeof(EFI_GUID),
++					 esdsz - sizeof(EFI_GUID),
++					 &esl->SignatureType,
++					 &esd->SignatureOwner,
++					 &var, &varsz);
++	if (EFI_ERROR(efi_status) || !var || !varsz) {
++		LogError(L"Couldn't allocate %lu bytes for mok variable \"%s\": %r\n",
++			 varsz, var, efi_status);
++		return efi_status;
++	}
++
++	dprint(L"new esl:\n");
++	dhexdumpat(var, varsz, 0);
++
++	efi_status = SetVariable(name, guid, attrs, varsz, var);
++	FreePool(var);
++	if (EFI_ERROR(efi_status)) {
++		LogError(L"Couldn't create mok variable \"%s\": %r\n",
++			 varsz, var, efi_status);
++		return efi_status;
++	}
++
++	*newsz = esdsz;
++
++	return efi_status;
++}
++
++static EFI_STATUS
++mirror_mok_db(CHAR16 *name, CHAR8 *name8, EFI_GUID *guid, UINT32 attrs,
++	      UINT8 *FullData, SIZE_T FullDataSize, BOOLEAN only_first)
++{
++	EFI_STATUS efi_status = EFI_SUCCESS;
++	SIZE_T max_var_sz;
++
++	if (only_first) {
++		efi_status = get_max_var_sz(attrs, &max_var_sz);
++		if (EFI_ERROR(efi_status)) {
++			LogError(L"Could not get maximum variable size: %r",
++				 efi_status);
++			return efi_status;
++		}
++
++		if (FullDataSize <= max_var_sz) {
++			efi_status = SetVariable(name, guid, attrs,
++						 FullDataSize, FullData);
++			return efi_status;
++		}
++	}
++
++	CHAR16 *namen;
++	CHAR8 *namen8;
++	UINTN namelen, namesz;
++
++	namelen = StrLen(name);
++	namesz = namelen * 2;
++	if (only_first) {
++		namen = name;
++		namen8 = name8;
++	} else {
++		namelen += 18;
++		namesz += 34;
++		namen = AllocateZeroPool(namesz);
++		if (!namen) {
++			LogError(L"Could not allocate %lu bytes", namesz);
++			return EFI_OUT_OF_RESOURCES;
++		}
++		namen8 = AllocateZeroPool(namelen);
++		if (!namen8) {
++			FreePool(namen);
++			LogError(L"Could not allocate %lu bytes", namelen);
++			return EFI_OUT_OF_RESOURCES;
++		}
++	}
++
++	UINTN pos, i;
++	const SIZE_T minsz = sizeof(EFI_SIGNATURE_LIST)
++			     + sizeof(EFI_SIGNATURE_DATA)
++			     + SHA1_DIGEST_SIZE;
++	BOOLEAN did_one = FALSE;
++
++	/*
++	 * Create any entries that can fit.
++	 */
++	if (!only_first) {
++		dprint(L"full data for \"%s\":\n", name);
++		dhexdumpat(FullData, FullDataSize, 0);
++	}
++	EFI_SIGNATURE_LIST *esl = NULL;
++	UINTN esl_end_pos = 0;
++	for (i = 0, pos = 0; FullDataSize - pos >= minsz && FullData; ) {
++		EFI_SIGNATURE_DATA *esd = NULL;
++
++		dprint(L"pos:0x%llx FullDataSize:0x%llx\n", pos, FullDataSize);
++		if (esl == NULL || pos >= esl_end_pos) {
++			UINT8 *nesl = FullData + pos;
++			dprint(L"esl:0x%llx->0x%llx\n", esl, nesl);
++			esl = (EFI_SIGNATURE_LIST *)nesl;
++			esl_end_pos = pos + esl->SignatureListSize;
++			dprint(L"pos:0x%llx->0x%llx\n", pos, pos + sizeof(*esl));
++			pos += sizeof(*esl);
++		}
++		esd = (EFI_SIGNATURE_DATA *)(FullData + pos);
++		if (pos >= FullDataSize)
++			break;
++		if (esl->SignatureListSize == 0 || esl->SignatureSize == 0)
++			break;
++
++		dprint(L"esl[%lu] 0x%llx = {sls=0x%lx, ss=0x%lx} esd:0x%llx\n",
++		       i, esl, esl->SignatureListSize, esl->SignatureSize, esd);
++
++		if (!only_first) {
++			SPrint(namen, namelen, L"%s%lu", name, i);
++			namen[namelen-1] = 0;
++			/* uggggh */
++			UINTN j;
++			for (j = 0; j < namelen; j++)
++				namen8[j] = (CHAR8)(namen[j] & 0xff);
++			namen8[namelen - 1] = 0;
++		}
++
++		/*
++		 * In case max_var_sz is computed dynamically, refresh the
++		 * value here.
++		 */
++		efi_status = get_max_var_sz(attrs, &max_var_sz);
++		if (EFI_ERROR(efi_status)) {
++			LogError(L"Could not get maximum variable size: %r",
++				 efi_status);
++			if (!only_first) {
++				FreePool(namen);
++				FreePool(namen8);
++			}
++			return efi_status;
++		}
++
++		SIZE_T howmany;
++		UINTN adj = 0;
++		howmany = min((max_var_sz - sizeof(*esl)) / esl->SignatureSize,
++			      (esl->SignatureListSize - sizeof(*esl)) / esl->SignatureSize);
++		if (!only_first && i == 0 && howmany >= 1) {
++			adj = howmany * esl->SignatureSize;
++			dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj);
++			pos += adj;
++			i++;
++			continue;
++
++		}
++
++		efi_status = mirror_one_esl(namen, guid, attrs,
++					    esl, esd, &adj, max_var_sz);
++		dprint(L"esd:0x%llx adj:0x%llx\n", esd, adj);
++		if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
++			LogError(L"Could not mirror mok variable \"%s\": %r\n",
++				 namen, efi_status);
++			break;
++		}
++
++		if (!EFI_ERROR(efi_status)) {
++			did_one = TRUE;
++			if (only_first)
++				break;
++			dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj);
++			pos += adj;
++			i++;
++		}
++	}
++
++	if (only_first && !did_one) {
++		/*
++		 * In this case we're going to try to create a
++		 * dummy variable so that there's one there.  It
++		 * may or may not work, because on some firmware
++		 * builds when the SetVariable call above fails it
++		 * does actually set the variable(!), so aside from
++		 * not using the allocation if it doesn't work, we
++		 * don't care about failures here.
++		 */
++		UINT8 *var;
++		UINTN varsz;
++
++		efi_status = variable_create_esl(
++				null_sha256, sizeof(null_sha256),
++				&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
++				&var, &varsz);
++		/*
++		 * from here we don't really care if it works or
++		 * doesn't.
++		 */
++		if (!EFI_ERROR(efi_status) && var && varsz) {
++			SetVariable(name, guid,
++				    EFI_VARIABLE_BOOTSERVICE_ACCESS
++				    | EFI_VARIABLE_RUNTIME_ACCESS,
++				    varsz, var);
++			FreePool(var);
++		}
++		efi_status = EFI_INVALID_PARAMETER;
++	} else if (EFI_ERROR(efi_status)) {
++		perror(L"Failed to set %s: %r\n", name, efi_status);
++	}
++	return efi_status;
++}
++
++
+ static EFI_STATUS nonnull(1)
+-mirror_one_mok_variable(struct mok_state_variable *v)
++mirror_one_mok_variable(struct mok_state_variable *v,
++			BOOLEAN only_first)
+ {
+ 	EFI_STATUS efi_status = EFI_SUCCESS;
+ 	uint8_t *FullData = NULL;
+ 	size_t FullDataSize = 0;
+ 	vendor_addend_category_t addend_category = VENDOR_ADDEND_NONE;
+ 	uint8_t *p = NULL;
+-
++	uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
++			 EFI_VARIABLE_RUNTIME_ACCESS;
++	BOOLEAN measure = v->flags & MOK_VARIABLE_MEASURE;
++	BOOLEAN log = v->flags & MOK_VARIABLE_LOG;
+ 	size_t build_cert_esl_sz = 0, addend_esl_sz = 0;
++	bool reuse = FALSE;
+ 
+ 	if (v->categorize_addend)
+ 		addend_category = v->categorize_addend(v);
+ 
+-	/*
+-	 * we're always mirroring the original data, whether this is an efi
+-	 * security database or not
+-	 */
+-	dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname);
+-	dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data);
+-	dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData);
+-	if (v->data_size) {
+-		FullDataSize = v->data_size;
+-		dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
+-		       FullDataSize, FullData);
+-	}
+-
+ 	/*
+ 	 * if it is, there's more data
+ 	 */
+@@ -227,7 +501,7 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 
+ 		/*
+ 		 * We're mirroring (into) an efi security database, aka an
+-		 * array of efi_signature_list_t.  Its layout goes like:
++		 * array of EFI_SIGNATURE_LIST.  Its layout goes like:
+ 		 *
+ 		 *   existing_variable_data
+ 		 *   existing_variable_data_size
+@@ -251,30 +525,7 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 		 */
+ 
+ 		/*
+-		 * first bit is existing data, but we added that above
+-		 */
+-
+-		/*
+-		 * then the build cert if it's there
+-		 */
+-		if (should_mirror_build_cert(v)) {
+-			efi_status = fill_esl(*v->build_cert,
+-					      *v->build_cert_size,
+-					      &EFI_CERT_TYPE_X509_GUID,
+-					      &SHIM_LOCK_GUID,
+-					      NULL, &build_cert_esl_sz);
+-			if (efi_status != EFI_BUFFER_TOO_SMALL) {
+-				perror(L"Could not add built-in cert to %s: %r\n",
+-				       v->name, efi_status);
+-				return efi_status;
+-			}
+-			FullDataSize += build_cert_esl_sz;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
+-			       FullDataSize, FullData);
+-		}
+-
+-		/*
+-		 * then the addend data
++		 * *first* vendor_db or vendor_cert
+ 		 */
+ 		switch (addend_category) {
+ 		case VENDOR_ADDEND_DB:
+@@ -282,7 +533,7 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 			 * if it's an ESL already, we use it wholesale
+ 			 */
+ 			FullDataSize += *v->addend_size;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx\n",
+ 			       FullDataSize, FullData);
+ 			break;
+ 		case VENDOR_ADDEND_X509:
+@@ -296,17 +547,51 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 				return efi_status;
+ 			}
+ 			FullDataSize += addend_esl_sz;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx\n",
+ 				      FullDataSize, FullData);
+ 			break;
+ 		default:
+ 		case VENDOR_ADDEND_NONE:
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx\n",
+ 				      FullDataSize, FullData);
+ 			break;
+ 		}
++
++		/*
++		 * then the build cert if it's there
++		 */
++		if (should_mirror_build_cert(v)) {
++			efi_status = fill_esl(*v->build_cert,
++					      *v->build_cert_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      NULL, &build_cert_esl_sz);
++			if (efi_status != EFI_BUFFER_TOO_SMALL) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			FullDataSize += build_cert_esl_sz;
++			dprint(L"FullDataSize:0x%lx FullData:0x%llx\n",
++			       FullDataSize, FullData);
++		}
++
+ 	}
+ 
++	/*
++	 * we're always mirroring the original data, whether this is an efi
++	 * security database or not
++	 */
++	dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname);
++	dprint(L"v->data_size:%lu v->data:0x%llx\n", v->data_size, v->data);
++	dprint(L"FullDataSize:%lu FullData:0x%llx\n", FullDataSize, FullData);
++	if (v->data_size) {
++		FullDataSize += v->data_size;
++		dprint(L"FullDataSize:%lu FullData:0x%llx\n",
++		       FullDataSize, FullData);
++	}
++	if (v->data_size == FullDataSize)
++		reuse = TRUE;
+ 
+ 	/*
+ 	 * Now we have the full size
+@@ -316,38 +601,33 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 		 * allocate the buffer, or use the old one if it's just the
+ 		 * existing data.
+ 		 */
+-		if (FullDataSize != v->data_size) {
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx allocating FullData\n",
++		if (FullDataSize == v->data_size) {
++			FullData = v->data;
++			FullDataSize = v->data_size;
++			p = FullData + FullDataSize;
++			dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++			v->data = NULL;
++			v->data_size = 0;
++		} else {
++			dprint(L"FullDataSize:%lu FullData:0x%llx allocating FullData\n",
+ 			       FullDataSize, FullData);
+-			FullData = AllocatePool(FullDataSize);
++			/*
++			 * make sure we've got some zeroes at the end, just
++			 * in case.
++			 */
++			UINTN allocsz = FullDataSize + sizeof(EFI_SIGNATURE_LIST);
++			allocsz = ALIGN_VALUE(allocsz, 4096);
++			FullData = AllocateZeroPool(FullDataSize);
+ 			if (!FullData) {
+-				FreePool(v->data);
+-				v->data = NULL;
+-				v->data_size = 0;
+ 				perror(L"Failed to allocate %lu bytes for %s\n",
+ 				       FullDataSize, v->name);
+ 				return EFI_OUT_OF_RESOURCES;
+ 			}
+ 			p = FullData;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
+-			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-			if (v->data && v->data_size) {
+-				CopyMem(p, v->data, v->data_size);
+-				p += v->data_size;
+-			}
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
+-			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-		} else {
+-			FullData = v->data;
+-			FullDataSize = v->data_size;
+-			p = FullData + FullDataSize;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
+-			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-			v->data = NULL;
+-			v->data_size = 0;
+ 		}
+ 	}
+-	dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++	dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 	       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 
+ 	/*
+@@ -355,35 +635,13 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 	 */
+ 	if (v->flags & MOK_MIRROR_KEYDB) {
+ 		/*
+-		 * first bit is existing data, but again, we added that above
++		 * first vendor_cert or vendor_db
+ 		 */
+-
+-		/*
+-		 * second is the build cert
+-		 */
+-		dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
+-		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-		if (should_mirror_build_cert(v)) {
+-			efi_status = fill_esl(*v->build_cert,
+-					      *v->build_cert_size,
+-					      &EFI_CERT_TYPE_X509_GUID,
+-					      &SHIM_LOCK_GUID,
+-					      p, &build_cert_esl_sz);
+-			if (EFI_ERROR(efi_status)) {
+-				perror(L"Could not add built-in cert to %s: %r\n",
+-				       v->name, efi_status);
+-				return efi_status;
+-			}
+-			p += build_cert_esl_sz;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
+-			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-		}
+-
+ 		switch (addend_category) {
+ 		case VENDOR_ADDEND_DB:
+ 			CopyMem(p, *v->addend, *v->addend_size);
+ 			p += *v->addend_size;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 			break;
+ 		case VENDOR_ADDEND_X509:
+@@ -397,16 +655,53 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 				return efi_status;
+ 			}
+ 			p += addend_esl_sz;
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 			break;
+ 		default:
+ 		case VENDOR_ADDEND_NONE:
+-			dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++			dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 			break;
+ 		}
++
++		/*
++		 * then is the build cert
++		 */
++		dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
++		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		if (should_mirror_build_cert(v)) {
++			efi_status = fill_esl(*v->build_cert,
++					      *v->build_cert_size,
++					      &EFI_CERT_TYPE_X509_GUID,
++					      &SHIM_LOCK_GUID,
++					      p, &build_cert_esl_sz);
++			if (EFI_ERROR(efi_status)) {
++				perror(L"Could not add built-in cert to %s: %r\n",
++				       v->name, efi_status);
++				return efi_status;
++			}
++			p += build_cert_esl_sz;
++			dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
++			       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		}
+ 	}
++
++	/*
++	 * last bit is existing data, unless it's the only thing,
++	 * in which case it's already there.
++	 */
++	if (!reuse) {
++		dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
++		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++		if (v->data && v->data_size) {
++			CopyMem(p, v->data, v->data_size);
++			p += v->data_size;
++		}
++		dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
++		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
++	}
++
+ 	/*
+ 	 * We always want to create our key databases, so in this case we
+ 	 * need a dummy entry
+@@ -422,68 +717,55 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+ 			return efi_status;
+ 		}
+ 		p = FullData + FullDataSize;
+-		dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n",
++		dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 		       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+ 	}
+ 
+-	dprint(L"FullDataSize:%lu FullData:0x%016llx p:0x%016llx pos:%lld\n",
++	dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
+ 	       FullDataSize, FullData, p, p-(uintptr_t)FullData);
+-	if (FullDataSize) {
+-		uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+-				 EFI_VARIABLE_RUNTIME_ACCESS;
+-		uint64_t max_storage_sz = 0;
+-		uint64_t remaining_sz = 0;
+-		uint64_t max_var_sz = 0;
+-		UINT8 *tmp = NULL;
+-		UINTN tmpsz = 0;
+-
+-		efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz,
+-						    &remaining_sz, &max_var_sz);
+-		if (EFI_ERROR(efi_status)) {
+-			perror(L"Could not get variable storage info: %r\n", efi_status);
+-			return efi_status;
+-		}
+-		dprint(L"calling SetVariable(\"%s\", 0x%016llx, 0x%08lx, %lu, 0x%016llx)\n",
+-		       v->rtname, v->guid,
+-		       EFI_VARIABLE_BOOTSERVICE_ACCESS
+-		       | EFI_VARIABLE_RUNTIME_ACCESS,
+-		       FullDataSize, FullData);
+-		efi_status = gRT->SetVariable(v->rtname, v->guid,
+-					      EFI_VARIABLE_BOOTSERVICE_ACCESS
+-					      | EFI_VARIABLE_RUNTIME_ACCESS,
+-					      FullDataSize, FullData);
+-		if (efi_status == EFI_INVALID_PARAMETER && max_var_sz < FullDataSize) {
++	if (FullDataSize && v->flags & MOK_MIRROR_KEYDB) {
++		dprint(L"calling mirror_mok_db(\"%s\",  datasz=%lu)\n",
++		       v->rtname, FullDataSize);
++		efi_status = mirror_mok_db(v->rtname, (CHAR8 *)v->rtname8, v->guid,
++					   attrs, FullData, FullDataSize,
++					   only_first);
++		dprint(L"mirror_mok_db(\"%s\",  datasz=%lu) returned %r\n",
++		       v->rtname, FullDataSize, efi_status);
++	} else if (FullDataSize && only_first) {
++		efi_status = SetVariable(v->rtname, v->guid, attrs,
++					 FullDataSize, FullData);
++	}
++	if (FullDataSize && only_first) {
++		if (measure) {
+ 			/*
+-			 * In this case we're going to try to create a
+-			 * dummy variable so that there's one there.  It
+-			 * may or may not work, because on some firmware
+-			 * builds when the SetVariable call above fails it
+-			 * does actually set the variable(!), so aside from
+-			 * not using the allocation if it doesn't work, we
+-			 * don't care about failures here.
++			 * Measure this into PCR 7 in the Microsoft format
+ 			 */
+-			console_print(L"WARNING: Maximum volatile variable size is %lu.\n", max_var_sz);
+-			console_print(L"WARNING: Cannot set %s (%lu bytes)\n", v->rtname, FullDataSize);
+-			perror(L"Failed to set %s: %r\n", v->rtname, efi_status);
+-			efi_status = variable_create_esl(
+-					null_sha256, sizeof(null_sha256),
+-					&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
+-					&tmp, &tmpsz);
++			efi_status = tpm_measure_variable(v->name, *v->guid,
++							  FullDataSize, FullData);
++			if (EFI_ERROR(efi_status)) {
++				dprint(L"tpm_measure_variable(\"%s\",%lu,0x%llx)->%r\n",
++				       v->name, FullDataSize, FullData, efi_status);
++				return efi_status;
++			}
++		}
++
++		if (log) {
+ 			/*
+-			 * from here we don't really care if it works or
+-			 * doens't.
++			 * Log this variable into whichever PCR the table
++			 * says.
+ 			 */
+-			if (!EFI_ERROR(efi_status) && tmp && tmpsz) {
+-				gRT->SetVariable(v->rtname, v->guid,
+-						 EFI_VARIABLE_BOOTSERVICE_ACCESS
+-						 | EFI_VARIABLE_RUNTIME_ACCESS,
+-						 tmpsz, tmp);
+-				FreePool(tmp);
++			EFI_PHYSICAL_ADDRESS datap =
++					(EFI_PHYSICAL_ADDRESS)(UINTN)FullData,
++			efi_status = tpm_log_event(datap, FullDataSize,
++						   v->pcr, (CHAR8 *)v->name8);
++			if (EFI_ERROR(efi_status)) {
++				dprint(L"tpm_log_event(0x%llx, %lu, %lu, \"%s\")->%r\n",
++				       FullData, FullDataSize, v->pcr, v->name,
++				       efi_status);
++				return efi_status;
+ 			}
+-			efi_status = EFI_INVALID_PARAMETER;
+-		} else if (EFI_ERROR(efi_status)) {
+-			perror(L"Failed to set %s: %r\n", v->rtname, efi_status);
+ 		}
++
+ 	}
+ 	if (v->data && v->data_size && v->data != FullData) {
+ 		FreePool(v->data);
+@@ -501,19 +783,20 @@ mirror_one_mok_variable(struct mok_state_variable *v)
+  * EFI_SECURITY_VIOLATION status at the same time.
+  */
+ static EFI_STATUS nonnull(1)
+-maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
++maybe_mirror_one_mok_variable(struct mok_state_variable *v,
++			      EFI_STATUS ret, BOOLEAN only_first)
+ {
+ 	EFI_STATUS efi_status;
+ 	BOOLEAN present = FALSE;
+ 
+ 	if (v->rtname) {
+-		if (v->flags & MOK_MIRROR_DELETE_FIRST) {
++		if (!only_first && (v->flags & MOK_MIRROR_DELETE_FIRST)) {
+ 			dprint(L"deleting \"%s\"\n", v->rtname);
+ 			efi_status = LibDeleteVariable(v->rtname, v->guid);
+ 			dprint(L"LibDeleteVariable(\"%s\",...) => %r\n", v->rtname, efi_status);
+ 		}
+ 
+-		efi_status = mirror_one_mok_variable(v);
++		efi_status = mirror_one_mok_variable(v, only_first);
+ 		if (EFI_ERROR(efi_status)) {
+ 			if (ret != EFI_SECURITY_VIOLATION)
+ 				ret = efi_status;
+@@ -530,34 +813,6 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret)
+ 		*v->state = v->data[0];
+ 	}
+ 
+-	if (v->flags & MOK_VARIABLE_MEASURE) {
+-		/*
+-		 * Measure this into PCR 7 in the Microsoft format
+-		 */
+-		efi_status = tpm_measure_variable(v->name, *v->guid,
+-						  v->data_size,
+-						  v->data);
+-		if (EFI_ERROR(efi_status)) {
+-			if (ret != EFI_SECURITY_VIOLATION)
+-				ret = efi_status;
+-		}
+-	}
+-
+-	if (v->flags & MOK_VARIABLE_LOG) {
+-		/*
+-		 * Log this variable into whichever PCR the table
+-		 * says.
+-		 */
+-		EFI_PHYSICAL_ADDRESS datap =
+-				(EFI_PHYSICAL_ADDRESS)(UINTN)v->data,
+-		efi_status = tpm_log_event(datap, v->data_size,
+-					   v->pcr, (CHAR8 *)v->name8);
+-		if (EFI_ERROR(efi_status)) {
+-			if (ret != EFI_SECURITY_VIOLATION)
+-				ret = efi_status;
+-		}
+-	}
+-
+ 	return ret;
+ }
+ 
+@@ -567,6 +822,66 @@ struct mok_variable_config_entry {
+ 	UINT8 data[];
+ };
+ 
++EFI_STATUS import_one_mok_state(struct mok_state_variable *v,
++				BOOLEAN only_first)
++{
++	EFI_STATUS ret = EFI_SUCCESS;
++	EFI_STATUS efi_status;
++
++	user_insecure_mode = 0;
++	ignore_db = 0;
++
++	UINT32 attrs = 0;
++	BOOLEAN delete = FALSE;
++
++	dprint(L"importing mok state for \"%s\"\n", v->name);
++
++	efi_status = get_variable_attr(v->name,
++				       &v->data, &v->data_size,
++				       *v->guid, &attrs);
++	if (efi_status == EFI_NOT_FOUND) {
++		v->data = NULL;
++		v->data_size = 0;
++	} else if (EFI_ERROR(efi_status)) {
++		perror(L"Could not verify %s: %r\n", v->name,
++		       efi_status);
++		delete = TRUE;
++	} else {
++		if (!(attrs & v->yes_attr)) {
++			perror(L"Variable %s is missing attributes:\n",
++			       v->name);
++			perror(L"  0x%08x should have 0x%08x set.\n",
++			       attrs, v->yes_attr);
++			delete = TRUE;
++		}
++		if (attrs & v->no_attr) {
++			perror(L"Variable %s has incorrect attribute:\n",
++			       v->name);
++			perror(L"  0x%08x should not have 0x%08x set.\n",
++			       attrs, v->no_attr);
++			delete = TRUE;
++		}
++	}
++	if (delete == TRUE) {
++		perror(L"Deleting bad variable %s\n", v->name);
++		efi_status = LibDeleteVariable(v->name, v->guid);
++		if (EFI_ERROR(efi_status)) {
++			perror(L"Failed to erase %s\n", v->name);
++			ret = EFI_SECURITY_VIOLATION;
++		}
++		FreePool(v->data);
++		v->data = NULL;
++		v->data_size = 0;
++	}
++
++	dprint(L"maybe mirroring \"%s\".  original data:\n", v->name);
++	dhexdumpat(v->data, v->data_size, 0);
++
++	ret = maybe_mirror_one_mok_variable(v, ret, only_first);
++	dprint(L"returning %r\n", ret);
++	return ret;
++}
++
+ /*
+  * Verify our non-volatile MoK state.  This checks the variables above
+  * accessable and have valid attributes.  If they don't, it removes
+@@ -594,58 +909,22 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 	size_t npages = 0;
+ 	struct mok_variable_config_entry config_template;
+ 
+-	dprint(L"importing mok state\n");
++	dprint(L"importing minimal mok state variables\n");
+ 	for (i = 0; mok_state_variables[i].name != NULL; i++) {
+ 		struct mok_state_variable *v = &mok_state_variables[i];
+-		UINT32 attrs = 0;
+-		BOOLEAN delete = FALSE;
+ 
+-		efi_status = get_variable_attr(v->name,
+-					       &v->data, &v->data_size,
+-					       *v->guid, &attrs);
+-		dprint(L"maybe mirroring %s\n", v->name);
+-		if (efi_status == EFI_NOT_FOUND) {
+-			v->data = NULL;
+-			v->data_size = 0;
+-		} else if (EFI_ERROR(efi_status)) {
+-			perror(L"Could not verify %s: %r\n", v->name,
+-			       efi_status);
++		efi_status = import_one_mok_state(v, TRUE);
++		if (EFI_ERROR(efi_status)) {
++			dprint(L"import_one_mok_state(ih, \"%s\", TRUE): %r\n",
++			       v->rtname);
+ 			/*
+ 			 * don't clobber EFI_SECURITY_VIOLATION from some
+ 			 * other variable in the list.
+ 			 */
+ 			if (ret != EFI_SECURITY_VIOLATION)
+ 				ret = efi_status;
+-			delete = TRUE;
+-		} else {
+-			if (!(attrs & v->yes_attr)) {
+-				perror(L"Variable %s is missing attributes:\n",
+-				       v->name);
+-				perror(L"  0x%08x should have 0x%08x set.\n",
+-				       attrs, v->yes_attr);
+-				delete = TRUE;
+-			}
+-			if (attrs & v->no_attr) {
+-				perror(L"Variable %s has incorrect attribute:\n",
+-				       v->name);
+-				perror(L"  0x%08x should not have 0x%08x set.\n",
+-				       attrs, v->no_attr);
+-				delete = TRUE;
+-			}
+-		}
+-		if (delete == TRUE) {
+-			perror(L"Deleting bad variable %s\n", v->name);
+-			efi_status = LibDeleteVariable(v->name, v->guid);
+-			if (EFI_ERROR(efi_status)) {
+-				perror(L"Failed to erase %s\n", v->name);
+-				ret = EFI_SECURITY_VIOLATION;
+-			}
+-			FreePool(v->data);
+-			v->data = NULL;
+-			v->data_size = 0;
+ 		}
+ 
+-		ret = maybe_mirror_one_mok_variable(v, ret);
+ 		if (v->data && v->data_size) {
+ 			config_sz += v->data_size;
+ 			config_sz += sizeof(config_template);
+@@ -669,8 +948,6 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		if (EFI_ERROR(efi_status) || !config_table) {
+ 			console_print(L"Allocating %lu pages for mok config table failed: %r\n",
+ 				      npages, efi_status);
+-			if (ret != EFI_SECURITY_VIOLATION)
+-				ret = efi_status;
+ 			config_table = NULL;
+ 		} else {
+ 			ZeroMem(config_table, npages << EFI_PAGE_SHIFT);
+@@ -703,6 +980,16 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 		}
+ 	}
+ 
++	/*
++	 * This is really just to make it easy for userland.
++	 */
++	dprint(L"importing full mok state variables\n");
++	for (i = 0; mok_state_variables[i].name != NULL; i++) {
++		struct mok_state_variable *v = &mok_state_variables[i];
++
++		import_one_mok_state(v, FALSE);
++	}
++
+ 	/*
+ 	 * Enter MokManager if necessary.  Any actual *changes* here will
+ 	 * cause MokManager to demand a machine reboot, so this is safe to
+@@ -712,6 +999,9 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
+ 	efi_status = check_mok_request(image_handle);
+ 	dprint(L"mok returned %r\n", efi_status);
+ 	if (EFI_ERROR(efi_status)) {
++		/*
++		 * don't clobber EFI_SECURITY_VIOLATION
++		 */
+ 		if (ret != EFI_SECURITY_VIOLATION)
+ 			ret = efi_status;
+ 		return ret;
+diff --git a/shim.c b/shim.c
+index 9248642bd57..1a4d7bb9ded 100644
+--- a/shim.c
++++ b/shim.c
+@@ -1445,7 +1445,10 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
+ 					   sha256hash, sha1hash);
+ 
+ 		if (EFI_ERROR(efi_status)) {
+-			console_error(L"Verification failed", efi_status);
++			if (verbose)
++				console_print(L"Verification failed: %r\n", efi_status);
++			else
++				console_error(L"Verification failed", efi_status);
+ 			return efi_status;
+ 		} else {
+ 			if (verbose)
+@@ -2648,7 +2651,6 @@ shim_init(void)
+ {
+ 	EFI_STATUS efi_status;
+ 
+-	setup_verbosity();
+ 	dprint(L"%a", shim_version);
+ 
+ 	/* Set the second stage loader */
+@@ -2797,6 +2799,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
+ 	 * Ensure that gnu-efi functions are available
+ 	 */
+ 	InitializeLib(image_handle, systab);
++	setup_verbosity();
+ 
+ 	dprint(L"vendor_authorized:0x%08lx vendor_authorized_size:%lu\n",
+ 		      __FILE__, __LINE__, __func__, vendor_authorized, vendor_authorized_size);
+diff --git a/include/PeImage.h b/include/PeImage.h
+index a606e8b2a9f..209b96fb8ff 100644
+--- a/include/PeImage.h
++++ b/include/PeImage.h
+@@ -768,7 +768,8 @@ typedef struct {
+ 	UINT8           CertData[1];
+ } WIN_CERTIFICATE_EFI_PKCS;
+ 
+-#define SHA256_DIGEST_SIZE  32
++#define SHA1_DIGEST_SIZE	20
++#define SHA256_DIGEST_SIZE	32
+ #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
+ 
+ typedef struct {
+-- 
+2.26.2
+
diff --git a/SOURCES/9998-MokListRT-Fatal.patch b/SOURCES/9998-MokListRT-Fatal.patch
deleted file mode 100644
index 6590ae9..0000000
--- a/SOURCES/9998-MokListRT-Fatal.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 9a2dd0a945720634b9f3608c3b3dfb99fafd4465 Mon Sep 17 00:00:00 2001
-From: Patrick Uiterwijk <patrick@puiterwijk.org>
-Date: Thu, 6 Dec 2018 10:08:45 +0100
-Subject: [PATCH] Make EFI variable copying fatal only on secureboot enabled
- systems
-
-I have come across systems that are unwilling to reserve enough memory for
-a MokListRT big enough for big certificates.
-This seems to be the case with firmware implementations that do not support
-secureboot, which is probably the reason they went with much lower variable
-storage.
-
-This patch set makes sure we can still boot on those systems, by only
-making the copy action fatal if the system has secure boot enabled, or if
-the error was anything other than EFI_INVALID_PARAMETER.
-
-Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
----
- shim.c | 14 +++++++++++---
- 1 file changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/shim.c b/shim.c
-index fcc11eb3..89ef0036 100644
---- a/shim.c
-+++ b/shim.c
-@@ -2632,9 +2632,17 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
- die:
- 		console_print(L"Something has gone seriously wrong: %s: %r\n",
- 			      msgs[msg], efi_status);
--		msleep(5000000);
--		gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION,
--				 0, NULL);
-+		/*
-+		 * Make copy failures fatal only if secure_mode is enabled, or
-+		 * the error was anything else than EFI_INVALID_PARAMETER.
-+		 * There are non-secureboot firmware implementations that don't
-+		 * reserve enough EFI variable memory to fit the variable.
-+		 */
-+		if (secure_mode() || efi_status != EFI_INVALID_PARAMETER) {
-+			msleep(5000000);
-+			gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION,
-+					 0, NULL);
-+		}
- 	}
- 
- 	efi_status = shim_init();
diff --git a/SOURCES/9999-Add-vendor-esl.patch b/SOURCES/9999-Add-vendor-esl.patch
deleted file mode 100644
index d37f2df..0000000
--- a/SOURCES/9999-Add-vendor-esl.patch
+++ /dev/null
@@ -1,296 +0,0 @@
-From ab26d9a5c035cd56e1b1ae8b0ef74e059fe61d77 Mon Sep 17 00:00:00 2001
-From: Patrick Uiterwijk <patrick@puiterwijk.org>
-Date: Sat, 21 Jul 2018 04:12:57 +0200
-Subject: [PATCH] Implement vendor EFI Signature List (ESL)
-
-Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
----
- Make.defaults |  3 ++
- cert.S        | 30 ++++++++++++++++++
- mok.c         | 86 +++++++++++++++++++++++++++------------------------
- shim.c        | 25 +++++++++++++++
- shim.h        |  2 ++
- 5 files changed, 106 insertions(+), 40 deletions(-)
-
-diff --git a/Make.defaults b/Make.defaults
-index 4c26c1a..0f9b979 100644
---- a/Make.defaults
-+++ b/Make.defaults
-@@ -126,6 +126,9 @@ CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/sha
- ifneq ($(origin VENDOR_CERT_FILE), undefined)
- 	CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\"
- endif
-+ifneq ($(origin VENDOR_ESL_FILE), undefined)
-+	CFLAGS += -DVENDOR_ESL_FILE=\"$(VENDOR_ESL_FILE)\"
-+endif
- ifneq ($(origin VENDOR_DBX_FILE), undefined)
- 	CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\"
- endif
-diff --git a/cert.S b/cert.S
-index cfc4525..7ad782a 100644
---- a/cert.S
-+++ b/cert.S
-@@ -8,12 +8,18 @@ cert_table:
- #else
- 	.long	0
- #endif
-+#if defined(VENDOR_ESL_FILE)
-+	.long	vendor_esl_priv_end - vendor_esl_priv
-+#else
-+	.long	0
-+#endif
- #if defined(VENDOR_DBX_FILE)
- 	.long	vendor_dbx_priv_end - vendor_dbx_priv
- #else
- 	.long	0
- #endif
- 	.long	vendor_cert_priv - cert_table
-+	.long	vendor_esl_priv - cert_table
- 	.long	vendor_dbx_priv - cert_table
- #if defined(VENDOR_CERT_FILE)
- 	.data
-@@ -39,6 +45,30 @@ vendor_cert_priv:
- 	.section .vendor_cert, "a", %progbits
- vendor_cert_priv_end:
- #endif
-+#if defined(VENDOR_ESL_FILE)
-+	.data
-+	.align	1
-+	.type	vendor_esl_priv, %object
-+	.size	vendor_esl_priv, vendor_esl_priv_end-vendor_esl_priv
-+	.section .vendor_cert, "a", %progbits
-+vendor_esl_priv:
-+.incbin VENDOR_ESL_FILE
-+vendor_esl_priv_end:
-+#else
-+	.bss
-+	.type	vendor_esl_priv, %object
-+	.size	vendor_esl_priv, 1
-+	.section .vendor_cert, "a", %progbits
-+vendor_esl_priv:
-+	.zero	1
-+
-+	.data
-+	.align 4
-+	.type	vendor_esl_size_priv, %object
-+	.size	vendor_esl_size_priv, 4
-+	.section .vendor_cert, "a", %progbits
-+vendor_esl_priv_end:
-+#endif
- #if defined(VENDOR_DBX_FILE)
- 	.data
- 	.align	1
-diff --git a/mok.c b/mok.c
-index 2b9d796..f52e286 100644
---- a/mok.c
-+++ b/mok.c
-@@ -62,12 +62,6 @@ struct mok_state_variable {
- 	EFI_GUID *guid;
- 	UINT8 *data;
- 	UINTN data_size;
--	/*
--	 * These two are indirect pointers just to make initialization
--	 * saner...
--	 */
--	UINT8 **addend_source;
--	UINT32 *addend_size;
- 	UINT32 yes_attr;
- 	UINT32 no_attr;
- 	UINT32 flags;
-@@ -75,10 +69,11 @@ struct mok_state_variable {
- 	UINT8 *state;
- };
- 
--#define MOK_MIRROR_KEYDB	0x01
--#define MOK_MIRROR_DELETE_FIRST	0x02
--#define MOK_VARIABLE_MEASURE	0x04
--#define MOK_VARIABLE_LOG	0x08
-+#define MOK_MIRROR_KEYDB		0x01
-+#define MOK_MIRROR_DELETE_FIRST		0x02
-+#define MOK_VARIABLE_MEASURE		0x04
-+#define MOK_VARIABLE_LOG		0x08
-+#define MOK_VARIABLE_APPEND_CERT	0x10
- 
- struct mok_state_variable mok_state_variables[] = {
- 	{.name = L"MokList",
-@@ -88,10 +83,9 @@ struct mok_state_variable mok_state_variables[] = {
- 	 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
- 		     EFI_VARIABLE_NON_VOLATILE,
- 	 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
--	 .addend_source = &vendor_cert,
--	 .addend_size = &vendor_cert_size,
- 	 .flags = MOK_MIRROR_KEYDB |
--		  MOK_VARIABLE_LOG,
-+		  MOK_VARIABLE_LOG |
-+		  MOK_VARIABLE_APPEND_CERT,
- 	 .pcr = 14,
- 	},
- 	{.name = L"MokListX",
-@@ -139,40 +133,54 @@ mirror_one_mok_variable(struct mok_state_variable *v)
- 	uint8_t *p = NULL;
- 
- 	if ((v->flags & MOK_MIRROR_KEYDB) &&
--	    v->addend_source && *v->addend_source &&
--	    v->addend_size && *v->addend_size) {
--		EFI_SIGNATURE_LIST *CertList = NULL;
--		EFI_SIGNATURE_DATA *CertData = NULL;
--		FullDataSize = v->data_size
--			     + sizeof (*CertList)
--			     + sizeof (EFI_GUID)
--			     + *v->addend_size;
-+	    (v->flags & MOK_VARIABLE_APPEND_CERT)) {
-+		FullDataSize = v->data_size;
-+
-+		if (vendor_esl_size) {
-+			FullDataSize += vendor_esl_size;
-+		}
-+		if (vendor_cert_size) {
-+			FullDataSize += sizeof (EFI_SIGNATURE_LIST)
-+				     + sizeof (EFI_GUID)
-+			             + vendor_cert_size;
-+		}
-+
- 		FullData = AllocatePool(FullDataSize);
- 		if (!FullData) {
- 			perror(L"Failed to allocate space for MokListRT\n");
- 			return EFI_OUT_OF_RESOURCES;
- 		}
- 		p = FullData;
--
- 		if (!EFI_ERROR(efi_status) && v->data_size > 0) {
- 			CopyMem(p, v->data, v->data_size);
- 			p += v->data_size;
- 		}
--		CertList = (EFI_SIGNATURE_LIST *)p;
--		p += sizeof (*CertList);
--		CertData = (EFI_SIGNATURE_DATA *)p;
--		p += sizeof (EFI_GUID);
--
--		CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
--		CertList->SignatureListSize = *v->addend_size
--					      + sizeof (*CertList)
--					      + sizeof (*CertData)
--					      -1;
--		CertList->SignatureHeaderSize = 0;
--		CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID);
--
--		CertData->SignatureOwner = SHIM_LOCK_GUID;
--		CopyMem(p, *v->addend_source, *v->addend_size);
-+
-+		if (vendor_esl_size) {
-+			CopyMem(p, vendor_esl, vendor_esl_size);
-+			p += vendor_esl_size;
-+		}
-+
-+		if (vendor_cert_size) {
-+			EFI_SIGNATURE_LIST *CertList = NULL;
-+			EFI_SIGNATURE_DATA *CertData = NULL;
-+
-+			CertList = (EFI_SIGNATURE_LIST *)p;
-+			p += sizeof (*CertList);
-+			CertData = (EFI_SIGNATURE_DATA *)p;
-+			p += sizeof (EFI_GUID);
-+
-+			CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
-+			CertList->SignatureListSize = vendor_cert_size
-+						      + sizeof (*CertList)
-+						      + sizeof (*CertData)
-+						      -1;
-+			CertList->SignatureHeaderSize = 0;
-+			CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID);
-+
-+			CertData->SignatureOwner = SHIM_LOCK_GUID;
-+			CopyMem(p, vendor_cert, vendor_cert_size);
-+		}
- 
- 		if (v->data && v->data_size)
- 			FreePool(v->data);
-@@ -247,9 +255,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
- 		UINT32 attrs = 0;
- 		BOOLEAN delete = FALSE, present, addend;
- 
--		addend = (v->addend_source && v->addend_size &&
--			  *v->addend_source && *v->addend_size)
--			? TRUE : FALSE;
-+		addend = (v->flags & MOK_VARIABLE_APPEND_CERT) != 0;
- 
- 		efi_status = get_variable_attr(v->name,
- 					       &v->data, &v->data_size,
-diff --git a/shim.c b/shim.c
-index 0015534..15b29fb 100644
---- a/shim.c
-+++ b/shim.c
-@@ -66,14 +66,18 @@ static UINT32 load_options_size;
-  */
- extern struct {
- 	UINT32 vendor_cert_size;
-+	UINT32 vendor_esl_size;
- 	UINT32 vendor_dbx_size;
- 	UINT32 vendor_cert_offset;
-+	UINT32 vendor_esl_offset;
- 	UINT32 vendor_dbx_offset;
- } cert_table;
- 
- UINT32 vendor_cert_size;
-+UINT32 vendor_esl_size;
- UINT32 vendor_dbx_size;
- UINT8 *vendor_cert;
-+UINT8 *vendor_esl;
- UINT8 *vendor_dbx;
- 
- /*
-@@ -1059,6 +1063,25 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
- 		}
- #endif /* defined(ENABLE_SHIM_CERT) */
- 
-+		/*
-+		 * Check against a built-in EFI Signature List (ESL)
-+		 */
-+		if (vendor_esl_size &&
-+		    check_db_cert_in_ram((EFI_SIGNATURE_LIST*)vendor_esl,
-+					 vendor_esl_size,
-+					 cert,
-+					 sha256hash,
-+					 L"Shim",
-+					 SHIM_LOCK_GUID) == DATA_FOUND) {
-+			update_verification_method(VERIFIED_BY_CERT);
-+			// tpm_measurement is done by check_db_cert_in_ram
-+			efi_status = EFI_SUCCESS;
-+			drain_openssl_errors();
-+			return efi_status;
-+		} else {
-+			LogError(L"check_db_cert_in_ram(vendor_esl) failed\n");
-+		}
-+
- 		/*
- 		 * And finally, check against shim's built-in key
- 		 */
-@@ -2535,8 +2558,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
- 	verification_method = VERIFIED_BY_NOTHING;
- 
- 	vendor_cert_size = cert_table.vendor_cert_size;
-+	vendor_esl_size = cert_table.vendor_esl_size;
- 	vendor_dbx_size = cert_table.vendor_dbx_size;
- 	vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
-+	vendor_esl = (UINT8 *)&cert_table + cert_table.vendor_esl_offset;
- 	vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
- 	CHAR16 *msgs[] = {
- 		L"import_mok_state() failed\n",
-diff --git a/shim.h b/shim.h
-index 04e770b..fb58b69 100644
---- a/shim.h
-+++ b/shim.h
-@@ -169,8 +169,10 @@ extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath);
- extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle);
- 
- extern UINT32 vendor_cert_size;
-+extern UINT32 vendor_esl_size;
- extern UINT32 vendor_dbx_size;
- extern UINT8 *vendor_cert;
-+extern UINT8 *vendor_esl;
- extern UINT8 *vendor_dbx;
- 
- extern UINT8 user_insecure_mode;
--- 
-2.18.1
-
diff --git a/SOURCES/centos.esl b/SOURCES/centos.esl
deleted file mode 100644
index c0815a7..0000000
Binary files a/SOURCES/centos.esl and /dev/null differ
diff --git a/SOURCES/db.aa64.esl b/SOURCES/db.aa64.esl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SOURCES/db.aa64.esl
diff --git a/SOURCES/dbx.aa64.esl b/SOURCES/dbx.aa64.esl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SOURCES/dbx.aa64.esl
diff --git a/SOURCES/dbx.x64.esl b/SOURCES/dbx.x64.esl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SOURCES/dbx.x64.esl
diff --git a/SOURCES/securebootca.cer b/SOURCES/securebootca.cer
deleted file mode 100644
index b235400..0000000
Binary files a/SOURCES/securebootca.cer and /dev/null differ
diff --git a/SPECS/shim.spec b/SPECS/shim.spec
index e674b0b..d37a266 100644
--- a/SPECS/shim.spec
+++ b/SPECS/shim.spec
@@ -1,25 +1,80 @@
 Name:           shim
 Version:        15
-Release:        5%{?dist}
+Release:        7%{?dist}
 Summary:        First-stage UEFI bootloader
 
 License:        BSD
 URL:            http://www.codon.org.uk/~mjg59/shim/
 Source0:        https://github.com/mjg59/shim/releases/download/%{version}/shim-%{version}.tar.bz2
-#Source1:        centos.crt
-# currently here's what's in our dbx: # nothing.
-#Source2:       dbx-x64.esl
-#Source3:       dbx-aa64.esl
-Source4:        shim-find-debuginfo.sh
-Source5:	centos.esl
-
-Patch0001:      0001-Make-sure-that-MOK-variables-always-get-mirrored.patch
-Patch0002:      0002-mok-fix-the-mirroring-of-RT-variables.patch
-Patch0003:      0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
-Patch0004:      0004-Make-VLogError-behave-as-expected.patch
-Patch0005:      0005-Once-again-try-even-harder-to-get-binaries-without-t.patch
-Patch9998:      9998-MokListRT-Fatal.patch
-Patch9999:      9999-Add-vendor-esl.patch
+Source1:        shim-find-debuginfo.sh
+
+Source100:      db.aa64.esl
+Source101:      dbx.aa64.esl
+Source200:      db.x64.esl
+Source201:      dbx.x64.esl
+
+Patch0001: 0001-Make-some-things-dprint-instead-of-console_print.patch
+Patch0002: 0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch
+Patch0003: 0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch
+Patch0004: 0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch
+Patch0005: 0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch
+Patch0006: 0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch
+Patch0007: 0007-httpboot-show-the-error-message-for-the-ChildHandle.patch
+Patch0008: 0008-Fix-typo-in-debug-path-in-shim.h.patch
+Patch0009: 0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch
+Patch0010: 0010-shim-Extend-invalid-reloc-size-warning-message.patch
+Patch0011: 0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch
+Patch0012: 0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch
+Patch0013: 0013-shim-Properly-generate-absolute-paths-from-relative-.patch
+Patch0014: 0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch
+Patch0015: 0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch
+Patch0016: 0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch
+Patch0017: 0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch
+Patch0018: 0018-Make.default-use-correct-flags-to-disable-unaligned-.patch
+Patch0019: 0019-Cryptlib-fix-build-on-32bit-ARM.patch
+Patch0020: 0020-Make-sure-that-MOK-variables-always-get-mirrored.patch
+Patch0021: 0021-mok-fix-the-mirroring-of-RT-variables.patch
+Patch0022: 0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch
+Patch0023: 0023-shim-only-include-shim_cert.h-in-shim.c.patch
+Patch0024: 0024-mok-also-mirror-the-build-cert-to-MokListRT.patch
+Patch0025: 0025-mok-minor-cleanups.patch
+Patch0026: 0026-Remove-call-to-TPM2-get_event_log.patch
+Patch0027: 0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch
+Patch0028: 0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch
+Patch0029: 0029-Once-again-try-even-harder-to-get-binaries-without-t.patch
+Patch0030: 0030-shim-Rework-pause-functions-and-add-read_counter.patch
+Patch0031: 0031-Hook-exit-when-shim_lock-protocol-installed.patch
+Patch0032: 0032-Work-around-stuff-Waddress-of-packed-member-finds.patch
+Patch0033: 0033-Fix-a-use-of-strlen-instead-of-Strlen.patch
+Patch0034: 0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch
+Patch0035: 0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch
+Patch0036: 0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch
+Patch0037: 0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch
+Patch0038: 0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch
+Patch0039: 0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch
+Patch0040: 0040-MokManager-avoid-Werror-address-of-packed-member.patch
+Patch0041: 0041-tpm-Don-t-log-duplicate-identical-events.patch
+Patch0042: 0042-Slightly-better-debugging-messages.patch
+Patch0043: 0043-Actually-check-for-errors-from-set_second_stage.patch
+Patch0044: 0044-translate_slashes-don-t-write-to-string-literals.patch
+Patch0045: 0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch
+Patch0046: 0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch
+Patch0047: 0047-Fix-the-license-on-our-buildid-extractor.patch
+Patch0048: 0048-Update-README.tpm.patch
+Patch0049: 0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch
+Patch0050: 0050-Remove-a-couple-of-incorrect-license-claims.patch
+Patch0051: 0051-MokManager-fix-uninitialized-value.patch
+Patch0052: 0052-Fix-some-volatile-usage-gcc-whines-about.patch
+Patch0053: 0053-MokManager-fix-a-wrong-allocation-failure-check.patch
+Patch0054: 0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch
+Patch0055: 0055-Fix-a-broken-tpm-type.patch
+Patch0056: 0056-Make-cert.S-not-impossible-to-read.patch
+Patch0057: 0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch
+Patch0058: 0058-Handle-binaries-with-multiple-signatures.patch
+Patch0059: 0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch
+Patch0060: 0060-Improve-debug-output-some.patch
+Patch0061: 0061-Also-use-a-config-table-to-mirror-mok-variables.patch
+Patch0062: 0062-Implement-lennysz-s-suggestions-for-MokListRT.patch
 
 BuildRequires: git openssl-devel openssl
 BuildRequires: pesign >= 0.106-1
@@ -130,24 +185,18 @@ git config --unset user.name
 COMMIT_ID=$(cat %{name}-%{version}-%{efiarch}/commit)
 MAKEFLAGS="RELEASE=%{release} ENABLE_HTTPBOOT=true COMMIT_ID=${COMMIT_ID}"
 %ifarch aarch64
-if [ -f "%{SOURCE1}" ]; then
-        MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}"
+if [ -s "%{SOURCE100}" ]; then
+        MAKEFLAGS="$MAKEFLAGS VENDOR_DB_FILE=%{SOURCE100}"
 fi
-if [ -f "%{SOURCE3}" ]; then
-        MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE3}"
-fi
-if [ -f "%{SOURCE5}" ]; then
-	MAKEFLAGS="$MAKEFLAGS VENDOR_ESL_FILE=%{SOURCE5}"
+if [ -s "%{SOURCE101}" ]; then
+        MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE101}"
 fi
 %else
-if [ -f "%{SOURCE1}" ]; then
-        MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}"
-fi
-if [ -f "%{SOURCE2}" ]; then
-        MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE2}"
+if [ -s "%{SOURCE200}" ]; then
+        MAKEFLAGS="$MAKEFLAGS VENDOR_DB_FILE=%{SOURCE200}"
 fi
-if [ -f "%{SOURCE5}" ]; then
-	MAKEFLAGS="$MAKEFLAGS VENDOR_ESL_FILE=%{SOURCE5}"
+if [ -s "%{SOURCE201}" ]; then
+        MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE201}"
 fi
 %endif
 cd %{name}-%{version}-%{efiarch}
@@ -183,7 +232,7 @@ cd ../%{name}-%{version}-%{efiarch}
 
 %ifarch x86_64
 %global __debug_install_post                                            \
-        bash %{SOURCE4}                                                 \\\
+        bash %{SOURCE1}                                                 \\\
                 %{?_missing_build_ids_terminate_build:--strict-build-id}\\\
                 %{?_find_debuginfo_opts}                                \\\
                 "%{_builddir}/%{?buildsubdir}/%{name}-%{version}-%{efiarch}" \
@@ -191,7 +240,7 @@ cd ../%{name}-%{version}-%{efiarch}
         mv debugfiles.list ../debugfiles-%{efiarch}.list                \
         cd ..                                                           \
         cd %{name}-%{version}-ia32                                      \
-        bash %{SOURCE4}                                                 \\\
+        bash %{SOURCE1}                                                 \\\
                 %{?_missing_build_ids_terminate_build:--strict-build-id}\\\
                 %{?_find_debuginfo_opts}                                \\\
                 "%{_builddir}/%{?buildsubdir}/%{name}-%{version}-ia32"  \
@@ -201,7 +250,7 @@ cd ../%{name}-%{version}-%{efiarch}
         %{nil}
 %else
 %global __debug_install_post                                            \
-        bash %{SOURCE4}                                                 \\\
+        bash %{SOURCE1}                                                 \\\
                 %{?_missing_build_ids_terminate_build:--strict-build-id}\\\
                 %{?_find_debuginfo_opts}                                \\\
                 "%{_builddir}/%{?buildsubdir}/%{name}-%{version}-%{efiarch}" \
@@ -232,10 +281,21 @@ cd ../%{name}-%{version}-%{efiarch}
 %endif
 
 %changelog
-* Tue Sep 03 2019 Fabian Arrotin <arrfab@centos.org> - 15-5.el7.centos
-- Added 9999-Add-vendor-esl.patch (Patrick Uiterwijk)            
-- Added 9998-MokListRT-Fatal.patch (https://github.com/rhboot/shim/pull/157) (#15522)
-- Rebuilt with combined centos.esl (so new and previous crt) 
+* Sat Jul 25 2020 Peter Jones <pjones@redhat.com> - 15-7
+- Implement Lenny's workaround.
+  Related: CVE-2020-10713
+  Related: CVE-2020-14308
+  Related: CVE-2020-14309
+  Related: CVE-2020-14310
+  Related: CVE-2020-14311
+
+* Thu Jul 23 2020 Peter Jones <pjones@redhat.com> - 15-6
+- Rebuild for bug fixes and new signing keys
+  Related: CVE-2020-10713
+  Related: CVE-2020-14308
+  Related: CVE-2020-14309
+  Related: CVE-2020-14310
+  Related: CVE-2020-14311
 
 * Mon Mar 18 2019 Peter Jones <pjones@redhat.com> - 15-5
 - Fix a couple more things that are breaking reproducability, and thus