Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
The package rpms/bcm283x-firmware.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/bcm283x-firmware.git/commit/?id=e01… .
Change:
+%ifarch aarch64
Thanks.
Full change:
============
commit e01cac83a7748ae0c75ee1ff6932b4260d069687
Author: Peter Robinson <pbrobinson(a)gmail.com>
Date: Fri Aug 31 20:01:26 2018 +0100
Latest firmware update, Change locations of firmware, Migration bits for ARMv7, Prepare for supporting HATs/overlays using config.txt
diff --git a/bcm2836-rpi-2-b.dtb b/bcm2836-rpi-2-b.dtb
new file mode 100644
index 0000000..06ba65b
Binary files /dev/null and b/bcm2836-rpi-2-b.dtb differ
diff --git a/bcm2837-rpi-3-b-plus.dtb b/bcm2837-rpi-3-b-plus.dtb
new file mode 100644
index 0000000..9fa2dd4
Binary files /dev/null and b/bcm2837-rpi-3-b-plus.dtb differ
diff --git a/bcm2837-rpi-3-b.dtb b/bcm2837-rpi-3-b.dtb
new file mode 100644
index 0000000..7ed21fb
Binary files /dev/null and b/bcm2837-rpi-3-b.dtb differ
diff --git a/bcm283x-firmware.spec b/bcm283x-firmware.spec
index ecaa0b3..80e4053 100644
--- a/bcm283x-firmware.spec
+++ b/bcm283x-firmware.spec
@@ -4,19 +4,28 @@
# git clone https://github.com/raspberrypi/firmware.git
# cd firmware/boot
# tar cJvf ../bcm283x-firmware-%{gitshort}.tar.xz *bin *dat *elf LICENCE.broadcom COPYING.linux overlays/
-%define gitshort 953a339
+%define gitshort ec3f856
Name: bcm283x-firmware
-Version: 20180810
+Version: 20180829
Release: 1.%{gitshort}%{?dist}
Summary: Broadcom bcm283x firmware for the Raspberry Pi
# see LICENSE.broadcom
+# DT Overlays covered under Linux Kernel GPLv2
License: Redistributable, no modification permitted
URL: https://github.com/raspberrypi/
+BuildRequires: efi-filesystem
+BuildRequires: efi-srpm-macros
+Requires: efi-filesystem
+
Source0: %{name}-%{gitshort}.tar.xz
Source1: config.txt
Source2: config-64.txt
+# Direct from Fedora kernel source
+Source3: bcm2836-rpi-2-b.dtb
+Source4: bcm2837-rpi-3-b.dtb
+Source5: bcm2837-rpi-3-b-plus.dtb
ExclusiveArch: %{arm} aarch64
@@ -30,22 +39,47 @@ Raspberry Pi.
%build
%install
-mkdir -p %{buildroot}/%{_datadir}/%{name}
-mkdir -p %{buildroot}/%{_datadir}/%{name}/overlays
-install -p %{SOURCE1} %{buildroot}/%{_datadir}/%{name}
-install -p %{SOURCE2} %{buildroot}/%{_datadir}/%{name}
-install -p *bin %{buildroot}/%{_datadir}/%{name}
-install -p *dat %{buildroot}/%{_datadir}/%{name}
-install -p *elf %{buildroot}/%{_datadir}/%{name}
-install -p overlays/README %{buildroot}/%{_datadir}/%{name}/overlays
-install -p overlays/*.dtbo %{buildroot}/%{_datadir}/%{name}/overlays
+mkdir -p %{buildroot}%{efi_esp_root}/overlays
+%ifarch %{arm}
+install -p %{SOURCE1} %{buildroot}%{efi_esp_root}/config.txt
+%endif
+%ifarch aarch64
+install -p %{SOURCE2} %{buildroot}%{efi_esp_root}/config.txt
+%endif
+install -p *bin %{buildroot}%{efi_esp_root}
+install -p *dat %{buildroot}%{efi_esp_root}
+install -p *elf %{buildroot}%{efi_esp_root}
+install -p %{SOURCE3} %{buildroot}%{efi_esp_root}
+install -p %{SOURCE4} %{buildroot}%{efi_esp_root}
+install -p %{SOURCE5} %{buildroot}%{efi_esp_root}
+install -p overlays/README %{buildroot}%{efi_esp_root}/overlays
+install -p overlays/*.dtbo %{buildroot}%{efi_esp_root}/overlays
+
+%pre
+if [ -d /boot/fw ]; then
+ mkdir /boot/efi
+ echo "`blkid /dev/*1 |grep vfat |head -1 | awk '{print $3}'` /boot/efi vfat umask=0077,shortname=winnt 0 2" >> /etc/fstab
+ mount /boot/efi
+ rmdir /boot/fw
+fi
%files
# DT Overlays covered under Linux Kernel GPLv2
%license LICENCE.broadcom COPYING.linux
-%{_datadir}/%{name}
+%config(noreplace) %{efi_esp_root}/config.txt
+%{efi_esp_root}/overlays
+%{efi_esp_root}/*bin
+%{efi_esp_root}/*dat
+%{efi_esp_root}/*elf
+%{efi_esp_root}/*.dtb
%changelog
+* Fri Aug 31 2018 Peter Robinson <pbrobinson(a)fedoraproject.org> 20180829-1.ec3f856
+- Latest firmware update
+- Change locations of firmware
+- Migration bits for ARMv7
+- Prepare for supporting HATs/overlays using config.txt
+
* Mon Aug 13 2018 Peter Robinson <pbrobinson(a)fedoraproject.org> 20180810-1.953a339
- Latest upstream firmware
diff --git a/sources b/sources
index 28bb110..a3e7a40 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (bcm283x-firmware-953a339.tar.xz) = 3abbe063ecf2f45d60d547942ff4a679a07f01662f64384528e8a62b9d010c25d9164fb8811dce78515d95247ffc28b2868b4c1f4fb6938e138f1b4c710b9805
+SHA512 (bcm283x-firmware-ec3f856.tar.xz) = 166106009bcbc7576366ca2332b5340efbdacbbd787cf065141c7835f5a00add361879d9101dc5d78d849f5ea76435c9589922daac8abbca7b89fd94ce8a4298
The package rpms/edk2.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/edk2.git/commit/?id=05b0353aa12fc3e… .
Change:
+ExclusiveArch: x86_64 aarch64
Thanks.
Full change:
============
commit 05b0353aa12fc3e3f4f6ad546820212b564616e5
Author: Cole Robinson <crobinso(a)redhat.com>
Date: Fri Aug 31 13:31:19 2018 -0400
Update to edk2 git cb5f4f45ce
- Remove upstreamed patches
- Update to qemu qemu-ovmf-secureboot-1.1.3
- Enable TPM2 support
- Fix RPM build option passthrough
diff --git a/0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch b/0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch
index de247bc..5d4d06a 100644
--- a/0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch
+++ b/0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch
@@ -1,3 +1,4 @@
+From 37942481c89eca732239c23fe606680e6e3faf77 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek(a)redhat.com>
Date: Wed, 27 Jan 2016 03:05:18 +0100
Subject: [PATCH] OvmfPkg: silence EFI_D_VERBOSE (0x00400000) in NvmExpressDxe
@@ -7,6 +8,7 @@ level.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
OvmfPkg/OvmfPkgIa32.dsc | 5 ++++-
OvmfPkg/OvmfPkgIa32X64.dsc | 5 ++++-
@@ -14,10 +16,10 @@ Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
-index 3f4d42d..048a144 100644
+index a28b511d5c..7f725ab198 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
-@@ -635,7 +635,10 @@
+@@ -738,7 +738,10 @@
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
@@ -30,10 +32,10 @@ index 3f4d42d..048a144 100644
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
-index 5688475..fac0cf0 100644
+index 115d0c01ff..d444a84267 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
-@@ -644,7 +644,10 @@
+@@ -747,7 +747,10 @@
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
@@ -46,10 +48,10 @@ index 5688475..fac0cf0 100644
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
-index dcf64b9..bc62a64 100644
+index 362eb789c7..f4e072870c 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
-@@ -642,7 +642,10 @@
+@@ -745,7 +745,10 @@
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
diff --git a/0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch b/0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch
index 71ec2b1..9264deb 100644
--- a/0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch
+++ b/0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch
@@ -1,3 +1,4 @@
+From 5e55066b33d894cb7e9b84179de449e8734cb57d Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek(a)redhat.com>
Date: Wed, 27 Jan 2016 03:05:18 +0100
Subject: [PATCH] OvmfPkg: silence EFI_D_VERBOSE (0x00400000) in the DXE core
@@ -8,6 +9,7 @@ not interested in. Suppress said output.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
OvmfPkg/OvmfPkgIa32.dsc | 2 ++
OvmfPkg/OvmfPkgIa32X64.dsc | 2 ++
@@ -15,10 +17,10 @@ Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
3 files changed, 6 insertions(+)
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
-index 767fd7d..40688dd 100644
+index 7f725ab198..83e47281ed 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
-@@ -562,6 +562,8 @@
+@@ -644,6 +644,8 @@
<LibraryClasses>
NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
@@ -28,10 +30,10 @@ index 767fd7d..40688dd 100644
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
-index 7460d50..3e75388 100644
+index d444a84267..a2adacfbd3 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
-@@ -571,6 +571,8 @@
+@@ -653,6 +653,8 @@
<LibraryClasses>
NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
@@ -41,10 +43,10 @@ index 7460d50..3e75388 100644
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
-index 765506a..e169f13 100644
+index f4e072870c..b57e32f432 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
-@@ -569,6 +569,8 @@
+@@ -651,6 +651,8 @@
<LibraryClasses>
NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
diff --git a/0003-OvmfPkg-enable-DEBUG_VERBOSE.patch b/0003-OvmfPkg-enable-DEBUG_VERBOSE.patch
index 6da6d05..776d50b 100644
--- a/0003-OvmfPkg-enable-DEBUG_VERBOSE.patch
+++ b/0003-OvmfPkg-enable-DEBUG_VERBOSE.patch
@@ -1,3 +1,4 @@
+From c667557c191923e981b972b5679fc49cec60d7e5 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek(a)redhat.com>
Date: Sun, 8 Jul 2012 14:26:07 +0200
Subject: [PATCH] OvmfPkg: enable DEBUG_VERBOSE
@@ -5,6 +6,7 @@ Subject: [PATCH] OvmfPkg: enable DEBUG_VERBOSE
Enable verbose debug logs.
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
OvmfPkg/OvmfPkgIa32.dsc | 2 +-
OvmfPkg/OvmfPkgIa32X64.dsc | 2 +-
@@ -12,10 +14,10 @@ Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
-index c0440d9..fa9661c 100644
+index 83e47281ed..cd0e71869b 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
-@@ -408,7 +408,7 @@
+@@ -486,7 +486,7 @@
# DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may
# // significantly impact boot performance
# DEBUG_ERROR 0x80000000 // Error
@@ -25,10 +27,10 @@ index c0440d9..fa9661c 100644
!ifdef $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
-index 6f94bc7..667584a 100644
+index a2adacfbd3..7f7a78f60a 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
-@@ -413,7 +413,7 @@
+@@ -491,7 +491,7 @@
# DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may
# // significantly impact boot performance
# DEBUG_ERROR 0x80000000 // Error
@@ -38,10 +40,10 @@ index 6f94bc7..667584a 100644
!ifdef $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
-index a92bf19..5ae8469 100644
+index b57e32f432..739807efc4 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
-@@ -413,7 +413,7 @@
+@@ -491,7 +491,7 @@
# DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may
# // significantly impact boot performance
# DEBUG_ERROR 0x80000000 // Error
diff --git a/0004-OvmfPkg-increase-max-debug-message-length-to-512.patch b/0004-OvmfPkg-increase-max-debug-message-length-to-512.patch
index 1bb9ee3..bedec89 100644
--- a/0004-OvmfPkg-increase-max-debug-message-length-to-512.patch
+++ b/0004-OvmfPkg-increase-max-debug-message-length-to-512.patch
@@ -1,14 +1,22 @@
+From 6324a2a8ae4fc96c9e13d39483c5ee0cb1fff619 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek(a)redhat.com>
Date: Thu, 20 Feb 2014 22:54:45 +0100
Subject: [PATCH] OvmfPkg: increase max debug message length to 512
-Contributed-under: TianoCore Contribution Agreement 1.0
+Upstream prefers short debug messages (sometimes even limited to 80
+characters), but any line length under 512 characters is just unsuitable
+for effective debugging. (For example, config strings in HII routing,
+logged by the platform driver "OvmfPkg/PlatformDxe" on DEBUG_VERBOSE
+level, can be several hundred characters long.) 512 is an empirically good
+value.
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
---
OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
-index 44850a9..b6927d0 100644
+index 36cde54976..c0c4eaee0f 100644
--- a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
+++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
@@ -27,7 +27,7 @@
@@ -16,7 +24,7 @@ index 44850a9..b6927d0 100644
// Define the maximum debug and assert message length that this library supports
//
-#define MAX_DEBUG_MESSAGE_LENGTH 0x100
-+#define MAX_DEBUG_MESSAGE_LENGTH 0x200
++#define MAX_DEBUG_MESSAGE_LENGTH 0x200
/**
- This constructor function does not have to do anything.
+ Prints a debug message to the debug output device if the specified error level is enabled.
diff --git a/0005-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch b/0005-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
deleted file mode 100644
index f1274ea..0000000
--- a/0005-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
+++ /dev/null
@@ -1,520 +0,0 @@
-From: Laszlo Ersek <lersek(a)redhat.com>
-Date: Tue, 20 May 2014 23:41:56 +0200
-Subject: [PATCH] OvmfPkg: QemuVideoDxe: enable debug messages in VbeShim
-
-Contributed-under: TianoCore Contribution Agreement 1.0
----
- OvmfPkg/QemuVideoDxe/VbeShim.asm | 2 +-
- OvmfPkg/QemuVideoDxe/VbeShim.h | 481 +++++++++++++++++++++++++--------------
- 2 files changed, 308 insertions(+), 175 deletions(-)
-
-diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.asm b/OvmfPkg/QemuVideoDxe/VbeShim.asm
-index 18fa920..9a185f2 100644
---- a/OvmfPkg/QemuVideoDxe/VbeShim.asm
-+++ b/OvmfPkg/QemuVideoDxe/VbeShim.asm
-@@ -18,7 +18,7 @@
- ;------------------------------------------------------------------------------
-
- ; enable this macro for debug messages
--;%define DEBUG
-+%define DEBUG
-
- %macro DebugLog 1
- %ifdef DEBUG
-diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.h b/OvmfPkg/QemuVideoDxe/VbeShim.h
-index cc9b6e1..db37f1d 100644
---- a/OvmfPkg/QemuVideoDxe/VbeShim.h
-+++ b/OvmfPkg/QemuVideoDxe/VbeShim.h
-@@ -517,185 +517,318 @@ STATIC CONST UINT8 mVbeShim[] = {
- /* 000001FE nop */ 0x90,
- /* 000001FF nop */ 0x90,
- /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
-- /* 00000203 jz 0x22d */ 0x74, 0x28,
-+ /* 00000203 jz 0x235 */ 0x74, 0x30,
- /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
-- /* 00000208 jz 0x245 */ 0x74, 0x3B,
-+ /* 00000208 jz 0x255 */ 0x74, 0x4B,
- /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
-- /* 0000020D jz 0x269 */ 0x74, 0x5A,
-+ /* 0000020D jz 0x289 */ 0x74, 0x7A,
- /* 0000020F cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
-- /* 00000212 jz word 0x331 */ 0x0F, 0x84, 0x1B, 0x01,
-+ /* 00000212 jz word 0x361 */ 0x0F, 0x84, 0x4B, 0x01,
- /* 00000216 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
-- /* 00000219 jz word 0x336 */ 0x0F, 0x84, 0x19, 0x01,
-+ /* 00000219 jz word 0x36e */ 0x0F, 0x84, 0x51, 0x01,
- /* 0000021D cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
-- /* 00000220 jz word 0x338 */ 0x0F, 0x84, 0x14, 0x01,
-+ /* 00000220 jz word 0x378 */ 0x0F, 0x84, 0x54, 0x01,
- /* 00000224 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
-- /* 00000227 jz word 0x33a */ 0x0F, 0x84, 0x0F, 0x01,
-- /* 0000022B jmp short 0x22b */ 0xEB, 0xFE,
-- /* 0000022D push es */ 0x06,
-- /* 0000022E push di */ 0x57,
-- /* 0000022F push ds */ 0x1E,
-- /* 00000230 push si */ 0x56,
-- /* 00000231 push cx */ 0x51,
-- /* 00000232 push cs */ 0x0E,
-- /* 00000233 pop ds */ 0x1F,
-- /* 00000234 mov si,0x0 */ 0xBE, 0x00, 0x00,
-- /* 00000237 mov cx,0x100 */ 0xB9, 0x00, 0x01,
-- /* 0000023A cld */ 0xFC,
-- /* 0000023B rep movsb */ 0xF3, 0xA4,
-- /* 0000023D pop cx */ 0x59,
-- /* 0000023E pop si */ 0x5E,
-- /* 0000023F pop ds */ 0x1F,
-- /* 00000240 pop di */ 0x5F,
-- /* 00000241 pop es */ 0x07,
-- /* 00000242 jmp word 0x34c */ 0xE9, 0x07, 0x01,
-- /* 00000245 push es */ 0x06,
-- /* 00000246 push di */ 0x57,
-- /* 00000247 push ds */ 0x1E,
-- /* 00000248 push si */ 0x56,
-- /* 00000249 push cx */ 0x51,
-- /* 0000024A and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
-- /* 0000024E cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
-- /* 00000252 jz 0x256 */ 0x74, 0x02,
-- /* 00000254 jmp short 0x22b */ 0xEB, 0xD5,
-- /* 00000256 push cs */ 0x0E,
-- /* 00000257 pop ds */ 0x1F,
-- /* 00000258 mov si,0x100 */ 0xBE, 0x00, 0x01,
-- /* 0000025B mov cx,0x100 */ 0xB9, 0x00, 0x01,
-- /* 0000025E cld */ 0xFC,
-- /* 0000025F rep movsb */ 0xF3, 0xA4,
-- /* 00000261 pop cx */ 0x59,
-- /* 00000262 pop si */ 0x5E,
-- /* 00000263 pop ds */ 0x1F,
-- /* 00000264 pop di */ 0x5F,
-- /* 00000265 pop es */ 0x07,
-- /* 00000266 jmp word 0x34c */ 0xE9, 0xE3, 0x00,
-- /* 00000269 push dx */ 0x52,
-- /* 0000026A push ax */ 0x50,
-- /* 0000026B cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
-- /* 0000026F jz 0x273 */ 0x74, 0x02,
-- /* 00000271 jmp short 0x22b */ 0xEB, 0xB8,
-- /* 00000273 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
-- /* 00000276 mov al,0x20 */ 0xB0, 0x20,
-- /* 00000278 out dx,al */ 0xEE,
-- /* 00000279 push dx */ 0x52,
-- /* 0000027A push ax */ 0x50,
-- /* 0000027B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 0000027E mov ax,0x4 */ 0xB8, 0x04, 0x00,
-- /* 00000281 out dx,ax */ 0xEF,
-- /* 00000282 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 00000285 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-- /* 00000288 out dx,ax */ 0xEF,
-- /* 00000289 pop ax */ 0x58,
-- /* 0000028A pop dx */ 0x5A,
-- /* 0000028B push dx */ 0x52,
-- /* 0000028C push ax */ 0x50,
-- /* 0000028D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 00000290 mov ax,0x5 */ 0xB8, 0x05, 0x00,
-- /* 00000293 out dx,ax */ 0xEF,
-- /* 00000294 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 00000297 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-- /* 0000029A out dx,ax */ 0xEF,
-- /* 0000029B pop ax */ 0x58,
-- /* 0000029C pop dx */ 0x5A,
-- /* 0000029D push dx */ 0x52,
-- /* 0000029E push ax */ 0x50,
-- /* 0000029F mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002A2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
-- /* 000002A5 out dx,ax */ 0xEF,
-- /* 000002A6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 000002A9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-- /* 000002AC out dx,ax */ 0xEF,
-- /* 000002AD pop ax */ 0x58,
-- /* 000002AE pop dx */ 0x5A,
-- /* 000002AF push dx */ 0x52,
-- /* 000002B0 push ax */ 0x50,
-- /* 000002B1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002B4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
-- /* 000002B7 out dx,ax */ 0xEF,
-- /* 000002B8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 000002BB mov ax,0x0 */ 0xB8, 0x00, 0x00,
-- /* 000002BE out dx,ax */ 0xEF,
-- /* 000002BF pop ax */ 0x58,
-- /* 000002C0 pop dx */ 0x5A,
-- /* 000002C1 push dx */ 0x52,
-- /* 000002C2 push ax */ 0x50,
-- /* 000002C3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002C6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
-- /* 000002C9 out dx,ax */ 0xEF,
-- /* 000002CA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 000002CD mov ax,0x20 */ 0xB8, 0x20, 0x00,
-- /* 000002D0 out dx,ax */ 0xEF,
-- /* 000002D1 pop ax */ 0x58,
-- /* 000002D2 pop dx */ 0x5A,
-- /* 000002D3 push dx */ 0x52,
-- /* 000002D4 push ax */ 0x50,
-- /* 000002D5 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002D8 mov ax,0x1 */ 0xB8, 0x01, 0x00,
-- /* 000002DB out dx,ax */ 0xEF,
-- /* 000002DC mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 000002DF mov ax,0x400 */ 0xB8, 0x00, 0x04,
-- /* 000002E2 out dx,ax */ 0xEF,
-- /* 000002E3 pop ax */ 0x58,
-- /* 000002E4 pop dx */ 0x5A,
-- /* 000002E5 push dx */ 0x52,
-- /* 000002E6 push ax */ 0x50,
-- /* 000002E7 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002EA mov ax,0x6 */ 0xB8, 0x06, 0x00,
-- /* 000002ED out dx,ax */ 0xEF,
-- /* 000002EE mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 000002F1 mov ax,0x400 */ 0xB8, 0x00, 0x04,
-- /* 000002F4 out dx,ax */ 0xEF,
-- /* 000002F5 pop ax */ 0x58,
-- /* 000002F6 pop dx */ 0x5A,
-- /* 000002F7 push dx */ 0x52,
-- /* 000002F8 push ax */ 0x50,
-- /* 000002F9 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 000002FC mov ax,0x2 */ 0xB8, 0x02, 0x00,
-- /* 000002FF out dx,ax */ 0xEF,
-- /* 00000300 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 00000303 mov ax,0x300 */ 0xB8, 0x00, 0x03,
-- /* 00000306 out dx,ax */ 0xEF,
-- /* 00000307 pop ax */ 0x58,
-- /* 00000308 pop dx */ 0x5A,
-- /* 00000309 push dx */ 0x52,
-- /* 0000030A push ax */ 0x50,
-- /* 0000030B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 0000030E mov ax,0x7 */ 0xB8, 0x07, 0x00,
-- /* 00000311 out dx,ax */ 0xEF,
-- /* 00000312 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 00000315 mov ax,0x300 */ 0xB8, 0x00, 0x03,
-- /* 00000318 out dx,ax */ 0xEF,
-- /* 00000319 pop ax */ 0x58,
-- /* 0000031A pop dx */ 0x5A,
-- /* 0000031B push dx */ 0x52,
-- /* 0000031C push ax */ 0x50,
-- /* 0000031D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-- /* 00000320 mov ax,0x4 */ 0xB8, 0x04, 0x00,
-- /* 00000323 out dx,ax */ 0xEF,
-- /* 00000324 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-- /* 00000327 mov ax,0x41 */ 0xB8, 0x41, 0x00,
-- /* 0000032A out dx,ax */ 0xEF,
-- /* 0000032B pop ax */ 0x58,
-- /* 0000032C pop dx */ 0x5A,
-- /* 0000032D pop ax */ 0x58,
-- /* 0000032E pop dx */ 0x5A,
-- /* 0000032F jmp short 0x34c */ 0xEB, 0x1B,
-- /* 00000331 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
-- /* 00000334 jmp short 0x34c */ 0xEB, 0x16,
-- /* 00000336 jmp short 0x350 */ 0xEB, 0x18,
-- /* 00000338 jmp short 0x350 */ 0xEB, 0x16,
-- /* 0000033A cmp al,0x3 */ 0x3C, 0x03,
-- /* 0000033C jz 0x345 */ 0x74, 0x07,
-- /* 0000033E cmp al,0x12 */ 0x3C, 0x12,
-- /* 00000340 jz 0x349 */ 0x74, 0x07,
-- /* 00000342 jmp word 0x22b */ 0xE9, 0xE6, 0xFE,
-- /* 00000345 mov al,0x30 */ 0xB0, 0x30,
-- /* 00000347 jmp short 0x34b */ 0xEB, 0x02,
-- /* 00000349 mov al,0x20 */ 0xB0, 0x20,
-- /* 0000034B iretw */ 0xCF,
-- /* 0000034C mov ax,0x4f */ 0xB8, 0x4F, 0x00,
-- /* 0000034F iretw */ 0xCF,
-- /* 00000350 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
-- /* 00000353 iretw */ 0xCF,
-+ /* 00000227 jz word 0x382 */ 0x0F, 0x84, 0x57, 0x01,
-+ /* 0000022B push si */ 0x56,
-+ /* 0000022C mov si,0x3e9 */ 0xBE, 0xE9, 0x03,
-+ /* 0000022F call word 0x3c4 */ 0xE8, 0x92, 0x01,
-+ /* 00000232 pop si */ 0x5E,
-+ /* 00000233 jmp short 0x233 */ 0xEB, 0xFE,
-+ /* 00000235 push es */ 0x06,
-+ /* 00000236 push di */ 0x57,
-+ /* 00000237 push ds */ 0x1E,
-+ /* 00000238 push si */ 0x56,
-+ /* 00000239 push cx */ 0x51,
-+ /* 0000023A push si */ 0x56,
-+ /* 0000023B mov si,0x3fb */ 0xBE, 0xFB, 0x03,
-+ /* 0000023E call word 0x3c4 */ 0xE8, 0x83, 0x01,
-+ /* 00000241 pop si */ 0x5E,
-+ /* 00000242 push cs */ 0x0E,
-+ /* 00000243 pop ds */ 0x1F,
-+ /* 00000244 mov si,0x0 */ 0xBE, 0x00, 0x00,
-+ /* 00000247 mov cx,0x100 */ 0xB9, 0x00, 0x01,
-+ /* 0000024A cld */ 0xFC,
-+ /* 0000024B rep movsb */ 0xF3, 0xA4,
-+ /* 0000024D pop cx */ 0x59,
-+ /* 0000024E pop si */ 0x5E,
-+ /* 0000024F pop ds */ 0x1F,
-+ /* 00000250 pop di */ 0x5F,
-+ /* 00000251 pop es */ 0x07,
-+ /* 00000252 jmp word 0x3ac */ 0xE9, 0x57, 0x01,
-+ /* 00000255 push es */ 0x06,
-+ /* 00000256 push di */ 0x57,
-+ /* 00000257 push ds */ 0x1E,
-+ /* 00000258 push si */ 0x56,
-+ /* 00000259 push cx */ 0x51,
-+ /* 0000025A push si */ 0x56,
-+ /* 0000025B mov si,0x404 */ 0xBE, 0x04, 0x04,
-+ /* 0000025E call word 0x3c4 */ 0xE8, 0x63, 0x01,
-+ /* 00000261 pop si */ 0x5E,
-+ /* 00000262 and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
-+ /* 00000266 cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
-+ /* 0000026A jz 0x276 */ 0x74, 0x0A,
-+ /* 0000026C push si */ 0x56,
-+ /* 0000026D mov si,0x432 */ 0xBE, 0x32, 0x04,
-+ /* 00000270 call word 0x3c4 */ 0xE8, 0x51, 0x01,
-+ /* 00000273 pop si */ 0x5E,
-+ /* 00000274 jmp short 0x233 */ 0xEB, 0xBD,
-+ /* 00000276 push cs */ 0x0E,
-+ /* 00000277 pop ds */ 0x1F,
-+ /* 00000278 mov si,0x100 */ 0xBE, 0x00, 0x01,
-+ /* 0000027B mov cx,0x100 */ 0xB9, 0x00, 0x01,
-+ /* 0000027E cld */ 0xFC,
-+ /* 0000027F rep movsb */ 0xF3, 0xA4,
-+ /* 00000281 pop cx */ 0x59,
-+ /* 00000282 pop si */ 0x5E,
-+ /* 00000283 pop ds */ 0x1F,
-+ /* 00000284 pop di */ 0x5F,
-+ /* 00000285 pop es */ 0x07,
-+ /* 00000286 jmp word 0x3ac */ 0xE9, 0x23, 0x01,
-+ /* 00000289 push dx */ 0x52,
-+ /* 0000028A push ax */ 0x50,
-+ /* 0000028B push si */ 0x56,
-+ /* 0000028C mov si,0x41a */ 0xBE, 0x1A, 0x04,
-+ /* 0000028F call word 0x3c4 */ 0xE8, 0x32, 0x01,
-+ /* 00000292 pop si */ 0x5E,
-+ /* 00000293 cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
-+ /* 00000297 jz 0x2a3 */ 0x74, 0x0A,
-+ /* 00000299 push si */ 0x56,
-+ /* 0000029A mov si,0x432 */ 0xBE, 0x32, 0x04,
-+ /* 0000029D call word 0x3c4 */ 0xE8, 0x24, 0x01,
-+ /* 000002A0 pop si */ 0x5E,
-+ /* 000002A1 jmp short 0x233 */ 0xEB, 0x90,
-+ /* 000002A3 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
-+ /* 000002A6 mov al,0x20 */ 0xB0, 0x20,
-+ /* 000002A8 out dx,al */ 0xEE,
-+ /* 000002A9 push dx */ 0x52,
-+ /* 000002AA push ax */ 0x50,
-+ /* 000002AB mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 000002AE mov ax,0x4 */ 0xB8, 0x04, 0x00,
-+ /* 000002B1 out dx,ax */ 0xEF,
-+ /* 000002B2 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 000002B5 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-+ /* 000002B8 out dx,ax */ 0xEF,
-+ /* 000002B9 pop ax */ 0x58,
-+ /* 000002BA pop dx */ 0x5A,
-+ /* 000002BB push dx */ 0x52,
-+ /* 000002BC push ax */ 0x50,
-+ /* 000002BD mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 000002C0 mov ax,0x5 */ 0xB8, 0x05, 0x00,
-+ /* 000002C3 out dx,ax */ 0xEF,
-+ /* 000002C4 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 000002C7 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-+ /* 000002CA out dx,ax */ 0xEF,
-+ /* 000002CB pop ax */ 0x58,
-+ /* 000002CC pop dx */ 0x5A,
-+ /* 000002CD push dx */ 0x52,
-+ /* 000002CE push ax */ 0x50,
-+ /* 000002CF mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 000002D2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
-+ /* 000002D5 out dx,ax */ 0xEF,
-+ /* 000002D6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 000002D9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
-+ /* 000002DC out dx,ax */ 0xEF,
-+ /* 000002DD pop ax */ 0x58,
-+ /* 000002DE pop dx */ 0x5A,
-+ /* 000002DF push dx */ 0x52,
-+ /* 000002E0 push ax */ 0x50,
-+ /* 000002E1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 000002E4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
-+ /* 000002E7 out dx,ax */ 0xEF,
-+ /* 000002E8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 000002EB mov ax,0x0 */ 0xB8, 0x00, 0x00,
-+ /* 000002EE out dx,ax */ 0xEF,
-+ /* 000002EF pop ax */ 0x58,
-+ /* 000002F0 pop dx */ 0x5A,
-+ /* 000002F1 push dx */ 0x52,
-+ /* 000002F2 push ax */ 0x50,
-+ /* 000002F3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 000002F6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
-+ /* 000002F9 out dx,ax */ 0xEF,
-+ /* 000002FA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 000002FD mov ax,0x20 */ 0xB8, 0x20, 0x00,
-+ /* 00000300 out dx,ax */ 0xEF,
-+ /* 00000301 pop ax */ 0x58,
-+ /* 00000302 pop dx */ 0x5A,
-+ /* 00000303 push dx */ 0x52,
-+ /* 00000304 push ax */ 0x50,
-+ /* 00000305 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 00000308 mov ax,0x1 */ 0xB8, 0x01, 0x00,
-+ /* 0000030B out dx,ax */ 0xEF,
-+ /* 0000030C mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 0000030F mov ax,0x400 */ 0xB8, 0x00, 0x04,
-+ /* 00000312 out dx,ax */ 0xEF,
-+ /* 00000313 pop ax */ 0x58,
-+ /* 00000314 pop dx */ 0x5A,
-+ /* 00000315 push dx */ 0x52,
-+ /* 00000316 push ax */ 0x50,
-+ /* 00000317 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 0000031A mov ax,0x6 */ 0xB8, 0x06, 0x00,
-+ /* 0000031D out dx,ax */ 0xEF,
-+ /* 0000031E mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 00000321 mov ax,0x400 */ 0xB8, 0x00, 0x04,
-+ /* 00000324 out dx,ax */ 0xEF,
-+ /* 00000325 pop ax */ 0x58,
-+ /* 00000326 pop dx */ 0x5A,
-+ /* 00000327 push dx */ 0x52,
-+ /* 00000328 push ax */ 0x50,
-+ /* 00000329 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 0000032C mov ax,0x2 */ 0xB8, 0x02, 0x00,
-+ /* 0000032F out dx,ax */ 0xEF,
-+ /* 00000330 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 00000333 mov ax,0x300 */ 0xB8, 0x00, 0x03,
-+ /* 00000336 out dx,ax */ 0xEF,
-+ /* 00000337 pop ax */ 0x58,
-+ /* 00000338 pop dx */ 0x5A,
-+ /* 00000339 push dx */ 0x52,
-+ /* 0000033A push ax */ 0x50,
-+ /* 0000033B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 0000033E mov ax,0x7 */ 0xB8, 0x07, 0x00,
-+ /* 00000341 out dx,ax */ 0xEF,
-+ /* 00000342 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 00000345 mov ax,0x300 */ 0xB8, 0x00, 0x03,
-+ /* 00000348 out dx,ax */ 0xEF,
-+ /* 00000349 pop ax */ 0x58,
-+ /* 0000034A pop dx */ 0x5A,
-+ /* 0000034B push dx */ 0x52,
-+ /* 0000034C push ax */ 0x50,
-+ /* 0000034D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
-+ /* 00000350 mov ax,0x4 */ 0xB8, 0x04, 0x00,
-+ /* 00000353 out dx,ax */ 0xEF,
-+ /* 00000354 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
-+ /* 00000357 mov ax,0x41 */ 0xB8, 0x41, 0x00,
-+ /* 0000035A out dx,ax */ 0xEF,
-+ /* 0000035B pop ax */ 0x58,
-+ /* 0000035C pop dx */ 0x5A,
-+ /* 0000035D pop ax */ 0x58,
-+ /* 0000035E pop dx */ 0x5A,
-+ /* 0000035F jmp short 0x3ac */ 0xEB, 0x4B,
-+ /* 00000361 push si */ 0x56,
-+ /* 00000362 mov si,0x411 */ 0xBE, 0x11, 0x04,
-+ /* 00000365 call word 0x3c4 */ 0xE8, 0x5C, 0x00,
-+ /* 00000368 pop si */ 0x5E,
-+ /* 00000369 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
-+ /* 0000036C jmp short 0x3ac */ 0xEB, 0x3E,
-+ /* 0000036E push si */ 0x56,
-+ /* 0000036F mov si,0x43f */ 0xBE, 0x3F, 0x04,
-+ /* 00000372 call word 0x3c4 */ 0xE8, 0x4F, 0x00,
-+ /* 00000375 pop si */ 0x5E,
-+ /* 00000376 jmp short 0x3b8 */ 0xEB, 0x40,
-+ /* 00000378 push si */ 0x56,
-+ /* 00000379 mov si,0x452 */ 0xBE, 0x52, 0x04,
-+ /* 0000037C call word 0x3c4 */ 0xE8, 0x45, 0x00,
-+ /* 0000037F pop si */ 0x5E,
-+ /* 00000380 jmp short 0x3b8 */ 0xEB, 0x36,
-+ /* 00000382 push si */ 0x56,
-+ /* 00000383 mov si,0x423 */ 0xBE, 0x23, 0x04,
-+ /* 00000386 call word 0x3c4 */ 0xE8, 0x3B, 0x00,
-+ /* 00000389 pop si */ 0x5E,
-+ /* 0000038A cmp al,0x3 */ 0x3C, 0x03,
-+ /* 0000038C jz 0x39d */ 0x74, 0x0F,
-+ /* 0000038E cmp al,0x12 */ 0x3C, 0x12,
-+ /* 00000390 jz 0x3a1 */ 0x74, 0x0F,
-+ /* 00000392 push si */ 0x56,
-+ /* 00000393 mov si,0x432 */ 0xBE, 0x32, 0x04,
-+ /* 00000396 call word 0x3c4 */ 0xE8, 0x2B, 0x00,
-+ /* 00000399 pop si */ 0x5E,
-+ /* 0000039A jmp word 0x233 */ 0xE9, 0x96, 0xFE,
-+ /* 0000039D mov al,0x30 */ 0xB0, 0x30,
-+ /* 0000039F jmp short 0x3a3 */ 0xEB, 0x02,
-+ /* 000003A1 mov al,0x20 */ 0xB0, 0x20,
-+ /* 000003A3 push si */ 0x56,
-+ /* 000003A4 mov si,0x3d6 */ 0xBE, 0xD6, 0x03,
-+ /* 000003A7 call word 0x3c4 */ 0xE8, 0x1A, 0x00,
-+ /* 000003AA pop si */ 0x5E,
-+ /* 000003AB iretw */ 0xCF,
-+ /* 000003AC push si */ 0x56,
-+ /* 000003AD mov si,0x3d6 */ 0xBE, 0xD6, 0x03,
-+ /* 000003B0 call word 0x3c4 */ 0xE8, 0x11, 0x00,
-+ /* 000003B3 pop si */ 0x5E,
-+ /* 000003B4 mov ax,0x4f */ 0xB8, 0x4F, 0x00,
-+ /* 000003B7 iretw */ 0xCF,
-+ /* 000003B8 push si */ 0x56,
-+ /* 000003B9 mov si,0x3dc */ 0xBE, 0xDC, 0x03,
-+ /* 000003BC call word 0x3c4 */ 0xE8, 0x05, 0x00,
-+ /* 000003BF pop si */ 0x5E,
-+ /* 000003C0 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
-+ /* 000003C3 iretw */ 0xCF,
-+ /* 000003C4 pushaw */ 0x60,
-+ /* 000003C5 push ds */ 0x1E,
-+ /* 000003C6 push cs */ 0x0E,
-+ /* 000003C7 pop ds */ 0x1F,
-+ /* 000003C8 mov dx,0x402 */ 0xBA, 0x02, 0x04,
-+ /* 000003CB lodsb */ 0xAC,
-+ /* 000003CC cmp al,0x0 */ 0x3C, 0x00,
-+ /* 000003CE jz 0x3d3 */ 0x74, 0x03,
-+ /* 000003D0 out dx,al */ 0xEE,
-+ /* 000003D1 jmp short 0x3cb */ 0xEB, 0xF8,
-+ /* 000003D3 pop ds */ 0x1F,
-+ /* 000003D4 popaw */ 0x61,
-+ /* 000003D5 ret */ 0xC3,
-+ /* 000003D6 inc bp */ 0x45,
-+ /* 000003D7 js 0x442 */ 0x78, 0x69,
-+ /* 000003D9 jz 0x3e5 */ 0x74, 0x0A,
-+ /* 000003DB add [di+0x6e],dl */ 0x00, 0x55, 0x6E,
-+ /* 000003DE jnc 0x455 */ 0x73, 0x75,
-+ /* 000003E0 jo 0x452 */ 0x70, 0x70,
-+ /* 000003E2 outsw */ 0x6F,
-+ /* 000003E3 jc 0x459 */ 0x72, 0x74,
-+ /* 000003E5 or al,[fs:bx+si] */ 0x65, 0x64, 0x0A, 0x00,
-+ /* 000003E9 push bp */ 0x55,
-+ /* 000003EA outsb */ 0x6E,
-+ /* 000003EB imul bp,[bp+0x6f],byte +0x77 */ 0x6B, 0x6E, 0x6F, 0x77,
-+ /* 000003EF outsb */ 0x6E,
-+ /* 000003F0 and [bp+0x75],al */ 0x20, 0x46, 0x75,
-+ /* 000003F3 outsb */ 0x6E,
-+ /* 000003F4 arpl [si+0x69],si */ 0x63, 0x74, 0x69,
-+ /* 000003F7 outsw */ 0x6F,
-+ /* 000003F8 outsb */ 0x6E,
-+ /* 000003F9 or al,[bx+si] */ 0x0A, 0x00,
-+ /* 000003FB inc di */ 0x47,
-+ /* 000003FC gs jz 0x448 */ 0x65, 0x74, 0x49,
-+ /* 000003FF outsb */ 0x6E,
-+ /* 00000400 outsd */ 0x66, 0x6F,
-+ /* 00000402 or al,[bx+si] */ 0x0A, 0x00,
-+ /* 00000404 inc di */ 0x47,
-+ /* 00000405 gs jz 0x455 */ 0x65, 0x74, 0x4D,
-+ /* 00000408 outsw */ 0x6F,
-+ /* 00000409 gs dec cx */ 0x64, 0x65, 0x49,
-+ /* 0000040C outsb */ 0x6E,
-+ /* 0000040D outsd */ 0x66, 0x6F,
-+ /* 0000040F or al,[bx+si] */ 0x0A, 0x00,
-+ /* 00000411 inc di */ 0x47,
-+ /* 00000412 gs jz 0x462 */ 0x65, 0x74, 0x4D,
-+ /* 00000415 outsw */ 0x6F,
-+ /* 00000416 or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
-+ /* 0000041A push bx */ 0x53,
-+ /* 0000041B gs jz 0x46b */ 0x65, 0x74, 0x4D,
-+ /* 0000041E outsw */ 0x6F,
-+ /* 0000041F or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
-+ /* 00000423 push bx */ 0x53,
-+ /* 00000424 gs jz 0x474 */ 0x65, 0x74, 0x4D,
-+ /* 00000427 outsw */ 0x6F,
-+ /* 00000428 gs dec sp */ 0x64, 0x65, 0x4C,
-+ /* 0000042B gs a32 popaw */ 0x65, 0x67, 0x61,
-+ /* 0000042E arpl [bx+di+0xa],di */ 0x63, 0x79, 0x0A,
-+ /* 00000431 add [di+0x6e],dl */ 0x00, 0x55, 0x6E,
-+ /* 00000434 imul bp,[bx+0x77],byte +0x6e */ 0x6B, 0x6F, 0x77, 0x6E,
-+ /* 00000438 and [di+0x6f],cl */ 0x20, 0x4D, 0x6F,
-+ /* 0000043B or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
-+ /* 0000043F inc di */ 0x47,
-+ /* 00000440 gs jz 0x493 */ 0x65, 0x74, 0x50,
-+ /* 00000443 insw */ 0x6D,
-+ /* 00000444 inc bx */ 0x43,
-+ /* 00000445 popaw */ 0x61,
-+ /* 00000446 jo 0x4a9 */ 0x70, 0x61,
-+ /* 00000448 bound bp,[bx+di+0x6c] */ 0x62, 0x69, 0x6C,
-+ /* 0000044B imul si,[si+0x69],word 0x7365 */ 0x69, 0x74, 0x69, 0x65, 0x73,
-+ /* 00000450 or al,[bx+si] */ 0x0A, 0x00,
-+ /* 00000452 push dx */ 0x52,
-+ /* 00000453 gs popaw */ 0x65, 0x61,
-+ /* 00000455 fs inc bp */ 0x64, 0x45,
-+ /* 00000457 fs */ 0x64,
-+ /* 00000458 db 0x69 */ 0x69,
-+ /* 00000459 or al,[fs:bx+si] */ 0x64, 0x0A, 0x00,
- };
- #endif
diff --git a/0005-advertise-OpenSSL-on-TianoCore-splash-screen-boot-lo.patch b/0005-advertise-OpenSSL-on-TianoCore-splash-screen-boot-lo.patch
new file mode 100644
index 0000000..7b26aef
--- /dev/null
+++ b/0005-advertise-OpenSSL-on-TianoCore-splash-screen-boot-lo.patch
@@ -0,0 +1,3123 @@
+From ade02daad705e1a4fd6468136de8fcb886f202a2 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 11 Jun 2014 23:33:33 +0200
+Subject: [PATCH] advertise OpenSSL on TianoCore splash screen / boot logo
+
+Because we may include the OpenSSL library in our OVMF and AAVMF builds
+now, we should advertise it as required by its license. This patch takes
+the original TianoCore logo, shifts it up by 20 pixels, and adds the
+horizontally centered message
+
+ This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/ )
+
+below.
+
+Logo-OpenSSL.bmp: PC bitmap, Windows 3.x format, 469 x 111 x 24
+Logo.bmp: PC bitmap, Windows 3.x format, 193 x 58 x 8
+
+Downstream only because upstream edk2 does not intend to release a
+secure-boot-enabled OVMF build. (However the advertising requirement in
+the OpenSSL license,
+"CryptoPkg/Library/OpensslLib/openssl-1.0.2*/LICENSE", has been discussed
+nonetheless, which is why I'm changing the logo.)
+
+Notes about the 9ece15a -> c9e5618 rebase:
+- Logo.bmp is no longer modified in-place; instead a modified copy is
+ created. That's because AAVMF includes the logo too, but it doesn't
+ include OpenSSL / Secure Boot, so we need the original copy too.
+
+Notes about the c9e5618 -> b9ffeab rebase:
+- AAVMF gained Secure Boot support, therefore the logo is again modified
+ in the common location, and no FDF changes are necessary.
+
+Notes about the d7c0dfa -> 90bb4c5 rebase:
+
+- squash in the following downstream-only commits (made originally for
+ <https://bugzilla.redhat.com/show_bug.cgi?id=1308678 >):
+
+ - eef9eb0 restore TianoCore splash logo without OpenSSL advertisment
+ (RHEL only)
+
+ - 25842f0 OvmfPkg, ArmVirtPkg: show OpenSSL-less logo without Secure
+ Boot (RH only)
+
+ The reason is that ideas keep changing when and where to include the
+ Secure Boot feature, so the logo must be controllable directly on the
+ build command line, from the RPM spec file. See the following
+ references:
+
+ - https://post-office.corp.redhat.com/mailman/private/virt-devel/2016-March/m…
+ - https://post-office.corp.redhat.com/mailman/private/virt-devel/2016-April/m…
+ - https://bugzilla.redhat.com/show_bug.cgi?id=1323363
+
+- This squashed variant should remain the final version of this patch.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- For more fun, upstream completely changed the way logo bitmaps are
+ embedded in the firmware binary (see for example commit ab970515d2c6,
+ "OvmfPkg: Use the new LogoDxe driver", 2016-09-26). Therefore in this
+ rebase, we reimplement the previous downstream-only commit e775fb20c999,
+ as described below.
+
+- Beyond the new bitmap file (which we preserve intact from the last
+ downstream branch), we introduce:
+
+ - a new IDF (image description file) referencing the new BMP,
+
+ - a new driver INF file, referencing the new BMP and new IDF (same C
+ source code though),
+
+ - a new UNI (~description) file for the new driver INF file.
+
+- In the OVMF DSC and FDF files, we select the new driver INF for
+ inclusion if either SECURE_BOOT_ENABLE, NETWORK_IP6_ENABLE, or
+ TLS_ENABLE is set, as they all make use of OpenSSL (although
+ different subsets of it).
+
+- In the AAVMF DSC and FDF files, we only look at SECURE_BOOT_ENABLE,
+ or NETWORK_IP6_ENABLE, because the ArmVirtQemu platform does not
+ support TLS_ENABLE yet.
+
+- This patch is best displayed with "git show --find-copies-harder".
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- After picking previous downstream-only commit 32192c62e289, carry new
+ upstream commit e01e9ae28250 ("MdeModulePkg/LogoDxe: Add missing
+ dependency gEfiHiiImageExProtocolGuid", 2017-03-16) over to
+ "LogoOpenSSLDxe.inf".
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 32192c62e289f261f5ce74acee48e5a94561f10b)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmVirtPkg/ArmVirtQemu.dsc | 4 +
+ ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 4 +
+ ArmVirtPkg/ArmVirtQemuKernel.dsc | 4 +
+ MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64 | 2743 ++++++++++++++++++++++++
+ MdeModulePkg/Logo/Logo-OpenSSL.idf | 15 +
+ MdeModulePkg/Logo/LogoOpenSSLDxe.inf | 61 +
+ MdeModulePkg/Logo/LogoOpenSSLDxe.uni | 22 +
+ OvmfPkg/OvmfPkgIa32.dsc | 4 +
+ OvmfPkg/OvmfPkgIa32.fdf | 4 +
+ OvmfPkg/OvmfPkgIa32X64.dsc | 4 +
+ OvmfPkg/OvmfPkgIa32X64.fdf | 4 +
+ OvmfPkg/OvmfPkgX64.dsc | 4 +
+ OvmfPkg/OvmfPkgX64.fdf | 4 +
+ 13 files changed, 2877 insertions(+)
+ create mode 100644 MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64
+ create mode 100644 MdeModulePkg/Logo/Logo-OpenSSL.idf
+ create mode 100644 MdeModulePkg/Logo/LogoOpenSSLDxe.inf
+ create mode 100644 MdeModulePkg/Logo/LogoOpenSSLDxe.uni
+
+diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
+index 885c6b14b8..a7a3899560 100644
+--- a/ArmVirtPkg/ArmVirtQemu.dsc
++++ b/ArmVirtPkg/ArmVirtQemu.dsc
+@@ -327,7 +327,11 @@
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE)
++ MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ MdeModulePkg/Logo/LogoDxe.inf
++!endif
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+index a6390bd4b8..20a5bcb27b 100644
+--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
++++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+@@ -202,7 +202,11 @@ READ_LOCK_STATUS = TRUE
+ #
+ # TianoCore logo (splash screen)
+ #
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE)
++ INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ INF MdeModulePkg/Logo/LogoDxe.inf
++!endif
+
+ #
+ # Ramdisk support
+diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
+index 434d6861a5..6e4e0249ef 100644
+--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
++++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
+@@ -316,7 +316,11 @@
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE)
++ MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ MdeModulePkg/Logo/LogoDxe.inf
++!endif
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+diff --git a/MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64 b/MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64
+new file mode 100644
+index 0000000000..567ca32f05
+--- /dev/null
++++ b/MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64
+@@ -0,0 +1,2743 @@
++Qk22YgIAAAAAADYAAAAoAAAA1QEAAG8AAAABABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWlpav7+/CQkJAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQUoKCg6enp7+/vrKys
++PT09AAAAAAAAAAAAAAAAAAAAAAAACQkJwMDAWlpaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAERERN3d3RUVFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALy8vHp6ehAQEAYGBi8vL8HBwWpqagAAAAAAAAAAAAAA
++AAAAAAAAABYWFt/f30NDQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgLU1NRU
++VFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAxMTEEBAQAAAAAAAAAAAAoKCjd3d0AAAAAAAAAAAAAAAAAAAAAAAAAAABXV1fS0tIB
++AQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAA////AAAAAAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAA////AAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAALy8vzs7O9/f309PTPj4+6urqAgICAAAAMzMzxcXF9fX18PDws7OzHx8f
++AAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA
++AAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAARkZG5eXl6urqAAAAAAAA
++////AAAAAAAAAAAAAAAA////AAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAgICaGhozMzM9fX19fX1ycnJYmJiAQEBAAAAAAAAAAAA////PDw8zMzM+Pj4
++5OTkYGBgAAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAA////AAAAAAAAAAAAAAAA
++////AAAAAAAAAAAARUVFtLS05eXl+vr68fHxxMTEU1NTAAAAAAAAAAAAAAAARUVFtLS05eXl+vr6
++8fHxxMTEU1NTAAAAAAAAAAAA////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAA////AAAAAAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAAAAAAaGho3t7e
+++vr629vbZWVlAAAAAAAAAAAAAAAA////AAAAAAAA////AAAAAAAAAAAAAAAAYWFhw8PDCAgI////
++AAAAAAAAAAAARkZG5eXl6urqAAAAAAAAAAAAAAAAAAAAT09Pzc3NAAAAAAAAAAAAAAAA////AAAA
++AAAAAAAAAAAA////AAAAAAAARkZG5eXl6urqAAAAAAAARkZG5eXl6urqAAAA////PDw8zMzM+Pj4
++5OTkYGBgAAAAAAAAAAAAAAAA////AAAAAAAA3NzcFRUVAAAAAAAA3NzcFRUVAAAAAAAAAAAAAAAA
++AAAAKysr////Ly8vAAAALy8v////KysrAAAAAAAAAAAAAAAAKysr////Ly8vAAAALy8v////Kysr
++AAAAAAAAAAAAAAAAAAAAKysr////Ly8vAAAALy8v////KysrAAAAAAAAAAAA////AAAAAAAAAAAA
++aGho3t7e+vr629vbZWVlAAAAAAAAAAAAAAAA////PDw8zMzM+Pj45OTkYGBgAAAAAAAAAAAAAAAA
++V1dX09PT+vr67+/vq6urICAgAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAMzMzxcXF9fX1
++8PDws7OzHx8fAAAAAAAAMzMzxcXF9fX18PDws7OzHx8fAAAAAAAAAAAA////AAAAAAAAAAAA////
++AAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAZ2dn5eXl
++9PT0urq6KCgo/Pz8AAAAAAAA3NzcFRUVAAAAAAAAAAAAAAAAzs7OS0tLAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAFJS
++Utvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDA
++wICAgAoKCi0tLb29vfj4+AAAAAAAAMLCwmxsbA0NDQgICG9vb76+vgAAAAAAAAAAAEhISN3d3T8/
++PwkJCRoaGoWFhbS0tAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP///wAAAAAAAAAAAAAA
++AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAOTk5DMzMwoKCgAAAAAAAP///wAAAAAAAAAAAAAAAP//
++/wAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKSkpMzM
++zERERAsLCwoKCj4+PsPDw5ubmwAAAAAAAAAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAEhI
++SN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAFhYWOvr62Zm
++ZhgYGAMDAxQUFE1NTdbW1lVVVQAAAAAAAFhYWOvr62ZmZhgYGAMDAxQUFE1NTdbW1lVVVQAAAAAA
++AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAA
++AAAAAFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAA
++AAAAAP///wAAAAAAAP///wAAAAAAAAAAAFFRUdLS0hEREQAAAP///wAAAAAAAAAAAOTk5DMzMwoK
++CgAAAAAAAAAAAAAAAAAAAJubm3d3dwAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAA
++AOTk5DMzMwoKCgAAAAAAAOTk5DMzMwoKCgAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAAAA
++AP///wAAAAAAAJqamlVVVQAAAAAAAJqamlVVVQAAAAAAAAAAAAAAAAAAAGpqav7+/mVlZQAAAGVl
++Zf7+/mlpaQAAAAAAAAAAAAAAAGpqav7+/mVlZQAAAGVlZf7+/mlpaQAAAAAAAAAAAAAAAAAAAGpq
++av7+/mVlZQAAAGVlZf7+/mlpaQAAAAAAAAAAAP///wAAAAAAAFJSUtvb2zY2NgkJCTMzM9fX11NT
++UwAAAAAAAAAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0
++tAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAMLCwmxsbA0NDQgICG9vb76+vgAAAAAAAMLC
++wmxsbA0NDQgICG9vb76+vgAAAAAAAAAAAP///wAAAAAAAAAAAP///wAAAAAAAFJSUtvb2zY2NgkJ
++CTMzM9fX11NTUwAAAAAAAP///wAAAAAAAAAAAAAAAGhoaM3NzSoqKgwMDFZWVtDQ0P///wAAAAAA
++AJqamlVVVQAAAAAAAAAAAAAAAHp6epaWlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAC9vb1OTk4AAAAAAAAAAABMTEy+
++vr4AAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADx8fESEhIAAAAAAAA8PDz///8A
++AAAAAAAAAAAAAAAAAAAAAAAICAj09PQAAAAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA
++AAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAC4uLhJSUkAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUVFTd3d0KCgoAAAAAAAAAAAAAAAAHBwfN
++zc1PT08AAAAAAAD///9KSkoAAAAAAAAAAABOTk7AwMAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAA
++AAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAADLy8tGRkYAAAAAAAAAAAAAAAAAAAAlJSXi
++4uIAAAAAAADLy8tGRkYAAAAAAAAAAAAAAAAAAAAlJSXi4uIAAAAAAAD///8AAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAC9vb1OTk4AAAAAAAAA
++AABMTEy+vr4AAAAAAAC9vb1OTk4AAAAAAAAAAABMTEy+vr4AAAAAAAAAAAD///8AAAAAAAD///8A
++AAAAAABDQ0Pd3d0eHh4AAAAAAAD///8AAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAADW
++1tYyMjIAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAD///8AAAAAAAAAAAAAAAD/
++//8AAAAAAAAAAAD///9KSkoAAAAAAAAAAABOTk7AwMAAAAAAAAAAAAAAAAAAAAAAAABWVlaWlpYA
++AAAAAABWVlaWlpYAAAAAAAAAAAAAAAAAAACpqanHx8ebm5sAAACbm5vFxcWoqKgAAAAAAAAAAAAA
++AACpqanHx8ebm5sAAACbm5vFxcWoqKgAAAAAAAAAAAAAAAAAAACpqanHx8ebm5sAAACbm5vFxcWo
++qKgAAAAAAAAAAAAAAAAAAAAAAAC9vb1OTk4AAAAAAAAAAABMTEy+vr4AAAAAAAAAAAD///9KSkoA
++AAAAAAAAAABOTk7AwMAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAICAj09PQAAAAAAAAAAAAAAAAAAAAAAAAICAj09PQA
++AAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAC9vb1OTk4AAAAAAAAAAABMTEy+vr4AAAAAAAD/
++//8AAAAAAAAAAAAAAADOzs5FRUUAAAAAAAAAAABxcXH///8AAAAAAABWVlaWlpYAAAAAAAAAAAAA
++AAA2NjbS0tIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAA////AAAAAAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA////AAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAACgoK////AAAAAAAAAAAAAAAAAAAAIiIi
++MjIyyMjIAAAAAAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++AAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA
++AAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAt7e3Xl5eAAAAAAAAAAAAAAAAAAAAAAAAVFRUtLS0AAAAAAAA////EBAQ
++AAAAAAAAAAAAFBQU5ubmAAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA
++AAAAAAAA////AAAAAAAAAwMDAAAAAAAAAAAAAAAAAAAAAAAAFhYW5+fnAAAAAAAAAwMDAAAAAAAA
++AAAAAAAAAAAAAAAAFhYW5+fnAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA7u7u
++EhISAAAAAAAAAAAAEhIS7u7uAAAAAAAAAAAA////AAAAAAAA////cHBwODg45OTkLS0tAAAAAAAA
++AAAA////AAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA7e3tFhYWAAAAAAAAAAAAAAAA
++////AAAAAAAAAAAAAAAA////AAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAA////EBAQ
++AAAAAAAAAAAAFBQU5ubmAAAAAAAAAAAAAAAAAAAAAAAAExMT1dXVAAAAAAAAExMT1dXVAAAAAAAA
++AAAAAAAAAAAA5+fnaWlp0dHRAAAA0dHRZWVl5ubmAAAAAAAAAAAAAAAA5+fnaWlp0dHRAAAA0dHR
++ZWVl5ubmAAAAAAAAAAAAAAAAAAAA5+fnaWlp0dHRAAAA0dHRZWVl5ubmAAAAAAAAAAAAAAAAAAAA
++AAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAAAAAA////EBAQAAAAAAAAAAAAFBQU5ubmAAAA
++AAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAA
++AAAAAAAAIiIiMjIyyMjIAAAAAAAAAAAAAAAAAAAAIiIiMjIyyMjIAAAAAAAAAAAA////AAAAAAAA
++AAAAAAAAAAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA////AAAAAAAAAAAAAAAA8/Pz
++DQ0NAAAAAAAAAAAAGRkZ////AAAAAAAAExMT1dXVAAAAAAAAAAAAAAAAGRkZ6urqAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAA
++AAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAoKCn5+ftra2v7+/re3tyMjIwAAAAAAAAAAAPz8
++/P////////////////////j4+AAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP///wAAAAAA
++AAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAA
++AAAAAP///wAAAAAAAPz8/P////////////////////j4+AAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr
++6xcXFwAAAAAAAAAAAAAAAAAAAAAAACIiIunp6QAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAA
++AAAAAPz8/P////////////////////j4+AAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAA
++AAAAAAAAAAAAAAAAABMTE1hYWNXV1V5eXgAAAAAAAAAAAAAAAAAAAAAAAAAAABMTE1hYWNXV1V5e
++XgAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
++/wAAAAAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8
++/AAAAAAAAAAAAP///wAAAAAAAP///+7u7vX19UFBQQAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP//
++/wAAAAAAAAAAAAAAAAAAAAAAAAAAAPv7+wUFBQAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP//
++/wAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAA
++AAAAAAAAAAAAAAAAAAAAAAAAAM3NzRkZGQAAAAAAAM3NzRkZGQAAAAAAAAAAACYmJu/v7wkJCfX1
++9RYWFvT09AgICOvr6yUlJQAAAAAAACYmJu/v7wkJCfX19RYWFvT09AgICOvr6yUlJQAAAAAAAAAA
++ACYmJu/v7wkJCfX19RYWFvT09AgICOvr6yUlJQAAAAAAAAAAAAAAAAAAAPz8/AICAgAAAAAAAAAA
++AAMDA/z8/AAAAAAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAAAAAAAPz8/P//////////////
++//////j4+AAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAoKCn5+ftra2v7+/re3tyMjIwAA
++AAAAAAoKCn5+ftra2v7+/re3tyMjIwAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAPz8/AIC
++AgAAAAAAAAAAAAMDA/z8/AAAAAAAAP///wAAAAAAAAAAAAAAAPv7+wICAgAAAAAAAAAAAAQEBP//
++/wAAAAAAAAAAAM3NzRkZGQAAAAAAAAAAAAYGBvr6+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAADv7+8QEBAAAAAAAAAA
++AAAQEBDw8PAAAAAAAAD///8PDw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA
++AAD///8AAAAAAACqqqqamppiYmIdHR0AAAAAAAAAAAAAAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh
++4eEAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8KCgoAAAAAAAABAQH///8AAAAAAAAA
++AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8ICAgAAAAAAAAAAAD///8AAAAAAADw8PAS
++EhIAAAAAAAAAAAAYGBjh4eEAAAAAAAAAAAAAAAAAAAAAAAAAAAD7+/sEBAQAAAAAAAAAAAAAAAAA
++AAAAAAAGBgb6+voAAAAAAAD///8TExMAAAAAAAAAAAASEhLo6OgAAAAAAADw8PASEhIAAAAAAAAA
++AAAYGBjh4eEAAAAAAAD///8KCgoAAAAAAAABAQH///8AAAAAAAAAAAAQEBBoaGiqqqrf39/y8vK0
++tLROTk4AAAAAAAAAAAAAAAAQEBBoaGiqqqrf39/y8vK0tLROTk4AAAAAAAAAAAD///8AAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAADv7+8QEBAA
++AAAAAAAAAAAQEBDw8PAAAAAAAADv7+8QEBAAAAAAAAAAAAAQEBDw8PAAAAAAAAAAAAD///8AAAAA
++AAD///8uLi7T09MwMDAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAA
++AAAAAADt7e0WFhYAAAAAAAAAAAAAAAD///8ICAgAAAAAAAAAAAD///8AAAAAAAD///8AAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAD///8TExMAAAAAAAAAAAASEhLo6OgAAAAAAAAAAAAAAAAAAAAAAAAA
++AACKiopZWVkAAAAAAACKiopZWVkAAAAAAAAAAABlZWWvr68AAADGxsZ2dnbHx8cAAACqqqpkZGQA
++AAAAAABlZWWvr68AAADGxsZ2dnbHx8cAAACqqqpkZGQAAAAAAAAAAABlZWWvr68AAADGxsZ2dnbH
++x8cAAACqqqpkZGQAAAAAAAAAAAAAAAAAAADv7+8QEBAAAAAAAAAAAAAQEBDw8PAAAAAAAAAAAAD/
++//8TExMAAAAAAAAAAAASEhLo6OgAAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEAAAAAAAD///8K
++CgoAAAAAAAABAQH///8AAAAAAACqqqqamppiYmIdHR0AAAAAAAAAAAAAAACqqqqamppiYmIdHR0A
++AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAADv7+8QEBAAAAAAAAAAAAAQEBDw8PAA
++AAAAAAD///8PDw8AAAAAAAAAAADo6OgQEBAAAAAAAAAAAAAbGxv///8AAAAAAAAAAACKiopZWVkA
++AAAAAAAAAAAZGRnq6uoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAA////
++REREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA8vLyDQ0N
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAAAAAAAAAAAAAA
++AAAA////AAAAAAAAAAAA////PT09AAAAAAAAExMT8PDwAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++AAAAAAAAAAAAAAAA////Ozs7AAAAAAAAExMT8vLyAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6ur
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA7e3tFBQUAAAAAAAAAAAAAAAAAAAAAAAAFRUV7OzsAAAAAAAA
++////U1NTAAAAAAAAAAAASkpKxMTEAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAA////
++PT09AAAAAAAAExMT8PDwAAAAAAAARERE6Ojop6enYmJiLS0tAwMDAAAAAAAAAAAAAAAAAAAARERE
++6Ojop6enYmJiLS0tAwMDAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAA
++AAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAAAAAA////AAAAAAAA////AAAAJiYm1NTUQ0ND
++AAAAAAAAAAAA////AAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA1tbWMjIyAAAAAAAA
++AAAAAAAA////Ozs7AAAAAAAAExMT8vLyAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAA
++////U1NTAAAAAAAAAAAASkpKxMTEAAAAAAAAAAAAAAAAAAAAAAAAAAAARkZGmpqaAAAAAAAARkZG
++mpqaAAAAAAAAAAAAo6OjbW1tAAAAjo6OxcXFj4+PAAAAZ2dno6OjAAAAAAAAo6OjbW1tAAAAjo6O
++xcXFj4+PAAAAZ2dno6OjAAAAAAAAAAAAo6OjbW1tAAAAjo6OxcXFj4+PAAAAZ2dno6OjAAAAAAAA
++AAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAAAAAA////U1NTAAAAAAAAAAAASkpK
++xMTEAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAA////PT09AAAAAAAAExMT8PDwAAAA
++AAAA8vLyDQ0NAAAAAAAAAAAAAAAAAAAAAAAA8vLyDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++AAAAAAAAAAAAAAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAA////REREAAAAAAAA
++AAAAxMTESEhIAAAAAAAAAAAAbGxs////AAAAAAAAAAAARkZGmpqaAAAAAAAAAAAANjY20tLSAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
++/wAAAAAAAAAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAEBAfHx8aurqyEhIQcHBwAAAAAAAAAA
++AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAMnJyWlpaQoKCg0NDW9vb8fHxwAAAAAA
++AAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAPb2
++9sDAwC0tLQsLC4KCgr+/vwAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAPr6+r6+
++vi0tLQ4ODoSEhL6+vgAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAAAAAAAAAAAAAAAA
++AAAAALy8vFBQUAAAAAAAAAAAAAAAAAAAAAAAAFRUVLu7uwAAAAAAAP39/c7Ozjo6OgsLCzExMdbW
++1lVVVQAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAPb29sDAwC0tLQsLC4KCgr+/vwAA
++AAAAANzc3Dk5OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANzc3Dk5OQAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAAAAFdXV9fX1zU1NQoKCi4u
++LtHR0U9PTwAAAAAAAAAAAP///wAAAAAAAP///wAAAAAAAB4eHtTU1FlZWQAAAAAAAP///wAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAJqamnd3dwAAAAAAAAAAAAAAAPr6+r6+vi0tLQ4O
++DoSEhL6+vgAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP39/c7Ozjo6OgsLCzExMdbW
++1lVVVQAAAAAAAAAAAP///wAAAAAAAAAAAAkJCdPT0wAAAAAAAAkJCdPT0wAAAAAAAAAAAOLi4isr
++KwAAAFVVVfz8/FdXVwAAACQkJOHh4QAAAAAAAOLi4isrKwAAAFVVVfz8/FdXVwAAACQkJOHh4QAA
++AAAAAAAAAOLi4isrKwAAAFVVVfz8/FdXVwAAACQkJOHh4QAAAAAAAAAAAAAAAAAAAFdXV9fX1zU1
++NQoKCi4uLtHR0U9PTwAAAAAAAAAAAP39/c7Ozjo6OgsLCzExMdbW1lVVVQAAAAAAAE1NTeXl5UZG
++RgsLCz8/P+Li4kJCQgAAAAAAAPb29sDAwC0tLQsLC4KCgr+/vwAAAAAAAMnJyWlpaQoKCg0NDW9v
++b8fHxwAAAAAAAMnJyWlpaQoKCg0NDW9vb8fHxwAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAA
++AFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAEBAfHx8aurqyEhIQcHBwAAAFVVVdfX1zMzMw0NDVhY
++WNjY2P39/QAAAAAAAAAAAAkJCdPT0wAAAAAAAAAAAHp6epWVlQAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDD///////////////8AAAAAAABpaWnc
++3Nz6+vrb29tWVlYAAAAAAAAHBwfo6Og7Ozvb29v5+fkAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAA
++AAAAAAAAAAD///8AAAAAAAAnJye5ubnw8PDy8vK/v78uLi4AAAAAAAAAAAAAAABfX1/R0dH29vba
++2tpfX18AAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAGBgbn5+c+Pj7R0dH29vbLy8suLi4A
++AAAAAAAAAAAAAAAAAAAAAAD4+Pj///////+QkJAAAAAAAAD7+/s9PT3S0tL5+fnR0dErKysAAAAA
++AAAAAABfX1/R0dH29vba2tpfX18AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABbW1vLy8sGBgYAAAAA
++AAAAAAAAAAAHBwfOzs5ZWVkAAAAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAAAAAAAABfX1/R
++0dH29vba2tpfX18AAAAAAAAGBgbn5+c+Pj7R0dH29vbLy8suLi4AAAAAAADs7OwaGhoAAAAAAAAA
++AAAAAAAAAAAqKiqUlJQAAAAAAADs7OwaGhoAAAAAAAAAAAAAAAAAAAAqKiqUlJQAAAAAAAD///8A
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA
++AABpaWnc3Nz6+vrb29tWVlYAAAAAAAAAAAAAAABpaWnc3Nz6+vrb29tWVlYAAAAAAAAAAAAAAAD/
++//8AAAAAAAD///8AAAAAAAAAAAAYGBjR0dFzc3MAAAD///8AAAAAAAD4+Pj///////+QkJAAAAAA
++AAAAAAAAAAAAAABOTk7Nzc0AAAAAAAAAAAAAAAD7+/s9PT3S0tL5+fnR0dErKysAAAD4+Pj/////
++//+QkJAAAAD4+Pj///////+QkJAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAAAAAAAAD///8A
++AAAAAAAAAAAAAAC9vb0cHBwAAAAAAAC9vb0cHBwAAAAhISHo6OgAAAAAAAAcHBz///8fHx8AAAAA
++AADh4eEgICAhISHo6OgAAAAAAAAcHBz///8fHx8AAAAAAADh4eEgICAAAAAhISHo6OgAAAAAAAAc
++HBz///8fHx8AAAAAAADh4eEgICAAAAAAAAAAAAAAAAAAAABpaWnc3Nz6+vrb29tWVlYAAAAAAAAA
++AAAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAAAAAAAABfX1/R0dH29vba2tpfX18AAAAAAAAG
++Bgbn5+c+Pj7R0dH29vbLy8suLi4AAAAAAAAnJye5ubnw8PDy8vK/v78uLi4AAAAAAAAnJye5ubnw
++8PDy8vK/v78uLi4AAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAABpaWnc3Nz6+vrb29tW
++VlYAAAAAAAAHBwfo6Og7Ozvb29v5+fkAAAAAAABTU1Pb29v39/fDw8MvLy/29vYCAgIAAAAAAAAA
++AAC9vb0cHBwAAAAAAADOzs5KSkoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAwMD////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAA3t7eAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBqampw8PDQEBACwsLCgoKQUFBxcXFpqamAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXFxcxMTEQUFBDw8PBAQEGBgYVlZW39/fb29vAAAA
++AAAAXFxcxMTEQUFBDw8PBAQEGBgYVlZW39/fb29vAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA////AAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEB0tLS
++VVVVAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eAAAAAAAAAAAAAAAA3t7eAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAenp6XV1d
++AAAAAAAAenp6XV1dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAenp6XV1dAAAAWFhY0NDQ
++AQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAPLy8j4+PgcHBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALq6ugAAAAAAAAAAAAAA
++AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAICAmlpacvLy/X19fX19cvLy2hoaAICAgAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAE1NTcfHx+rq6vv7+/Hx8cjIyGZmZgAAAAAAAAAAAAAAAE1NTcfHx+rq6vv7
+++/Hx8cjIyGZmZgAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
++/////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAALq6ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCQt7e3hYWFgAAAAAAAP///wAA
++AAAAAAAAAAAAAAAAAAAAAAAAALq6ugAAAAAAAAAAAAAAALq6ugAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY2Np6engAAAAAAADY2Np6engAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY2Np6enhcXF+Dg4EFBQQAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSnU1NT39/cAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZWVnAwMAJCQkAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAACAgLOzs4AAAAAAAACAgLOzs4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAACAgLX19fCwsJZWVkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+fn55eXlbW1tAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+++Pj4a2trAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUFBUdHR/Pz81NTUwAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJe7u7gAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAB5eXnLy8sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQH///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAA
++AAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA////AAAAAAAAAAAAMzMzxcXF
++9fX18PDws7OzHx8fAAAAAAAAAAAAAAAAAAAAAAAAAAAA////PDw8zMzM+Pj45OTkYGBgAAAAAAAA
++AAAA////AAAAAAAAAAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAAAAAAU1NTx8fH9/f3
++zs7OPj4+9vb2AgICAAAALy8vzs7O9/f309PTPj4+6urqAgICAAAAAAAAX19f5ubm9PT0vLy8Jycn
++AAAAAAAAAAAARkZG5eXl6urqAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA
++AAAAAAAA////AAAAAAAAAAAAX19f5ubm9PT0vLy8JycnAAAAAAAA////AAAAAAAALy8vzs7O9/f3
++09PTPj4+6urqAgICAAAAAAAAAAAAU1NTx8fH9/f3zs7OPj4+9vb2AgICAAAAAAAAV1dX09PT+vr6
++7+/vq6urICAgAAAAAAAAMzMzxcXF9fX18PDws7OzHx8fAAAAAAAAAAAAAAAAAAAAAAAAMzMzxcXF
++9fX18PDws7OzHx8fAAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAA////AAAAAAAAAAAA
++AAAARkZG5eXl6urqAAAAAAAAKysr////Ly8vAAAALy8v////KysrAAAAAAAAAAAAMTExxsbG9fX1
++6+vroaGhFBQUenp69fX1AAAAAAAA////AAAAAAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAg
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAU1NTx8fH9/f3zs7OPj4+9vb2AgICAAAAAAAAV1dX09PT+vr6
++7+/vq6urICAgAAAAAAAAAAAAfn5+////REREAAAAAAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6ur
++ICAgAAAAAAAA////AAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAAAAAAAAAA////PDw8zMzM+Pj4
++5OTkYGBgAAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAAAAAAU1NTx8fH9/f3zs7O
++Pj4+9vb2AgICAAAAAAAAAAAAAAAABQUF8/PzPDw8zs7O+Pj44+PjZ2dnAAAAAAAAAAAAAAAAAAAA
++Pz8//v7+ExMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARkZG5eXl6urqAAAA////AAAAAAAAAAAA
++AAAA////AAAAAAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AgICaGhozMzM9fX19fX1ycnJYmJiAQEBAAAAAAAAAAAAAAAA////PDw8zMzM+Pj45OTkYGBgAAAA
++AAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA
++AAAARUVFtLS05eXl+vr68fHxxMTEU1NTAAAAAAAAAAAAAAAARUVFtLS05eXl+vr68fHxxMTEU1NT
++AAAAAAAAAAAA////////////////////////////AAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAaGho3t7e+vr629vbZWVlAAAA
++AAAAAAAAAAAA////AAAAAAAAAAAAV1dX09PT+vr67+/vq6urICAgAAAAAAAAAAAAX19f5ubm9PT0
++vLy8JycnAAAAAAAARkZG5eXl6urqAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAP//
++/wAAAAAAAAAAAAAAAP///wAAAAAAAP///wAAAAAAAAAAAMLCwmxsbA0NDQgICG9vb76+vgAAAAAA
++AAAAAAAAAAAAAAAAAAAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAP///wAAAAAAAAAAAAAA
++AFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAFtbW8/PzysrKwsLC0NDQ9PT0/7+/gAAAAAAAMDA
++wICAgAoKCi0tLb29vfj4+AAAAAAAAEdHR9HR0R8fHwkJCWRkZMzMzAAAAAAAAAAAAOTk5DMzMwoK
++CgAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAEdH
++R9HR0R8fHwkJCWRkZMzMzAAAAAAAAP///wAAAAAAAMDAwICAgAoKCi0tLb29vfj4+AAAAAAAAAAA
++AFtbW8/PzysrKwsLC0NDQ9PT0/7+/gAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAMLC
++wmxsbA0NDQgICG9vb76+vgAAAAAAAAAAAAAAAAAAAAAAAMLCwmxsbA0NDQgICG9vb76+vgAAAAAA
++AFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAP///wAAAAAAAAAAAAAAAOTk5DMzMwoKCgAAAAAA
++AGpqav7+/mVlZQAAAGVlZf7+/mlpaQAAAAAAAAAAANDQ0GlpaQkJCR0dHWlpab29veLi4iMjIwAA
++AAAAAP///wAAAAAAAAAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAAAAAAAAAAAAAAAA
++AFtbW8/PzysrKwsLC0NDQ9PT0/7+/gAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAAAA
++ANHR0c3NzZ6engAAAAAAAAAAAAAAAEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAP///wAAAAAA
++AFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAEhI
++SN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAFtbW8/PzysrKwsLC0NDQ9PT0/7+/gAAAAAAAAAAAAAA
++AAAAAAAAAP39/c7Ozj09PQoKCi8vL9PT00NDQwAAAAAAAAAAAAAAAHd3d/Hx8WhoaAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAOTk5DMzMwoKCgAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAEhI
++SN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAAAAAAAAAAAAAAAAAAAAAKSkpMzMzERERAsLCwoKCj4+
++PsPDw5ubmwAAAAAAAAAAAAAAAP7+/srKyj09PQoKCjExMdfX10xMTAAAAAAAAEhISN3d3T8/PwkJ
++CRoaGoWFhbS0tAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAFhYWOvr62ZmZhgYGAMDAxQU
++FE1NTdbW1lVVVQAAAAAAAFhYWOvr62ZmZhgYGAMDAxQUFE1NTdbW1lVVVQAAAAAAAP///wAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAFJSUtvb2zY2NgkJCTMzM9fX11NTUwAAAAAAAAAAAP///wAAAAAA
++AEhISN3d3T8/PwkJCRoaGoWFhbS0tAAAAAAAAEdHR9HR0R8fHwkJCWRkZMzMzAAAAAAAAOTk5DMz
++MwoKCgAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8A
++AAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAICAj09PQAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++//9KSkoAAAAAAAAAAABOTk7AwMAAAAAAAAD///8AAAAAAAAAAAAAAAC9vb1OTk4AAAAAAAAAAABM
++TEy+vr4AAAAAAADGxsZGRkYAAAAAAAAAAABcXFz///8AAAAAAADx8fESEhIAAAAAAAA8PDz///8A
++AAAAAAC/v79JSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++//8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAC/v79JSUkAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAADx8fESEhIAAAAAAAA8PDz///8AAAAAAAAAAADGxsZGRkYAAAAAAAAAAABc
++XFz///8AAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAj09PQA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAj09PQAAAAAAAC9vb1OTk4AAAAAAAAAAABM
++TEy+vr4AAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAACpqanHx8ebm5sAAACbm5vF
++xcWoqKgAAAAAAAAAAAD39/cLCwsAAAAAAAAAAABOTk7///8AAAAAAAAAAAD///8AAAAAAAAAAAAA
++AAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADGxsZGRkYAAAAAAAAAAABc
++XFz///8AAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCT6+vpDQ0Pq6uoHBwcAAAAA
++AAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAC9vb1OTk4AAAAAAAAAAABM
++TEy+vr4AAAAAAAD///9KSkoAAAAAAAAAAABOTk7AwMAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAA
++AAAAAAAAAADGxsZGRkYAAAAAAAAAAABcXFz///8AAAAAAAAAAAAAAAAAAAAAAAD///9TU1MAAAAA
++AAAAAABERESqqqoAAAAAAAAAAAAAAADW1tZycnLJyckAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++//8AAAAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAABUVFTd3d0KCgoAAAAAAAAAAAAAAAAHBwfNzc1PT08AAAAAAAAA
++AAD///9KSkoAAAAAAAAAAABOTk7AwMAAAAAAAAC4uLhJSUkAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++//8AAAAAAAAAAAAAAAD///8AAAAAAADLy8tGRkYAAAAAAAAAAAAAAAAAAAAlJSXi4uIAAAAAAADL
++y8tGRkYAAAAAAAAAAAAAAAAAAAAlJSXi4uIAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA
++AAC9vb1OTk4AAAAAAAAAAABMTEy+vr4AAAAAAAAAAAD///8AAAAAAAC4uLhJSUkAAAAAAAAAAAAA
++AAAAAAAAAAAAAAC/v79JSUkAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAA
++////AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAA////AAAAAAAAAAAA
++AAAAAAAAAAAAIiIiMjIyyMjIAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EBAQAAAAAAAAAAAAFBQU
++5ubmAAAAAAAA////AAAAAAAAAAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA8vLyDQ0N
++AAAAAAAAAAAAFBQU////AAAAAAAA////AAAAAAAAAAAACgoK////AAAAAAAA5+fnERERAAAAAAAA
++AAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////
++AAAAAAAAAAAAAAAA////AAAAAAAA5+fnERERAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA////
++AAAAAAAAAAAACgoK////AAAAAAAAAAAA8vLyDQ0NAAAAAAAAAAAAFBQU////AAAAAAAA7e3tDg4O
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiMjIyyMjIAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAIiIiMjIyyMjIAAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA////AAAA
++AAAAAAAAAAAA////AAAAAAAAAAAAAAAA5+fnaWlp0dHRAAAA0dHRZWVl5ubmAAAAAAAAAAAAr6+v
++hYWFJSUlEBAQBgYGBgYG////AAAAAAAAAAAA////AAAAAAAAAAAAAAAA7e3tDg4OAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLyDQ0NAAAAAAAAAAAAFBQU////AAAAAAAA7e3tDg4O
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAd3d3oaGhAAAAnJycUlJSAAAAAAAAAAAA7e3tDg4OAAAAAAAA
++AAAAAAAAAAAAAAAAAAAA////AAAAAAAA7u7uEhISAAAAAAAAAAAAEhIS7u7uAAAAAAAA////EBAQ
++AAAAAAAAAAAAFBQU5ubmAAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLyDQ0NAAAA
++AAAAAAAAFBQU////AAAAAAAAAAAAAAAAAAAAAAAA////EBAQAAAAAAAAAAAAEBAQ4uLiAAAAAAAA
++AAAANTU12dnZBQUFurq6KioqAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAA////AAAA
++AAAAAAAAAAAA////AAAAAAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAt7e3Xl5eAAAAAAAAAAAAAAAAAAAAAAAAVFRUtLS0AAAAAAAAAAAA////EBAQAAAAAAAAAAAA
++FBQU5ubmAAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////
++AAAAAAAAAwMDAAAAAAAAAAAAAAAAAAAAAAAAFhYW5+fnAAAAAAAAAwMDAAAAAAAAAAAAAAAAAAAA
++AAAAFhYW5+fnAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA7u7uEhISAAAAAAAAAAAA
++EhIS7u7uAAAAAAAAAAAA////AAAAAAAA7e3tDg4OAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+fnERER
++AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAP///wAAAAAAAAAAAAoKCn5+ftra2v7+/re3tyMj
++IwAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAAAAAAAP///wAAAAAA
++AAAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAPr6+gICAgAAAAAAAAAAAAMDA////wAA
++AAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAPr6+gQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
++/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAA
++AAAAAPr6+gQEBAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAP///wAAAAAAAAAAAAAAAP///wAA
++AAAAAAAAAPr6+gICAgAAAAAAAAAAAAMDA////wAAAAAAAPz8/P////////////////////j4+AAA
++AAAAAAoKCn5+ftra2v7+/re3tyMjIwAAAAAAAAAAAAAAAAAAAAAAAAoKCn5+ftra2v7+/re3tyMj
++IwAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAA
++AAAAACYmJu/v7wkJCfX19RYWFvT09AgICOvr6yUlJQAAAAAAAAcHB4GBgdDQ0O3t7fr6+v7+/v//
++/wAAAAAAAAAAAP///wAAAAAAAAAAAAAAAPz8/P////////////////////j4+AAAAAAAAAAAAAAA
++AAAAAAAAAPr6+gICAgAAAAAAAAAAAAMDA////wAAAAAAAPz8/P////////////////////j4+AAA
++AAAAAMrKylVVVQAAAFFRUaurqwAAAAAAAAAAAPz8/P////////////////////j4+AAAAAAAAP//
++/wAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAA
++AAAAAPz8/P////////////////////j4+AAAAAAAAPr6+gICAgAAAAAAAAAAAAMDA////wAAAAAA
++AAAAAAAAAAAAAAAAAP///wICAgAAAAAAAAAAAAICAvr6+gAAAAAAAAAAAJSUlGhoaAAAADo6OouL
++iwAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAA
++AAAAAPz8/P////////////////////j4+AAAAAAAAAAAAAAAAAAAAAAAAOvr6xcXFwAAAAAAAAAA
++AAAAAAAAAAAAACIiIunp6QAAAAAAAAAAAP///wMDAwAAAAAAAAAAAAUFBfn5+QAAAAAAAPz8/P//
++//////////////////j4+AAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAA
++AAAAABMTE1hYWNXV1V5eXgAAAAAAAAAAAAAAAAAAAAAAAAAAABMTE1hYWNXV1V5eXgAAAAAAAP//
++/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAPz8/AICAgAAAAAAAAAAAAMDA/z8/AAAAAAAAAAAAP//
++/wAAAAAAAPz8/P////////////////////j4+AAAAAAAAPr6+gQEBAAAAAAAAAAAAAAAAAAAAAAA
++AP///wAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAD///8ICAgAAAAAAAAA
++AAD///8AAAAAAAD///8AAAAAAAAAAACqqqqamppiYmIdHR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8TExMAAAAAAAAAAAASEhLo6OgAAAAAAAD///8PDw8AAAAAAAAAAADv7+8QEBAAAAAA
++AAAAAAAQEBDw8PAAAAAAAADj4+MPDw8AAAAAAAAAAAAQEBD///8AAAAAAAD///8AAAAAAAAAAAAA
++AAD///8AAAAAAADr6+sREREAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAAAAAD///8KCgoAAAAAAAABAQH///8AAAAAAADr6+sREREAAAAAAAAA
++AAAAAAAAAAAAAAD///8AAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAADj4+MPDw8AAAAA
++AAAAAAAQEBD///8AAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEAAAAAAACqqqqamppiYmIdHR0A
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqqqamppiYmIdHR0AAAAAAAAAAAAAAADv7+8QEBAAAAAA
++AAAAAAAQEBDw8PAAAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAABlZWWvr68AAADGxsZ2
++dnbHx8cAAACqqqpkZGQAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgL///8AAAAAAAAAAAD///8PDw8A
++AAAAAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEAAAAAAAAAAAAAAAAAAAAAAADj4+MPDw8AAAAA
++AAAAAAAQEBD///8AAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEAAAAeHh75+fkODg4AAAAMDAzw
++8PANDQ0AAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEAAAAAAAD///8AAAAAAADv7+8QEBAAAAAA
++AAAAAAAQEBDw8PAAAAAAAAD///8TExMAAAAAAAAAAAASEhLo6OgAAAAAAADw8PASEhIAAAAAAAAA
++AAAYGBjh4eEAAAAAAADj4+MPDw8AAAAAAAAAAAAQEBD///8AAAAAAAAAAAAAAAAAAAAAAAD///8T
++ExMAAAAAAAAAAAAODg7v7+8AAAAAAAAGBgbr6+sZGRkAAAADAwPY2NgEBAQAAAAAAAAAAAAAAAAA
++AAAAAAD///8AAAAAAAAAAAD///8ICAgAAAAAAAAAAAD///8AAAAAAAAAAADw8PASEhIAAAAAAAAA
++AAAYGBjh4eEAAAAAAAAAAAAAAAAAAAAAAAD7+/sEBAQAAAAAAAAAAAAAAAAAAAAAAAAGBgb6+voA
++AAAAAAAAAAD///8TExMAAAAAAAAAAAASEhLo6OgAAAAAAADw8PASEhIAAAAAAAAAAAAYGBjh4eEA
++AAAAAAD///8KCgoAAAAAAAABAQH///8AAAAAAAAAAAAQEBBoaGiqqqrf39/y8vK0tLROTk4AAAAA
++AAAAAAAAAAAQEBBoaGiqqqrf39/y8vK0tLROTk4AAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAD////////////////////y8vLDw8NbW1sAAAAAAAAAAAD///8PDw8A
++AAAAAAAAAADv7+8QEBAAAAAAAAAAAAAQEBDw8PAAAAAAAAAAAAD///8AAAAAAADw8PASEhIAAAAA
++AAAAAAAYGBjh4eEAAAAAAADr6+sREREAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA
++AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAA////Ozs7AAAAAAAAExMT8vLyAAAAAAAA////AAAA
++AAAAAAAA8vLyDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////U1NTAAAAAAAA
++AAAASkpKxMTEAAAAAAAA////REREAAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAA
++tbW1REREAAAAAAAAAAAAS0tL////AAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAAAvr6+QUFB
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAA
++AAAA////PT09AAAAAAAAExMT8PDwAAAAAAAAvr6+QUFBAAAAAAAAAAAAAAAAAAAAAAAA////AAAA
++AAAA////AAAAAAAAAAAAAAAA////AAAAAAAAAAAAtbW1REREAAAAAAAAAAAAS0tL////AAAAAAAA
++vr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAA8vLyDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAA8vLyDQ0NAAAAAAAAAAAAAAAAAAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAA
++////AAAAAAAAAAAAAAAA////AAAAAAAAAAAAo6OjbW1tAAAAjo6OxcXFj4+PAAAAZ2dno6OjAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAHx8f7OzsAAAAAAAAAAAA////REREAAAAAAAAAAAAvr6+VlZWAAAA
++AAAAAAAAWlpaq6urAAAAAAAAAAAAAAAAAAAAAAAAtbW1REREAAAAAAAAAAAAS0tL////AAAAAAAA
++vr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAcHBwvb29AAAAAAAAAAAAu7u7X19fAAAAAAAAvr6+VlZW
++AAAAAAAAAAAAWlpaq6urAAAAAAAA////AAAAAAAAwMDASUlJAAAAAAAAAAAAR0dHw8PDAAAAAAAA
++////U1NTAAAAAAAAAAAASkpKxMTEAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAAtbW1
++REREAAAAAAAAAAAAS0tL////AAAAAAAAAAAAAAAAAAAAAAAA////UlJSAAAAAAAAAAAASUlJvr6+
++AAAAAAAAUlJSyMjIAAAAAAAAAAAAra2tTU1NAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAA
++////Ozs7AAAAAAAAExMT8vLyAAAAAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAAAAAA
++AAAAAAAAAAAA7e3tFBQUAAAAAAAAAAAAAAAAAAAAAAAAFRUV7OzsAAAAAAAAAAAA////U1NTAAAA
++AAAAAAAASkpKxMTEAAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAA////PT09AAAAAAAA
++ExMT8PDwAAAAAAAARERE6Ojop6enYmJiLS0tAwMDAAAAAAAAAAAAAAAAAAAARERE6Ojop6enYmJi
++LS0tAwMDAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++////AAAAAAAAAAAAAAAABQUFFxcXeHh4eHh4AAAAAAAA////REREAAAAAAAAAAAAwMDASUlJAAAA
++AAAAAAAAR0dHw8PDAAAAAAAAAAAA////AAAAAAAAvr6+VlZWAAAAAAAAAAAAWlpaq6urAAAAAAAA
++vr6+QUFBAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAA
++AAAAAAAAAAAAAPr6+r6+vi0tLQ4ODoSEhL6+vgAAAAAAAP///wAAAAAAAAAAAMnJyWlpaQoKCg0N
++DW9vb8fHxwAAAAAAAAAAAAAAAAAAAAAAAAAAAP39/c7Ozjo6OgsLCzExMdbW1lVVVQAAAAEBAfHx
++8aurqyEhIQcHBwAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAAAAEVFRdLS0i8vLwwMDENDQ87O
++zv///wAAAAAAAP///wAAAAAAAAAAAAAAAP///wAAAAAAAE9PT8jIyCUlJQkJCWdnZ8bGxgAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAPb29sDAwC0tLQsLC4KC
++gr+/vwAAAAAAAE9PT8jIyCUlJQkJCWdnZ8bGxgAAAAAAAP///wAAAAAAAP///wAAAAAAAAAAAAAA
++AP///wAAAAAAAAAAAEVFRdLS0i8vLwwMDENDQ87Ozv///wAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li
++4kJCQgAAAAAAAMnJyWlpaQoKCg0NDW9vb8fHxwAAAAAAAAAAAAAAAAAAAAAAAMnJyWlpaQoKCg0N
++DW9vb8fHxwAAAAAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAAAAP///wAAAAAAAAAAAAAAAP//
++/wAAAAAAAAAAAOLi4isrKwAAAFVVVfz8/FdXVwAAACQkJOHh4QAAAAAAAMfHx21tbRMTEwUFBSQk
++JJ6enqGhoQAAAAAAAAEBAfHx8aurqyEhIQcHBwAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAA
++AAAAAAAAAAAAAAAAAEVFRdLS0i8vLwwMDENDQ87Ozv///wAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li
++4kJCQgAAAMPDw3FxcQAAAAAAAAAAAHBwcLm5uQAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAA
++AAAAAP///wAAAAAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAAAAP39/c7Ozjo6OgsLCzExMdbW
++1lVVVQAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAEVFRdLS0i8vLwwMDENDQ87Ozv//
++/wAAAAAAAAAAAAAAAAAAAAAAAP39/dDQ0ENDQwwMDCwsLMzMzFFRUQAAAAAAALGxsXh4eAAAAAAA
++AAAAAGZmZq6urgAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAPr6+r6+vi0tLQ4ODoSEhL6+
++vgAAAAAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAAAAAAAAAAAAAAAAALy8vFBQUAAA
++AAAAAAAAAAAAAAAAAAAAAFRUVLu7uwAAAAAAAAAAAP39/c7Ozjo6OgsLCzExMdbW1lVVVQAAAAAA
++AE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAPb29sDAwC0tLQsLC4KCgr+/vwAAAAAAANzc3Dk5
++OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANzc3Dk5OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAA
++AAAAAAwMDOrq6gAAAAEBAfHx8aurqyEhIQcHBwAAAFdXV9fX1zU1NQoKCi4uLtHR0U9PTwAAAAAA
++AAAAAP///wAAAAAAAE1NTeXl5UZGRgsLCz8/P+Li4kJCQgAAAAAAAE9PT8jIyCUlJQkJCWdnZ8bG
++xgAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAD7+/s9PT3S
++0tL5+fnR0dErKysAAAAAAAD///8AAAAAAAAAAAAnJye5ubnw8PDy8vK/v78uLi4AAAAAAAAAAAAA
++AAAAAAAAAAAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAHBwfo6Og7Ozvb29v5+fkAAAAAAABp
++aWnc3Nz6+vrb29tWVlYAAAAAAAAAAAAAAABVVVXMzMz39/fLy8s6Ojr///8AAAAAAAD///8AAAAA
++AAAAAAAAAAD///8AAAAAAAAAAABgYGDk5OTz8/O4uLgkJCQAAAAAAAD4+Pj///////+QkJAAAAAA
++AAAAAAAAAAAAAAD///8AAAAAAAAAAAAGBgbn5+c+Pj7R0dH29vbLy8suLi4AAAAAAAAAAABgYGDk
++5OTz8/O4uLgkJCQAAAAAAAD///8AAAAAAAD///8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAABV
++VVXMzMz39/fLy8s6Ojr///8AAAAAAAAAAABfX1/R0dH29vba2tpfX18AAAAAAAAAAAAnJye5ubnw
++8PDy8vK/v78uLi4AAAAAAAAAAAAAAAAAAAAAAAAnJye5ubnw8PDy8vK/v78uLi4AAAAAAAAAAABp
++aWnc3Nz6+vrb29tWVlYAAAAwMDD///////////////8AAAD4+Pj///////+QkJAhISHo6OgAAAAA
++AAAcHBz///8fHx8AAAAAAADh4eEgICAAAAAiIiKoqKjs7Oz7+/vh4eGUlJQODg4AAAAAAAAHBwfo
++6Og7Ozvb29v5+fkAAAAAAABfX1/R0dH29vba2tpfX18AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV
++VVXMzMz39/fLy8s6Ojr///8AAAAAAAAAAABfX1/R0dH29vba2tpfX18AAAAYGBj9/f0lJSUAAAAA
++AAAAAAAlJSX8/PwWFhYAAAAAAABfX1/R0dH29vba2tpfX18AAAAAAAAAAAD///8AAAAAAAAAAABp
++aWnc3Nz6+vrb29tWVlYAAAAAAAAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAAAAAAAABfX1/R
++0dH29vba2tpfX18AAAAAAAAAAAAAAABVVVXMzMz39/fLy8s6Ojr///8AAAAAAAAAAAAAAAAAAAAA
++AAD///87OzvLy8v4+Pjh4eFmZmYAAAAAAAAVFRX6+vooKCgAAAAAAAAAAAAfHx/6+voVFRUAAAAA
++AAAAAAAAAAD4+Pj///////+QkJAAAAD7+/s9PT3S0tL5+fnR0dErKysAAAAAAAAAAAAAAABfX1/R
++0dH29vba2tpfX18AAAAAAAAAAAAAAAAAAAAAAAAAAABbW1vLy8sGBgYAAAAAAAAAAAAAAAAHBwfO
++zs5ZWVkAAAAAAAAFBQXz8/M8PDzPz8/5+fnk5ORmZmYAAAAAAAAAAAAAAABfX1/R0dH29vba2tpf
++X18AAAAAAAAGBgbn5+c+Pj7R0dH29vbLy8suLi4AAAAAAADs7OwaGhoAAAAAAAAAAAAAAAAAAAAq
++KiqUlJQAAAAAAADs7OwaGhoAAAAAAAAAAAAAAAAAAAAqKiqUlJQAAAAAAAD///8AAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAMDAzw8PAAAAAHBwfo
++6Og7Ozvb29v5+fkAAAAAAABpaWnc3Nz6+vrb29tWVlYAAAAAAAAAAAAAAAD///8AAAAAAAAAAABf
++X1/R0dH29vba2tpfX18AAAAAAAAAAAAAAABgYGDk5OTz8/O4uLgkJCQAAAD4+Pj///////+QkJAA
++AAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAwMD////AAAAAAAAAAAAAAAA3t7eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eAAAA
++AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAQEBqampw8PDQEBACwsLCgoKQUFBxcXFpqamAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAXFxcxMTEQUFBDw8PBAQEGBgYVlZW39/fb29vAAAAAAAAXFxcxMTE
++QUFBDw8PBAQEGBgYVlZW39/fb29vAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAA////AAAAAAAAAAAAAAAACQkJICAghoaGjo6OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eAAAAAAAAAP//////////////////////
++/////////////wAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAALq6ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLy8j4+PgcHBwAA
++AAAAALq6ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALq6ugAAAAAAAAAAAP///wAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAICAmlpacvLy/X19fX19cvLy2hoaAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAE1NTcfHx+rq6vv7+/Hx8cjIyGZmZgAAAAAAAAAAAAAAAE1NTcfHx+rq6vv7+/Hx8cjIyGZm
++ZgAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////
++//////b29s/Pz3NzcwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAALq6ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++//8AAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSnU1NT39/cAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA
++AAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAA////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////wAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+OcGdtRTltRTlvSD5tRTltRTlz
++TUBtRTlvSD5tRTltRTlzTUD///+pkoqOcGeUdm2Udm2Udm2Udm2Udm2Udm2Udm2Udm2Udm2Udm3/
++///Qw761oZu1oZu1oZu9q6W1oZu1oZu1oZu1oZu1oZu1oZu1oZv9/f3n4d/az8zaz8zaz8zaz8za
++z8zaz8zaz8zaz8zaz8zaz8zaz8z9/f3z8O7n4d/n4d/r5uTn4d/r5uTr5uTv6+rr5uTr5uTn4d/n
++4d/9/Pz7+vr39fT39fT39fT59/f39fT39fT59/f39fT59/f59/f39fT9/f3/////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAA////////////b0g+PAcAQQ0APAcAPAcAQQ0APAcAPAcAPAcAQQ0APAcATBwN
++////lHZtZTsubUU5bUU5bUU5bUU5b0g+b0g+b0g+bUU5b0g+bUU5////vaulmn92oYd+oYd+mn92
++oYd+oYd+oYd+mn92oYd+mn92mn92/fz82s/M0MO+0MO+0MO+0MO+xrey0MO+0MO+0MO+xreyxrey
++0MO+/fz87+vq4tvY4tvY4tvY4tvY4tvY4tvYxrey0MO+4tvY4tvY4tvY/Pv7+vn58/Du9fPy9fPy
++9fPy9fPy9fPy9fPy9fPy9fPy9fPy9fPy/f39////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++2s/M5+Hf////////////////////////////////////////////////////////////////////
++////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////
++/////21FOUENAEQSAUQSAUQSAUQSAUQSAUQSAUQSAUENAEQSAUQSAf///5p/dm1FOXNNQHNNQHNN
++QHNNQHNNQHNNQHNNQHNNQHNNQHNNQP///72rpZp/dqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqmS
++ipp/dv38/OLb2NDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvv38/O/r6uLb2Ovm5OLb
++2OLb2Ovm5Ovm5IFfVaGHfu/r6ufh3+Lb2Pz7+/38/P39/ff19Pn39/f19Pf19Pf19PXz8vXz8vf1
++9Pn39/Pw7v39/f////////////////////////////7+/v//////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////4trYbWhm///////////////
++//////////////////////////////////////////////////////////////7+/v//////////
++/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////9zTUA8BwBEEgFEEgFB
++DQBEEgFEEgFBDQBEEgFEEgFEEgFEEgH///+Udm1tRTlzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBz
++TUBzTUD///+9q6Waf3ahh36hh36hh36hh36hh36hh36hh36pkoqhh36hh379/Pzi29jQw77Qw77Q
++w77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw779/Pzv6+ri29ipkopvSD5tRTmaf3bn4d+La2FdMSN8
++WU21oZvr5uS1oZuBX1Wpkorv6+qaf3bn4d+9q6W9q6X59/f6+fnaz8yhh3759/f9/f3////n4d+h
++h37r5uSLa2GOcGeUdm3r5uShh36pkoq1oZvaz8zn4d+GZVuOcGfr5uTQw761oZv///+pkori29jG
++t7LGt7Lr5uShh37//v7////39fShh37v6+r///////+9q6XQw769q6XGt7L///+hh37z8O6pkorn
++4d/Qw761oZv18/KUdm3i29ipkorQw77///+hh36GZVuUdm3Gt7Kpkorr5uT///+1oZt8WU21oZv9
++/Pz///////+9q6V8WU2BX1WUdm3v6+r///+9q6V8WU2pkor////39fSGZVvn4d/////Gt7J8WU2a
++f3b39fSpkoraz8zi29iBX1WUdm339fSOcGdtRTmGZVvaz8zQw761oZv18/Khh3759/epkori29jQ
++w76BX1Waf3b39fS9q6XQw77n4d+hh3739fSOcGe9q6X///////////////8AAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAA////////////bUU5PAcARBIBRBIBRBIBRBIBRBIBRBIBRBIBRBIB
++RBIBRBIB////mn92bUU5c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01A////vauloYd+oYd+
++qZKKoYd+oYd+oYd+oYd+oYd+oYd+oYd+mn92/fz84tvYxrey0MO+0MO+0MO+0MO+0MO+0MO+0MO+
++0MO+0MO+0MO+/fz88/DuvaulTBwNtaGbxreyVScYqZKKjnBnXTEjoYd+XTEjtaGbXTEjvaulZTsu
++xreyZTsu4tvYmn92lHZt/Pv7/v79vaulb0g+////////////2s/MbUU5i2thfFlNqZKKPAcA4tvY
++VScY5+Hfb0g+xreyfFlNlHZthmVbjnBntaGbgV9V////b0g+0MO+oYd+lHZt2s/Mb0g+/v79////
++7+vqXTEj5+Hf////////jnBnqZKKjnBnqZKK////VScY6+bkb0g+0MO+qZKKi2th0MO+PAcAqZKK
++VScYgV9V2s/MTBwNvaulTBwNqZKKbUU52s/M2s/MVScYxreyZTsu2s/M////////i2thi2th4tvY
++i2thd1JG2s/MVScYxreybUU50MO+2s/MPAcAqZKK9fPyVScYvauld1JGvaulgV9VtaGbc01AoYd+
++fFlNlHZtmn92ZTsuqZKKbUU5oYd+hmVb6+bkZTsu9/X0ZTsuxreyXTEjtaGbfFlNtaGbhmVbtaGb
++2s/MZTsu2s/MVScY7+vq////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AP///////////29IPjwHAEQSAUENAEENAEQSAUQSAUQSAUQSAUQSAUQSAUQSAf///5p/dm1FOXNN
++QHNNQHNNQHNNQHNNQHNNQHNNQHNNQHNNQHNNQP///8a3spp/dqGHfqGHfqGHfqGHfqGHfqGHfqGH
++fqGHfqGHfpp/dv38/NrPzNDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvv38/PPw7nxZ
++TZp/du/r6u/r6qmSim1FOYZlW6GHfvf19G1FOXdSRl0xI4trYW9IPsa3smU7LuLb2KGHfpR2bfv6
+++v39/ca3sl0xI7Whm7Whm/Xz8trPzG1FOdDDvmU7LnxZTUwcDeLb2F0xI////3dSRrWhm21FOevm
++5Ofh32U7LqmSiotrYf///3dSRtrPzKmSiqGHftrPzG1FOf7+/v////Pw7mU7LtDDvuvm5P///5R2
++bamSipR2bamSiv///10xI+/r6ndSRtDDvrWhm45wZ6GHfl0xI2U7Ll0xI2U7LtrPzHdSRnxZTVUn
++GLWhm3NNQOLb2KmSilUnGItrYXdSRtrPzP///////45wZ6mSiv////Xz8m9IPqGHfkwcDYZlW3dS
++RtDDvpR2bW1FOXxZTdDDvkwcDYZlW3xZTb2rpYFfVbWhm2U7LvPw7tDDvnNNQItrYbWhm////21F
++OYZlW45wZ+/r6mU7Lvn393dSRqmSil0xI4FfVXxZTbWhm45wZ7Whm9rPzG9IPtDDvm1FOf//////
++/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////9tRTk8BwBE
++EgFEEgFEEgFEEgFEEgFEEgFEEgFEEgFEEgFMHA3///+af3ZtRTlzTUBzTUBzTUBzTUBzTUBzTUBz
++TUBzTUBzTUBzTUD////Gt7Kaf3ahh36hh36hh36pkoqhh36hh36hh36hh36hh36hh379/Pzi29jQ
++w77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw779/Pzz8O5zTUCpkorr5uTn4d+9q6VlOy6G
++ZVtvSD7Qw75dMSOhh35dMSPQw75dMSO1oZtVJxjGt7KGZVuaf3b8+/v9/f29q6VdMSOpkop8WU2B
++X1Xaz8xvSD7Qw76OcGe9q6VMHA3az8xVJxjr5uRvSD61oZtlOy7Gt7Kpkop8WU21oZttRTnn4d9t
++RTm1oZuUdm18WU3Gt7JvSD7////////z8O5dMSNtRTlvSD7Gt7KUdm2pkoqOcGeGZVvr5uRMHA3Q
++w75tRTm1oZuhh36BX1VdMSPGt7JBDQCOcGeGZVupkoqOcGfGt7JtRTmpkoptRTm9q6W1oZtlOy7G
++t7JdMSPGt7L///////+OcGehh37///////93Ukahh35VJxjQw75lOy6pkoptRTnQw75lOy61oZtd
++MSPGt7JvSD6pkoqGZVu1oZtlOy7Qw76hh36BX1WOcGd8WU3i29hlOy6af3ZtRTnaz8xVJxjaz8xl
++Oy69q6VdMSO9q6V8WU2hh36La2GUdm3Gt7JlOy7Gt7JlOy77+vr///////////////8AAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////bUU5QQ0AQQ0ARBIBQQ0ARBIBRBIBQQ0A
++RBIBRBIBRBIBRBIB////mn92bUU5c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01A////vaul
++oYd+oYd+oYd+oYd+oYd+qZKKoYd+oYd+oYd+oYd+oYd+/fz84tvY0MO+0MO+0MO+0MO+0MO+0MO+
++0MO+0MO+0MO+0MO+0MO+/fz88/Dumn92c01A6+bk7+vqi2thd1JGqZKKZTsuXTEjlHZt4tvYlHZt
++ZTsuhmVb8/DuhmVbb0g+ZTsu0MO++vn5/f39vaulc01A////5+HfVScYxreybUU56+bkc01AbUU5
++lHZtvaulQQ0AlHZtVScYfFlNtaGbbUU5ZTsu0MO+2s/MXTEjc01AjnBnb0g+ZTsui2thXTEjqZKK
++////////8/DuZTsu5+Hf////////taGbxreytaGbXTEji2thd1JGc01Ac01AfFlNbUU5vaullHZt
++7+vqjnBn0MO+xreyqZKKmn92bUU5d1JG5+HflHZtVScYtaGbhmVbbUU5jnBn+/r6////////i2th
++qZKK////4tvYVScY6+bklHZtZTsujnBn2s/Mi2th////oYd+xreyoYd+ZTsufFlN7+vqgV9Vvaul
++0MO+ZTsubUU54tvYtaGbbUU5ZTsuqZKK2s/Mc01AZTsugV9Vc01AfFlN9/X0qZKKZTsud1JG8/Du
++taGbb0g+ZTsuqZKKoYd+PAcA0MO+////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAP///////////29IPjwHAEQSAUENAEQSAUQSAUQSAUQSAUQSAUQSAUQSAUQSAf///5p/
++dm1FOXNNQHNNQHNNQHNNQHNNQHNNQHNNQHNNQHNNQHNNQP///72rpZp/dqGHfqGHfqGHfqmSiqGH
++fqmSiqGHfqGHfqGHfpp/dv38/OLb2NDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvv38
++/PPw7trPzGU7LndSRoFfVVUnGMa3sufh3+Lb2NrPzOfh3+Lb2Pv6+u/r6vXz8vn39/Xz8u/r6vPw
++7vn39/Xz8v39/b2rpV0xI45wZ3dSRotrYdrPzGU7Lv38/P38/PXz8v///+/r6m9IPv///4FfVWU7
++Luvm5Pv6+vn39/////////z7+/f19P////r5+fn39/38/Pf19P////////////Pw7l0xI4ZlW5R2
++baGHfr2rpca3sv////r5+fn39/////f19Pr5+fr5+fn39/////7+/v////////////////7+/v//
++//Xz8vz7+/////////f19Pz7+/39/fXz8v38/P///////////5R2bWU7LpR2bV0xI6GHfv//////
++//Xz8v7+/f7+/v7+/v/////+/v7+/v/+//Xz8vv6+v///3xZTb2rpf////f19Pn39/////////z7
+++/Xz8v/+//////39/ff19P////f19Pr5+f/////+//Xz8vv6+v////////38/Pf19P///9rPzHdS
++Rv///////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////9t
++RTlBDQBBDQBEEgFEEgFEEgFEEgFEEgFBDQBEEgFEEgFMHA3///+af3ZtRTlzTUBzTUBzTUBzTUBz
++TUBzTUBzTUBzTUBzTUBzTUD///+9q6Whh36hh36hh36hh36hh36hh36hh36hh36hh36pkoqhh379
++/Pzi29jQw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw779/Pzv6+ri29jaz8ypkoqpkorQ
++w77n4d/i29ji29jn4d/i29ji29j8+/v7+vr18/L18/L39fT39fT18/L18/L18/L59/fn4d/Gt7K9
++q6XQw7739fT39fTaz8z+/v7////////////////v6+r////v6+rGt7Lz8O7/////////////////
++///////////////////////////////////////9/PzQw77Gt7LGt7LQw77az8zi29j/////////
++////////////////////////////////////////////////////////////////////////////
++///////////////////////////n4d/Qw77Gt7Laz8z9/Pz/////////////////////////////
++///////////////////////i29jr5uT/////////////////////////////////////////////
++///////////////////////////////////////////////////r5uT///////////////////8A
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////b0g+PAcARBIBQQ0ARBIBRBIB
++RBIBRBIBQQ0ARBIBQQ0ATBwN////mn92bUU5c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01A
++////vaulmn92oYd+qZKKoYd+oYd+oYd+oYd+oYd+oYd+oYd+oYd+/fz84tvY0MO+0MO+0MO+0MO+
++0MO+0MO+0MO+0MO+0MO+0MO+0MO+/fz87+vq4tvY5+Hf6+bk6+bk5+Hf4tvY4tvY4tvY4tvY4tvY
++4tvY/Pv7+vn59fPy9fPy9fPy9fPy9fPy9fPy9fPy9fPy+ff3/Pv7/fz8/v7+////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAP///////////3NNQEENAEQSAUwcDUQSAUQSAUQSAUQSAUwcDUQSAUwcDUwc
++Df///5p/dm1FOXdSRndSRndSRndSRndSRndSRndSRndSRnNNQHdSRv///72rpaGHfqmSiqGHfqGH
++fqmSiqmSiqGHfqmSiqGHfqmSiqGHfv38/OLb2NDDvtrPzNDDvtDDvtDDvtDDvtDDvtDDvtDDvtDD
++vtDDvv38/O/r6uLb2Ofh3+Lb2OLb2OLb2Ofh3+Lb2OLb2OLb2OLb2OLb2Pz7+/r5+fXz8vXz8vXz
++8vXz8vXz8vXz8vXz8vXz8vXz8vXz8vXz8v39/f//////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////v7//v7//v7//v7//v7//v7//v7//v7//v7//v7//v7//v7/////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////taGblHZtmn92mn92
++mn92lHZtmn92mn92lHZtmn92mn92mn92////0MO+taGbtaGbvaultaGbvaulvaulvaulvaulvaul
++taGbvaul////5+Hf2s/M2s/M2s/M2s/M2s/M2s/M2s/M4tvY2s/M4tvY2s/M/fz8////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAP///////////45wZ2U7Lm1FOW1FOW1FOW1FOW1FOW1FOW1FOW1F
++OW1FOXNNQP///7Whm5p/dqGHfqGHfpp/dqGHfqGHfpp/dqGHfpp/dqGHfqGHfv///9rPzNDDvtDD
++vtDDvtDDvtDDvtDDvtDDvsa3stDDvtDDvtDDvvz7+///////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAD///////////+OcGdzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUD///+9q6Waf3ah
++h36hh36hh36hh36hh36pkoqhh36pkoqhh36hh37////i29jQw77Qw77Qw77Qw77Qw77Qw77Qw77Q
++w77Qw77Qw77Qw778+/v////////////////9/Pz39fT39fT39fT7+vr/////////////////////
++///////////6+fn39fT39fT39fT9/f3////////////////////6+fnv6+rz8O7v6+rv6+r59/f/
++///////////6+fn39fT59/fz8O79/Pz////+/v759/f39fT39fT59/f/////////////////////
++///7+vr39fT39fT39fT+/v7////////////////////////////7+vrv6+rz8O7v6+rz8O739fT/
++///////////////////////////////////////////////////////////4+v/r8v/r8v/r8v/r
++8v/r8v/1+f/////////////////////////////////////////////////////+/v/y9v/r8v/r
++8v/r8v/y9v/8/f/////////////////////////////8/f/y9v/1+f/1+f/8/f//////////////
++///////////////////////////////1+f/r8v/r8v/r8v/r8v/1+f//////////////////////
++//////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////lHZtbUU5
++c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ad1JG////vauloYd+oYd+oYd+oYd+oYd+oYd+oYd+
++oYd+oYd+oYd+oYd+////4tvY0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+/Pv7////
++////////////2s/MVScYVScYVScYoYd+////////////////////////////////qZKKTBwNVScY
++XTEj5+Hf////////////+ff3oYd+ZTsuTBwNPAcAPAcAQQ0AXTEji2th0MO+/fz8d1JGVScYVScY
++bUU58/Du////9fPyd1JGTBwNVScYi2th////////////////////////qZKKVScYXTEjVScY6+bk
++////////////////////6+bkoYd+ZTsuTBwNPAcAPAcAPAcAVScYjnBnxrey////////////////
++/////////////////////////P3/wtj/Toz/LHb/AFX/AFX/AFX/AFX/AFX/E2X/ZJr/q8n/+vz/
++////////////////////////////////9fn/q8n/Toz/E2X/AFX/AFX/AFX/E2X/PoL/lLr/6/L/
++////////////////////wtj/E2X/LHb/AFX/0+L/////////////////////////////////////
++q8n/ZJr/LHb/E2X/AFX/AFX/AFX/LHb/Toz/wtj/////////////////////////////AAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////45wZ29IPnNNQHNNQHNNQHNNQHNNQHNN
++QHNNQHNNQHNNQHNNQP///72rpZp/dqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfv///+Lb
++2NDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvvz7+////////////////9DDvjwHAEEN
++ADwHAJp/dv///////////////////////////////5p/djwHADwHAEQSAeLb2P////////Xz8m1F
++OTwHAEENAEENADwHADwHADwHADwHADwHAEwcDWU7LkwcDTwHADwHAKmSiv////////Pw7l0xIzwH
++ADwHAHdSRv///////////////////////6mSijwHAEENADwHAO/r6v///////////////8a3skwc
++DTwHADwHADwHADwHADwHADwHAEENADwHAEENAIZlW/n39////////////////////////////8LY
++/z6C/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/xNl/wBV/wBV/z6C/9Pi////////////////////
++/////+vy/z6C/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/yx2/8LY/////////////////6vJ
++/wBV/wBV/wBV/8LY//////////////////////////////X5/3am/wBV/wBV/wBV/wBV/wBV/wBV
++/wBV/wBV/wBV/wBV/3am/////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAD///////////+Udm1tRTlzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUB3Ukb///+9
++q6Whh36hh36hh36hh36hh36hh36hh36hh36hh36hh36hh37////i29jGt7LQw77Qw77Qw77Qw77Q
++w77Qw77Qw77Qw77Qw77Gt7L8+/v////////////////az8xBDQBEEgE8BwCaf3b/////////////
++//////////////////+af3ZBDQBBDQBMHA3i29j///////+pkoo8BwBEEgFBDQBVJxiOcGepkoqh
++h36GZVtEEgE8BwBBDQBEEgFEEgFEEgHaz8z////////z8O5lOy48BwA8BwB8WU3/////////////
++//////////+pkoo8BwBEEgE8BwDr5uT////////////Qw75MHA1BDQBBDQA8BwBlOy6OcGeaf3Z3
++UkZEEgE8BwBEEgE8BwB8WU38+/v///////////////////+ryf8TZf8AVf8TZf8AVf8AVf8TZf8+
++gv8+gv8+gv8TZf8AVf8AVf8AVf8AVf8TZf/C2P/////////////////y9v8sdv8AVf8AVf8AVf8T
++Zf9OjP92pv9kmv8sdv8AVf8AVf8AVf8TZf/C2P////////////+ryf8AVf8TZf8AVf/C2P//////
++//////////////////////92pv8AVf8AVf8AVf8AVf8+gv92pv9kmv8+gv8AVf8AVf8AVf8AVf92
++pv////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////
++lHZtb0g+c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01A////vaulmn92oYd+oYd+oYd+oYd+
++oYd+oYd+oYd+oYd+oYd+oYd+////2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+
++/Pv7////////////////2s/MPAcARBIBPAcAmn92////////////////////////////////oYd+
++PAcAQQ0ATBwN4tvY////+/r6b0g+PAcAQQ0ATBwNxrey////////////////4tvYc01APAcARBIB
++QQ0AVScY6+bk////////8/DuZTsuPAcAPAcAd1JG////////////////////////oYd+PAcARBIB
++PAcA7+vq/////////fz8XTEjPAcARBIBQQ0AoYd++ff3/////////v7+2s/MZTsuPAcARBIBPAcA
++taGb////////////////0+L/E2X/AFX/E2X/AFX/E2X/q8n/6/L/9fn/+Pr/+Pr/4uz/q8n/E2X/
++AFX/E2X/AFX/E2X/4uz/////////////dqb/AFX/E2X/AFX/PoL/4uz/////////////8vb/dqb/
++AFX/AFX/AFX/PoL//f7/////////lLr/AFX/AFX/AFX/wtj/////////////////////////q8n/
++AFX/AFX/AFX/E2X/q8n/////////////////q8n/E2X/AFX/AFX/AFX/wtj/////////////////
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////5R2bW9IPnNNQHNNQHNNQHNN
++QHNNQHNNQHNNQHNNQHNNQHdSRv///7Whm6GHfqGHfqGHfqmSiqGHfqGHfqGHfqGHfqGHfqGHfqGH
++fv///9rPzNDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvvz7+////////////////9DD
++vkENAEQSATwHAJp/dv///////////////////////////////5p/dkENAEENAEwcDeLb2P////n3
++921FOTwHAEENAF0xI/Xz8v///////////////////+/r6kwcDUQSAUENAFUnGO/r6v////////Pw
++7mU7LkENADwHAHxZTf///////////////////////6mSijwHAEQSATwHAO/r6v///////72rpTwH
++AEQSATwHAI5wZ////////////////////////9rPzEwcDUQSAUENAGU7Lv7+/v///////////z6C
++/wBV/wBV/wBV/06M//X5/////////////////////////////+Ls/yx2/wBV/wBV/wBV/06M////
++//////r8/yx2/wBV/wBV/xNl/+vy/////////////////////////z6C/wBV/wBV/wBV/8LY////
++/////6vJ/wBV/xNl/wBV/8LY/////////////////////////06M/wBV/wBV/wBV/5S6////////
++/////////////////5S6/wBV/wBV/wBV/2Sa/////////////////wAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAD///////////+Udm1tRTlzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBzTUBz
++TUD///+9q6Waf3apkoqhh36hh36hh36hh36hh36hh36pkoqhh36pkor////i29jGt7LQw77Qw77Q
++w77Qw77Qw77Qw77Qw77Qw77Qw77Qw778+/v////////////////az8xBDQBBDQA8BwCaf3b/////
++//////////////////////////+hh348BwBBDQBMHA3i29j///////+BX1U8BwBEEgFBDQCGZVvi
++29jr5uT8+/v///////////+La2E8BwBBDQBVJxjv6+r////////z8O5lOy5BDQA8BwB8WU3/////
++//////////////////+hh348BwBBDQA8BwDr5uT///////+OcGc8BwBEEgFEEgHaz8z/////////
++//////////////////98WU1BDQBBDQBEEgHv6+r////////C2P8AVf8AVf8AVf8TZf/y9v//////
++///////////////////////////////T4v8TZf8AVf8TZf8TZf/T4v/////C2P8AVf8AVf8AVf+U
++uv/////////////////////////////C2P8AVf8TZf8AVf92pv////////+ryf8AVf8AVf8AVf/C
++2P/////////////////////y9v8sdv8AVf8AVf8+gv/////////////////////////////+/v+r
++yf/T4v/r8v/6/P/+/v////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
++////////lHZtbUU5c01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ac01Ad1JG////taGboYd+oYd+qZKK
++oYd+oYd+oYd+oYd+qZKKoYd+oYd+oYd+////2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+
++0MO+0MO+/Pv7////////////////0MO+QQ0ARBIBPAcAmn92////////////////////////////
++////mn92QQ0AQQ0ATBwN4tvY////////2s/MTBwNPAcARBIBQQ0APAcAXTEjc01AgV9Vmn92xrey
++hmVbPAcAQQ0ATBwN7+vq////////8/DuZTsuQQ0APAcAfFlN////////////////////////oYd+
++PAcARBIBPAcA7+vq////////d1JGPAcAPAcAXTEj7+vq////////////////////////////qZKK
++PAcARBIBQQ0A2s/M////////Toz/AFX/AFX/AFX/lLr/////////////////////////////////
++////////////ZJr/AFX/AFX/AFX/lLr/////lLr/AFX/E2X/AFX/q8n/////////////////////
++////////4uz/E2X/AFX/AFX/ZJr/////////q8n/AFX/E2X/AFX/wtj/////////////////////
++0+L/E2X/AFX/AFX/E2X/dqb/ZJr/dqb/ZJr/dqb/ZJr/ZJr/ZJr/dqb/dqb/ZJr/q8n/////////
++////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////5R2bXNNQHNNQHNN
++QHNNQHNNQHNNQHNNQHNNQHNNQHNNQHdSRv///72rpZp/dqmSiqGHfqGHfqGHfqGHfqGHfqGHfqGH
++fqGHfqGHfv///9rPzMa3stDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvvz7+///////////
++/////9DDvkENAEQSATwHAJp/dv///////////////////////////////6GHfjwHAEENAEwcDeLb
++2P///////////9rPzGU7LjwHADwHADwHADwHADwHADwHADwHAEENAEQSAUQSAUENAFUnGO/r6v//
++//////Pw7mU7LjwHADwHAHxZTf///////////////////////6mSijwHAEQSATwHAOvm5P////38
++/HNNQDwHAEENAF0xI+/r6v///////////////////////////72rpTwHAEQSAUQSAdrPzP////r8
++/yx2/wBV/wBV/wBV/+Ls/////////////////////////////////////////////8LY/2Sa/6vJ
++/+Ls//r8/////5S6/wBV/wBV/xNl/8LY/////////////////////////////+vy/xNl/wBV/wBV
++/2Sa/////////6vJ/wBV/wBV/wBV/8LY/////////////////////+Ls/wBV/wBV/wBV/wBV/wBV
++/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/z6C//7//////////////wAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+Udm1tRTlzTUBzTUBzTUBzTUBzTUBzTUBzTUBz
++TUBzTUB3Ukb///+9q6Whh36hh36hh36hh36hh36hh36hh36hh36hh36hh36hh37////i29jQw77Q
++w77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw778+/v////////////////Qw75BDQBEEgE8BwCa
++f3b///////////////////////////////+hh348BwBBDQBMHA3i29j////////////////59/fQ
++w76Udm13UkZdMSNMHA1BDQBBDQBBDQBBDQBEEgFBDQBVJxjv6+r////////z8O5lOy5BDQA8BwB3
++Ukb///////////////////////+hh35BDQBBDQA8BwDv6+r///////93UkY8BwA8BwBdMSPv6+r/
++//////////////////////////+pkoo8BwBBDQBBDQDaz8z////i7P8TZf8AVf8AVf8sdv/y9v//
++//////////////////////////////////////////////////////////////////+Uuv8AVf8A
++Vf8AVf+ryf/////////////////////////////i7P8AVf8AVf8AVf9kmv////////+ryf8AVf8A
++Vf8AVf/C2P/////////////////////i7P8TZf8AVf8AVf8AVf8AVf8AVf8AVf8TZf8AVf8AVf8A
++Vf8AVf8AVf8TZf8AVf9kmv////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAA////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////v7+/f39/f39/f39/f39/f39/f39/f39
++/f39/f39/f39/f39////////////////////2s/MQQ0AQQ0APAcAmn92////////////////////
++////////////oYd+PAcAQQ0ATBwN4tvY////////8/Du4tvY2s/M2s/M+ff3/////fz8+vn57+vq
++0MO+taGbZTsuQQ0AQQ0ATBwN7+vq////////8/DuXTEjPAcAQQ0AZTsu+ff3////////////////
++////qZKKPAcARBIBPAcA6+bk////////jnBnPAcARBIBQQ0A2s/M////////////////////////
++////fFlNQQ0ARBIBRBIB7+vq////0+L/AFX/E2X/AFX/Toz/////////////////////////////
++////////////////////////////////////////////wtj/AFX/AFX/AFX/dqb/////////////
++////////////////q8n/AFX/AFX/AFX/dqb/////////q8n/AFX/AFX/AFX/lLr/////////////
++////////8vb/LHb/AFX/AFX/LHb/wtj/wtj/0+L/wtj/0+L/0+L/0+L/lLr/AFX/AFX/AFX/dqb/
++////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////8a3sr2r
++pb2rpb2rpb2rpb2rpb2rpb2rpb2rpb2rpb2rpb2rpf///+fh39rPzOLb2NrPzOLb2OLb2NrPzOLb
++2NrPzNrPzOLb2NrPzP7+/f//////////////////////////////////////////////////////
++/////////////9DDvkENAEQSATwHAJp/dv///////////////////////////////5p/dkENAEEN
++AEwcDeLb2P///////7Whm0wcDUQSATwHAMa3sv///////////////////////5R2bTwHAEQSAVUn
++GOvm5P////////Pw7mU7LkENAEENAEQSAdDDvv///////////////////45wZzwHAEQSATwHAO/r
++6v///////8a3sjwHAEQSATwHAIFfVf///////////////////////9DDvkwcDUQSATwHAHNNQP//
++/////8LY/wBV/wBV/wBV/06M////////////////////////////////////////////////////
++//////////////////////7//xNl/wBV/wBV/xNl/+Ls//////////////////////j6/z6C/wBV
++/wBV/wBV/9Pi/////////6vJ/wBV/xNl/wBV/yx2//7+/////////////////////2Sa/wBV/xNl
++/wBV/5S6/////////////////////////2Sa/wBV/wBV/wBV/8LY/////////////////wAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+pkoqaf3aaf3ahh36af3aaf3aaf3ah
++h36hh36af3aaf3ahh37////i29jGt7LQw77Qw77Gt7LQw77Gt7LQw77Qw77Qw77Gt7LQw779/f3/
++///////////////////////////////////////////////////////////////////Qw75BDQBE
++EgE8BwCaf3b///////////////////////////////+af3ZBDQBBDQBMHA3i29j////////i29hM
++HA08BwBBDQBVJxjaz8z9/f3////////9/PzGt7JMHA1EEgFBDQBdMSP8+/v////////z8O5lOy48
++BwBEEgFBDQBdMSPGt7L18/L////8+/u9q6VMHA1BDQBBDQBVJxjv6+r////////+/v1lOy5BDQBE
++EgFBDQCOcGfr5uT////////6+fm9q6VMHA1BDQBBDQA8BwDGt7L////////T4v8sdv8AVf8AVf8+
++gv/1+f//////////////////////////////////////////////////////////////////////
++//+Uuv8AVf8AVf8AVf8sdv/C2P/+/v/////////T4v8+gv8AVf8AVf8AVf9OjP////////////+U
++uv8AVf8AVf8AVf8AVf9OjP/C2P/C2P9kmv+ryf/////T4v8TZf8AVf8AVf8TZf+Uuv/4+v//////
++///i7P92pv8AVf8AVf8AVf8+gv////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAA////////////vaulmn92oYd+oYd+oYd+oYd+oYd+oYd+oYd+qZKKoYd+qZKK////
++2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+/f39////////////////////////
++////////////////////////////////////////////2s/MQQ0ARBIBPAcAmn92////////////
++////////////////////oYd+PAcAQQ0ATBwN4tvY////////////mn92PAcAQQ0AQQ0ARBIBbUU5
++c01Ac01AZTsuTBwNQQ0ARBIBPAcAjnBn////////////8/DuZTsuQQ0AQQ0AQQ0APAcATBwNXTEj
++bUU5ZTsuRBIBQQ0AQQ0APAcAjnBn////////////////0MO+TBwNPAcARBIBPAcAVScYbUU5c01A
++ZTsuQQ0ARBIBQQ0APAcAmn92////////////6/L/E2X/AFX/AFX/E2X/4uz/////////////////
++////////////////////////////////////////////////////////+Pr/Toz/AFX/AFX/AFX/
++AFX/LHb/Toz/PoL/E2X/AFX/AFX/AFX/E2X/4uz/////////////q8n/AFX/AFX/AFX/AFX/AFX/
++AFX/AFX/AFX/PoL/+vz/////lLr/AFX/AFX/AFX/AFX/LHb/PoL/PoL/LHb/AFX/AFX/AFX/E2X/
++4uz/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////
++/7Whm6GHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfv///9rPzNDDvtDDvtDDvtDDvtDD
++vtDDvtDDvtDDvtDDvtDDvtDDvv39/f//////////////////////////////////////////////
++/////////////////////9DDvkENAEENAEENAJp/dv///////////////////////////////5p/
++djwHADwHAEQSAeLb2P////////////n395R2bUENADwHAEENADwHADwHADwHADwHAEENAEENADwH
++AG1FOfXz8v////////////Pw7mU7LjwHAEENAF0xI0wcDTwHADwHADwHADwHAEENAEENADwHAG9I
++Pu/r6v///////////////////9DDvmU7LjwHADwHAEENADwHADwHADwHAEENADwHAEQSAaGHfv//
++/////////////////06M/wBV/wBV/wBV/6vJ////////////////////////////////////////
++/////5S6/3am/6vJ/9Pi//j6//////////////X5/2Sa/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV
++/wBV/z6C/+Ls/////////////////6vJ/wBV/wBV/xNl/xNl/wBV/wBV/wBV/wBV/wBV/8LY////
++/////6vJ/xNl/wBV/wBV/wBV/wBV/wBV/wBV/wBV/wBV/yx2/8LY////////////////////////
++/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+9q6Waf3apkoqhh36hh36h
++h36hh36hh36hh36hh36hh36hh37////i29jQw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Q
++w779/f3////////////////////////////////////////////////////////////////////a
++z8w8BwBEEgE8BwCaf3b///////////////////////////////+1oZtzTUBzTUB8WU3r5uT/////
++///////////////az8yUdm1lOy5MHA1VJxhMHA1MHA1VJxhtRTm1oZvz8O7////////////////3
++9fSLa2FzTUBzTUC1oZvaz8yBX1VVJxhMHA1MHA1VJxhtRTm1oZv18/L/////////////////////
++///////39fS1oZt3UkZMHA1MHA1MHA1MHA1dMSOUdm3i29j///////////////////////+ryf8A
++Vf8TZf8AVf8sdv/9/v/////////////////////////////////////i7P8TZf8AVf8AVf8sdv/i
++7P/////////////////9/v/C2P9kmv8sdv8TZf8TZf8TZf8TZf8+gv/C2P/4+v//////////////
++//////+ryf9OjP8+gv9kmv/T4v8+gv8AVf8TZf8TZf9kmv/i7P/////////////i7P+Uuv8sdv8T
++Zf8TZf8TZf8TZf8+gv+ryf/y9v////////////////////////////8AAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAA////////////taGboYd+oYd+oYd+oYd+oYd+oYd+oYd+oYd+oYd+oYd+
++qZKK////2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+/f39////////////////
++////////////////////////////////////////////////////2s/MQQ0AQQ0APAcAmn92////
++////////////////////////////////////////////////////////////////////////////
++////8/Du5+Hf6+bk6+bk+ff3////////////////////////////////////////////////////
++/////f396+bk5+Hf8/Du/////////////////////////////////////////////////////f39
++6+bk6+bk8/Du////////////////////////////////////+vz/LHb/AFX/E2X/AFX/ZJr/////
++////////////////////////////+Pr/Toz/AFX/AFX/AFX/PoL/////////////////////////
++/////////v7/4uz/4uz/4uz/+vz/////////////////////////////////////////////////
++////////6/L/4uz/+vz/////////////////////////////////6/L/4uz/4uz/8vb/////////
++////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
++/////////72rpZp/dqGHfqGHfqGHfqmSiqGHfqGHfqGHfqGHfqGHfqGHfv///+Lb2NDDvtDDvtDD
++vtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvv39/f//////////////////////////////////////
++//Xz8u/r6vPw7u/r6vPw7u/r6vXz8sa3skENAEQSATwHAJR2bfXz8u/r6u/r6u/r6vPw7u/r6u/r
++6v///9DDvqGHfqGHfqmSiu/r6v//////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////8LY/xNl/wBV/wBV/wBV/z6C/9Pi//L2//3+//////////j6
++/9Pi/06M/wBV/wBV/wBV/wBV/9Pi////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+1oZuhh36hh36h
++h36hh36hh36hh36hh36hh36hh36hh36pkor////az8zQw77Qw77Qw77Qw77Qw77Qw77Qw77Qw77Q
++w77Qw77Qw779/f3///////////////////////////////////////+hh35MHA1MHA1VJxhVJxhM
++HA1VJxhMHA1EEgFEEgFEEgFMHA1VJxhVJxhVJxhVJxhVJxhVJxhVJxj///+af3Y8BwA8BwBBDQDi
++29j/////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////+ryf8TZf8AVf8TZf8AVf8AVf8sdv9OjP9kmv9kmv8+gv8AVf8AVf8AVf8AVf8AVf+r
++yf//////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////8AAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////vaulmn92oYd+qZKKoYd+oYd+oYd+oYd+oYd+
++oYd+oYd+qZKK////2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+/f39////////
++////////////////////////////////lHZtPAcAQQ0APAcAPAcAPAcAPAcAPAcAQQ0AQQ0AQQ0A
++PAcAPAcAPAcAPAcAPAcAPAcAPAcAPAcA////mn92PAcAPAcATBwN4tvY////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////wtj/PoL/
++AFX/AFX/AFX/AFX/AFX/AFX/AFX/AFX/AFX/AFX/AFX/E2X/q8n/////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAP///////////7Whm6GHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfqGHfv///+Lb2NDD
++vtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvtDDvv39/f//////////////////////////////
++/////////6GHflUnGFUnGF0xI10xI1UnGF0xI1UnGFUnGFUnGFUnGF0xI1UnGF0xI1UnGFUnGF0x
++I1UnGFUnGP///6mSilUnGF0xI10xI+fh3///////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////z9/8LY/2Sa/yx2/wBV/wBV/wBV
++/wBV/wBV/wBV/yx2/3am/+vy////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////+1oZua
++f3ahh36hh36pkoqhh36hh36hh36hh36hh36hh36hh37////az8zGt7LQw77Qw77Qw77Qw77Qw77Q
++w77Qw77Qw77Qw77Qw779/f3////////////////////////////////////////6+fn39fT39fT3
++9fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT39fT////7+vr39fT3
++9fT39fT9/f3/////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++///////////////////////////////////////1+f/i7P/C2P+ryf/C2P/C2P/i7P/6/P//////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////8AAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////taGboYd+oYd+oYd+oYd+oYd+oYd+
++oYd+oYd+oYd+oYd+oYd+////2s/M0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+0MO+/f39
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAP////////////39/f38/P38/P38/P38/P38/P38/P38/P38/P38/P38/P38/P//
++//39/f38/P38/P38/P38/P38/P38/P38/P38/P38/P38/P38/P//////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////
++///z8O7r5uTr5uTr5uTr5uTv6+rr5uTv6+rr5uTv6+rr5uTr5uT/////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////5+Hf4tvY4tvY4tvY4tvY
++4tvY4tvY4tvY4tvY4tvY4tvY4tvY////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAP///////////+fh3+Lb2OLb2OLb2OLb2Ofh3+Lb2OLb2OLb2OLb2OLb
++2OLb2P//////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
++///////////r5uTi29ji29ji29ji29ji29ji29jn4d/i29ji29ji29jn4d//////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////5+Hf4tvY4tvY
++4tvY4tvY4tvY5+Hf4tvY5+Hf4tvY4tvY4tvY////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////AAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////+vm5OLb2OLb2OLb2OLb2OLb2OLb2Ofh3+Lb
++2Ofh3+Lb2OLb2P//////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAD////////////n4d/i29ji29ji29ji29ji29ji29ji29ji29ji29ji29ji29j/////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////6+bk
++4tvY4tvY4tvY4tvY4tvY4tvY4tvY4tvY5+Hf4tvY4tvY////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////AAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////+fh3+Lb2OLb2OLb2OLb2Ofh3+Lb
++2Ofh3+Lb2OLb2OLb2OLb2P//////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAD////////////r5uTi29ji29jn4d/i29ji29jn4d/i29ji29ji29ji29ji29j/
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
++////5+Hf4tvY4tvY4tvY5+Hf4tvY4tvY4tvY4tvY4tvY4tvY5+Hf////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////+vm5OLb2OLb2OLb2OLb
++2OLb2OLb2OLb2OLb2OLb2OLb2OLb2P//////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////wAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAD////////////9/f39/Pz9/Pz9/Pz9/Pz9/Pz9/Pz9/Pz9/Pz9/Pz9
++/Pz9/Pz/////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////wAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+diff --git a/MdeModulePkg/Logo/Logo-OpenSSL.idf b/MdeModulePkg/Logo/Logo-OpenSSL.idf
+new file mode 100644
+index 0000000000..e527cff79b
+--- /dev/null
++++ b/MdeModulePkg/Logo/Logo-OpenSSL.idf
+@@ -0,0 +1,15 @@
++// /** @file
++// Platform Logo image definition file.
++//
++// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
++//
++// This program and the accompanying materials
++// are licensed and made available under the terms and conditions of the BSD License
++// which accompanies this distribution. The full text of the license may be found at
++// http://opensource.org/licenses/bsd-license.php
++// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
++//
++// **/
++
++#image IMG_LOGO Logo-OpenSSL.bmp
+diff --git a/MdeModulePkg/Logo/LogoOpenSSLDxe.inf b/MdeModulePkg/Logo/LogoOpenSSLDxe.inf
+new file mode 100644
+index 0000000000..2f79d873e2
+--- /dev/null
++++ b/MdeModulePkg/Logo/LogoOpenSSLDxe.inf
+@@ -0,0 +1,61 @@
++## @file
++# The default logo bitmap picture shown on setup screen.
++#
++# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
++#
++# This program and the accompanying materials
++# are licensed and made available under the terms and conditions of the BSD License
++# which accompanies this distribution. The full text of the license may be found at
++# http://opensource.org/licenses/bsd-license.php
++# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
++#
++#
++##
++
++[Defines]
++ INF_VERSION = 0x00010005
++ BASE_NAME = LogoOpenSSLDxe
++ MODULE_UNI_FILE = LogoOpenSSLDxe.uni
++ FILE_GUID = 9CAE7B89-D48D-4D68-BBC4-4C0F1D48CDFF
++ MODULE_TYPE = DXE_DRIVER
++ VERSION_STRING = 1.0
++
++ ENTRY_POINT = InitializeLogo
++#
++# This flag specifies whether HII resource section is generated into PE image.
++#
++ UEFI_HII_RESOURCE_SECTION = TRUE
++
++#
++# The following information is for reference only and not required by the build tools.
++#
++# VALID_ARCHITECTURES = IA32 X64
++#
++
++[Sources]
++ Logo-OpenSSL.bmp
++ Logo.c
++ Logo-OpenSSL.idf
++
++[Packages]
++ MdeModulePkg/MdeModulePkg.dec
++ MdePkg/MdePkg.dec
++
++[LibraryClasses]
++ UefiBootServicesTableLib
++ UefiDriverEntryPoint
++ DebugLib
++
++[Protocols]
++ gEfiHiiDatabaseProtocolGuid ## CONSUMES
++ gEfiHiiImageExProtocolGuid ## CONSUMES
++ gEfiHiiPackageListProtocolGuid ## PRODUCES CONSUMES
++ gEdkiiPlatformLogoProtocolGuid ## PRODUCES
++
++[Depex]
++ gEfiHiiDatabaseProtocolGuid AND
++ gEfiHiiImageExProtocolGuid
++
++[UserExtensions.TianoCore."ExtraFiles"]
++ LogoDxeExtra.uni
+diff --git a/MdeModulePkg/Logo/LogoOpenSSLDxe.uni b/MdeModulePkg/Logo/LogoOpenSSLDxe.uni
+new file mode 100644
+index 0000000000..7227ac3910
+--- /dev/null
++++ b/MdeModulePkg/Logo/LogoOpenSSLDxe.uni
+@@ -0,0 +1,22 @@
++// /** @file
++// The logo bitmap picture (with OpenSSL advertisment) shown on setup screen.
++//
++// This module provides the logo bitmap picture (with OpenSSL advertisment)
++// shown on setup screen, through EDKII Platform Logo protocol.
++//
++// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
++//
++// This program and the accompanying materials
++// are licensed and made available under the terms and conditions of the BSD License
++// which accompanies this distribution. The full text of the license may be found at
++// http://opensource.org/licenses/bsd-license.php
++// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
++//
++// **/
++
++
++#string STR_MODULE_ABSTRACT #language en-US "Provides the logo bitmap picture (with OpenSSL advertisment) shown on setup screen."
++
++#string STR_MODULE_DESCRIPTION #language en-US "This module provides the logo bitmap picture (with OpenSSL advertisment) shown on setup screen, through EDKII Platform Logo protocol."
++
+diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
+index cd0e71869b..0a49336c0d 100644
+--- a/OvmfPkg/OvmfPkgIa32.dsc
++++ b/OvmfPkg/OvmfPkgIa32.dsc
+@@ -694,7 +694,11 @@
+ NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf
+ !endif
+ }
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++ MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ MdeModulePkg/Logo/LogoDxe.inf
++!endif
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
+index 52b8b1fea1..4177379a23 100644
+--- a/OvmfPkg/OvmfPkgIa32.fdf
++++ b/OvmfPkg/OvmfPkgIa32.fdf
+@@ -295,7 +295,11 @@ INF ShellPkg/Application/Shell/Shell.inf
+ INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
+
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ INF MdeModulePkg/Logo/LogoDxe.inf
++!endif
+
+ #
+ # Network modules
+diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
+index 7f7a78f60a..a3d51ef0f7 100644
+--- a/OvmfPkg/OvmfPkgIa32X64.dsc
++++ b/OvmfPkg/OvmfPkgIa32X64.dsc
+@@ -703,7 +703,11 @@
+ NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf
+ !endif
+ }
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++ MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ MdeModulePkg/Logo/LogoDxe.inf
++!endif
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
+index 70845d6972..5e57161154 100644
+--- a/OvmfPkg/OvmfPkgIa32X64.fdf
++++ b/OvmfPkg/OvmfPkgIa32X64.fdf
+@@ -296,7 +296,11 @@ INF ShellPkg/Application/Shell/Shell.inf
+ INF RuleOverride = BINARY USE = X64 EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
+
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ INF MdeModulePkg/Logo/LogoDxe.inf
++!endif
+
+ #
+ # Network modules
+diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
+index 739807efc4..f9b4ab4dfa 100644
+--- a/OvmfPkg/OvmfPkgX64.dsc
++++ b/OvmfPkg/OvmfPkgX64.dsc
+@@ -701,7 +701,11 @@
+ NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf
+ !endif
+ }
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++ MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ MdeModulePkg/Logo/LogoDxe.inf
++!endif
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
+index 1eb46ac9a2..c81b422517 100644
+--- a/OvmfPkg/OvmfPkgX64.fdf
++++ b/OvmfPkg/OvmfPkgX64.fdf
+@@ -296,7 +296,11 @@ INF ShellPkg/Application/Shell/Shell.inf
+ INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
+
++!if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
++INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
++!else
+ INF MdeModulePkg/Logo/LogoDxe.inf
++!endif
+
+ #
+ # Network modules
diff --git a/0006-EXCLUDE_SHELL_FROM_FD.patch b/0006-EXCLUDE_SHELL_FROM_FD.patch
deleted file mode 100644
index 3a67839..0000000
--- a/0006-EXCLUDE_SHELL_FROM_FD.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From: Gerd Hoffmann <kraxel(a)redhat.com>
-Date: Thu, 18 Feb 2016 10:52:44 +0100
-Subject: [PATCH] EXCLUDE_SHELL_FROM_FD
-
----
- OvmfPkg/OvmfPkgIa32.fdf | 2 ++
- OvmfPkg/OvmfPkgIa32X64.fdf | 2 ++
- OvmfPkg/OvmfPkgX64.fdf | 2 ++
- 3 files changed, 6 insertions(+)
-
-diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
-index 2a5b211..ebdab17 100644
---- a/OvmfPkg/OvmfPkgIa32.fdf
-+++ b/OvmfPkg/OvmfPkgIa32.fdf
-@@ -281,11 +281,13 @@ INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
-
- INF FatPkg/EnhancedFatDxe/Fat.inf
-
-+!ifndef $(EXCLUDE_SHELL_FROM_FD)
- !ifndef $(USE_OLD_SHELL)
- INF ShellPkg/Application/Shell/Shell.inf
- !else
- INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
- !endif
-+!endif
-
- INF MdeModulePkg/Logo/LogoDxe.inf
-
-diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
-index 1c7df21..adf53f3 100644
---- a/OvmfPkg/OvmfPkgIa32X64.fdf
-+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
-@@ -281,11 +281,13 @@ INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
-
- INF FatPkg/EnhancedFatDxe/Fat.inf
-
-+!ifndef $(EXCLUDE_SHELL_FROM_FD)
- !ifndef $(USE_OLD_SHELL)
- INF ShellPkg/Application/Shell/Shell.inf
- !else
- INF RuleOverride = BINARY USE = X64 EdkShellBinPkg/FullShell/FullShell.inf
- !endif
-+!endif
-
- INF MdeModulePkg/Logo/LogoDxe.inf
-
-diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
-index 3bb11cb..edf1098 100644
---- a/OvmfPkg/OvmfPkgX64.fdf
-+++ b/OvmfPkg/OvmfPkgX64.fdf
-@@ -281,11 +281,13 @@ INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
-
- INF FatPkg/EnhancedFatDxe/Fat.inf
-
-+!ifndef $(EXCLUDE_SHELL_FROM_FD)
- !ifndef $(USE_OLD_SHELL)
- INF ShellPkg/Application/Shell/Shell.inf
- !else
- INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
- !endif
-+!endif
-
- INF MdeModulePkg/Logo/LogoDxe.inf
-
diff --git a/0006-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch b/0006-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
new file mode 100644
index 0000000..33b54aa
--- /dev/null
+++ b/0006-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
@@ -0,0 +1,540 @@
+From e4021f592da913f7f2b841ce6d4272fb8410ac7f Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Thu, 12 Jun 2014 00:17:59 +0200
+Subject: [PATCH] OvmfPkg: QemuVideoDxe: enable debug messages in VbeShim
+
+The Int10h VBE Shim is capable of emitting short debug messages when the
+win2k8r2 UEFI guest uses (emulates) the Video BIOS. In upstream the quiet
+version is preferred; for us debug messages are important as a default.
+
+For this patch, the DEBUG macro is enabled in the assembly file, and then
+the header file is regenerated from the assembly, by running
+"OvmfPkg/QemuVideoDxe/VbeShim.sh".
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit ccda46526bb2e573d9b54f0db75d27e442b4566f)
+(cherry picked from commit ed45b26dbeadd63dd8f2edf627290957d8bbb3b2)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ OvmfPkg/QemuVideoDxe/VbeShim.asm | 2 +-
+ OvmfPkg/QemuVideoDxe/VbeShim.h | 481 ++++++++++++++++++++-----------
+ 2 files changed, 308 insertions(+), 175 deletions(-)
+
+diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.asm b/OvmfPkg/QemuVideoDxe/VbeShim.asm
+index 18fa9209d4..f87ed5cf30 100644
+--- a/OvmfPkg/QemuVideoDxe/VbeShim.asm
++++ b/OvmfPkg/QemuVideoDxe/VbeShim.asm
+@@ -18,7 +18,7 @@
+ ;------------------------------------------------------------------------------
+
+ ; enable this macro for debug messages
+-;%define DEBUG
++%define DEBUG
+
+ %macro DebugLog 1
+ %ifdef DEBUG
+diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.h b/OvmfPkg/QemuVideoDxe/VbeShim.h
+index cc9b6e14cd..325d6478a1 100644
+--- a/OvmfPkg/QemuVideoDxe/VbeShim.h
++++ b/OvmfPkg/QemuVideoDxe/VbeShim.h
+@@ -517,185 +517,318 @@ STATIC CONST UINT8 mVbeShim[] = {
+ /* 000001FE nop */ 0x90,
+ /* 000001FF nop */ 0x90,
+ /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
+- /* 00000203 jz 0x22d */ 0x74, 0x28,
++ /* 00000203 jz 0x235 */ 0x74, 0x30,
+ /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
+- /* 00000208 jz 0x245 */ 0x74, 0x3B,
++ /* 00000208 jz 0x255 */ 0x74, 0x4B,
+ /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
+- /* 0000020D jz 0x269 */ 0x74, 0x5A,
++ /* 0000020D jz 0x289 */ 0x74, 0x7A,
+ /* 0000020F cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
+- /* 00000212 jz word 0x331 */ 0x0F, 0x84, 0x1B, 0x01,
++ /* 00000212 jz word 0x361 */ 0x0F, 0x84, 0x4B, 0x01,
+ /* 00000216 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
+- /* 00000219 jz word 0x336 */ 0x0F, 0x84, 0x19, 0x01,
++ /* 00000219 jz word 0x36e */ 0x0F, 0x84, 0x51, 0x01,
+ /* 0000021D cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
+- /* 00000220 jz word 0x338 */ 0x0F, 0x84, 0x14, 0x01,
++ /* 00000220 jz word 0x378 */ 0x0F, 0x84, 0x54, 0x01,
+ /* 00000224 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
+- /* 00000227 jz word 0x33a */ 0x0F, 0x84, 0x0F, 0x01,
+- /* 0000022B jmp short 0x22b */ 0xEB, 0xFE,
+- /* 0000022D push es */ 0x06,
+- /* 0000022E push di */ 0x57,
+- /* 0000022F push ds */ 0x1E,
+- /* 00000230 push si */ 0x56,
+- /* 00000231 push cx */ 0x51,
+- /* 00000232 push cs */ 0x0E,
+- /* 00000233 pop ds */ 0x1F,
+- /* 00000234 mov si,0x0 */ 0xBE, 0x00, 0x00,
+- /* 00000237 mov cx,0x100 */ 0xB9, 0x00, 0x01,
+- /* 0000023A cld */ 0xFC,
+- /* 0000023B rep movsb */ 0xF3, 0xA4,
+- /* 0000023D pop cx */ 0x59,
+- /* 0000023E pop si */ 0x5E,
+- /* 0000023F pop ds */ 0x1F,
+- /* 00000240 pop di */ 0x5F,
+- /* 00000241 pop es */ 0x07,
+- /* 00000242 jmp word 0x34c */ 0xE9, 0x07, 0x01,
+- /* 00000245 push es */ 0x06,
+- /* 00000246 push di */ 0x57,
+- /* 00000247 push ds */ 0x1E,
+- /* 00000248 push si */ 0x56,
+- /* 00000249 push cx */ 0x51,
+- /* 0000024A and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
+- /* 0000024E cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
+- /* 00000252 jz 0x256 */ 0x74, 0x02,
+- /* 00000254 jmp short 0x22b */ 0xEB, 0xD5,
+- /* 00000256 push cs */ 0x0E,
+- /* 00000257 pop ds */ 0x1F,
+- /* 00000258 mov si,0x100 */ 0xBE, 0x00, 0x01,
+- /* 0000025B mov cx,0x100 */ 0xB9, 0x00, 0x01,
+- /* 0000025E cld */ 0xFC,
+- /* 0000025F rep movsb */ 0xF3, 0xA4,
+- /* 00000261 pop cx */ 0x59,
+- /* 00000262 pop si */ 0x5E,
+- /* 00000263 pop ds */ 0x1F,
+- /* 00000264 pop di */ 0x5F,
+- /* 00000265 pop es */ 0x07,
+- /* 00000266 jmp word 0x34c */ 0xE9, 0xE3, 0x00,
+- /* 00000269 push dx */ 0x52,
+- /* 0000026A push ax */ 0x50,
+- /* 0000026B cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
+- /* 0000026F jz 0x273 */ 0x74, 0x02,
+- /* 00000271 jmp short 0x22b */ 0xEB, 0xB8,
+- /* 00000273 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
+- /* 00000276 mov al,0x20 */ 0xB0, 0x20,
+- /* 00000278 out dx,al */ 0xEE,
+- /* 00000279 push dx */ 0x52,
+- /* 0000027A push ax */ 0x50,
+- /* 0000027B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 0000027E mov ax,0x4 */ 0xB8, 0x04, 0x00,
+- /* 00000281 out dx,ax */ 0xEF,
+- /* 00000282 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 00000285 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+- /* 00000288 out dx,ax */ 0xEF,
+- /* 00000289 pop ax */ 0x58,
+- /* 0000028A pop dx */ 0x5A,
+- /* 0000028B push dx */ 0x52,
+- /* 0000028C push ax */ 0x50,
+- /* 0000028D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 00000290 mov ax,0x5 */ 0xB8, 0x05, 0x00,
+- /* 00000293 out dx,ax */ 0xEF,
+- /* 00000294 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 00000297 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+- /* 0000029A out dx,ax */ 0xEF,
+- /* 0000029B pop ax */ 0x58,
+- /* 0000029C pop dx */ 0x5A,
+- /* 0000029D push dx */ 0x52,
+- /* 0000029E push ax */ 0x50,
+- /* 0000029F mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002A2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
+- /* 000002A5 out dx,ax */ 0xEF,
+- /* 000002A6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 000002A9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+- /* 000002AC out dx,ax */ 0xEF,
+- /* 000002AD pop ax */ 0x58,
+- /* 000002AE pop dx */ 0x5A,
+- /* 000002AF push dx */ 0x52,
+- /* 000002B0 push ax */ 0x50,
+- /* 000002B1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002B4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
+- /* 000002B7 out dx,ax */ 0xEF,
+- /* 000002B8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 000002BB mov ax,0x0 */ 0xB8, 0x00, 0x00,
+- /* 000002BE out dx,ax */ 0xEF,
+- /* 000002BF pop ax */ 0x58,
+- /* 000002C0 pop dx */ 0x5A,
+- /* 000002C1 push dx */ 0x52,
+- /* 000002C2 push ax */ 0x50,
+- /* 000002C3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002C6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
+- /* 000002C9 out dx,ax */ 0xEF,
+- /* 000002CA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 000002CD mov ax,0x20 */ 0xB8, 0x20, 0x00,
+- /* 000002D0 out dx,ax */ 0xEF,
+- /* 000002D1 pop ax */ 0x58,
+- /* 000002D2 pop dx */ 0x5A,
+- /* 000002D3 push dx */ 0x52,
+- /* 000002D4 push ax */ 0x50,
+- /* 000002D5 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002D8 mov ax,0x1 */ 0xB8, 0x01, 0x00,
+- /* 000002DB out dx,ax */ 0xEF,
+- /* 000002DC mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 000002DF mov ax,0x400 */ 0xB8, 0x00, 0x04,
+- /* 000002E2 out dx,ax */ 0xEF,
+- /* 000002E3 pop ax */ 0x58,
+- /* 000002E4 pop dx */ 0x5A,
+- /* 000002E5 push dx */ 0x52,
+- /* 000002E6 push ax */ 0x50,
+- /* 000002E7 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002EA mov ax,0x6 */ 0xB8, 0x06, 0x00,
+- /* 000002ED out dx,ax */ 0xEF,
+- /* 000002EE mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 000002F1 mov ax,0x400 */ 0xB8, 0x00, 0x04,
+- /* 000002F4 out dx,ax */ 0xEF,
+- /* 000002F5 pop ax */ 0x58,
+- /* 000002F6 pop dx */ 0x5A,
+- /* 000002F7 push dx */ 0x52,
+- /* 000002F8 push ax */ 0x50,
+- /* 000002F9 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 000002FC mov ax,0x2 */ 0xB8, 0x02, 0x00,
+- /* 000002FF out dx,ax */ 0xEF,
+- /* 00000300 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 00000303 mov ax,0x300 */ 0xB8, 0x00, 0x03,
+- /* 00000306 out dx,ax */ 0xEF,
+- /* 00000307 pop ax */ 0x58,
+- /* 00000308 pop dx */ 0x5A,
+- /* 00000309 push dx */ 0x52,
+- /* 0000030A push ax */ 0x50,
+- /* 0000030B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 0000030E mov ax,0x7 */ 0xB8, 0x07, 0x00,
+- /* 00000311 out dx,ax */ 0xEF,
+- /* 00000312 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 00000315 mov ax,0x300 */ 0xB8, 0x00, 0x03,
+- /* 00000318 out dx,ax */ 0xEF,
+- /* 00000319 pop ax */ 0x58,
+- /* 0000031A pop dx */ 0x5A,
+- /* 0000031B push dx */ 0x52,
+- /* 0000031C push ax */ 0x50,
+- /* 0000031D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+- /* 00000320 mov ax,0x4 */ 0xB8, 0x04, 0x00,
+- /* 00000323 out dx,ax */ 0xEF,
+- /* 00000324 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+- /* 00000327 mov ax,0x41 */ 0xB8, 0x41, 0x00,
+- /* 0000032A out dx,ax */ 0xEF,
+- /* 0000032B pop ax */ 0x58,
+- /* 0000032C pop dx */ 0x5A,
+- /* 0000032D pop ax */ 0x58,
+- /* 0000032E pop dx */ 0x5A,
+- /* 0000032F jmp short 0x34c */ 0xEB, 0x1B,
+- /* 00000331 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
+- /* 00000334 jmp short 0x34c */ 0xEB, 0x16,
+- /* 00000336 jmp short 0x350 */ 0xEB, 0x18,
+- /* 00000338 jmp short 0x350 */ 0xEB, 0x16,
+- /* 0000033A cmp al,0x3 */ 0x3C, 0x03,
+- /* 0000033C jz 0x345 */ 0x74, 0x07,
+- /* 0000033E cmp al,0x12 */ 0x3C, 0x12,
+- /* 00000340 jz 0x349 */ 0x74, 0x07,
+- /* 00000342 jmp word 0x22b */ 0xE9, 0xE6, 0xFE,
+- /* 00000345 mov al,0x30 */ 0xB0, 0x30,
+- /* 00000347 jmp short 0x34b */ 0xEB, 0x02,
+- /* 00000349 mov al,0x20 */ 0xB0, 0x20,
+- /* 0000034B iretw */ 0xCF,
+- /* 0000034C mov ax,0x4f */ 0xB8, 0x4F, 0x00,
+- /* 0000034F iretw */ 0xCF,
+- /* 00000350 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
+- /* 00000353 iretw */ 0xCF,
++ /* 00000227 jz word 0x382 */ 0x0F, 0x84, 0x57, 0x01,
++ /* 0000022B push si */ 0x56,
++ /* 0000022C mov si,0x3e9 */ 0xBE, 0xE9, 0x03,
++ /* 0000022F call word 0x3c4 */ 0xE8, 0x92, 0x01,
++ /* 00000232 pop si */ 0x5E,
++ /* 00000233 jmp short 0x233 */ 0xEB, 0xFE,
++ /* 00000235 push es */ 0x06,
++ /* 00000236 push di */ 0x57,
++ /* 00000237 push ds */ 0x1E,
++ /* 00000238 push si */ 0x56,
++ /* 00000239 push cx */ 0x51,
++ /* 0000023A push si */ 0x56,
++ /* 0000023B mov si,0x3fb */ 0xBE, 0xFB, 0x03,
++ /* 0000023E call word 0x3c4 */ 0xE8, 0x83, 0x01,
++ /* 00000241 pop si */ 0x5E,
++ /* 00000242 push cs */ 0x0E,
++ /* 00000243 pop ds */ 0x1F,
++ /* 00000244 mov si,0x0 */ 0xBE, 0x00, 0x00,
++ /* 00000247 mov cx,0x100 */ 0xB9, 0x00, 0x01,
++ /* 0000024A cld */ 0xFC,
++ /* 0000024B rep movsb */ 0xF3, 0xA4,
++ /* 0000024D pop cx */ 0x59,
++ /* 0000024E pop si */ 0x5E,
++ /* 0000024F pop ds */ 0x1F,
++ /* 00000250 pop di */ 0x5F,
++ /* 00000251 pop es */ 0x07,
++ /* 00000252 jmp word 0x3ac */ 0xE9, 0x57, 0x01,
++ /* 00000255 push es */ 0x06,
++ /* 00000256 push di */ 0x57,
++ /* 00000257 push ds */ 0x1E,
++ /* 00000258 push si */ 0x56,
++ /* 00000259 push cx */ 0x51,
++ /* 0000025A push si */ 0x56,
++ /* 0000025B mov si,0x404 */ 0xBE, 0x04, 0x04,
++ /* 0000025E call word 0x3c4 */ 0xE8, 0x63, 0x01,
++ /* 00000261 pop si */ 0x5E,
++ /* 00000262 and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
++ /* 00000266 cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
++ /* 0000026A jz 0x276 */ 0x74, 0x0A,
++ /* 0000026C push si */ 0x56,
++ /* 0000026D mov si,0x432 */ 0xBE, 0x32, 0x04,
++ /* 00000270 call word 0x3c4 */ 0xE8, 0x51, 0x01,
++ /* 00000273 pop si */ 0x5E,
++ /* 00000274 jmp short 0x233 */ 0xEB, 0xBD,
++ /* 00000276 push cs */ 0x0E,
++ /* 00000277 pop ds */ 0x1F,
++ /* 00000278 mov si,0x100 */ 0xBE, 0x00, 0x01,
++ /* 0000027B mov cx,0x100 */ 0xB9, 0x00, 0x01,
++ /* 0000027E cld */ 0xFC,
++ /* 0000027F rep movsb */ 0xF3, 0xA4,
++ /* 00000281 pop cx */ 0x59,
++ /* 00000282 pop si */ 0x5E,
++ /* 00000283 pop ds */ 0x1F,
++ /* 00000284 pop di */ 0x5F,
++ /* 00000285 pop es */ 0x07,
++ /* 00000286 jmp word 0x3ac */ 0xE9, 0x23, 0x01,
++ /* 00000289 push dx */ 0x52,
++ /* 0000028A push ax */ 0x50,
++ /* 0000028B push si */ 0x56,
++ /* 0000028C mov si,0x41a */ 0xBE, 0x1A, 0x04,
++ /* 0000028F call word 0x3c4 */ 0xE8, 0x32, 0x01,
++ /* 00000292 pop si */ 0x5E,
++ /* 00000293 cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
++ /* 00000297 jz 0x2a3 */ 0x74, 0x0A,
++ /* 00000299 push si */ 0x56,
++ /* 0000029A mov si,0x432 */ 0xBE, 0x32, 0x04,
++ /* 0000029D call word 0x3c4 */ 0xE8, 0x24, 0x01,
++ /* 000002A0 pop si */ 0x5E,
++ /* 000002A1 jmp short 0x233 */ 0xEB, 0x90,
++ /* 000002A3 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
++ /* 000002A6 mov al,0x20 */ 0xB0, 0x20,
++ /* 000002A8 out dx,al */ 0xEE,
++ /* 000002A9 push dx */ 0x52,
++ /* 000002AA push ax */ 0x50,
++ /* 000002AB mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 000002AE mov ax,0x4 */ 0xB8, 0x04, 0x00,
++ /* 000002B1 out dx,ax */ 0xEF,
++ /* 000002B2 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 000002B5 mov ax,0x0 */ 0xB8, 0x00, 0x00,
++ /* 000002B8 out dx,ax */ 0xEF,
++ /* 000002B9 pop ax */ 0x58,
++ /* 000002BA pop dx */ 0x5A,
++ /* 000002BB push dx */ 0x52,
++ /* 000002BC push ax */ 0x50,
++ /* 000002BD mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 000002C0 mov ax,0x5 */ 0xB8, 0x05, 0x00,
++ /* 000002C3 out dx,ax */ 0xEF,
++ /* 000002C4 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 000002C7 mov ax,0x0 */ 0xB8, 0x00, 0x00,
++ /* 000002CA out dx,ax */ 0xEF,
++ /* 000002CB pop ax */ 0x58,
++ /* 000002CC pop dx */ 0x5A,
++ /* 000002CD push dx */ 0x52,
++ /* 000002CE push ax */ 0x50,
++ /* 000002CF mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 000002D2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
++ /* 000002D5 out dx,ax */ 0xEF,
++ /* 000002D6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 000002D9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
++ /* 000002DC out dx,ax */ 0xEF,
++ /* 000002DD pop ax */ 0x58,
++ /* 000002DE pop dx */ 0x5A,
++ /* 000002DF push dx */ 0x52,
++ /* 000002E0 push ax */ 0x50,
++ /* 000002E1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 000002E4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
++ /* 000002E7 out dx,ax */ 0xEF,
++ /* 000002E8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 000002EB mov ax,0x0 */ 0xB8, 0x00, 0x00,
++ /* 000002EE out dx,ax */ 0xEF,
++ /* 000002EF pop ax */ 0x58,
++ /* 000002F0 pop dx */ 0x5A,
++ /* 000002F1 push dx */ 0x52,
++ /* 000002F2 push ax */ 0x50,
++ /* 000002F3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 000002F6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
++ /* 000002F9 out dx,ax */ 0xEF,
++ /* 000002FA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 000002FD mov ax,0x20 */ 0xB8, 0x20, 0x00,
++ /* 00000300 out dx,ax */ 0xEF,
++ /* 00000301 pop ax */ 0x58,
++ /* 00000302 pop dx */ 0x5A,
++ /* 00000303 push dx */ 0x52,
++ /* 00000304 push ax */ 0x50,
++ /* 00000305 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 00000308 mov ax,0x1 */ 0xB8, 0x01, 0x00,
++ /* 0000030B out dx,ax */ 0xEF,
++ /* 0000030C mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 0000030F mov ax,0x400 */ 0xB8, 0x00, 0x04,
++ /* 00000312 out dx,ax */ 0xEF,
++ /* 00000313 pop ax */ 0x58,
++ /* 00000314 pop dx */ 0x5A,
++ /* 00000315 push dx */ 0x52,
++ /* 00000316 push ax */ 0x50,
++ /* 00000317 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 0000031A mov ax,0x6 */ 0xB8, 0x06, 0x00,
++ /* 0000031D out dx,ax */ 0xEF,
++ /* 0000031E mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 00000321 mov ax,0x400 */ 0xB8, 0x00, 0x04,
++ /* 00000324 out dx,ax */ 0xEF,
++ /* 00000325 pop ax */ 0x58,
++ /* 00000326 pop dx */ 0x5A,
++ /* 00000327 push dx */ 0x52,
++ /* 00000328 push ax */ 0x50,
++ /* 00000329 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 0000032C mov ax,0x2 */ 0xB8, 0x02, 0x00,
++ /* 0000032F out dx,ax */ 0xEF,
++ /* 00000330 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 00000333 mov ax,0x300 */ 0xB8, 0x00, 0x03,
++ /* 00000336 out dx,ax */ 0xEF,
++ /* 00000337 pop ax */ 0x58,
++ /* 00000338 pop dx */ 0x5A,
++ /* 00000339 push dx */ 0x52,
++ /* 0000033A push ax */ 0x50,
++ /* 0000033B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 0000033E mov ax,0x7 */ 0xB8, 0x07, 0x00,
++ /* 00000341 out dx,ax */ 0xEF,
++ /* 00000342 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 00000345 mov ax,0x300 */ 0xB8, 0x00, 0x03,
++ /* 00000348 out dx,ax */ 0xEF,
++ /* 00000349 pop ax */ 0x58,
++ /* 0000034A pop dx */ 0x5A,
++ /* 0000034B push dx */ 0x52,
++ /* 0000034C push ax */ 0x50,
++ /* 0000034D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
++ /* 00000350 mov ax,0x4 */ 0xB8, 0x04, 0x00,
++ /* 00000353 out dx,ax */ 0xEF,
++ /* 00000354 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
++ /* 00000357 mov ax,0x41 */ 0xB8, 0x41, 0x00,
++ /* 0000035A out dx,ax */ 0xEF,
++ /* 0000035B pop ax */ 0x58,
++ /* 0000035C pop dx */ 0x5A,
++ /* 0000035D pop ax */ 0x58,
++ /* 0000035E pop dx */ 0x5A,
++ /* 0000035F jmp short 0x3ac */ 0xEB, 0x4B,
++ /* 00000361 push si */ 0x56,
++ /* 00000362 mov si,0x411 */ 0xBE, 0x11, 0x04,
++ /* 00000365 call word 0x3c4 */ 0xE8, 0x5C, 0x00,
++ /* 00000368 pop si */ 0x5E,
++ /* 00000369 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
++ /* 0000036C jmp short 0x3ac */ 0xEB, 0x3E,
++ /* 0000036E push si */ 0x56,
++ /* 0000036F mov si,0x43f */ 0xBE, 0x3F, 0x04,
++ /* 00000372 call word 0x3c4 */ 0xE8, 0x4F, 0x00,
++ /* 00000375 pop si */ 0x5E,
++ /* 00000376 jmp short 0x3b8 */ 0xEB, 0x40,
++ /* 00000378 push si */ 0x56,
++ /* 00000379 mov si,0x452 */ 0xBE, 0x52, 0x04,
++ /* 0000037C call word 0x3c4 */ 0xE8, 0x45, 0x00,
++ /* 0000037F pop si */ 0x5E,
++ /* 00000380 jmp short 0x3b8 */ 0xEB, 0x36,
++ /* 00000382 push si */ 0x56,
++ /* 00000383 mov si,0x423 */ 0xBE, 0x23, 0x04,
++ /* 00000386 call word 0x3c4 */ 0xE8, 0x3B, 0x00,
++ /* 00000389 pop si */ 0x5E,
++ /* 0000038A cmp al,0x3 */ 0x3C, 0x03,
++ /* 0000038C jz 0x39d */ 0x74, 0x0F,
++ /* 0000038E cmp al,0x12 */ 0x3C, 0x12,
++ /* 00000390 jz 0x3a1 */ 0x74, 0x0F,
++ /* 00000392 push si */ 0x56,
++ /* 00000393 mov si,0x432 */ 0xBE, 0x32, 0x04,
++ /* 00000396 call word 0x3c4 */ 0xE8, 0x2B, 0x00,
++ /* 00000399 pop si */ 0x5E,
++ /* 0000039A jmp word 0x233 */ 0xE9, 0x96, 0xFE,
++ /* 0000039D mov al,0x30 */ 0xB0, 0x30,
++ /* 0000039F jmp short 0x3a3 */ 0xEB, 0x02,
++ /* 000003A1 mov al,0x20 */ 0xB0, 0x20,
++ /* 000003A3 push si */ 0x56,
++ /* 000003A4 mov si,0x3d6 */ 0xBE, 0xD6, 0x03,
++ /* 000003A7 call word 0x3c4 */ 0xE8, 0x1A, 0x00,
++ /* 000003AA pop si */ 0x5E,
++ /* 000003AB iretw */ 0xCF,
++ /* 000003AC push si */ 0x56,
++ /* 000003AD mov si,0x3d6 */ 0xBE, 0xD6, 0x03,
++ /* 000003B0 call word 0x3c4 */ 0xE8, 0x11, 0x00,
++ /* 000003B3 pop si */ 0x5E,
++ /* 000003B4 mov ax,0x4f */ 0xB8, 0x4F, 0x00,
++ /* 000003B7 iretw */ 0xCF,
++ /* 000003B8 push si */ 0x56,
++ /* 000003B9 mov si,0x3dc */ 0xBE, 0xDC, 0x03,
++ /* 000003BC call word 0x3c4 */ 0xE8, 0x05, 0x00,
++ /* 000003BF pop si */ 0x5E,
++ /* 000003C0 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
++ /* 000003C3 iretw */ 0xCF,
++ /* 000003C4 pushaw */ 0x60,
++ /* 000003C5 push ds */ 0x1E,
++ /* 000003C6 push cs */ 0x0E,
++ /* 000003C7 pop ds */ 0x1F,
++ /* 000003C8 mov dx,0x402 */ 0xBA, 0x02, 0x04,
++ /* 000003CB lodsb */ 0xAC,
++ /* 000003CC cmp al,0x0 */ 0x3C, 0x00,
++ /* 000003CE jz 0x3d3 */ 0x74, 0x03,
++ /* 000003D0 out dx,al */ 0xEE,
++ /* 000003D1 jmp short 0x3cb */ 0xEB, 0xF8,
++ /* 000003D3 pop ds */ 0x1F,
++ /* 000003D4 popaw */ 0x61,
++ /* 000003D5 ret */ 0xC3,
++ /* 000003D6 inc bp */ 0x45,
++ /* 000003D7 js 0x442 */ 0x78, 0x69,
++ /* 000003D9 jz 0x3e5 */ 0x74, 0x0A,
++ /* 000003DB add [di+0x6e],dl */ 0x00, 0x55, 0x6E,
++ /* 000003DE jnc 0x455 */ 0x73, 0x75,
++ /* 000003E0 jo 0x452 */ 0x70, 0x70,
++ /* 000003E2 outsw */ 0x6F,
++ /* 000003E3 jc 0x459 */ 0x72, 0x74,
++ /* 000003E5 or al,[fs:bx+si] */ 0x65, 0x64, 0x0A, 0x00,
++ /* 000003E9 push bp */ 0x55,
++ /* 000003EA outsb */ 0x6E,
++ /* 000003EB imul bp,[bp+0x6f],byte +0x77 */ 0x6B, 0x6E, 0x6F, 0x77,
++ /* 000003EF outsb */ 0x6E,
++ /* 000003F0 and [bp+0x75],al */ 0x20, 0x46, 0x75,
++ /* 000003F3 outsb */ 0x6E,
++ /* 000003F4 arpl [si+0x69],si */ 0x63, 0x74, 0x69,
++ /* 000003F7 outsw */ 0x6F,
++ /* 000003F8 outsb */ 0x6E,
++ /* 000003F9 or al,[bx+si] */ 0x0A, 0x00,
++ /* 000003FB inc di */ 0x47,
++ /* 000003FC gs jz 0x448 */ 0x65, 0x74, 0x49,
++ /* 000003FF outsb */ 0x6E,
++ /* 00000400 outsd */ 0x66, 0x6F,
++ /* 00000402 or al,[bx+si] */ 0x0A, 0x00,
++ /* 00000404 inc di */ 0x47,
++ /* 00000405 gs jz 0x455 */ 0x65, 0x74, 0x4D,
++ /* 00000408 outsw */ 0x6F,
++ /* 00000409 gs dec cx */ 0x64, 0x65, 0x49,
++ /* 0000040C outsb */ 0x6E,
++ /* 0000040D outsd */ 0x66, 0x6F,
++ /* 0000040F or al,[bx+si] */ 0x0A, 0x00,
++ /* 00000411 inc di */ 0x47,
++ /* 00000412 gs jz 0x462 */ 0x65, 0x74, 0x4D,
++ /* 00000415 outsw */ 0x6F,
++ /* 00000416 or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
++ /* 0000041A push bx */ 0x53,
++ /* 0000041B gs jz 0x46b */ 0x65, 0x74, 0x4D,
++ /* 0000041E outsw */ 0x6F,
++ /* 0000041F or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
++ /* 00000423 push bx */ 0x53,
++ /* 00000424 gs jz 0x474 */ 0x65, 0x74, 0x4D,
++ /* 00000427 outsw */ 0x6F,
++ /* 00000428 gs dec sp */ 0x64, 0x65, 0x4C,
++ /* 0000042B gs a32 popaw */ 0x65, 0x67, 0x61,
++ /* 0000042E arpl [bx+di+0xa],di */ 0x63, 0x79, 0x0A,
++ /* 00000431 add [di+0x6e],dl */ 0x00, 0x55, 0x6E,
++ /* 00000434 imul bp,[bx+0x77],byte +0x6e */ 0x6B, 0x6F, 0x77, 0x6E,
++ /* 00000438 and [di+0x6f],cl */ 0x20, 0x4D, 0x6F,
++ /* 0000043B or al,[gs:bx+si] */ 0x64, 0x65, 0x0A, 0x00,
++ /* 0000043F inc di */ 0x47,
++ /* 00000440 gs jz 0x493 */ 0x65, 0x74, 0x50,
++ /* 00000443 insw */ 0x6D,
++ /* 00000444 inc bx */ 0x43,
++ /* 00000445 popaw */ 0x61,
++ /* 00000446 jo 0x4a9 */ 0x70, 0x61,
++ /* 00000448 bound bp,[bx+di+0x6c] */ 0x62, 0x69, 0x6C,
++ /* 0000044B imul si,[si+0x69],word 0x7365 */ 0x69, 0x74, 0x69, 0x65, 0x73,
++ /* 00000450 or al,[bx+si] */ 0x0A, 0x00,
++ /* 00000452 push dx */ 0x52,
++ /* 00000453 gs popaw */ 0x65, 0x61,
++ /* 00000455 fs inc bp */ 0x64, 0x45,
++ /* 00000457 fs */ 0x64,
++ /* 00000458 db 0x69 */ 0x69,
++ /* 00000459 or al,[fs:bx+si] */ 0x64, 0x0A, 0x00,
+ };
+ #endif
diff --git a/0007-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch b/0007-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
new file mode 100644
index 0000000..a651a68
--- /dev/null
+++ b/0007-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
@@ -0,0 +1,129 @@
+From b6e4c1bf03878da7bd82224d523c44fd1fa96aaa Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Tue, 25 Feb 2014 18:40:35 +0100
+Subject: [PATCH] MdeModulePkg: TerminalDxe: add other text resolutions
+
+When the console output is multiplexed to several devices by
+ConSplitterDxe, then ConSplitterDxe builds an intersection of text modes
+supported by all console output devices.
+
+Two notable output devices are provided by:
+(1) MdeModulePkg/Universal/Console/GraphicsConsoleDxe,
+(2) MdeModulePkg/Universal/Console/TerminalDxe.
+
+GraphicsConsoleDxe supports four modes at most -- see
+InitializeGraphicsConsoleTextMode() and "mGraphicsConsoleModeData":
+
+(1a) 80x25 (required by the UEFI spec as mode 0),
+(1b) 80x50 (not necessarily supported, but if it is, then the UEFI spec
+ requires the driver to provide it as mode 1),
+(1c) 100x31 (corresponding to graphics resolution 800x600, which the UEFI
+ spec requires from all plug-in graphics devices),
+(1d) "full screen" resolution, derived form the underlying GOP's
+ horizontal and vertical resolutions with division by EFI_GLYPH_WIDTH
+ (8) and EFI_GLYPH_HEIGHT (19), respectively.
+
+The automatic "full screen resolution" makes GraphicsConsoleDxe's
+character console very flexible. However, TerminalDxe (which runs on
+serial ports) only provides the following fixed resolutions -- see
+InitializeTerminalConsoleTextMode() and "mTerminalConsoleModeData":
+
+(2a) 80x25 (required by the UEFI spec as mode 0),
+(2b) 80x50 (since the character resolution of a serial device cannot be
+ interrogated easily, this is added unconditionally as mode 1),
+(2c) 100x31 (since the character resolution of a serial device cannot be
+ interrogated easily, this is added unconditionally as mode 2).
+
+When ConSplitterDxe combines (1) and (2), multiplexing console output to
+both video output and serial terminal, the list of commonly supported text
+modes (ie. the "intersection") comprises:
+
+(3a) 80x25, unconditionally, from (1a) and (2a),
+(3b) 80x50, if the graphics console provides at least 640x950 pixel
+ resolution, from (1b) and (2b)
+(3c) 100x31, if the graphics device is a plug-in one (because in that case
+ 800x600 is a mandated pixel resolution), from (1c) and (2c).
+
+Unfortunately, the "full screen resolution" (1d) of the GOP-based text
+console is not available in general.
+
+Mitigate this problem by extending "mTerminalConsoleModeData" with a
+handful of text resolutions that are derived from widespread maximal pixel
+resolutions. This way TerminalDxe won't cause ConSplitterDxe to filter out
+the most frequent (1d) values from the intersection, and eg. the MODE
+command in the UEFI shell will offer the "best" (ie. full screen)
+resolution too.
+
+Upstream status: three calendar months (with on-and-off discussion and
+patches) have not been enough to find a solution to this problem that
+would please all stakeholders.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- adapt commit 0bc77c63de03 (code and commit message) to upstream commit
+ 390b95a49c14 ("MdeModulePkg/TerminalDxe: Refine
+ InitializeTerminalConsoleTextMode", 2017-01-10).
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 99dc3720ac86059f60156197328cc433603c536e)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ .../Universal/Console/TerminalDxe/Terminal.c | 41 +++++++++++++++++--
+ 1 file changed, 38 insertions(+), 3 deletions(-)
+
+diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
+index 66dd3ad550..78a198379a 100644
+--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
++++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
+@@ -113,9 +113,44 @@ TERMINAL_DEV mTerminalDevTemplate = {
+ };
+
+ TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
+- {80, 25},
+- {80, 50},
+- {100, 31},
++ { 80, 25 }, // from graphics resolution 640 x 480
++ { 80, 50 }, // from graphics resolution 640 x 960
++ { 100, 25 }, // from graphics resolution 800 x 480
++ { 100, 31 }, // from graphics resolution 800 x 600
++ { 104, 32 }, // from graphics resolution 832 x 624
++ { 120, 33 }, // from graphics resolution 960 x 640
++ { 128, 31 }, // from graphics resolution 1024 x 600
++ { 128, 40 }, // from graphics resolution 1024 x 768
++ { 144, 45 }, // from graphics resolution 1152 x 864
++ { 144, 45 }, // from graphics resolution 1152 x 870
++ { 160, 37 }, // from graphics resolution 1280 x 720
++ { 160, 40 }, // from graphics resolution 1280 x 760
++ { 160, 40 }, // from graphics resolution 1280 x 768
++ { 160, 42 }, // from graphics resolution 1280 x 800
++ { 160, 50 }, // from graphics resolution 1280 x 960
++ { 160, 53 }, // from graphics resolution 1280 x 1024
++ { 170, 40 }, // from graphics resolution 1360 x 768
++ { 170, 40 }, // from graphics resolution 1366 x 768
++ { 175, 55 }, // from graphics resolution 1400 x 1050
++ { 180, 47 }, // from graphics resolution 1440 x 900
++ { 200, 47 }, // from graphics resolution 1600 x 900
++ { 200, 63 }, // from graphics resolution 1600 x 1200
++ { 210, 55 }, // from graphics resolution 1680 x 1050
++ { 240, 56 }, // from graphics resolution 1920 x 1080
++ { 240, 63 }, // from graphics resolution 1920 x 1200
++ { 240, 75 }, // from graphics resolution 1920 x 1440
++ { 250, 105 }, // from graphics resolution 2000 x 2000
++ { 256, 80 }, // from graphics resolution 2048 x 1536
++ { 256, 107 }, // from graphics resolution 2048 x 2048
++ { 320, 75 }, // from graphics resolution 2560 x 1440
++ { 320, 84 }, // from graphics resolution 2560 x 1600
++ { 320, 107 }, // from graphics resolution 2560 x 2048
++ { 350, 110 }, // from graphics resolution 2800 x 2100
++ { 400, 126 }, // from graphics resolution 3200 x 2400
++ { 480, 113 }, // from graphics resolution 3840 x 2160
++ { 512, 113 }, // from graphics resolution 4096 x 2160
++ { 960, 227 }, // from graphics resolution 7680 x 4320
++ { 1024, 227 }, // from graphics resolution 8192 x 4320
+ //
+ // New modes can be added here.
+ //
diff --git a/0007-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch b/0007-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
deleted file mode 100644
index 6882c12..0000000
--- a/0007-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
+++ /dev/null
@@ -1,1129 +0,0 @@
-From da502f7cc283055a65ab3caeaa62eb5c6a6fddb5 Mon Sep 17 00:00:00 2001
-From: Laszlo Ersek <lersek(a)redhat.com>
-Date: Mon, 6 Jul 2015 20:22:02 +0200
-Subject: [PATCH] OvmfPkg: EnrollDefaultKeys: application for enrolling default
- keys
-
-(A port of the <https://bugzilla.redhat.com/show_bug.cgi?id=1148296 > patch
-to Gerd's public RPMs.)
-
-This application is meant to be invoked by the management layer, after
-booting the UEFI shell and getting a shell prompt on the serial console.
-The app enrolls a number of certificates (see below), and then reports
-status to the serial console as well. The expected output is "info:
-success":
-
-> Shell> EnrollDefaultKeys.efi
-> info: SetupMode=1 SecureBoot=0 SecureBootEnable=0 CustomMode=0 VendorKeys=1
-> info: SetupMode=0 SecureBoot=1 SecureBootEnable=1 CustomMode=0 VendorKeys=0
-> info: success
-> Shell>
-
-In case of success, the management layer can force off or reboot the VM
-(for example with the "reset -s" or "reset -c" UEFI shell commands,
-respectively), and start the guest installation with SecureBoot enabled.
-
-PK:
-- A unique, static, ad-hoc certificate whose private half has been
- destroyed (more precisely, never saved) and is therefore unusable for
- signing. (The command for creating this certificate is saved in the
- source code.)
-
-KEK:
-- same ad-hoc certificate as used for the PK,
-- "Microsoft Corporation KEK CA 2011" -- the dbx data in Fedora's dbxtool
- package is signed (indirectly, through a chain) with this; enrolling
- such a KEK should allow guests to install those updates.
-
-DB:
-- "Microsoft Windows Production PCA 2011" -- to load Windows 8 and Windows
- Server 2012 R2,
-- "Microsoft Corporation UEFI CA 2011" -- to load Linux and signed PCI
- oproms.
-
-Contributed-under: TianoCore Contribution Agreement 1.0
-Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
----
- OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c | 963 ++++++++++++++++++++++++
- OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf | 51 ++
- OvmfPkg/OvmfPkgIa32.dsc | 4 +
- OvmfPkg/OvmfPkgIa32X64.dsc | 4 +
- OvmfPkg/OvmfPkgX64.dsc | 4 +
- 5 files changed, 1026 insertions(+)
- create mode 100644 OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
- create mode 100644 OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
-
-diff --git a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
-new file mode 100644
-index 0000000..447288f
---- /dev/null
-+++ b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
-@@ -0,0 +1,963 @@
-+/** @file
-+ Enroll default PK, KEK, DB.
-+
-+ Copyright (C) 2014, Red Hat, Inc.
-+
-+ This program and the accompanying materials are licensed and made available
-+ under the terms and conditions of the BSD License which accompanies this
-+ distribution. The full text of the license may be found at
-+ http://opensource.org/licenses/bsd-license .
-+
-+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
-+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-+**/
-+#include <Guid/AuthenticatedVariableFormat.h> // gEfiCustomModeEnableGuid
-+#include <Guid/GlobalVariable.h> // EFI_SETUP_MODE_NAME
-+#include <Guid/ImageAuthentication.h> // EFI_IMAGE_SECURITY_DATABASE
-+#include <Library/BaseMemoryLib.h> // CopyGuid()
-+#include <Library/DebugLib.h> // ASSERT()
-+#include <Library/MemoryAllocationLib.h> // FreePool()
-+#include <Library/ShellCEntryLib.h> // ShellAppMain()
-+#include <Library/UefiLib.h> // AsciiPrint()
-+#include <Library/UefiRuntimeServicesTableLib.h> // gRT
-+
-+//
-+// The example self-signed certificate below, which we'll use for both Platform
-+// Key, and first Key Exchange Key, has been generated with the following
-+// non-interactive openssl command. The passphrase is read from /dev/urandom,
-+// and not saved, and the private key is written to /dev/null. In other words,
-+// we can't sign anything else against this certificate, which is our purpose.
-+//
-+/*
-+ openssl req \
-+ -passout file:<(head -c 16 /dev/urandom) \
-+ -x509 \
-+ -newkey rsa:2048 \
-+ -keyout /dev/null \
-+ -outform DER \
-+ -subj $(
-+ printf /C=US
-+ printf /ST=TestStateOrProvince
-+ printf /L=TestLocality
-+ printf /O=TestOrganization
-+ printf /OU=TestOrganizationalUnit
-+ printf /CN=TestCommonName
-+ printf /emailAddress=test(a)example.com
-+ ) \
-+ 2>/dev/null \
-+ | xxd -i
-+*/
-+STATIC CONST UINT8 ExampleCert[] = {
-+ 0x30, 0x82, 0x04, 0x45, 0x30, 0x82, 0x03, 0x2d, 0xa0, 0x03, 0x02, 0x01, 0x02,
-+ 0x02, 0x09, 0x00, 0xcf, 0x9f, 0x51, 0xa3, 0x07, 0xdb, 0x54, 0xa1, 0x30, 0x0d,
-+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
-+ 0x30, 0x81, 0xb8, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-+ 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
-+ 0x13, 0x54, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x50,
-+ 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03,
-+ 0x55, 0x04, 0x07, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x63, 0x61,
-+ 0x6c, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a,
-+ 0x0c, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a,
-+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
-+ 0x0b, 0x0c, 0x16, 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69,
-+ 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x31,
-+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x54, 0x65, 0x73,
-+ 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x31, 0x1f,
-+ 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
-+ 0x16, 0x10, 0x74, 0x65, 0x73, 0x74, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
-+ 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x30,
-+ 0x30, 0x39, 0x31, 0x33, 0x32, 0x38, 0x32, 0x32, 0x5a, 0x17, 0x0d, 0x31, 0x34,
-+ 0x31, 0x31, 0x30, 0x38, 0x31, 0x33, 0x32, 0x38, 0x32, 0x32, 0x5a, 0x30, 0x81,
-+ 0xb8, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
-+ 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x13, 0x54,
-+ 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x50, 0x72, 0x6f,
-+ 0x76, 0x69, 0x6e, 0x63, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
-+ 0x07, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
-+ 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x10,
-+ 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74,
-+ 0x69, 0x6f, 0x6e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
-+ 0x16, 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61,
-+ 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x17, 0x30,
-+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x43,
-+ 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x31, 0x1f, 0x30, 0x1d,
-+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10,
-+ 0x74, 0x65, 0x73, 0x74, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
-+ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
-+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
-+ 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbf, 0xf1, 0xce,
-+ 0x17, 0x32, 0xac, 0xc4, 0x4b, 0xb2, 0xed, 0x84, 0x76, 0xe5, 0xd0, 0xf8, 0x21,
-+ 0xac, 0x10, 0xf8, 0x18, 0x09, 0x0e, 0x07, 0x13, 0x76, 0x21, 0x5c, 0xc4, 0xcc,
-+ 0xd5, 0xe6, 0x25, 0xa7, 0x26, 0x53, 0x79, 0x2f, 0x16, 0x4b, 0x85, 0xbd, 0xae,
-+ 0x42, 0x64, 0x58, 0xcb, 0x5e, 0xe8, 0x6e, 0x5a, 0xd0, 0xc4, 0x0f, 0x38, 0x16,
-+ 0xbe, 0xd3, 0x22, 0xa7, 0x3c, 0x9b, 0x8b, 0x5e, 0xcb, 0x62, 0x35, 0xc5, 0x9b,
-+ 0xe2, 0x8e, 0x4c, 0x65, 0x57, 0x4f, 0xcb, 0x27, 0xad, 0xe7, 0x63, 0xa7, 0x77,
-+ 0x2b, 0xd5, 0x02, 0x42, 0x70, 0x46, 0xac, 0xba, 0xb6, 0x60, 0x57, 0xd9, 0xce,
-+ 0x31, 0xc5, 0x12, 0x03, 0x4a, 0xf7, 0x2a, 0x2b, 0x40, 0x06, 0xb4, 0xdb, 0x31,
-+ 0xb7, 0x83, 0x6c, 0x67, 0x87, 0x98, 0x8b, 0xce, 0x1b, 0x30, 0x7a, 0xfa, 0x35,
-+ 0x6c, 0x86, 0x20, 0x74, 0xc5, 0x7d, 0x32, 0x31, 0x18, 0xeb, 0x69, 0xf7, 0x2d,
-+ 0x20, 0xc4, 0xf0, 0xd2, 0xfa, 0x67, 0x81, 0xc1, 0xbb, 0x23, 0xbb, 0x75, 0x1a,
-+ 0xe4, 0xb4, 0x49, 0x99, 0xdf, 0x12, 0x4c, 0xe3, 0x6d, 0x76, 0x24, 0x85, 0x24,
-+ 0xae, 0x5a, 0x9e, 0xbd, 0x54, 0x1c, 0xf9, 0x0e, 0xed, 0x96, 0xb5, 0xd8, 0xa2,
-+ 0x0d, 0x2a, 0x38, 0x5d, 0x12, 0x97, 0xb0, 0x4d, 0x75, 0x85, 0x1e, 0x47, 0x6d,
-+ 0xe1, 0x25, 0x59, 0xcb, 0xe9, 0x33, 0x86, 0x6a, 0xef, 0x98, 0x24, 0xa0, 0x2b,
-+ 0x02, 0x7b, 0xc0, 0x9f, 0x88, 0x03, 0xb0, 0xbe, 0x22, 0x65, 0x83, 0x77, 0xb3,
-+ 0x30, 0xba, 0xe0, 0x3b, 0x54, 0x31, 0x3a, 0x45, 0x81, 0x9c, 0x48, 0xaf, 0xc1,
-+ 0x11, 0x5b, 0xf2, 0x3a, 0x1e, 0x33, 0x1b, 0x8f, 0x0e, 0x04, 0xa4, 0x16, 0xd4,
-+ 0x6b, 0x57, 0xee, 0xe7, 0xba, 0xf5, 0xee, 0xaf, 0xe2, 0x4c, 0x50, 0xf8, 0x68,
-+ 0x57, 0x88, 0xfb, 0x7f, 0xa3, 0xcf, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50,
-+ 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
-+ 0x1e, 0x44, 0xe5, 0xef, 0xcd, 0x6e, 0x1f, 0xdb, 0xcb, 0x4f, 0x94, 0x8f, 0xe3,
-+ 0x3b, 0x1a, 0x8c, 0xe6, 0x95, 0x29, 0x61, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
-+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1e, 0x44, 0xe5, 0xef, 0xcd, 0x6e,
-+ 0x1f, 0xdb, 0xcb, 0x4f, 0x94, 0x8f, 0xe3, 0x3b, 0x1a, 0x8c, 0xe6, 0x95, 0x29,
-+ 0x61, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01,
-+ 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-+ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x12, 0x9c, 0x3e, 0x38,
-+ 0xfc, 0x26, 0xea, 0x6d, 0xb7, 0x5c, 0x29, 0x3c, 0x76, 0x20, 0x0c, 0xb2, 0xa9,
-+ 0x0f, 0xdf, 0xc0, 0x85, 0xfe, 0xeb, 0xec, 0x1d, 0x5d, 0x73, 0x84, 0xac, 0x8a,
-+ 0xb4, 0x2a, 0x86, 0x38, 0x30, 0xaf, 0xd2, 0x2d, 0x2a, 0xde, 0x54, 0xc8, 0x5c,
-+ 0x29, 0x90, 0x24, 0xf2, 0x39, 0xc1, 0xa5, 0x00, 0xb4, 0xb7, 0xd8, 0xdc, 0x59,
-+ 0x64, 0x50, 0x62, 0x5f, 0x54, 0xf1, 0x73, 0x02, 0x4d, 0x43, 0xc5, 0xc3, 0xc4,
-+ 0x0e, 0x62, 0x60, 0x8c, 0x53, 0x66, 0x57, 0x77, 0xb5, 0x81, 0xda, 0x1f, 0x81,
-+ 0xda, 0xe9, 0xd6, 0x5e, 0x82, 0xce, 0xa7, 0x5c, 0xc0, 0xa6, 0xbe, 0x9c, 0x5c,
-+ 0x7b, 0xa5, 0x15, 0xc8, 0xd7, 0x14, 0x53, 0xd3, 0x5c, 0x1c, 0x9f, 0x8a, 0x9f,
-+ 0x66, 0x15, 0xd5, 0xd3, 0x2a, 0x27, 0x0c, 0xee, 0x9f, 0x80, 0x39, 0x88, 0x7b,
-+ 0x24, 0xde, 0x0c, 0x61, 0xa3, 0x44, 0xd8, 0x8d, 0x2e, 0x79, 0xf8, 0x1e, 0x04,
-+ 0x5a, 0xcb, 0xd6, 0x9c, 0xa3, 0x22, 0x8f, 0x09, 0x32, 0x1e, 0xe1, 0x65, 0x8f,
-+ 0x10, 0x5f, 0xd8, 0x52, 0x56, 0xd5, 0x77, 0xac, 0x58, 0x46, 0x60, 0xba, 0x2e,
-+ 0xe2, 0x3f, 0x58, 0x7d, 0x60, 0xfc, 0x31, 0x4a, 0x3a, 0xaf, 0x61, 0x55, 0x5f,
-+ 0xfb, 0x68, 0x14, 0x74, 0xda, 0xdc, 0x42, 0x78, 0xcc, 0xee, 0xff, 0x5c, 0x03,
-+ 0x24, 0x26, 0x2c, 0xb8, 0x3a, 0x81, 0xad, 0xdb, 0xe7, 0xed, 0xe1, 0x62, 0x84,
-+ 0x07, 0x1a, 0xc8, 0xa4, 0x4e, 0xb0, 0x87, 0xf7, 0x96, 0xd8, 0x33, 0x9b, 0x0d,
-+ 0xa7, 0x77, 0xae, 0x5b, 0xaf, 0xad, 0xe6, 0x5a, 0xc9, 0xfa, 0xa4, 0xe4, 0xe5,
-+ 0x57, 0xbb, 0x97, 0xdd, 0x92, 0x85, 0xd8, 0x03, 0x45, 0xfe, 0xd8, 0x6b, 0xb1,
-+ 0xdb, 0x85, 0x36, 0xb9, 0xd9, 0x28, 0xbf, 0x17, 0xae, 0x11, 0xde, 0x10, 0x19,
-+ 0x26, 0x5b, 0xc0, 0x3d, 0xc7
-+};
-+
-+//
-+// Second KEK: "Microsoft Corporation KEK CA 2011".
-+// SHA1: 31:59:0b:fd:89:c9:d7:4e:d0:87:df:ac:66:33:4b:39:31:25:4b:30
-+//
-+// "dbx" updates in "dbxtool" are signed with a key derived from this KEK.
-+//
-+STATIC CONST UINT8 MicrosoftKEK[] = {
-+ 0x30, 0x82, 0x05, 0xe8, 0x30, 0x82, 0x03, 0xd0, 0xa0, 0x03, 0x02, 0x01, 0x02,
-+ 0x02, 0x0a, 0x61, 0x0a, 0xd1, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30,
-+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
-+ 0x00, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
-+ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
-+ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
-+ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
-+ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
-+ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3b, 0x30,
-+ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x4d, 0x69, 0x63, 0x72, 0x6f,
-+ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
-+ 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72,
-+ 0x74, 0x79, 0x20, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x70, 0x6c, 0x61, 0x63,
-+ 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30,
-+ 0x36, 0x32, 0x34, 0x32, 0x30, 0x34, 0x31, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x32,
-+ 0x36, 0x30, 0x36, 0x32, 0x34, 0x32, 0x30, 0x35, 0x31, 0x32, 0x39, 0x5a, 0x30,
-+ 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
-+ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
-+ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30,
-+ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f,
-+ 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15,
-+ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
-+ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2a, 0x30, 0x28, 0x06,
-+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
-+ 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
-+ 0x6e, 0x20, 0x4b, 0x45, 0x4b, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31,
-+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
-+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0xe8, 0xb5, 0x8a, 0xbf, 0xad,
-+ 0x57, 0x26, 0xb0, 0x26, 0xc3, 0xea, 0xe7, 0xfb, 0x57, 0x7a, 0x44, 0x02, 0x5d,
-+ 0x07, 0x0d, 0xda, 0x4a, 0xe5, 0x74, 0x2a, 0xe6, 0xb0, 0x0f, 0xec, 0x6d, 0xeb,
-+ 0xec, 0x7f, 0xb9, 0xe3, 0x5a, 0x63, 0x32, 0x7c, 0x11, 0x17, 0x4f, 0x0e, 0xe3,
-+ 0x0b, 0xa7, 0x38, 0x15, 0x93, 0x8e, 0xc6, 0xf5, 0xe0, 0x84, 0xb1, 0x9a, 0x9b,
-+ 0x2c, 0xe7, 0xf5, 0xb7, 0x91, 0xd6, 0x09, 0xe1, 0xe2, 0xc0, 0x04, 0xa8, 0xac,
-+ 0x30, 0x1c, 0xdf, 0x48, 0xf3, 0x06, 0x50, 0x9a, 0x64, 0xa7, 0x51, 0x7f, 0xc8,
-+ 0x85, 0x4f, 0x8f, 0x20, 0x86, 0xce, 0xfe, 0x2f, 0xe1, 0x9f, 0xff, 0x82, 0xc0,
-+ 0xed, 0xe9, 0xcd, 0xce, 0xf4, 0x53, 0x6a, 0x62, 0x3a, 0x0b, 0x43, 0xb9, 0xe2,
-+ 0x25, 0xfd, 0xfe, 0x05, 0xf9, 0xd4, 0xc4, 0x14, 0xab, 0x11, 0xe2, 0x23, 0x89,
-+ 0x8d, 0x70, 0xb7, 0xa4, 0x1d, 0x4d, 0xec, 0xae, 0xe5, 0x9c, 0xfa, 0x16, 0xc2,
-+ 0xd7, 0xc1, 0xcb, 0xd4, 0xe8, 0xc4, 0x2f, 0xe5, 0x99, 0xee, 0x24, 0x8b, 0x03,
-+ 0xec, 0x8d, 0xf2, 0x8b, 0xea, 0xc3, 0x4a, 0xfb, 0x43, 0x11, 0x12, 0x0b, 0x7e,
-+ 0xb5, 0x47, 0x92, 0x6c, 0xdc, 0xe6, 0x04, 0x89, 0xeb, 0xf5, 0x33, 0x04, 0xeb,
-+ 0x10, 0x01, 0x2a, 0x71, 0xe5, 0xf9, 0x83, 0x13, 0x3c, 0xff, 0x25, 0x09, 0x2f,
-+ 0x68, 0x76, 0x46, 0xff, 0xba, 0x4f, 0xbe, 0xdc, 0xad, 0x71, 0x2a, 0x58, 0xaa,
-+ 0xfb, 0x0e, 0xd2, 0x79, 0x3d, 0xe4, 0x9b, 0x65, 0x3b, 0xcc, 0x29, 0x2a, 0x9f,
-+ 0xfc, 0x72, 0x59, 0xa2, 0xeb, 0xae, 0x92, 0xef, 0xf6, 0x35, 0x13, 0x80, 0xc6,
-+ 0x02, 0xec, 0xe4, 0x5f, 0xcc, 0x9d, 0x76, 0xcd, 0xef, 0x63, 0x92, 0xc1, 0xaf,
-+ 0x79, 0x40, 0x84, 0x79, 0x87, 0x7f, 0xe3, 0x52, 0xa8, 0xe8, 0x9d, 0x7b, 0x07,
-+ 0x69, 0x8f, 0x15, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x4f, 0x30,
-+ 0x82, 0x01, 0x4b, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
-+ 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
-+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x62, 0xfc, 0x43, 0xcd, 0xa0, 0x3e, 0xa4,
-+ 0xcb, 0x67, 0x12, 0xd2, 0x5b, 0xd9, 0x55, 0xac, 0x7b, 0xcc, 0xb6, 0x8a, 0x5f,
-+ 0x30, 0x19, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02,
-+ 0x04, 0x0c, 0x1e, 0x0a, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00,
-+ 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01,
-+ 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
-+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
-+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0x66, 0x52, 0x43, 0xe1, 0x7e, 0x58, 0x11,
-+ 0xbf, 0xd6, 0x4e, 0x9e, 0x23, 0x55, 0x08, 0x3b, 0x3a, 0x22, 0x6a, 0xa8, 0x30,
-+ 0x5c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x55, 0x30, 0x53, 0x30, 0x51, 0xa0,
-+ 0x4f, 0xa0, 0x4d, 0x86, 0x4b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63,
-+ 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e,
-+ 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x70,
-+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f,
-+ 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f,
-+ 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63,
-+ 0x72, 0x6c, 0x30, 0x60, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01,
-+ 0x01, 0x04, 0x54, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
-+ 0x05, 0x07, 0x30, 0x02, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
-+ 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
-+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x74,
-+ 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61,
-+ 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d,
-+ 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09,
-+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
-+ 0x02, 0x01, 0x00, 0xd4, 0x84, 0x88, 0xf5, 0x14, 0x94, 0x18, 0x02, 0xca, 0x2a,
-+ 0x3c, 0xfb, 0x2a, 0x92, 0x1c, 0x0c, 0xd7, 0xa0, 0xd1, 0xf1, 0xe8, 0x52, 0x66,
-+ 0xa8, 0xee, 0xa2, 0xb5, 0x75, 0x7a, 0x90, 0x00, 0xaa, 0x2d, 0xa4, 0x76, 0x5a,
-+ 0xea, 0x79, 0xb7, 0xb9, 0x37, 0x6a, 0x51, 0x7b, 0x10, 0x64, 0xf6, 0xe1, 0x64,
-+ 0xf2, 0x02, 0x67, 0xbe, 0xf7, 0xa8, 0x1b, 0x78, 0xbd, 0xba, 0xce, 0x88, 0x58,
-+ 0x64, 0x0c, 0xd6, 0x57, 0xc8, 0x19, 0xa3, 0x5f, 0x05, 0xd6, 0xdb, 0xc6, 0xd0,
-+ 0x69, 0xce, 0x48, 0x4b, 0x32, 0xb7, 0xeb, 0x5d, 0xd2, 0x30, 0xf5, 0xc0, 0xf5,
-+ 0xb8, 0xba, 0x78, 0x07, 0xa3, 0x2b, 0xfe, 0x9b, 0xdb, 0x34, 0x56, 0x84, 0xec,
-+ 0x82, 0xca, 0xae, 0x41, 0x25, 0x70, 0x9c, 0x6b, 0xe9, 0xfe, 0x90, 0x0f, 0xd7,
-+ 0x96, 0x1f, 0xe5, 0xe7, 0x94, 0x1f, 0xb2, 0x2a, 0x0c, 0x8d, 0x4b, 0xff, 0x28,
-+ 0x29, 0x10, 0x7b, 0xf7, 0xd7, 0x7c, 0xa5, 0xd1, 0x76, 0xb9, 0x05, 0xc8, 0x79,
-+ 0xed, 0x0f, 0x90, 0x92, 0x9c, 0xc2, 0xfe, 0xdf, 0x6f, 0x7e, 0x6c, 0x0f, 0x7b,
-+ 0xd4, 0xc1, 0x45, 0xdd, 0x34, 0x51, 0x96, 0x39, 0x0f, 0xe5, 0x5e, 0x56, 0xd8,
-+ 0x18, 0x05, 0x96, 0xf4, 0x07, 0xa6, 0x42, 0xb3, 0xa0, 0x77, 0xfd, 0x08, 0x19,
-+ 0xf2, 0x71, 0x56, 0xcc, 0x9f, 0x86, 0x23, 0xa4, 0x87, 0xcb, 0xa6, 0xfd, 0x58,
-+ 0x7e, 0xd4, 0x69, 0x67, 0x15, 0x91, 0x7e, 0x81, 0xf2, 0x7f, 0x13, 0xe5, 0x0d,
-+ 0x8b, 0x8a, 0x3c, 0x87, 0x84, 0xeb, 0xe3, 0xce, 0xbd, 0x43, 0xe5, 0xad, 0x2d,
-+ 0x84, 0x93, 0x8e, 0x6a, 0x2b, 0x5a, 0x7c, 0x44, 0xfa, 0x52, 0xaa, 0x81, 0xc8,
-+ 0x2d, 0x1c, 0xbb, 0xe0, 0x52, 0xdf, 0x00, 0x11, 0xf8, 0x9a, 0x3d, 0xc1, 0x60,
-+ 0xb0, 0xe1, 0x33, 0xb5, 0xa3, 0x88, 0xd1, 0x65, 0x19, 0x0a, 0x1a, 0xe7, 0xac,
-+ 0x7c, 0xa4, 0xc1, 0x82, 0x87, 0x4e, 0x38, 0xb1, 0x2f, 0x0d, 0xc5, 0x14, 0x87,
-+ 0x6f, 0xfd, 0x8d, 0x2e, 0xbc, 0x39, 0xb6, 0xe7, 0xe6, 0xc3, 0xe0, 0xe4, 0xcd,
-+ 0x27, 0x84, 0xef, 0x94, 0x42, 0xef, 0x29, 0x8b, 0x90, 0x46, 0x41, 0x3b, 0x81,
-+ 0x1b, 0x67, 0xd8, 0xf9, 0x43, 0x59, 0x65, 0xcb, 0x0d, 0xbc, 0xfd, 0x00, 0x92,
-+ 0x4f, 0xf4, 0x75, 0x3b, 0xa7, 0xa9, 0x24, 0xfc, 0x50, 0x41, 0x40, 0x79, 0xe0,
-+ 0x2d, 0x4f, 0x0a, 0x6a, 0x27, 0x76, 0x6e, 0x52, 0xed, 0x96, 0x69, 0x7b, 0xaf,
-+ 0x0f, 0xf7, 0x87, 0x05, 0xd0, 0x45, 0xc2, 0xad, 0x53, 0x14, 0x81, 0x1f, 0xfb,
-+ 0x30, 0x04, 0xaa, 0x37, 0x36, 0x61, 0xda, 0x4a, 0x69, 0x1b, 0x34, 0xd8, 0x68,
-+ 0xed, 0xd6, 0x02, 0xcf, 0x6c, 0x94, 0x0c, 0xd3, 0xcf, 0x6c, 0x22, 0x79, 0xad,
-+ 0xb1, 0xf0, 0xbc, 0x03, 0xa2, 0x46, 0x60, 0xa9, 0xc4, 0x07, 0xc2, 0x21, 0x82,
-+ 0xf1, 0xfd, 0xf2, 0xe8, 0x79, 0x32, 0x60, 0xbf, 0xd8, 0xac, 0xa5, 0x22, 0x14,
-+ 0x4b, 0xca, 0xc1, 0xd8, 0x4b, 0xeb, 0x7d, 0x3f, 0x57, 0x35, 0xb2, 0xe6, 0x4f,
-+ 0x75, 0xb4, 0xb0, 0x60, 0x03, 0x22, 0x53, 0xae, 0x91, 0x79, 0x1d, 0xd6, 0x9b,
-+ 0x41, 0x1f, 0x15, 0x86, 0x54, 0x70, 0xb2, 0xde, 0x0d, 0x35, 0x0f, 0x7c, 0xb0,
-+ 0x34, 0x72, 0xba, 0x97, 0x60, 0x3b, 0xf0, 0x79, 0xeb, 0xa2, 0xb2, 0x1c, 0x5d,
-+ 0xa2, 0x16, 0xb8, 0x87, 0xc5, 0xe9, 0x1b, 0xf6, 0xb5, 0x97, 0x25, 0x6f, 0x38,
-+ 0x9f, 0xe3, 0x91, 0xfa, 0x8a, 0x79, 0x98, 0xc3, 0x69, 0x0e, 0xb7, 0xa3, 0x1c,
-+ 0x20, 0x05, 0x97, 0xf8, 0xca, 0x14, 0xae, 0x00, 0xd7, 0xc4, 0xf3, 0xc0, 0x14,
-+ 0x10, 0x75, 0x6b, 0x34, 0xa0, 0x1b, 0xb5, 0x99, 0x60, 0xf3, 0x5c, 0xb0, 0xc5,
-+ 0x57, 0x4e, 0x36, 0xd2, 0x32, 0x84, 0xbf, 0x9e
-+};
-+
-+//
-+// First DB entry: "Microsoft Windows Production PCA 2011"
-+// SHA1: 58:0a:6f:4c:c4:e4:b6:69:b9:eb:dc:1b:2b:3e:08:7b:80:d0:67:8d
-+//
-+// Windows 8 and Windows Server 2012 R2 boot loaders are signed with a chain
-+// rooted in this certificate.
-+//
-+STATIC CONST UINT8 MicrosoftPCA[] = {
-+ 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02,
-+ 0x02, 0x0a, 0x61, 0x07, 0x76, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30,
-+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
-+ 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
-+ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
-+ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
-+ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
-+ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
-+ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x32, 0x30,
-+ 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x4d, 0x69, 0x63, 0x72, 0x6f,
-+ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72,
-+ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
-+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1e, 0x17,
-+ 0x0d, 0x31, 0x31, 0x31, 0x30, 0x31, 0x39, 0x31, 0x38, 0x34, 0x31, 0x34, 0x32,
-+ 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x31, 0x30, 0x31, 0x39, 0x31, 0x38, 0x35, 0x31,
-+ 0x34, 0x32, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
-+ 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f,
-+ 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52,
-+ 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
-+ 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
-+ 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31,
-+ 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x4d, 0x69, 0x63,
-+ 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77,
-+ 0x73, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
-+ 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30,
-+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
-+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,
-+ 0x01, 0x00, 0xdd, 0x0c, 0xbb, 0xa2, 0xe4, 0x2e, 0x09, 0xe3, 0xe7, 0xc5, 0xf7,
-+ 0x96, 0x69, 0xbc, 0x00, 0x21, 0xbd, 0x69, 0x33, 0x33, 0xef, 0xad, 0x04, 0xcb,
-+ 0x54, 0x80, 0xee, 0x06, 0x83, 0xbb, 0xc5, 0x20, 0x84, 0xd9, 0xf7, 0xd2, 0x8b,
-+ 0xf3, 0x38, 0xb0, 0xab, 0xa4, 0xad, 0x2d, 0x7c, 0x62, 0x79, 0x05, 0xff, 0xe3,
-+ 0x4a, 0x3f, 0x04, 0x35, 0x20, 0x70, 0xe3, 0xc4, 0xe7, 0x6b, 0xe0, 0x9c, 0xc0,
-+ 0x36, 0x75, 0xe9, 0x8a, 0x31, 0xdd, 0x8d, 0x70, 0xe5, 0xdc, 0x37, 0xb5, 0x74,
-+ 0x46, 0x96, 0x28, 0x5b, 0x87, 0x60, 0x23, 0x2c, 0xbf, 0xdc, 0x47, 0xa5, 0x67,
-+ 0xf7, 0x51, 0x27, 0x9e, 0x72, 0xeb, 0x07, 0xa6, 0xc9, 0xb9, 0x1e, 0x3b, 0x53,
-+ 0x35, 0x7c, 0xe5, 0xd3, 0xec, 0x27, 0xb9, 0x87, 0x1c, 0xfe, 0xb9, 0xc9, 0x23,
-+ 0x09, 0x6f, 0xa8, 0x46, 0x91, 0xc1, 0x6e, 0x96, 0x3c, 0x41, 0xd3, 0xcb, 0xa3,
-+ 0x3f, 0x5d, 0x02, 0x6a, 0x4d, 0xec, 0x69, 0x1f, 0x25, 0x28, 0x5c, 0x36, 0xff,
-+ 0xfd, 0x43, 0x15, 0x0a, 0x94, 0xe0, 0x19, 0xb4, 0xcf, 0xdf, 0xc2, 0x12, 0xe2,
-+ 0xc2, 0x5b, 0x27, 0xee, 0x27, 0x78, 0x30, 0x8b, 0x5b, 0x2a, 0x09, 0x6b, 0x22,
-+ 0x89, 0x53, 0x60, 0x16, 0x2c, 0xc0, 0x68, 0x1d, 0x53, 0xba, 0xec, 0x49, 0xf3,
-+ 0x9d, 0x61, 0x8c, 0x85, 0x68, 0x09, 0x73, 0x44, 0x5d, 0x7d, 0xa2, 0x54, 0x2b,
-+ 0xdd, 0x79, 0xf7, 0x15, 0xcf, 0x35, 0x5d, 0x6c, 0x1c, 0x2b, 0x5c, 0xce, 0xbc,
-+ 0x9c, 0x23, 0x8b, 0x6f, 0x6e, 0xb5, 0x26, 0xd9, 0x36, 0x13, 0xc3, 0x4f, 0xd6,
-+ 0x27, 0xae, 0xb9, 0x32, 0x3b, 0x41, 0x92, 0x2c, 0xe1, 0xc7, 0xcd, 0x77, 0xe8,
-+ 0xaa, 0x54, 0x4e, 0xf7, 0x5c, 0x0b, 0x04, 0x87, 0x65, 0xb4, 0x43, 0x18, 0xa8,
-+ 0xb2, 0xe0, 0x6d, 0x19, 0x77, 0xec, 0x5a, 0x24, 0xfa, 0x48, 0x03, 0x02, 0x03,
-+ 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x43, 0x30, 0x82, 0x01, 0x3f, 0x30, 0x10,
-+ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03,
-+ 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
-+ 0x14, 0xa9, 0x29, 0x02, 0x39, 0x8e, 0x16, 0xc4, 0x97, 0x78, 0xcd, 0x90, 0xf9,
-+ 0x9e, 0x4f, 0x9a, 0xe1, 0x7c, 0x55, 0xaf, 0x53, 0x30, 0x19, 0x06, 0x09, 0x2b,
-+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0c, 0x1e, 0x0a, 0x00,
-+ 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03,
-+ 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03,
-+ 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
-+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
-+ 0xd5, 0xf6, 0x56, 0xcb, 0x8f, 0xe8, 0xa2, 0x5c, 0x62, 0x68, 0xd1, 0x3d, 0x94,
-+ 0x90, 0x5b, 0xd7, 0xce, 0x9a, 0x18, 0xc4, 0x30, 0x56, 0x06, 0x03, 0x55, 0x1d,
-+ 0x1f, 0x04, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0xa0, 0x49, 0xa0, 0x47, 0x86, 0x45,
-+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69,
-+ 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70,
-+ 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
-+ 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x52, 0x6f, 0x6f, 0x43, 0x65, 0x72, 0x41,
-+ 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x33,
-+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x5a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
-+ 0x07, 0x01, 0x01, 0x04, 0x4e, 0x30, 0x4c, 0x30, 0x4a, 0x06, 0x08, 0x2b, 0x06,
-+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74, 0x74, 0x70, 0x3a,
-+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
-+ 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65,
-+ 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x52, 0x6f, 0x6f, 0x43, 0x65, 0x72,
-+ 0x41, 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x32,
-+ 0x33, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-+ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x14,
-+ 0xfc, 0x7c, 0x71, 0x51, 0xa5, 0x79, 0xc2, 0x6e, 0xb2, 0xef, 0x39, 0x3e, 0xbc,
-+ 0x3c, 0x52, 0x0f, 0x6e, 0x2b, 0x3f, 0x10, 0x13, 0x73, 0xfe, 0xa8, 0x68, 0xd0,
-+ 0x48, 0xa6, 0x34, 0x4d, 0x8a, 0x96, 0x05, 0x26, 0xee, 0x31, 0x46, 0x90, 0x61,
-+ 0x79, 0xd6, 0xff, 0x38, 0x2e, 0x45, 0x6b, 0xf4, 0xc0, 0xe5, 0x28, 0xb8, 0xda,
-+ 0x1d, 0x8f, 0x8a, 0xdb, 0x09, 0xd7, 0x1a, 0xc7, 0x4c, 0x0a, 0x36, 0x66, 0x6a,
-+ 0x8c, 0xec, 0x1b, 0xd7, 0x04, 0x90, 0xa8, 0x18, 0x17, 0xa4, 0x9b, 0xb9, 0xe2,
-+ 0x40, 0x32, 0x36, 0x76, 0xc4, 0xc1, 0x5a, 0xc6, 0xbf, 0xe4, 0x04, 0xc0, 0xea,
-+ 0x16, 0xd3, 0xac, 0xc3, 0x68, 0xef, 0x62, 0xac, 0xdd, 0x54, 0x6c, 0x50, 0x30,
-+ 0x58, 0xa6, 0xeb, 0x7c, 0xfe, 0x94, 0xa7, 0x4e, 0x8e, 0xf4, 0xec, 0x7c, 0x86,
-+ 0x73, 0x57, 0xc2, 0x52, 0x21, 0x73, 0x34, 0x5a, 0xf3, 0xa3, 0x8a, 0x56, 0xc8,
-+ 0x04, 0xda, 0x07, 0x09, 0xed, 0xf8, 0x8b, 0xe3, 0xce, 0xf4, 0x7e, 0x8e, 0xae,
-+ 0xf0, 0xf6, 0x0b, 0x8a, 0x08, 0xfb, 0x3f, 0xc9, 0x1d, 0x72, 0x7f, 0x53, 0xb8,
-+ 0xeb, 0xbe, 0x63, 0xe0, 0xe3, 0x3d, 0x31, 0x65, 0xb0, 0x81, 0xe5, 0xf2, 0xac,
-+ 0xcd, 0x16, 0xa4, 0x9f, 0x3d, 0xa8, 0xb1, 0x9b, 0xc2, 0x42, 0xd0, 0x90, 0x84,
-+ 0x5f, 0x54, 0x1d, 0xff, 0x89, 0xea, 0xba, 0x1d, 0x47, 0x90, 0x6f, 0xb0, 0x73,
-+ 0x4e, 0x41, 0x9f, 0x40, 0x9f, 0x5f, 0xe5, 0xa1, 0x2a, 0xb2, 0x11, 0x91, 0x73,
-+ 0x8a, 0x21, 0x28, 0xf0, 0xce, 0xde, 0x73, 0x39, 0x5f, 0x3e, 0xab, 0x5c, 0x60,
-+ 0xec, 0xdf, 0x03, 0x10, 0xa8, 0xd3, 0x09, 0xe9, 0xf4, 0xf6, 0x96, 0x85, 0xb6,
-+ 0x7f, 0x51, 0x88, 0x66, 0x47, 0x19, 0x8d, 0xa2, 0xb0, 0x12, 0x3d, 0x81, 0x2a,
-+ 0x68, 0x05, 0x77, 0xbb, 0x91, 0x4c, 0x62, 0x7b, 0xb6, 0xc1, 0x07, 0xc7, 0xba,
-+ 0x7a, 0x87, 0x34, 0x03, 0x0e, 0x4b, 0x62, 0x7a, 0x99, 0xe9, 0xca, 0xfc, 0xce,
-+ 0x4a, 0x37, 0xc9, 0x2d, 0xa4, 0x57, 0x7c, 0x1c, 0xfe, 0x3d, 0xdc, 0xb8, 0x0f,
-+ 0x5a, 0xfa, 0xd6, 0xc4, 0xb3, 0x02, 0x85, 0x02, 0x3a, 0xea, 0xb3, 0xd9, 0x6e,
-+ 0xe4, 0x69, 0x21, 0x37, 0xde, 0x81, 0xd1, 0xf6, 0x75, 0x19, 0x05, 0x67, 0xd3,
-+ 0x93, 0x57, 0x5e, 0x29, 0x1b, 0x39, 0xc8, 0xee, 0x2d, 0xe1, 0xcd, 0xe4, 0x45,
-+ 0x73, 0x5b, 0xd0, 0xd2, 0xce, 0x7a, 0xab, 0x16, 0x19, 0x82, 0x46, 0x58, 0xd0,
-+ 0x5e, 0x9d, 0x81, 0xb3, 0x67, 0xaf, 0x6c, 0x35, 0xf2, 0xbc, 0xe5, 0x3f, 0x24,
-+ 0xe2, 0x35, 0xa2, 0x0a, 0x75, 0x06, 0xf6, 0x18, 0x56, 0x99, 0xd4, 0x78, 0x2c,
-+ 0xd1, 0x05, 0x1b, 0xeb, 0xd0, 0x88, 0x01, 0x9d, 0xaa, 0x10, 0xf1, 0x05, 0xdf,
-+ 0xba, 0x7e, 0x2c, 0x63, 0xb7, 0x06, 0x9b, 0x23, 0x21, 0xc4, 0xf9, 0x78, 0x6c,
-+ 0xe2, 0x58, 0x17, 0x06, 0x36, 0x2b, 0x91, 0x12, 0x03, 0xcc, 0xa4, 0xd9, 0xf2,
-+ 0x2d, 0xba, 0xf9, 0x94, 0x9d, 0x40, 0xed, 0x18, 0x45, 0xf1, 0xce, 0x8a, 0x5c,
-+ 0x6b, 0x3e, 0xab, 0x03, 0xd3, 0x70, 0x18, 0x2a, 0x0a, 0x6a, 0xe0, 0x5f, 0x47,
-+ 0xd1, 0xd5, 0x63, 0x0a, 0x32, 0xf2, 0xaf, 0xd7, 0x36, 0x1f, 0x2a, 0x70, 0x5a,
-+ 0xe5, 0x42, 0x59, 0x08, 0x71, 0x4b, 0x57, 0xba, 0x7e, 0x83, 0x81, 0xf0, 0x21,
-+ 0x3c, 0xf4, 0x1c, 0xc1, 0xc5, 0xb9, 0x90, 0x93, 0x0e, 0x88, 0x45, 0x93, 0x86,
-+ 0xe9, 0xb1, 0x20, 0x99, 0xbe, 0x98, 0xcb, 0xc5, 0x95, 0xa4, 0x5d, 0x62, 0xd6,
-+ 0xa0, 0x63, 0x08, 0x20, 0xbd, 0x75, 0x10, 0x77, 0x7d, 0x3d, 0xf3, 0x45, 0xb9,
-+ 0x9f, 0x97, 0x9f, 0xcb, 0x57, 0x80, 0x6f, 0x33, 0xa9, 0x04, 0xcf, 0x77, 0xa4,
-+ 0x62, 0x1c, 0x59, 0x7e
-+};
-+
-+//
-+// Second DB entry: "Microsoft Corporation UEFI CA 2011"
-+// SHA1: 46:de:f6:3b:5c:e6:1c:f8:ba:0d:e2:e6:63:9c:10:19:d0:ed:14:f3
-+//
-+// To verify the "shim" binary and PCI expansion ROMs with.
-+//
-+STATIC CONST UINT8 MicrosoftUefiCA[] = {
-+ 0x30, 0x82, 0x06, 0x10, 0x30, 0x82, 0x03, 0xf8, 0xa0, 0x03, 0x02, 0x01, 0x02,
-+ 0x02, 0x0a, 0x61, 0x08, 0xd3, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30,
-+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
-+ 0x00, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
-+ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
-+ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
-+ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
-+ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
-+ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3b, 0x30,
-+ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x4d, 0x69, 0x63, 0x72, 0x6f,
-+ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
-+ 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72,
-+ 0x74, 0x79, 0x20, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x70, 0x6c, 0x61, 0x63,
-+ 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30,
-+ 0x36, 0x32, 0x37, 0x32, 0x31, 0x32, 0x32, 0x34, 0x35, 0x5a, 0x17, 0x0d, 0x32,
-+ 0x36, 0x30, 0x36, 0x32, 0x37, 0x32, 0x31, 0x33, 0x32, 0x34, 0x35, 0x5a, 0x30,
-+ 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
-+ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
-+ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30,
-+ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f,
-+ 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15,
-+ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
-+ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2b, 0x30, 0x29, 0x06,
-+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
-+ 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
-+ 0x6e, 0x20, 0x55, 0x45, 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31,
-+ 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
-+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0x08, 0x6c, 0x4c, 0xc7,
-+ 0x45, 0x09, 0x6a, 0x4b, 0x0c, 0xa4, 0xc0, 0x87, 0x7f, 0x06, 0x75, 0x0c, 0x43,
-+ 0x01, 0x54, 0x64, 0xe0, 0x16, 0x7f, 0x07, 0xed, 0x92, 0x7d, 0x0b, 0xb2, 0x73,
-+ 0xbf, 0x0c, 0x0a, 0xc6, 0x4a, 0x45, 0x61, 0xa0, 0xc5, 0x16, 0x2d, 0x96, 0xd3,
-+ 0xf5, 0x2b, 0xa0, 0xfb, 0x4d, 0x49, 0x9b, 0x41, 0x80, 0x90, 0x3c, 0xb9, 0x54,
-+ 0xfd, 0xe6, 0xbc, 0xd1, 0x9d, 0xc4, 0xa4, 0x18, 0x8a, 0x7f, 0x41, 0x8a, 0x5c,
-+ 0x59, 0x83, 0x68, 0x32, 0xbb, 0x8c, 0x47, 0xc9, 0xee, 0x71, 0xbc, 0x21, 0x4f,
-+ 0x9a, 0x8a, 0x7c, 0xff, 0x44, 0x3f, 0x8d, 0x8f, 0x32, 0xb2, 0x26, 0x48, 0xae,
-+ 0x75, 0xb5, 0xee, 0xc9, 0x4c, 0x1e, 0x4a, 0x19, 0x7e, 0xe4, 0x82, 0x9a, 0x1d,
-+ 0x78, 0x77, 0x4d, 0x0c, 0xb0, 0xbd, 0xf6, 0x0f, 0xd3, 0x16, 0xd3, 0xbc, 0xfa,
-+ 0x2b, 0xa5, 0x51, 0x38, 0x5d, 0xf5, 0xfb, 0xba, 0xdb, 0x78, 0x02, 0xdb, 0xff,
-+ 0xec, 0x0a, 0x1b, 0x96, 0xd5, 0x83, 0xb8, 0x19, 0x13, 0xe9, 0xb6, 0xc0, 0x7b,
-+ 0x40, 0x7b, 0xe1, 0x1f, 0x28, 0x27, 0xc9, 0xfa, 0xef, 0x56, 0x5e, 0x1c, 0xe6,
-+ 0x7e, 0x94, 0x7e, 0xc0, 0xf0, 0x44, 0xb2, 0x79, 0x39, 0xe5, 0xda, 0xb2, 0x62,
-+ 0x8b, 0x4d, 0xbf, 0x38, 0x70, 0xe2, 0x68, 0x24, 0x14, 0xc9, 0x33, 0xa4, 0x08,
-+ 0x37, 0xd5, 0x58, 0x69, 0x5e, 0xd3, 0x7c, 0xed, 0xc1, 0x04, 0x53, 0x08, 0xe7,
-+ 0x4e, 0xb0, 0x2a, 0x87, 0x63, 0x08, 0x61, 0x6f, 0x63, 0x15, 0x59, 0xea, 0xb2,
-+ 0x2b, 0x79, 0xd7, 0x0c, 0x61, 0x67, 0x8a, 0x5b, 0xfd, 0x5e, 0xad, 0x87, 0x7f,
-+ 0xba, 0x86, 0x67, 0x4f, 0x71, 0x58, 0x12, 0x22, 0x04, 0x22, 0x22, 0xce, 0x8b,
-+ 0xef, 0x54, 0x71, 0x00, 0xce, 0x50, 0x35, 0x58, 0x76, 0x95, 0x08, 0xee, 0x6a,
-+ 0xb1, 0xa2, 0x01, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x76,
-+ 0x30, 0x82, 0x01, 0x72, 0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01,
-+ 0x82, 0x37, 0x15, 0x01, 0x04, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x23,
-+ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x02, 0x04, 0x16,
-+ 0x04, 0x14, 0xf8, 0xc1, 0x6b, 0xb7, 0x7f, 0x77, 0x53, 0x4a, 0xf3, 0x25, 0x37,
-+ 0x1d, 0x4e, 0xa1, 0x26, 0x7b, 0x0f, 0x20, 0x70, 0x80, 0x30, 0x1d, 0x06, 0x03,
-+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x13, 0xad, 0xbf, 0x43, 0x09, 0xbd,
-+ 0x82, 0x70, 0x9c, 0x8c, 0xd5, 0x4f, 0x31, 0x6e, 0xd5, 0x22, 0x98, 0x8a, 0x1b,
-+ 0xd4, 0x30, 0x19, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14,
-+ 0x02, 0x04, 0x0c, 0x1e, 0x0a, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43,
-+ 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02,
-+ 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
-+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
-+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0x66, 0x52, 0x43, 0xe1, 0x7e, 0x58,
-+ 0x11, 0xbf, 0xd6, 0x4e, 0x9e, 0x23, 0x55, 0x08, 0x3b, 0x3a, 0x22, 0x6a, 0xa8,
-+ 0x30, 0x5c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x55, 0x30, 0x53, 0x30, 0x51,
-+ 0xa0, 0x4f, 0xa0, 0x4d, 0x86, 0x4b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
-+ 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
-+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f,
-+ 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43,
-+ 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f,
-+ 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e,
-+ 0x63, 0x72, 0x6c, 0x30, 0x60, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
-+ 0x01, 0x01, 0x04, 0x54, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, 0x06, 0x01,
-+ 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
-+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66,
-+ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65, 0x72,
-+ 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50,
-+ 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30,
-+ 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06,
-+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
-+ 0x82, 0x02, 0x01, 0x00, 0x35, 0x08, 0x42, 0xff, 0x30, 0xcc, 0xce, 0xf7, 0x76,
-+ 0x0c, 0xad, 0x10, 0x68, 0x58, 0x35, 0x29, 0x46, 0x32, 0x76, 0x27, 0x7c, 0xef,
-+ 0x12, 0x41, 0x27, 0x42, 0x1b, 0x4a, 0xaa, 0x6d, 0x81, 0x38, 0x48, 0x59, 0x13,
-+ 0x55, 0xf3, 0xe9, 0x58, 0x34, 0xa6, 0x16, 0x0b, 0x82, 0xaa, 0x5d, 0xad, 0x82,
-+ 0xda, 0x80, 0x83, 0x41, 0x06, 0x8f, 0xb4, 0x1d, 0xf2, 0x03, 0xb9, 0xf3, 0x1a,
-+ 0x5d, 0x1b, 0xf1, 0x50, 0x90, 0xf9, 0xb3, 0x55, 0x84, 0x42, 0x28, 0x1c, 0x20,
-+ 0xbd, 0xb2, 0xae, 0x51, 0x14, 0xc5, 0xc0, 0xac, 0x97, 0x95, 0x21, 0x1c, 0x90,
-+ 0xdb, 0x0f, 0xfc, 0x77, 0x9e, 0x95, 0x73, 0x91, 0x88, 0xca, 0xbd, 0xbd, 0x52,
-+ 0xb9, 0x05, 0x50, 0x0d, 0xdf, 0x57, 0x9e, 0xa0, 0x61, 0xed, 0x0d, 0xe5, 0x6d,
-+ 0x25, 0xd9, 0x40, 0x0f, 0x17, 0x40, 0xc8, 0xce, 0xa3, 0x4a, 0xc2, 0x4d, 0xaf,
-+ 0x9a, 0x12, 0x1d, 0x08, 0x54, 0x8f, 0xbd, 0xc7, 0xbc, 0xb9, 0x2b, 0x3d, 0x49,
-+ 0x2b, 0x1f, 0x32, 0xfc, 0x6a, 0x21, 0x69, 0x4f, 0x9b, 0xc8, 0x7e, 0x42, 0x34,
-+ 0xfc, 0x36, 0x06, 0x17, 0x8b, 0x8f, 0x20, 0x40, 0xc0, 0xb3, 0x9a, 0x25, 0x75,
-+ 0x27, 0xcd, 0xc9, 0x03, 0xa3, 0xf6, 0x5d, 0xd1, 0xe7, 0x36, 0x54, 0x7a, 0xb9,
-+ 0x50, 0xb5, 0xd3, 0x12, 0xd1, 0x07, 0xbf, 0xbb, 0x74, 0xdf, 0xdc, 0x1e, 0x8f,
-+ 0x80, 0xd5, 0xed, 0x18, 0xf4, 0x2f, 0x14, 0x16, 0x6b, 0x2f, 0xde, 0x66, 0x8c,
-+ 0xb0, 0x23, 0xe5, 0xc7, 0x84, 0xd8, 0xed, 0xea, 0xc1, 0x33, 0x82, 0xad, 0x56,
-+ 0x4b, 0x18, 0x2d, 0xf1, 0x68, 0x95, 0x07, 0xcd, 0xcf, 0xf0, 0x72, 0xf0, 0xae,
-+ 0xbb, 0xdd, 0x86, 0x85, 0x98, 0x2c, 0x21, 0x4c, 0x33, 0x2b, 0xf0, 0x0f, 0x4a,
-+ 0xf0, 0x68, 0x87, 0xb5, 0x92, 0x55, 0x32, 0x75, 0xa1, 0x6a, 0x82, 0x6a, 0x3c,
-+ 0xa3, 0x25, 0x11, 0xa4, 0xed, 0xad, 0xd7, 0x04, 0xae, 0xcb, 0xd8, 0x40, 0x59,
-+ 0xa0, 0x84, 0xd1, 0x95, 0x4c, 0x62, 0x91, 0x22, 0x1a, 0x74, 0x1d, 0x8c, 0x3d,
-+ 0x47, 0x0e, 0x44, 0xa6, 0xe4, 0xb0, 0x9b, 0x34, 0x35, 0xb1, 0xfa, 0xb6, 0x53,
-+ 0xa8, 0x2c, 0x81, 0xec, 0xa4, 0x05, 0x71, 0xc8, 0x9d, 0xb8, 0xba, 0xe8, 0x1b,
-+ 0x44, 0x66, 0xe4, 0x47, 0x54, 0x0e, 0x8e, 0x56, 0x7f, 0xb3, 0x9f, 0x16, 0x98,
-+ 0xb2, 0x86, 0xd0, 0x68, 0x3e, 0x90, 0x23, 0xb5, 0x2f, 0x5e, 0x8f, 0x50, 0x85,
-+ 0x8d, 0xc6, 0x8d, 0x82, 0x5f, 0x41, 0xa1, 0xf4, 0x2e, 0x0d, 0xe0, 0x99, 0xd2,
-+ 0x6c, 0x75, 0xe4, 0xb6, 0x69, 0xb5, 0x21, 0x86, 0xfa, 0x07, 0xd1, 0xf6, 0xe2,
-+ 0x4d, 0xd1, 0xda, 0xad, 0x2c, 0x77, 0x53, 0x1e, 0x25, 0x32, 0x37, 0xc7, 0x6c,
-+ 0x52, 0x72, 0x95, 0x86, 0xb0, 0xf1, 0x35, 0x61, 0x6a, 0x19, 0xf5, 0xb2, 0x3b,
-+ 0x81, 0x50, 0x56, 0xa6, 0x32, 0x2d, 0xfe, 0xa2, 0x89, 0xf9, 0x42, 0x86, 0x27,
-+ 0x18, 0x55, 0xa1, 0x82, 0xca, 0x5a, 0x9b, 0xf8, 0x30, 0x98, 0x54, 0x14, 0xa6,
-+ 0x47, 0x96, 0x25, 0x2f, 0xc8, 0x26, 0xe4, 0x41, 0x94, 0x1a, 0x5c, 0x02, 0x3f,
-+ 0xe5, 0x96, 0xe3, 0x85, 0x5b, 0x3c, 0x3e, 0x3f, 0xbb, 0x47, 0x16, 0x72, 0x55,
-+ 0xe2, 0x25, 0x22, 0xb1, 0xd9, 0x7b, 0xe7, 0x03, 0x06, 0x2a, 0xa3, 0xf7, 0x1e,
-+ 0x90, 0x46, 0xc3, 0x00, 0x0d, 0xd6, 0x19, 0x89, 0xe3, 0x0e, 0x35, 0x27, 0x62,
-+ 0x03, 0x71, 0x15, 0xa6, 0xef, 0xd0, 0x27, 0xa0, 0xa0, 0x59, 0x37, 0x60, 0xf8,
-+ 0x38, 0x94, 0xb8, 0xe0, 0x78, 0x70, 0xf8, 0xba, 0x4c, 0x86, 0x87, 0x94, 0xf6,
-+ 0xe0, 0xae, 0x02, 0x45, 0xee, 0x65, 0xc2, 0xb6, 0xa3, 0x7e, 0x69, 0x16, 0x75,
-+ 0x07, 0x92, 0x9b, 0xf5, 0xa6, 0xbc, 0x59, 0x83, 0x58
-+};
-+
-+//
-+// The most important thing about the variable payload is that it is a list of
-+// lists, where the element size of any given *inner* list is constant.
-+//
-+// Since X509 certificates vary in size, each of our *inner* lists will contain
-+// one element only (one X.509 certificate). This is explicitly mentioned in
-+// the UEFI specification, in "28.4.1 Signature Database", in a Note.
-+//
-+// The list structure looks as follows:
-+//
-+// struct EFI_VARIABLE_AUTHENTICATION_2 { |
-+// struct EFI_TIME { |
-+// UINT16 Year; |
-+// UINT8 Month; |
-+// UINT8 Day; |
-+// UINT8 Hour; |
-+// UINT8 Minute; |
-+// UINT8 Second; |
-+// UINT8 Pad1; |
-+// UINT32 Nanosecond; |
-+// INT16 TimeZone; |
-+// UINT8 Daylight; |
-+// UINT8 Pad2; |
-+// } TimeStamp; |
-+// |
-+// struct WIN_CERTIFICATE_UEFI_GUID { | |
-+// struct WIN_CERTIFICATE { | |
-+// UINT32 dwLength; ----------------------------------------+ |
-+// UINT16 wRevision; | |
-+// UINT16 wCertificateType; | |
-+// } Hdr; | +- DataSize
-+// | |
-+// EFI_GUID CertType; | |
-+// UINT8 CertData[1] = { <--- "struct hack" | |
-+// struct EFI_SIGNATURE_LIST { | | |
-+// EFI_GUID SignatureType; | | |
-+// UINT32 SignatureListSize; -------------------------+ | |
-+// UINT32 SignatureHeaderSize; | | |
-+// UINT32 SignatureSize; ---------------------------+ | | |
-+// UINT8 SignatureHeader[SignatureHeaderSize]; | | | |
-+// v | | |
-+// struct EFI_SIGNATURE_DATA { | | | |
-+// EFI_GUID SignatureOwner; | | | |
-+// UINT8 SignatureData[1] = { <--- "struct hack" | | | |
-+// X.509 payload | | | |
-+// } | | | |
-+// } Signatures[]; | | |
-+// } SigLists[]; | |
-+// }; | |
-+// } AuthInfo; | |
-+// }; |
-+//
-+// Given that the "struct hack" invokes undefined behavior (which is why C99
-+// introduced the flexible array member), and because subtracting those pesky
-+// sizes of 1 is annoying, and because the format is fully specified in the
-+// UEFI specification, we'll introduce two matching convenience structures that
-+// are customized for our X.509 purposes.
-+//
-+#pragma pack(1)
-+typedef struct {
-+ EFI_TIME TimeStamp;
-+
-+ //
-+ // dwLength covers data below
-+ //
-+ UINT32 dwLength;
-+ UINT16 wRevision;
-+ UINT16 wCertificateType;
-+ EFI_GUID CertType;
-+} SINGLE_HEADER;
-+
-+typedef struct {
-+ //
-+ // SignatureListSize covers data below
-+ //
-+ EFI_GUID SignatureType;
-+ UINT32 SignatureListSize;
-+ UINT32 SignatureHeaderSize; // constant 0
-+ UINT32 SignatureSize;
-+
-+ //
-+ // SignatureSize covers data below
-+ //
-+ EFI_GUID SignatureOwner;
-+
-+ //
-+ // X.509 certificate follows
-+ //
-+} REPEATING_HEADER;
-+#pragma pack()
-+
-+/**
-+ Enroll a set of DER-formatted X.509 certificates in a global variable,
-+ overwriting it.
-+
-+ The variable will be rewritten with NV+BS+RT+AT attributes.
-+
-+ @param[in] VariableName The name of the variable to overwrite.
-+
-+ @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to
-+ overwrite.
-+
-+ @param[in] ... A list of
-+
-+ IN CONST UINT8 *Cert,
-+ IN UINTN CertSize,
-+ IN CONST EFI_GUID *OwnerGuid
-+
-+ triplets. If the first component of a triplet is
-+ NULL, then the other two components are not
-+ accessed, and processing is terminated. The list of
-+ X.509 certificates is enrolled in the variable
-+ specified, overwriting it. The OwnerGuid component
-+ identifies the agent installing the certificate.
-+
-+ @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert
-+ value is NULL), or one of the CertSize values
-+ is 0, or one of the CertSize values would
-+ overflow the accumulated UINT32 data size.
-+
-+ @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable
-+ payload.
-+
-+ @retval EFI_SUCCESS Enrollment successful; the variable has been
-+ overwritten (or created).
-+
-+ @return Error codes from gRT->GetTime() and
-+ gRT->SetVariable().
-+**/
-+STATIC
-+EFI_STATUS
-+EFIAPI
-+EnrollListOfX509Certs (
-+ IN CHAR16 *VariableName,
-+ IN EFI_GUID *VendorGuid,
-+ ...
-+ )
-+{
-+ UINTN DataSize;
-+ SINGLE_HEADER *SingleHeader;
-+ REPEATING_HEADER *RepeatingHeader;
-+ VA_LIST Marker;
-+ CONST UINT8 *Cert;
-+ EFI_STATUS Status;
-+ UINT8 *Data;
-+ UINT8 *Position;
-+
-+ Status = EFI_SUCCESS;
-+
-+ //
-+ // compute total size first, for UINT32 range check, and allocation
-+ //
-+ DataSize = sizeof *SingleHeader;
-+ VA_START (Marker, VendorGuid);
-+ for (Cert = VA_ARG (Marker, CONST UINT8 *);
-+ Cert != NULL;
-+ Cert = VA_ARG (Marker, CONST UINT8 *)) {
-+ UINTN CertSize;
-+
-+ CertSize = VA_ARG (Marker, UINTN);
-+ (VOID)VA_ARG (Marker, CONST EFI_GUID *);
-+
-+ if (CertSize == 0 ||
-+ CertSize > MAX_UINT32 - sizeof *RepeatingHeader ||
-+ DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) {
-+ Status = EFI_INVALID_PARAMETER;
-+ break;
-+ }
-+ DataSize += sizeof *RepeatingHeader + CertSize;
-+ }
-+ VA_END (Marker);
-+
-+ if (DataSize == sizeof *SingleHeader) {
-+ Status = EFI_INVALID_PARAMETER;
-+ }
-+ if (EFI_ERROR (Status)) {
-+ goto Out;
-+ }
-+
-+ Data = AllocatePool (DataSize);
-+ if (Data == NULL) {
-+ Status = EFI_OUT_OF_RESOURCES;
-+ goto Out;
-+ }
-+
-+ Position = Data;
-+
-+ SingleHeader = (SINGLE_HEADER *)Position;
-+ Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL);
-+ if (EFI_ERROR (Status)) {
-+ goto FreeData;
-+ }
-+ SingleHeader->TimeStamp.Pad1 = 0;
-+ SingleHeader->TimeStamp.Nanosecond = 0;
-+ SingleHeader->TimeStamp.TimeZone = 0;
-+ SingleHeader->TimeStamp.Daylight = 0;
-+ SingleHeader->TimeStamp.Pad2 = 0;
-+#if 0
-+ SingleHeader->dwLength = DataSize - sizeof SingleHeader->TimeStamp;
-+#else
-+ //
-+ // This looks like a bug in edk2. According to the UEFI specification,
-+ // dwLength is "The length of the entire certificate, including the length of
-+ // the header, in bytes". That shouldn't stop right after CertType -- it
-+ // should include everything below it.
-+ //
-+ SingleHeader->dwLength = sizeof *SingleHeader
-+ - sizeof SingleHeader->TimeStamp;
-+#endif
-+ SingleHeader->wRevision = 0x0200;
-+ SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID;
-+ CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid);
-+ Position += sizeof *SingleHeader;
-+
-+ VA_START (Marker, VendorGuid);
-+ for (Cert = VA_ARG (Marker, CONST UINT8 *);
-+ Cert != NULL;
-+ Cert = VA_ARG (Marker, CONST UINT8 *)) {
-+ UINTN CertSize;
-+ CONST EFI_GUID *OwnerGuid;
-+
-+ CertSize = VA_ARG (Marker, UINTN);
-+ OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *);
-+
-+ RepeatingHeader = (REPEATING_HEADER *)Position;
-+ CopyGuid (&RepeatingHeader->SignatureType, &gEfiCertX509Guid);
-+ RepeatingHeader->SignatureListSize =
-+ (UINT32)(sizeof *RepeatingHeader + CertSize);
-+ RepeatingHeader->SignatureHeaderSize = 0;
-+ RepeatingHeader->SignatureSize =
-+ (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize);
-+ CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid);
-+ Position += sizeof *RepeatingHeader;
-+
-+ CopyMem (Position, Cert, CertSize);
-+ Position += CertSize;
-+ }
-+ VA_END (Marker);
-+
-+ ASSERT (Data + DataSize == Position);
-+
-+ Status = gRT->SetVariable (VariableName, VendorGuid,
-+ (EFI_VARIABLE_NON_VOLATILE |
-+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
-+ EFI_VARIABLE_RUNTIME_ACCESS |
-+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
-+ DataSize, Data);
-+
-+FreeData:
-+ FreePool (Data);
-+
-+Out:
-+ if (EFI_ERROR (Status)) {
-+ AsciiPrint ("error: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName,
-+ VendorGuid, Status);
-+ }
-+ return Status;
-+}
-+
-+
-+STATIC
-+EFI_STATUS
-+EFIAPI
-+GetExact (
-+ IN CHAR16 *VariableName,
-+ IN EFI_GUID *VendorGuid,
-+ OUT VOID *Data,
-+ IN UINTN DataSize,
-+ IN BOOLEAN AllowMissing
-+ )
-+{
-+ UINTN Size;
-+ EFI_STATUS Status;
-+
-+ Size = DataSize;
-+ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data);
-+ if (EFI_ERROR (Status)) {
-+ if (Status == EFI_NOT_FOUND && AllowMissing) {
-+ ZeroMem (Data, DataSize);
-+ return EFI_SUCCESS;
-+ }
-+
-+ AsciiPrint ("error: GetVariable(\"%s\", %g): %r\n", VariableName,
-+ VendorGuid, Status);
-+ return Status;
-+ }
-+
-+ if (Size != DataSize) {
-+ AsciiPrint ("error: GetVariable(\"%s\", %g): expected size 0x%Lx, "
-+ "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size);
-+ return EFI_PROTOCOL_ERROR;
-+ }
-+
-+ return EFI_SUCCESS;
-+}
-+
-+typedef struct {
-+ UINT8 SetupMode;
-+ UINT8 SecureBoot;
-+ UINT8 SecureBootEnable;
-+ UINT8 CustomMode;
-+ UINT8 VendorKeys;
-+} SETTINGS;
-+
-+STATIC
-+EFI_STATUS
-+EFIAPI
-+GetSettings (
-+ OUT SETTINGS *Settings
-+ )
-+{
-+ EFI_STATUS Status;
-+
-+ Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,
-+ &Settings->SetupMode, sizeof Settings->SetupMode, FALSE);
-+ if (EFI_ERROR (Status)) {
-+ return Status;
-+ }
-+
-+ Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,
-+ &Settings->SecureBoot, sizeof Settings->SecureBoot, FALSE);
-+ if (EFI_ERROR (Status)) {
-+ return Status;
-+ }
-+
-+ Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME,
-+ &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable,
-+ sizeof Settings->SecureBootEnable, TRUE);
-+ if (EFI_ERROR (Status)) {
-+ return Status;
-+ }
-+
-+ Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
-+ &Settings->CustomMode, sizeof Settings->CustomMode, FALSE);
-+ if (EFI_ERROR (Status)) {
-+ return Status;
-+ }
-+
-+ Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid,
-+ &Settings->VendorKeys, sizeof Settings->VendorKeys, FALSE);
-+ return Status;
-+}
-+
-+STATIC
-+VOID
-+EFIAPI
-+PrintSettings (
-+ IN CONST SETTINGS *Settings
-+ )
-+{
-+ AsciiPrint ("info: SetupMode=%d SecureBoot=%d SecureBootEnable=%d "
-+ "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot,
-+ Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys);
-+}
-+
-+
-+INTN
-+EFIAPI
-+ShellAppMain (
-+ IN UINTN Argc,
-+ IN CHAR16 **Argv
-+ )
-+{
-+ EFI_STATUS Status;
-+ SETTINGS Settings;
-+
-+ Status = GetSettings (&Settings);
-+ if (EFI_ERROR (Status)) {
-+ return 1;
-+ }
-+ PrintSettings (&Settings);
-+
-+ if (Settings.SetupMode != 1) {
-+ AsciiPrint ("error: already in User Mode\n");
-+ return 1;
-+ }
-+
-+ if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {
-+ Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE;
-+ Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
-+ (EFI_VARIABLE_NON_VOLATILE |
-+ EFI_VARIABLE_BOOTSERVICE_ACCESS),
-+ sizeof Settings.CustomMode, &Settings.CustomMode);
-+ if (EFI_ERROR (Status)) {
-+ AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
-+ &gEfiCustomModeEnableGuid, Status);
-+ return 1;
-+ }
-+ }
-+
-+ Status = EnrollListOfX509Certs (
-+ EFI_IMAGE_SECURITY_DATABASE,
-+ &gEfiImageSecurityDatabaseGuid,
-+ MicrosoftPCA, sizeof MicrosoftPCA, &gEfiCallerIdGuid,
-+ MicrosoftUefiCA, sizeof MicrosoftUefiCA, &gEfiCallerIdGuid,
-+ NULL);
-+ if (EFI_ERROR (Status)) {
-+ return 1;
-+ }
-+
-+ Status = EnrollListOfX509Certs (
-+ EFI_KEY_EXCHANGE_KEY_NAME,
-+ &gEfiGlobalVariableGuid,
-+ ExampleCert, sizeof ExampleCert, &gEfiCallerIdGuid,
-+ MicrosoftKEK, sizeof MicrosoftKEK, &gEfiCallerIdGuid,
-+ NULL);
-+ if (EFI_ERROR (Status)) {
-+ return 1;
-+ }
-+
-+ Status = EnrollListOfX509Certs (
-+ EFI_PLATFORM_KEY_NAME,
-+ &gEfiGlobalVariableGuid,
-+ ExampleCert, sizeof ExampleCert, &gEfiGlobalVariableGuid,
-+ NULL);
-+ if (EFI_ERROR (Status)) {
-+ return 1;
-+ }
-+
-+ Settings.CustomMode = STANDARD_SECURE_BOOT_MODE;
-+ Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
-+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
-+ sizeof Settings.CustomMode, &Settings.CustomMode);
-+ if (EFI_ERROR (Status)) {
-+ AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
-+ &gEfiCustomModeEnableGuid, Status);
-+ return 1;
-+ }
-+
-+ Status = GetSettings (&Settings);
-+ if (EFI_ERROR (Status)) {
-+ return 1;
-+ }
-+ PrintSettings (&Settings);
-+
-+ if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 ||
-+ Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 ||
-+ Settings.VendorKeys != 0) {
-+ AsciiPrint ("error: unexpected\n");
-+ return 1;
-+ }
-+
-+ AsciiPrint ("info: success\n");
-+ return 0;
-+}
-diff --git a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
-new file mode 100644
-index 0000000..ac919bb
---- /dev/null
-+++ b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
-@@ -0,0 +1,51 @@
-+## @file
-+# Enroll default PK, KEK, DB.
-+#
-+# Copyright (C) 2014, Red Hat, Inc.
-+#
-+# This program and the accompanying materials are licensed and made available
-+# under the terms and conditions of the BSD License which accompanies this
-+# distribution. The full text of the license may be found at
-+# http://opensource.org/licenses/bsd-license .
-+#
-+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
-+# IMPLIED.
-+##
-+
-+[Defines]
-+ INF_VERSION = 0x00010006
-+ BASE_NAME = EnrollDefaultKeys
-+ FILE_GUID = D5C1DF0B-1BAC-4EDF-BA48-08834009CA5A
-+ MODULE_TYPE = UEFI_APPLICATION
-+ VERSION_STRING = 0.1
-+ ENTRY_POINT = ShellCEntryLib
-+
-+#
-+# VALID_ARCHITECTURES = IA32 X64
-+#
-+
-+[Sources]
-+ EnrollDefaultKeys.c
-+
-+[Packages]
-+ MdePkg/MdePkg.dec
-+ MdeModulePkg/MdeModulePkg.dec
-+ SecurityPkg/SecurityPkg.dec
-+ ShellPkg/ShellPkg.dec
-+
-+[Guids]
-+ gEfiCertPkcs7Guid
-+ gEfiCertX509Guid
-+ gEfiCustomModeEnableGuid
-+ gEfiGlobalVariableGuid
-+ gEfiImageSecurityDatabaseGuid
-+ gEfiSecureBootEnableDisableGuid
-+
-+[LibraryClasses]
-+ BaseMemoryLib
-+ DebugLib
-+ MemoryAllocationLib
-+ ShellCEntryLib
-+ UefiLib
-+ UefiRuntimeServicesTableLib
-diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
-index 8af3267..6fb5c9c 100644
---- a/OvmfPkg/OvmfPkgIa32.dsc
-+++ b/OvmfPkg/OvmfPkgIa32.dsc
-@@ -749,6 +749,10 @@
-
- !if $(SECURE_BOOT_ENABLE) == TRUE
- SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
-+ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
-+ <LibraryClasses>
-+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
-+ }
- !endif
-
- OvmfPkg/PlatformDxe/Platform.inf
-diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
-index 4bb38d0..e5abaff 100644
---- a/OvmfPkg/OvmfPkgIa32X64.dsc
-+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
-@@ -758,6 +758,10 @@
-
- !if $(SECURE_BOOT_ENABLE) == TRUE
- SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
-+ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
-+ <LibraryClasses>
-+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
-+ }
- !endif
-
- OvmfPkg/PlatformDxe/Platform.inf
-diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
-index be3aa1f..4c36a7d 100644
---- a/OvmfPkg/OvmfPkgX64.dsc
-+++ b/OvmfPkg/OvmfPkgX64.dsc
-@@ -756,6 +756,10 @@
-
- !if $(SECURE_BOOT_ENABLE) == TRUE
- SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
-+ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
-+ <LibraryClasses>
-+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
-+ }
- !endif
-
- OvmfPkg/PlatformDxe/Platform.inf
---
-1.8.3.1
-
diff --git a/0008-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch b/0008-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
deleted file mode 100644
index 61aa133..0000000
--- a/0008-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
+++ /dev/null
@@ -1,113 +0,0 @@
-From: Laszlo Ersek <lersek(a)redhat.com>
-Date: Tue, 25 Feb 2014 18:40:35 +0100
-Subject: [PATCH] MdeModulePkg: TerminalDxe: add other text resolutions
-
-When the console output is multiplexed to several devices by
-ConSplitterDxe, then ConSplitterDxe builds an intersection of text modes
-supported by all console output devices.
-
-Two notable output devices are provided by:
-(1) MdeModulePkg/Universal/Console/GraphicsConsoleDxe,
-(2) MdeModulePkg/Universal/Console/TerminalDxe.
-
-GraphicsConsoleDxe supports four modes at most -- see
-InitializeGraphicsConsoleTextMode():
-
-(1a) 80x25 (required by the UEFI spec as mode 0),
-(1b) 80x50 (not necessarily supported, but if it is, then the UEFI spec
- requires the driver to provide it as mode 1),
-(1c) 100x31 (corresponding to graphics resolution 800x600, which the UEFI
- spec requires from all plug-in graphics devices),
-(1d) "full screen" resolution, derived form the underlying GOP's
- horizontal and vertical resolutions with division by EFI_GLYPH_WIDTH
- (8) and EFI_GLYPH_HEIGHT (19), respectively.
-
-The automatic "full screen resolution" makes GraphicsConsoleDxe's
-character console very flexible. However, TerminalDxe (which runs on
-serial ports) only provides the following fixed resolutions -- see
-InitializeTerminalConsoleTextMode():
-
-(2a) 80x25 (required by the UEFI spec as mode 0),
-(2b) 80x50 (since the character resolution of a serial device cannot be
- interrogated easily, this is added unconditionally as mode 1)
-(2c) modes 2 and above come from "mTerminalConsoleModeData". This table
- currently only contains one mode, 100x31.
-
-When ConSplitterDxe combines (1) and (2), multiplexing console output to
-both video output and serial terminal, the list of commonly supported text
-modes (ie. the "intersection") comprises:
-
-(3a) 80x25, unconditionally, from (1a) and (2a),
-(3b) 80x50, if the graphics console provides at least 640x950 pixel
- resolution, from (1b) and (2b)
-(3c) 100x31, if the graphics device is a plug-in one (because in that case
- 800x600 is a mandated pixel resolution), from (1c) and (2c).
-
-Unfortunately, the "full screen resolution" (1d) of the GOP-based text
-console is not available in general.
-
-Mitigate this problem by extending "mTerminalConsoleModeData" with a
-handful of text resolutions that are derived from widespread maximal pixel
-resolutions. This way TerminalDxe won't cause ConSplitterDxe to filter out
-the most frequent (1d) values from the intersection, and eg. the MODE
-command in the UEFI shell will offer the "best" (ie. full screen)
-resolution too.
-
-Contributed-under: TianoCore Contribution Agreement 1.0
-Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
----
- .../Universal/Console/TerminalDxe/Terminal.c | 41 ++++++++++++++++++++--
- 1 file changed, 38 insertions(+), 3 deletions(-)
-
-diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
-index 5d55969..13620ac 100644
---- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
-+++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
-@@ -113,9 +113,44 @@ TERMINAL_DEV mTerminalDevTemplate = {
- };
-
- TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
-- {80, 25},
-- {80, 50},
-- {100, 31},
-+ { 80, 25 }, // from graphics resolution 640 x 480
-+ { 80, 50 }, // from graphics resolution 640 x 480
-+ { 100, 25 }, // from graphics resolution 800 x 480
-+ { 100, 31 }, // from graphics resolution 800 x 600
-+ { 104, 32 }, // from graphics resolution 832 x 624
-+ { 120, 33 }, // from graphics resolution 960 x 640
-+ { 128, 31 }, // from graphics resolution 1024 x 600
-+ { 128, 40 }, // from graphics resolution 1024 x 768
-+ { 144, 45 }, // from graphics resolution 1152 x 864
-+ { 144, 45 }, // from graphics resolution 1152 x 870
-+ { 160, 37 }, // from graphics resolution 1280 x 720
-+ { 160, 40 }, // from graphics resolution 1280 x 760
-+ { 160, 40 }, // from graphics resolution 1280 x 768
-+ { 160, 42 }, // from graphics resolution 1280 x 800
-+ { 160, 50 }, // from graphics resolution 1280 x 960
-+ { 160, 53 }, // from graphics resolution 1280 x 1024
-+ { 170, 40 }, // from graphics resolution 1360 x 768
-+ { 170, 40 }, // from graphics resolution 1366 x 768
-+ { 175, 55 }, // from graphics resolution 1400 x 1050
-+ { 180, 47 }, // from graphics resolution 1440 x 900
-+ { 200, 47 }, // from graphics resolution 1600 x 900
-+ { 200, 63 }, // from graphics resolution 1600 x 1200
-+ { 210, 55 }, // from graphics resolution 1680 x 1050
-+ { 240, 56 }, // from graphics resolution 1920 x 1080
-+ { 240, 63 }, // from graphics resolution 1920 x 1200
-+ { 240, 75 }, // from graphics resolution 1920 x 1440
-+ { 250, 105 }, // from graphics resolution 2000 x 2000
-+ { 256, 80 }, // from graphics resolution 2048 x 1536
-+ { 256, 107 }, // from graphics resolution 2048 x 2048
-+ { 320, 75 }, // from graphics resolution 2560 x 1440
-+ { 320, 84 }, // from graphics resolution 2560 x 1600
-+ { 320, 107 }, // from graphics resolution 2560 x 2048
-+ { 350, 110 }, // from graphics resolution 2800 x 2100
-+ { 400, 126 }, // from graphics resolution 3200 x 2400
-+ { 480, 113 }, // from graphics resolution 3840 x 2160
-+ { 512, 113 }, // from graphics resolution 4096 x 2160
-+ { 960, 227 }, // from graphics resolution 7680 x 4320
-+ { 1024, 227 }, // from graphics resolution 8192 x 4320
- //
- // New modes can be added here.
- //
diff --git a/0008-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch b/0008-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch
new file mode 100644
index 0000000..51edfae
--- /dev/null
+++ b/0008-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch
@@ -0,0 +1,128 @@
+From f337eb3972afcccabe86fe663202a758337d0ab8 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Tue, 25 Feb 2014 22:40:01 +0100
+Subject: [PATCH] MdeModulePkg: TerminalDxe: set xterm resolution on mode
+ change (RH only)
+
+The
+
+ CSI Ps ; Ps ; Ps t
+
+escape sequence serves for window manipulation. We can use the
+
+ CSI 8 ; <rows> ; <columns> t
+
+sequence to adapt eg. the xterm window size to the selected console mode.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- refresh commit 519b9751573e against various context changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- Refresh downstream-only commit 2909e025db68 against "MdeModulePkg.dec"
+ context change from upstream commits e043f7895b83 ("MdeModulePkg: Add
+ PCD PcdPteMemoryEncryptionAddressOrMask", 2017-02-27) and 76081dfcc5b2
+ ("MdeModulePkg: Add PROMPT&HELP string of pcd to UNI file", 2017-03-03).
+
+Reference: <http://rtfm.etla.org/xterm/ctlseq.html >
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 2909e025db6878723b49644a8a0cf160d07e6444)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ MdeModulePkg/MdeModulePkg.dec | 4 +++
+ .../Console/TerminalDxe/TerminalConOut.c | 30 +++++++++++++++++++
+ .../Console/TerminalDxe/TerminalDxe.inf | 2 ++
+ 3 files changed, 36 insertions(+)
+
+diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
+index 6a6d9660ed..2dc1cf94e2 100644
+--- a/MdeModulePkg/MdeModulePkg.dec
++++ b/MdeModulePkg/MdeModulePkg.dec
+@@ -1936,6 +1936,10 @@
+ # @Prompt The address mask when memory encryption is enabled.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0|UINT64|0x30001047
+
++ ## Controls whether TerminalDxe outputs an XTerm resize sequence on terminal
++ # mode change.
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE|BOOLEAN|0x00010080
++
+ [PcdsPatchableInModule]
+ ## Specify memory size with page number for PEI code when
+ # Loading Module at Fixed Address feature is enabled.
+diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
+index 4d7218e415..295e7641a5 100644
+--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
++++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
+@@ -13,6 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
++#include <Library/PrintLib.h>
++
+ #include "Terminal.h"
+
+ //
+@@ -86,6 +88,16 @@ CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0
+ CHAR16 mCursorForwardString[] = { ESC, '[', '0', '0', 'C', 0 };
+ CHAR16 mCursorBackwardString[] = { ESC, '[', '0', '0', 'D', 0 };
+
++//
++// Note that this is an ASCII format string, taking two INT32 arguments:
++// rows, columns.
++//
++// A %d (INT32) format specification can expand to at most 11 characters.
++//
++CHAR8 mResizeTextAreaFormatString[] = "\x1B[8;%d;%dt";
++#define RESIZE_SEQ_SIZE (sizeof mResizeTextAreaFormatString + 2 * (11 - 2))
++
++
+ //
+ // Body of the ConOut functions
+ //
+@@ -508,6 +520,24 @@ TerminalConOutSetMode (
+ return EFI_DEVICE_ERROR;
+ }
+
++ if (PcdGetBool (PcdResizeXterm)) {
++ CHAR16 ResizeSequence[RESIZE_SEQ_SIZE];
++
++ UnicodeSPrintAsciiFormat (
++ ResizeSequence,
++ sizeof ResizeSequence,
++ mResizeTextAreaFormatString,
++ (INT32) TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows,
++ (INT32) TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns
++ );
++ TerminalDevice->OutputEscChar = TRUE;
++ Status = This->OutputString (This, ResizeSequence);
++ TerminalDevice->OutputEscChar = FALSE;
++ if (EFI_ERROR (Status)) {
++ return EFI_DEVICE_ERROR;
++ }
++ }
++
+ This->Mode->Mode = (INT32) ModeNumber;
+
+ Status = This->ClearScreen (This);
+diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+index 0780296798..bd2ba828a6 100644
+--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
++++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+@@ -60,6 +60,7 @@
+ DebugLib
+ PcdLib
+ BaseLib
++ PrintLib
+
+ [Guids]
+ ## SOMETIMES_PRODUCES ## Variable:L"ConInDev"
+@@ -88,6 +89,7 @@
+ [Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm ## CONSUMES
+
+ # [Event]
+ # # Relative timer event set by UnicodeToEfiKey(), used to be one 2 seconds input timeout.
diff --git a/0009-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch b/0009-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch
new file mode 100644
index 0000000..0672e56
--- /dev/null
+++ b/0009-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch
@@ -0,0 +1,90 @@
+From 30251344cfbd25212394c377b80cd720a3b85d46 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 14 Oct 2015 15:59:06 +0200
+Subject: [PATCH] OvmfPkg: take PcdResizeXterm from the QEMU command line (RH
+ only)
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- refresh downstream-only commit 8abc2a6ddad2 against context differences
+ in the DSC files from upstream commit 5e167d7e784c
+ ("OvmfPkg/PlatformPei: don't allocate reserved mem varstore if
+ SMM_REQUIRE", 2017-03-12).
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 6fa0c4d67c0bb8bde2ddd6db41c19eb0c40b2721)
+(cherry picked from commit 8abc2a6ddad25af7e88dc0cf57d55dfb75fbf92d)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ OvmfPkg/OvmfPkgIa32.dsc | 1 +
+ OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
+ OvmfPkg/OvmfPkgX64.dsc | 1 +
+ OvmfPkg/PlatformPei/Platform.c | 1 +
+ OvmfPkg/PlatformPei/PlatformPei.inf | 1 +
+ 5 files changed, 5 insertions(+)
+
+diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
+index 0a49336c0d..8dc3ad2be4 100644
+--- a/OvmfPkg/OvmfPkgIa32.dsc
++++ b/OvmfPkg/OvmfPkgIa32.dsc
+@@ -535,6 +535,7 @@
+ # ($(SMM_REQUIRE) == FALSE)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
+index a3d51ef0f7..d81cd865d5 100644
+--- a/OvmfPkg/OvmfPkgIa32X64.dsc
++++ b/OvmfPkg/OvmfPkgIa32X64.dsc
+@@ -541,6 +541,7 @@
+ # ($(SMM_REQUIRE) == FALSE)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
+index f9b4ab4dfa..85bd8d4bf6 100644
+--- a/OvmfPkg/OvmfPkgX64.dsc
++++ b/OvmfPkg/OvmfPkgX64.dsc
+@@ -540,6 +540,7 @@
+ # ($(SMM_REQUIRE) == FALSE)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
+index 5a78668126..544ac547bf 100644
+--- a/OvmfPkg/PlatformPei/Platform.c
++++ b/OvmfPkg/PlatformPei/Platform.c
+@@ -670,6 +670,7 @@ InitializePlatform (
+ PeiFvInitialization ();
+ MemMapInitialization ();
+ NoexecDxeInitialization ();
++ UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdResizeXterm);
+ }
+
+ AmdSevInitialize ();
+diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
+index 9c5ad9961c..31baaa0a22 100644
+--- a/OvmfPkg/PlatformPei/PlatformPei.inf
++++ b/OvmfPkg/PlatformPei/PlatformPei.inf
+@@ -94,6 +94,7 @@
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
diff --git a/0009-Tweak-the-tools_def-to-support-cross-compiling.patch b/0009-Tweak-the-tools_def-to-support-cross-compiling.patch
deleted file mode 100644
index a9b8dfb..0000000
--- a/0009-Tweak-the-tools_def-to-support-cross-compiling.patch
+++ /dev/null
@@ -1,515 +0,0 @@
-From 63b708ccad8afd0b887258888a53fd4945cff682 Mon Sep 17 00:00:00 2001
-Message-Id: <63b708ccad8afd0b887258888a53fd4945cff682.1478467625.git.crobinso(a)redhat.com>
-From: Paolo Bonzini <pbonzini(a)redhat.com>
-Date: Sun, 6 Nov 2016 13:50:31 -0500
-Subject: [PATCH] Tweak the tools_def to support cross-compiling.
-
-These files are meant for customization, so this is not upstream.
----
- BaseTools/Conf/tools_def.template | 343 ++++++++++++++++++--------------------
- 1 file changed, 161 insertions(+), 182 deletions(-)
-
-diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
-index 39fda78..97f5557 100755
---- a/BaseTools/Conf/tools_def.template
-+++ b/BaseTools/Conf/tools_def.template
-@@ -178,27 +178,6 @@ DEFINE CYGWIN_BINIA32 = c:/cygwin/opt/tiano/i386-tiano-pe/i386-tiano-pe
- DEFINE CYGWIN_BINX64 = c:/cygwin/opt/tiano/x86_64-pc-mingw64/x86_64-pc-mingw64/bin/
- DEFINE CYGWIN_BINIPF = c:/cygwin/opt/tiano/gcc/ipf/bin/ia64-pc-elf-
-
--DEFINE GCC44_IA32_PREFIX = ENV(GCC44_BIN)
--DEFINE GCC44_X64_PREFIX = ENV(GCC44_BIN)
--
--DEFINE GCC45_IA32_PREFIX = ENV(GCC45_BIN)
--DEFINE GCC45_X64_PREFIX = ENV(GCC45_BIN)
--
--DEFINE GCC46_IA32_PREFIX = ENV(GCC46_BIN)
--DEFINE GCC46_X64_PREFIX = ENV(GCC46_BIN)
--
--DEFINE GCC47_IA32_PREFIX = ENV(GCC47_BIN)
--DEFINE GCC47_X64_PREFIX = ENV(GCC47_BIN)
--
--DEFINE GCC48_IA32_PREFIX = ENV(GCC48_BIN)
--DEFINE GCC48_X64_PREFIX = ENV(GCC48_BIN)
--
--DEFINE GCC49_IA32_PREFIX = ENV(GCC49_BIN)
--DEFINE GCC49_X64_PREFIX = ENV(GCC49_BIN)
--
--DEFINE GCC5_IA32_PREFIX = ENV(GCC5_BIN)
--DEFINE GCC5_X64_PREFIX = ENV(GCC5_BIN)
--
- DEFINE UNIX_IASL_BIN = ENV(IASL_PREFIX)iasl
- DEFINE WIN_IASL_BIN = ENV(IASL_PREFIX)iasl.exe
- DEFINE WIN_ASL_BIN = ENV(IASL_PREFIX)asl.exe
-@@ -4590,7 +4569,7 @@ DEFINE GCC5_AARCH64_ASLDLINK_FLAGS = DEF(GCC49_AARCH64_ASLDLINK_FLAGS)
- ####################################################################################
- *_GCC44_*_*_FAMILY = GCC
-
--*_GCC44_*_MAKE_PATH = DEF(GCC44_IA32_PREFIX)make
-+*_GCC44_*_MAKE_PATH = make
- *_GCC44_*_*_DLL = ENV(GCC44_DLL)
- *_GCC44_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -4605,17 +4584,17 @@ DEFINE GCC5_AARCH64_ASLDLINK_FLAGS = DEF(GCC49_AARCH64_ASLDLINK_FLAGS)
- ##################
- # GCC44 IA32 definitions
- ##################
--*_GCC44_IA32_OBJCOPY_PATH = DEF(GCC44_IA32_PREFIX)objcopy
--*_GCC44_IA32_CC_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_SLINK_PATH = DEF(GCC44_IA32_PREFIX)ar
--*_GCC44_IA32_DLINK_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_ASLDLINK_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_ASM_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_PP_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_VFRPP_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_ASLCC_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_ASLPP_PATH = DEF(GCC44_IA32_PREFIX)gcc
--*_GCC44_IA32_RC_PATH = DEF(GCC44_IA32_PREFIX)objcopy
-+*_GCC44_IA32_OBJCOPY_PATH = ENV(GCC44_IA32_PREFIX)objcopy
-+*_GCC44_IA32_CC_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_SLINK_PATH = ENV(GCC44_IA32_PREFIX)ar
-+*_GCC44_IA32_DLINK_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_ASLDLINK_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_ASM_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_PP_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_VFRPP_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_ASLCC_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_ASLPP_PATH = ENV(GCC44_IA32_PREFIX)gcc
-+*_GCC44_IA32_RC_PATH = ENV(GCC44_IA32_PREFIX)objcopy
-
- *_GCC44_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC44_IA32_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -4633,17 +4612,17 @@ RELEASE_GCC44_IA32_CC_FLAGS = DEF(GCC44_IA32_CC_FLAGS) -Os
- ##################
- # GCC44 X64 definitions
- ##################
--*_GCC44_X64_OBJCOPY_PATH = DEF(GCC44_X64_PREFIX)objcopy
--*_GCC44_X64_CC_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_SLINK_PATH = DEF(GCC44_X64_PREFIX)ar
--*_GCC44_X64_DLINK_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_ASLDLINK_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_ASM_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_PP_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_VFRPP_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_ASLCC_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_ASLPP_PATH = DEF(GCC44_X64_PREFIX)gcc
--*_GCC44_X64_RC_PATH = DEF(GCC44_X64_PREFIX)objcopy
-+*_GCC44_X64_OBJCOPY_PATH = ENV(GCC44_X64_PREFIX)objcopy
-+*_GCC44_X64_CC_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_SLINK_PATH = ENV(GCC44_X64_PREFIX)ar
-+*_GCC44_X64_DLINK_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_ASLDLINK_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_ASM_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_PP_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_VFRPP_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_ASLCC_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_ASLPP_PATH = ENV(GCC44_X64_PREFIX)gcc
-+*_GCC44_X64_RC_PATH = ENV(GCC44_X64_PREFIX)objcopy
-
- *_GCC44_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC44_X64_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -4666,7 +4645,7 @@ RELEASE_GCC44_X64_CC_FLAGS = DEF(GCC44_X64_CC_FLAGS) -Os
- ####################################################################################
- *_GCC45_*_*_FAMILY = GCC
-
--*_GCC45_*_MAKE_PATH = DEF(GCC45_IA32_PREFIX)make
-+*_GCC45_*_MAKE_PATH = make
- *_GCC45_*_*_DLL = ENV(GCC45_DLL)
- *_GCC45_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -4681,17 +4660,17 @@ RELEASE_GCC44_X64_CC_FLAGS = DEF(GCC44_X64_CC_FLAGS) -Os
- ##################
- # GCC45 IA32 definitions
- ##################
--*_GCC45_IA32_OBJCOPY_PATH = DEF(GCC45_IA32_PREFIX)objcopy
--*_GCC45_IA32_CC_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_SLINK_PATH = DEF(GCC45_IA32_PREFIX)ar
--*_GCC45_IA32_DLINK_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_ASLDLINK_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_ASM_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_PP_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_VFRPP_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_ASLCC_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_ASLPP_PATH = DEF(GCC45_IA32_PREFIX)gcc
--*_GCC45_IA32_RC_PATH = DEF(GCC45_IA32_PREFIX)objcopy
-+*_GCC45_IA32_OBJCOPY_PATH = ENV(GCC45_IA32_PREFIX)objcopy
-+*_GCC45_IA32_CC_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_SLINK_PATH = ENV(GCC45_IA32_PREFIX)ar
-+*_GCC45_IA32_DLINK_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_ASLDLINK_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_ASM_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_PP_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_VFRPP_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_ASLCC_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_ASLPP_PATH = ENV(GCC45_IA32_PREFIX)gcc
-+*_GCC45_IA32_RC_PATH = ENV(GCC45_IA32_PREFIX)objcopy
-
- *_GCC45_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC45_IA32_ASLDLINK_FLAGS = DEF(GCC45_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -4709,17 +4688,17 @@ RELEASE_GCC45_IA32_CC_FLAGS = DEF(GCC45_IA32_CC_FLAGS) -Os
- ##################
- # GCC45 X64 definitions
- ##################
--*_GCC45_X64_OBJCOPY_PATH = DEF(GCC45_X64_PREFIX)objcopy
--*_GCC45_X64_CC_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_SLINK_PATH = DEF(GCC45_X64_PREFIX)ar
--*_GCC45_X64_DLINK_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_ASLDLINK_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_ASM_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_PP_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_VFRPP_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_ASLCC_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_ASLPP_PATH = DEF(GCC45_X64_PREFIX)gcc
--*_GCC45_X64_RC_PATH = DEF(GCC45_X64_PREFIX)objcopy
-+*_GCC45_X64_OBJCOPY_PATH = ENV(GCC45_X64_PREFIX)objcopy
-+*_GCC45_X64_CC_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_SLINK_PATH = ENV(GCC45_X64_PREFIX)ar
-+*_GCC45_X64_DLINK_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_ASLDLINK_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_ASM_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_PP_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_VFRPP_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_ASLCC_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_ASLPP_PATH = ENV(GCC45_X64_PREFIX)gcc
-+*_GCC45_X64_RC_PATH = ENV(GCC45_X64_PREFIX)objcopy
-
- *_GCC45_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC45_X64_ASLDLINK_FLAGS = DEF(GCC45_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -4742,7 +4721,7 @@ RELEASE_GCC45_X64_CC_FLAGS = DEF(GCC45_X64_CC_FLAGS) -Os
- ####################################################################################
- *_GCC46_*_*_FAMILY = GCC
-
--*_GCC46_*_MAKE_PATH = DEF(GCC46_IA32_PREFIX)make
-+*_GCC46_*_MAKE_PATH = make
- *_GCC46_*_*_DLL = ENV(GCC46_DLL)
- *_GCC46_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -4757,17 +4736,17 @@ RELEASE_GCC45_X64_CC_FLAGS = DEF(GCC45_X64_CC_FLAGS) -Os
- ##################
- # GCC46 IA32 definitions
- ##################
--*_GCC46_IA32_OBJCOPY_PATH = DEF(GCC46_IA32_PREFIX)objcopy
--*_GCC46_IA32_CC_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_SLINK_PATH = DEF(GCC46_IA32_PREFIX)ar
--*_GCC46_IA32_DLINK_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_ASLDLINK_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_ASM_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_PP_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_VFRPP_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_ASLCC_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_ASLPP_PATH = DEF(GCC46_IA32_PREFIX)gcc
--*_GCC46_IA32_RC_PATH = DEF(GCC46_IA32_PREFIX)objcopy
-+*_GCC46_IA32_OBJCOPY_PATH = ENV(GCC46_IA32_PREFIX)objcopy
-+*_GCC46_IA32_CC_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_SLINK_PATH = ENV(GCC46_IA32_PREFIX)ar
-+*_GCC46_IA32_DLINK_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_ASLDLINK_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_ASM_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_PP_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_VFRPP_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_ASLCC_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_ASLPP_PATH = ENV(GCC46_IA32_PREFIX)gcc
-+*_GCC46_IA32_RC_PATH = ENV(GCC46_IA32_PREFIX)objcopy
-
- *_GCC46_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC46_IA32_ASLDLINK_FLAGS = DEF(GCC46_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -4785,17 +4764,17 @@ RELEASE_GCC46_IA32_CC_FLAGS = DEF(GCC46_IA32_CC_FLAGS) -Os -Wno-unused-but
- ##################
- # GCC46 X64 definitions
- ##################
--*_GCC46_X64_OBJCOPY_PATH = DEF(GCC46_X64_PREFIX)objcopy
--*_GCC46_X64_CC_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_SLINK_PATH = DEF(GCC46_X64_PREFIX)ar
--*_GCC46_X64_DLINK_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_ASLDLINK_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_ASM_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_PP_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_VFRPP_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_ASLCC_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_ASLPP_PATH = DEF(GCC46_X64_PREFIX)gcc
--*_GCC46_X64_RC_PATH = DEF(GCC46_X64_PREFIX)objcopy
-+*_GCC46_X64_OBJCOPY_PATH = ENV(GCC46_X64_PREFIX)objcopy
-+*_GCC46_X64_CC_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_SLINK_PATH = ENV(GCC46_X64_PREFIX)ar
-+*_GCC46_X64_DLINK_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_ASLDLINK_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_ASM_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_PP_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_VFRPP_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_ASLCC_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_ASLPP_PATH = ENV(GCC46_X64_PREFIX)gcc
-+*_GCC46_X64_RC_PATH = ENV(GCC46_X64_PREFIX)objcopy
-
- *_GCC46_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC46_X64_ASLDLINK_FLAGS = DEF(GCC46_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -4851,7 +4830,7 @@ RELEASE_GCC46_ARM_CC_FLAGS = DEF(GCC46_ARM_CC_FLAGS) -Wno-unused-but-set-v
- ####################################################################################
- *_GCC47_*_*_FAMILY = GCC
-
--*_GCC47_*_MAKE_PATH = DEF(GCC47_IA32_PREFIX)make
-+*_GCC47_*_MAKE_PATH = make
- *_GCC47_*_*_DLL = ENV(GCC47_DLL)
- *_GCC47_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -4866,17 +4845,17 @@ RELEASE_GCC46_ARM_CC_FLAGS = DEF(GCC46_ARM_CC_FLAGS) -Wno-unused-but-set-v
- ##################
- # GCC47 IA32 definitions
- ##################
--*_GCC47_IA32_OBJCOPY_PATH = DEF(GCC47_IA32_PREFIX)objcopy
--*_GCC47_IA32_CC_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_SLINK_PATH = DEF(GCC47_IA32_PREFIX)ar
--*_GCC47_IA32_DLINK_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_ASLDLINK_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_ASM_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_PP_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_VFRPP_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_ASLCC_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_ASLPP_PATH = DEF(GCC47_IA32_PREFIX)gcc
--*_GCC47_IA32_RC_PATH = DEF(GCC47_IA32_PREFIX)objcopy
-+*_GCC47_IA32_OBJCOPY_PATH = ENV(GCC47_IA32_PREFIX)objcopy
-+*_GCC47_IA32_CC_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_SLINK_PATH = ENV(GCC47_IA32_PREFIX)ar
-+*_GCC47_IA32_DLINK_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_ASLDLINK_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_ASM_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_PP_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_VFRPP_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_ASLCC_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_ASLPP_PATH = ENV(GCC47_IA32_PREFIX)gcc
-+*_GCC47_IA32_RC_PATH = ENV(GCC47_IA32_PREFIX)objcopy
-
- *_GCC47_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC47_IA32_ASLDLINK_FLAGS = DEF(GCC47_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -4894,17 +4873,17 @@ RELEASE_GCC47_IA32_CC_FLAGS = DEF(GCC47_IA32_CC_FLAGS) -Os -Wno-unused-but
- ##################
- # GCC47 X64 definitions
- ##################
--*_GCC47_X64_OBJCOPY_PATH = DEF(GCC47_X64_PREFIX)objcopy
--*_GCC47_X64_CC_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_SLINK_PATH = DEF(GCC47_X64_PREFIX)ar
--*_GCC47_X64_DLINK_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_ASLDLINK_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_ASM_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_PP_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_VFRPP_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_ASLCC_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_ASLPP_PATH = DEF(GCC47_X64_PREFIX)gcc
--*_GCC47_X64_RC_PATH = DEF(GCC47_X64_PREFIX)objcopy
-+*_GCC47_X64_OBJCOPY_PATH = ENV(GCC47_X64_PREFIX)objcopy
-+*_GCC47_X64_CC_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_SLINK_PATH = ENV(GCC47_X64_PREFIX)ar
-+*_GCC47_X64_DLINK_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_ASLDLINK_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_ASM_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_PP_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_VFRPP_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_ASLCC_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_ASLPP_PATH = ENV(GCC47_X64_PREFIX)gcc
-+*_GCC47_X64_RC_PATH = ENV(GCC47_X64_PREFIX)objcopy
-
- *_GCC47_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC47_X64_ASLDLINK_FLAGS = DEF(GCC47_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -4988,7 +4967,7 @@ RELEASE_GCC47_AARCH64_CC_FLAGS = DEF(GCC47_AARCH64_CC_FLAGS) -Wno-unused-but-s
- ####################################################################################
- *_GCC48_*_*_FAMILY = GCC
-
--*_GCC48_*_MAKE_PATH = DEF(GCC48_IA32_PREFIX)make
-+*_GCC48_*_MAKE_PATH = make
- *_GCC48_*_*_DLL = ENV(GCC48_DLL)
- *_GCC48_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -5003,17 +4982,17 @@ RELEASE_GCC47_AARCH64_CC_FLAGS = DEF(GCC47_AARCH64_CC_FLAGS) -Wno-unused-but-s
- ##################
- # GCC48 IA32 definitions
- ##################
--*_GCC48_IA32_OBJCOPY_PATH = DEF(GCC48_IA32_PREFIX)objcopy
--*_GCC48_IA32_CC_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_SLINK_PATH = DEF(GCC48_IA32_PREFIX)ar
--*_GCC48_IA32_DLINK_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_ASLDLINK_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_ASM_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_PP_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_VFRPP_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_ASLCC_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_ASLPP_PATH = DEF(GCC48_IA32_PREFIX)gcc
--*_GCC48_IA32_RC_PATH = DEF(GCC48_IA32_PREFIX)objcopy
-+*_GCC48_IA32_OBJCOPY_PATH = ENV(GCC48_IA32_PREFIX)objcopy
-+*_GCC48_IA32_CC_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_SLINK_PATH = ENV(GCC48_IA32_PREFIX)ar
-+*_GCC48_IA32_DLINK_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_ASLDLINK_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_ASM_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_PP_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_VFRPP_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_ASLCC_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_ASLPP_PATH = ENV(GCC48_IA32_PREFIX)gcc
-+*_GCC48_IA32_RC_PATH = ENV(GCC48_IA32_PREFIX)objcopy
-
- *_GCC48_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC48_IA32_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -5031,17 +5010,17 @@ RELEASE_GCC48_IA32_CC_FLAGS = DEF(GCC48_IA32_CC_FLAGS) -Os -Wno-unused-but
- ##################
- # GCC48 X64 definitions
- ##################
--*_GCC48_X64_OBJCOPY_PATH = DEF(GCC48_X64_PREFIX)objcopy
--*_GCC48_X64_CC_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_SLINK_PATH = DEF(GCC48_X64_PREFIX)ar
--*_GCC48_X64_DLINK_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_ASLDLINK_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_ASM_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_PP_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_VFRPP_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_ASLCC_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_ASLPP_PATH = DEF(GCC48_X64_PREFIX)gcc
--*_GCC48_X64_RC_PATH = DEF(GCC48_X64_PREFIX)objcopy
-+*_GCC48_X64_OBJCOPY_PATH = ENV(GCC48_X64_PREFIX)objcopy
-+*_GCC48_X64_CC_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_SLINK_PATH = ENV(GCC48_X64_PREFIX)ar
-+*_GCC48_X64_DLINK_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_ASLDLINK_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_ASM_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_PP_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_VFRPP_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_ASLCC_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_ASLPP_PATH = ENV(GCC48_X64_PREFIX)gcc
-+*_GCC48_X64_RC_PATH = ENV(GCC48_X64_PREFIX)objcopy
-
- *_GCC48_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC48_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -5125,7 +5104,7 @@ RELEASE_GCC48_AARCH64_CC_FLAGS = DEF(GCC48_AARCH64_CC_FLAGS) -Wno-unused-but-s
- ####################################################################################
- *_GCC49_*_*_FAMILY = GCC
-
--*_GCC49_*_MAKE_PATH = DEF(GCC49_IA32_PREFIX)make
-+*_GCC49_*_MAKE_PATH = make
- *_GCC49_*_*_DLL = ENV(GCC49_DLL)
- *_GCC49_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -5140,17 +5119,17 @@ RELEASE_GCC48_AARCH64_CC_FLAGS = DEF(GCC48_AARCH64_CC_FLAGS) -Wno-unused-but-s
- ##################
- # GCC49 IA32 definitions
- ##################
--*_GCC49_IA32_OBJCOPY_PATH = DEF(GCC49_IA32_PREFIX)objcopy
--*_GCC49_IA32_CC_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_SLINK_PATH = DEF(GCC49_IA32_PREFIX)ar
--*_GCC49_IA32_DLINK_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_ASLDLINK_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_ASM_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_PP_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_VFRPP_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_ASLCC_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_ASLPP_PATH = DEF(GCC49_IA32_PREFIX)gcc
--*_GCC49_IA32_RC_PATH = DEF(GCC49_IA32_PREFIX)objcopy
-+*_GCC49_IA32_OBJCOPY_PATH = ENV(GCC49_IA32_PREFIX)objcopy
-+*_GCC49_IA32_CC_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_SLINK_PATH = ENV(GCC49_IA32_PREFIX)ar
-+*_GCC49_IA32_DLINK_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_ASLDLINK_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_ASM_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_PP_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_VFRPP_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_ASLCC_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_ASLPP_PATH = ENV(GCC49_IA32_PREFIX)gcc
-+*_GCC49_IA32_RC_PATH = ENV(GCC49_IA32_PREFIX)objcopy
-
- *_GCC49_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
- *_GCC49_IA32_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -5168,17 +5147,17 @@ RELEASE_GCC49_IA32_CC_FLAGS = DEF(GCC49_IA32_CC_FLAGS) -Os -Wno-unused-but
- ##################
- # GCC49 X64 definitions
- ##################
--*_GCC49_X64_OBJCOPY_PATH = DEF(GCC49_X64_PREFIX)objcopy
--*_GCC49_X64_CC_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_SLINK_PATH = DEF(GCC49_X64_PREFIX)ar
--*_GCC49_X64_DLINK_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_ASLDLINK_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_ASM_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_PP_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_VFRPP_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_ASLCC_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_ASLPP_PATH = DEF(GCC49_X64_PREFIX)gcc
--*_GCC49_X64_RC_PATH = DEF(GCC49_X64_PREFIX)objcopy
-+*_GCC49_X64_OBJCOPY_PATH = ENV(GCC49_X64_PREFIX)objcopy
-+*_GCC49_X64_CC_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_SLINK_PATH = ENV(GCC49_X64_PREFIX)ar
-+*_GCC49_X64_DLINK_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_ASLDLINK_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_ASM_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_PP_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_VFRPP_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_ASLCC_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_ASLPP_PATH = ENV(GCC49_X64_PREFIX)gcc
-+*_GCC49_X64_RC_PATH = ENV(GCC49_X64_PREFIX)objcopy
-
- *_GCC49_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
- *_GCC49_X64_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
-@@ -5268,7 +5247,7 @@ RELEASE_GCC49_AARCH64_DLINK_FLAGS = DEF(GCC49_AARCH64_DLINK_FLAGS)
- ####################################################################################
- *_GCC5_*_*_FAMILY = GCC
-
--*_GCC5_*_MAKE_PATH = DEF(GCC5_IA32_PREFIX)make
-+*_GCC5_*_MAKE_PATH = make
- *_GCC5_*_*_DLL = ENV(GCC5_DLL)
- *_GCC5_*_ASL_PATH = DEF(UNIX_IASL_BIN)
-
-@@ -5283,17 +5262,17 @@ RELEASE_GCC49_AARCH64_DLINK_FLAGS = DEF(GCC49_AARCH64_DLINK_FLAGS)
- ##################
- # GCC5 IA32 definitions
- ##################
--*_GCC5_IA32_OBJCOPY_PATH = DEF(GCC5_IA32_PREFIX)objcopy
--*_GCC5_IA32_CC_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_SLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc-ar
--*_GCC5_IA32_DLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_ASLDLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_ASM_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_PP_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_VFRPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_ASLCC_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_ASLPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
--*_GCC5_IA32_RC_PATH = DEF(GCC5_IA32_PREFIX)objcopy
-+*_GCC5_IA32_OBJCOPY_PATH = ENV(GCC5_IA32_PREFIX)objcopy
-+*_GCC5_IA32_CC_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_SLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc-ar
-+*_GCC5_IA32_DLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_ASLDLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_ASM_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_PP_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_VFRPP_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_ASLCC_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_ASLPP_PATH = ENV(GCC5_IA32_PREFIX)gcc
-+*_GCC5_IA32_RC_PATH = ENV(GCC5_IA32_PREFIX)objcopy
-
- *_GCC5_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto
- *_GCC5_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
-@@ -5315,17 +5294,17 @@ RELEASE_GCC5_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,
- ##################
- # GCC5 X64 definitions
- ##################
--*_GCC5_X64_OBJCOPY_PATH = DEF(GCC5_X64_PREFIX)objcopy
--*_GCC5_X64_CC_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_SLINK_PATH = DEF(GCC5_X64_PREFIX)gcc-ar
--*_GCC5_X64_DLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_ASLDLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_ASM_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_PP_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_VFRPP_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_ASLCC_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_ASLPP_PATH = DEF(GCC5_X64_PREFIX)gcc
--*_GCC5_X64_RC_PATH = DEF(GCC5_X64_PREFIX)objcopy
-+*_GCC5_X64_OBJCOPY_PATH = ENV(GCC5_X64_PREFIX)objcopy
-+*_GCC5_X64_CC_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_SLINK_PATH = ENV(GCC5_X64_PREFIX)gcc-ar
-+*_GCC5_X64_DLINK_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_ASLDLINK_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_ASM_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_PP_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_VFRPP_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_ASLCC_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_ASLPP_PATH = ENV(GCC5_X64_PREFIX)gcc
-+*_GCC5_X64_RC_PATH = ENV(GCC5_X64_PREFIX)objcopy
-
- *_GCC5_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto
- *_GCC5_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
---
-2.9.3
-
diff --git a/0010-ArmVirtPkg-QemuFwCfgLib-allow-UEFI_DRIVER-client-mod.patch b/0010-ArmVirtPkg-QemuFwCfgLib-allow-UEFI_DRIVER-client-mod.patch
new file mode 100644
index 0000000..a29a8bc
--- /dev/null
+++ b/0010-ArmVirtPkg-QemuFwCfgLib-allow-UEFI_DRIVER-client-mod.patch
@@ -0,0 +1,36 @@
+From 92f37a3d72213d9b76bc47c4f194f2ea989a71a1 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Tue, 12 Apr 2016 20:50:25 +0200
+Subject: [PATCH] ArmVirtPkg: QemuFwCfgLib: allow UEFI_DRIVER client modules
+ (RH only)
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 8e2153358aa2bba2c91faa87a70beadcaae03fd8)
+(cherry picked from commit 5af259a93f4bbee5515ae18638068125e170f2cd)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+index eff4a21650..adf1ff6c6a 100644
+--- a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
++++ b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+@@ -22,7 +22,7 @@
+ FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+- LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER
++ LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER UEFI_DRIVER
+
+ CONSTRUCTOR = QemuFwCfgInitialize
+
diff --git a/0010-VfrCompile-fix-invalid-comparison-between-pointer-an.patch b/0010-VfrCompile-fix-invalid-comparison-between-pointer-an.patch
deleted file mode 100644
index 21a345a..0000000
--- a/0010-VfrCompile-fix-invalid-comparison-between-pointer-an.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 06c3814868bebbe7f2cd9a51c11fbfc407c14349 Mon Sep 17 00:00:00 2001
-From: Paolo Bonzini <pbonzini(a)redhat.com>
-Date: Mon, 13 Feb 2017 13:49:14 +0100
-Subject: [PATCH] VfrCompile: fix invalid comparison between pointer and
- integer
-
-This would be valid C but is not valid C++, so change the comparison
-to do what it has always been doing.
-
-Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
----
- BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
-index 3ca57ed..2f97975 100644
---- a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
-+++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
-@@ -3372,7 +3372,7 @@ CVfrStringDB::GetVarStoreNameFormStringId (
- UINT8 BlockType;
- EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
-
-- if (mStringFileName == '\0' ) {
-+ if (mStringFileName == NULL) {
- return NULL;
- }
-
---
-2.9.3
-
diff --git a/0011-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch b/0011-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch
new file mode 100644
index 0000000..6d7967e
--- /dev/null
+++ b/0011-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch
@@ -0,0 +1,197 @@
+From 6a27daa40698f06a34c209bd90092011d70f7795 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Sun, 26 Jul 2015 08:02:50 +0000
+Subject: [PATCH] ArmVirtPkg: take PcdResizeXterm from the QEMU command line
+ (RH only)
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- Adapt commit 6b97969096a3 to the fact that upstream has deprecated such
+ setter functions for dynamic PCDs that don't return a status code (such
+ as PcdSetBool()). Employ PcdSetBoolS(), and assert that it succeeds --
+ there's really no circumstance in this case when it could fail.
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- Refresh downstream-only commit d4564d39dfdb against context changes in
+ "ArmVirtPkg/ArmVirtQemu.dsc" from upstream commit 7e5f1b673870
+ ("ArmVirtPkg/PlatformHasAcpiDtDxe: allow guest level ACPI disable
+ override", 2017-03-29).
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit d4564d39dfdbf74e762af43314005a2c026cb262)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmVirtPkg/ArmVirtQemu.dsc | 7 +-
+ .../TerminalPcdProducerLib.c | 87 +++++++++++++++++++
+ .../TerminalPcdProducerLib.inf | 41 +++++++++
+ 3 files changed, 134 insertions(+), 1 deletion(-)
+ create mode 100644 ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c
+ create mode 100644 ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf
+
+diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
+index a7a3899560..86d5d5a666 100644
+--- a/ArmVirtPkg/ArmVirtQemu.dsc
++++ b/ArmVirtPkg/ArmVirtQemu.dsc
+@@ -206,6 +206,8 @@
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
+
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE
++
+ [PcdsDynamicHii]
+ gArmVirtTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gArmVirtVariableGuid|0x0|FALSE|NV,BS
+
+@@ -282,7 +284,10 @@
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+- MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
++ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf {
++ <LibraryClasses>
++ NULL|ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf
++ }
+ MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+diff --git a/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c
+new file mode 100644
+index 0000000000..814ad48199
+--- /dev/null
++++ b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c
+@@ -0,0 +1,87 @@
++/** @file
++* Plugin library for setting up dynamic PCDs for TerminalDxe, from fw_cfg
++*
++* Copyright (C) 2015-2016, Red Hat, Inc.
++* Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
++*
++* This program and the accompanying materials are licensed and made available
++* under the terms and conditions of the BSD License which accompanies this
++* distribution. The full text of the license may be found at
++* http://opensource.org/licenses/bsd-license.php
++*
++* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
++* IMPLIED.
++*
++**/
++
++#include <Library/DebugLib.h>
++#include <Library/PcdLib.h>
++#include <Library/QemuFwCfgLib.h>
++
++STATIC
++RETURN_STATUS
++GetNamedFwCfgBoolean (
++ IN CONST CHAR8 *FwCfgFileName,
++ OUT BOOLEAN *Setting
++ )
++{
++ RETURN_STATUS Status;
++ FIRMWARE_CONFIG_ITEM FwCfgItem;
++ UINTN FwCfgSize;
++ UINT8 Value[3];
++
++ Status = QemuFwCfgFindFile (FwCfgFileName, &FwCfgItem, &FwCfgSize);
++ if (RETURN_ERROR (Status)) {
++ return Status;
++ }
++ if (FwCfgSize > sizeof Value) {
++ return RETURN_BAD_BUFFER_SIZE;
++ }
++ QemuFwCfgSelectItem (FwCfgItem);
++ QemuFwCfgReadBytes (FwCfgSize, Value);
++
++ if ((FwCfgSize == 1) ||
++ (FwCfgSize == 2 && Value[1] == '\n') ||
++ (FwCfgSize == 3 && Value[1] == '\r' && Value[2] == '\n')) {
++ switch (Value[0]) {
++ case '0':
++ case 'n':
++ case 'N':
++ *Setting = FALSE;
++ return RETURN_SUCCESS;
++
++ case '1':
++ case 'y':
++ case 'Y':
++ *Setting = TRUE;
++ return RETURN_SUCCESS;
++
++ default:
++ break;
++ }
++ }
++ return RETURN_PROTOCOL_ERROR;
++}
++
++#define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
++ do { \
++ BOOLEAN Setting; \
++ RETURN_STATUS PcdStatus; \
++ \
++ if (!RETURN_ERROR (GetNamedFwCfgBoolean ( \
++ "opt/org.tianocore.edk2.aavmf/" #TokenName, &Setting))) { \
++ PcdStatus = PcdSetBoolS (TokenName, Setting); \
++ ASSERT_RETURN_ERROR (PcdStatus); \
++ } \
++ } while (0)
++
++RETURN_STATUS
++EFIAPI
++TerminalPcdProducerLibConstructor (
++ VOID
++ )
++{
++ UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdResizeXterm);
++ return RETURN_SUCCESS;
++}
+diff --git a/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf
+new file mode 100644
+index 0000000000..fecb37bcdf
+--- /dev/null
++++ b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf
+@@ -0,0 +1,41 @@
++## @file
++# Plugin library for setting up dynamic PCDs for TerminalDxe, from fw_cfg
++#
++# Copyright (C) 2015-2016, Red Hat, Inc.
++# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
++#
++# This program and the accompanying materials are licensed and made available
++# under the terms and conditions of the BSD License which accompanies this
++# distribution. The full text of the license may be found at
++# http://opensource.org/licenses/bsd-license.php
++#
++# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
++# IMPLIED.
++#
++##
++
++[Defines]
++ INF_VERSION = 0x00010005
++ BASE_NAME = TerminalPcdProducerLib
++ FILE_GUID = 4a0c5ed7-8c42-4c01-8f4c-7bf258316a96
++ MODULE_TYPE = BASE
++ VERSION_STRING = 1.0
++ LIBRARY_CLASS = TerminalPcdProducerLib|DXE_DRIVER
++ CONSTRUCTOR = TerminalPcdProducerLibConstructor
++
++[Sources]
++ TerminalPcdProducerLib.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++ OvmfPkg/OvmfPkg.dec
++ MdeModulePkg/MdeModulePkg.dec
++
++[LibraryClasses]
++ DebugLib
++ PcdLib
++ QemuFwCfgLib
++
++[Pcd]
++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm
diff --git a/0012-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch b/0012-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch
new file mode 100644
index 0000000..0a4b6e3
--- /dev/null
+++ b/0012-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch
@@ -0,0 +1,113 @@
+From 84570add9731d2099c6e5be43f96aed508fd4c39 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Tue, 4 Nov 2014 23:02:53 +0100
+Subject: [PATCH] OvmfPkg: allow exclusion of the shell from the firmware image
+
+When '-D EXCLUDE_SHELL_FROM_FD' is passed to 'build', exclude the shell
+binary from the firmware image.
+
+Peter Jones advised us that firmware vendors for physical systems disable
+the memory-mapped, firmware image-contained UEFI shell in
+SecureBoot-enabled builds. The reason being that the memory-mapped shell
+can always load, it may have direct access to various hardware in the
+system, and it can run UEFI shell scripts (which cannot be signed at all).
+
+Intended use of the new build option:
+
+- In-tree builds: don't pass '-D EXCLUDE_SHELL_FROM_FD'. The resultant
+ firmware image will contain a shell binary, independently of SecureBoot
+ enablement, which is flexible for interactive development. (Ie. no
+ change for in-tree builds.)
+
+- RPM builds: pass both '-D SECURE_BOOT_ENABLE' and
+ '-D EXCLUDE_SHELL_FROM_FD'. The resultant RPM will provide:
+
+ - OVMF_CODE.fd: SecureBoot-enabled firmware, without builtin UEFI shell,
+
+ - OVMF_VARS.fd: variable store template matching OVMF_CODE.fd,
+
+ - UefiShell.iso: a bootable ISO image with the shell on it as default
+ boot loader. The shell binary will load when SecureBoot is turned off,
+ and won't load when SecureBoot is turned on (because it is not
+ signed).
+
+ UefiShell.iso is the reason we're not excluding the shell from the DSC
+ files as well, only the FDF files -- when '-D EXCLUDE_SHELL_FROM_FD'
+ is specified, the shell binary needs to be built the same, only it
+ will be included in UefiShell.iso.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 9c391def70366cabae08e6008814299c3372fafd)
+(cherry picked from commit d9dd9ee42937b2611fe37183cc9ec7f62d946933)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ OvmfPkg/OvmfPkgIa32.fdf | 2 ++
+ OvmfPkg/OvmfPkgIa32X64.fdf | 2 ++
+ OvmfPkg/OvmfPkgX64.fdf | 2 ++
+ 3 files changed, 6 insertions(+)
+
+diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
+index 4177379a23..8c0b6ee1bd 100644
+--- a/OvmfPkg/OvmfPkgIa32.fdf
++++ b/OvmfPkg/OvmfPkgIa32.fdf
+@@ -288,12 +288,14 @@ INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResour
+ INF FatPkg/EnhancedFatDxe/Fat.inf
+ INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
++!ifndef $(EXCLUDE_SHELL_FROM_FD)
+ !ifndef $(USE_OLD_SHELL)
+ INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+ INF ShellPkg/Application/Shell/Shell.inf
+ !else
+ INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
++!endif
+
+ !if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
+ INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
+diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
+index 5e57161154..8de20366d2 100644
+--- a/OvmfPkg/OvmfPkgIa32X64.fdf
++++ b/OvmfPkg/OvmfPkgIa32X64.fdf
+@@ -289,12 +289,14 @@ INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResour
+ INF FatPkg/EnhancedFatDxe/Fat.inf
+ INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
++!ifndef $(EXCLUDE_SHELL_FROM_FD)
+ !ifndef $(USE_OLD_SHELL)
+ INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+ INF ShellPkg/Application/Shell/Shell.inf
+ !else
+ INF RuleOverride = BINARY USE = X64 EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
++!endif
+
+ !if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
+ INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
+diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
+index c81b422517..49ef829a3a 100644
+--- a/OvmfPkg/OvmfPkgX64.fdf
++++ b/OvmfPkg/OvmfPkgX64.fdf
+@@ -289,12 +289,14 @@ INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResour
+ INF FatPkg/EnhancedFatDxe/Fat.inf
+ INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
++!ifndef $(EXCLUDE_SHELL_FROM_FD)
+ !ifndef $(USE_OLD_SHELL)
+ INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+ INF ShellPkg/Application/Shell/Shell.inf
+ !else
+ INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
+ !endif
++!endif
+
+ !if ($(SECURE_BOOT_ENABLE) == TRUE) || ($(NETWORK_IP6_ENABLE) == TRUE) || ($(TLS_ENABLE) == TRUE)
+ INF MdeModulePkg/Logo/LogoOpenSSLDxe.inf
diff --git a/0013-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch b/0013-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
new file mode 100644
index 0000000..cb60132
--- /dev/null
+++ b/0013-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
@@ -0,0 +1,1328 @@
+From 685d43b29b2ac4b19572bda1ebeb989d69d74ebb Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Tue, 4 Nov 2014 23:02:55 +0100
+Subject: [PATCH] OvmfPkg: EnrollDefaultKeys: application for enrolling default
+ keys
+
+This application is meant to be invoked by the management layer, after
+booting the UEFI shell and getting a shell prompt on the serial console.
+The app enrolls a number of certificates (see below), and then reports
+status to the serial console as well. The expected output is "info:
+success":
+
+> Shell> EnrollDefaultKeys.efi
+> info: SetupMode=1 SecureBoot=0 SecureBootEnable=0 CustomMode=0 VendorKeys=1
+> info: SetupMode=0 SecureBoot=1 SecureBootEnable=1 CustomMode=0 VendorKeys=0
+> info: success
+> Shell>
+
+In case of success, the management layer can force off or reboot the VM
+(for example with the "reset -s" or "reset -c" UEFI shell commands,
+respectively), and start the guest installation with SecureBoot enabled.
+
+PK:
+- A unique, static, ad-hoc certificate whose private half has been
+ destroyed (more precisely, never saved) and is therefore unusable for
+ signing. (The command for creating this certificate is saved in the
+ source code.) Background:
+
+On 09/30/14 20:00, Peter Jones wrote:
+> We should generate a special key that's not in our normal signing chains
+> for PK and KEK. The reason for this is that [in practice] PK gets
+> treated as part of DB (*).
+>
+> [Shipping a key in our normal signing chains] as PK means you can run
+> grub directly, in which case it won't have access to the shim protocol.
+> When grub is run without the shim protocol registered, it assumes SB is
+> disabled and boots without verifying the kernel. We don't want that to
+> be a thing you can do, but allowing that is the inevitable result of
+> shipping with any of our normal signing chain in PK or KEK.
+>
+> (* USRT has actually agreed that since you can escalate to this behavior
+> if you have the secret half of a key in KEK or PK anyway, and many
+> vendors had already shipped it this way, that it is fine and I think
+> even *expected* at this point, even though it wasn't formally in the
+> UEFI 2.3.1 Spec that introduced Secure Boot. I'll try and make sure the
+> language reflects that in an upcoming spec revision.)
+>
+> So let me get SRT to issue a special key to use for PK and KEK. We can
+> use it just for those operations, and make sure it's protected with the
+> same processes and controls as our other signing keys.
+
+ Until SRT generates such a key for us, this ad-hoc key should be a good
+ placeholder.
+
+KEK:
+- same ad-hoc certificate as used for the PK,
+- "Microsoft Corporation KEK CA 2011" -- the dbx data in Fedora's dbxtool
+ package is signed (indirectly, through a chain) with this; enrolling
+ such a KEK should allow guests to install those updates.
+
+DB:
+- "Microsoft Windows Production PCA 2011" -- to load Windows 8 and Windows
+ Server 2012 R2,
+- "Microsoft Corporation UEFI CA 2011" -- to load Linux and signed PCI
+ oproms.
+
+*UPDATE*
+
+OvmfPkg: EnrollDefaultKeys: pick up official Red Hat PK/KEK (RHEL only)
+
+Replace the placeholder ExampleCert with a certificate generated and
+managed by the Red Hat Security Response Team.
+
+> Certificate:
+> Data:
+> Version: 3 (0x2)
+> Serial Number: 18371740789028339953 (0xfef588e8f396c0f1)
+> Signature Algorithm: sha256WithRSAEncryption
+> Issuer: CN=Red Hat Secure Boot (PK/KEK key 1)/emailAddress=secalert(a)redhat.com
+> Validity
+> Not Before: Oct 31 11:15:37 2014 GMT
+> Not After : Oct 25 11:15:37 2037 GMT
+> Subject: CN=Red Hat Secure Boot (PK/KEK key 1)/emailAddress=secalert(a)redhat.com
+> Subject Public Key Info:
+> Public Key Algorithm: rsaEncryption
+> Public-Key: (2048 bit)
+> Modulus:
+> 00:90:1f:84:7b:8d:bc:eb:97:26:82:6d:88:ab:8a:
+> c9:8c:68:70:f9:df:4b:07:b2:37:83:0b:02:c8:67:
+> 68:30:9e:e3:f0:f0:99:4a:b8:59:57:c6:41:f6:38:
+> 8b:fe:66:4c:49:e9:37:37:92:2e:98:01:1e:5b:14:
+> 50:e6:a8:8d:25:0d:f5:86:e6:ab:30:cb:40:16:ea:
+> 8d:8b:16:86:70:43:37:f2:ce:c0:91:df:71:14:8e:
+> 99:0e:89:b6:4c:6d:24:1e:8c:e4:2f:4f:25:d0:ba:
+> 06:f8:c6:e8:19:18:76:73:1d:81:6d:a8:d8:05:cf:
+> 3a:c8:7b:28:c8:36:a3:16:0d:29:8c:99:9a:68:dc:
+> ab:c0:4d:8d:bf:5a:bb:2b:a9:39:4b:04:97:1c:f9:
+> 36:bb:c5:3a:86:04:ae:af:d4:82:7b:e0:ab:de:49:
+> 05:68:fc:f6:ae:68:1a:6c:90:4d:57:19:3c:64:66:
+> 03:f6:c7:52:9b:f7:94:cf:93:6a:a1:68:c9:aa:cf:
+> 99:6b:bc:aa:5e:08:e7:39:1c:f7:f8:0f:ba:06:7e:
+> f1:cb:e8:76:dd:fe:22:da:ad:3a:5e:5b:34:ea:b3:
+> c9:e0:4d:04:29:7e:b8:60:b9:05:ef:b5:d9:17:58:
+> 56:16:60:b9:30:32:f0:36:4a:c3:f2:79:8d:12:40:
+> 70:f3
+> Exponent: 65537 (0x10001)
+> X509v3 extensions:
+> X509v3 Basic Constraints:
+> CA:FALSE
+> Netscape Comment:
+> OpenSSL Generated Certificate
+> X509v3 Subject Key Identifier:
+> 3C:E9:60:E3:FF:19:A1:0A:7B:A3:42:F4:8D:42:2E:B4:D5:9C:72:EC
+> X509v3 Authority Key Identifier:
+> keyid:3C:E9:60:E3:FF:19:A1:0A:7B:A3:42:F4:8D:42:2E:B4:D5:9C:72:EC
+>
+> Signature Algorithm: sha256WithRSAEncryption
+> 5c:4d:92:88:b4:82:5f:1d:ad:8b:11:ec:df:06:a6:7a:a5:2b:
+> 9f:37:55:0c:8d:6e:05:00:ad:b7:0c:41:89:69:cf:d6:65:06:
+> 9b:51:78:d2:ad:c7:bf:9c:dc:05:73:7f:e7:1e:39:13:b4:ea:
+> b6:30:7d:40:75:ab:9c:43:0b:df:b0:c2:1b:bf:30:e0:f4:fe:
+> c0:db:62:21:98:f6:c5:af:de:3b:4f:49:0a:e6:1e:f9:86:b0:
+> 3f:0d:d6:d4:46:37:db:54:74:5e:ff:11:c2:60:c6:70:58:c5:
+> 1c:6f:ec:b2:d8:6e:6f:c3:bc:33:87:38:a4:f3:44:64:9c:34:
+> 3b:28:94:26:78:27:9f:16:17:e8:3b:69:0a:25:a9:73:36:7e:
+> 9e:37:5c:ec:e8:3f:db:91:f9:12:b3:3d:ce:e7:dd:15:c3:ae:
+> 8c:05:20:61:9b:95:de:9b:af:fa:b1:5c:1c:e5:97:e7:c3:34:
+> 11:85:f5:8a:27:26:a4:70:36:ec:0c:f6:83:3d:90:f7:36:f3:
+> f9:f3:15:d4:90:62:be:53:b4:af:d3:49:af:ef:f4:73:e8:7b:
+> 76:e4:44:2a:37:ba:81:a4:99:0c:3a:31:24:71:a0:e4:e4:b7:
+> 1a:cb:47:e4:aa:22:cf:ef:75:61:80:e3:43:b7:48:57:73:11:
+> 3d:78:9b:69
+> -----BEGIN CERTIFICATE-----
+> MIIDoDCCAoigAwIBAgIJAP71iOjzlsDxMA0GCSqGSIb3DQEBCwUAMFExKzApBgNV
+> BAMTIlJlZCBIYXQgU2VjdXJlIEJvb3QgKFBLL0tFSyBrZXkgMSkxIjAgBgkqhkiG
+> 9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMTQxMDMxMTExNTM3WhcNMzcx
+> MDI1MTExNTM3WjBRMSswKQYDVQQDEyJSZWQgSGF0IFNlY3VyZSBCb290IChQSy9L
+> RUsga2V5IDEpMSIwIAYJKoZIhvcNAQkBFhNzZWNhbGVydEByZWRoYXQuY29tMIIB
+> IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkB+Ee42865cmgm2Iq4rJjGhw
+> +d9LB7I3gwsCyGdoMJ7j8PCZSrhZV8ZB9jiL/mZMSek3N5IumAEeWxRQ5qiNJQ31
+> huarMMtAFuqNixaGcEM38s7Akd9xFI6ZDom2TG0kHozkL08l0LoG+MboGRh2cx2B
+> bajYBc86yHsoyDajFg0pjJmaaNyrwE2Nv1q7K6k5SwSXHPk2u8U6hgSur9SCe+Cr
+> 3kkFaPz2rmgabJBNVxk8ZGYD9sdSm/eUz5NqoWjJqs+Za7yqXgjnORz3+A+6Bn7x
+> y+h23f4i2q06Xls06rPJ4E0EKX64YLkF77XZF1hWFmC5MDLwNkrD8nmNEkBw8wID
+> AQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy
+> YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUPOlg4/8ZoQp7o0L0jUIutNWccuww
+> HwYDVR0jBBgwFoAUPOlg4/8ZoQp7o0L0jUIutNWccuwwDQYJKoZIhvcNAQELBQAD
+> ggEBAFxNkoi0gl8drYsR7N8GpnqlK583VQyNbgUArbcMQYlpz9ZlBptReNKtx7+c
+> 3AVzf+ceORO06rYwfUB1q5xDC9+wwhu/MOD0/sDbYiGY9sWv3jtPSQrmHvmGsD8N
+> 1tRGN9tUdF7/EcJgxnBYxRxv7LLYbm/DvDOHOKTzRGScNDsolCZ4J58WF+g7aQol
+> qXM2fp43XOzoP9uR+RKzPc7n3RXDrowFIGGbld6br/qxXBzll+fDNBGF9YonJqRw
+> NuwM9oM9kPc28/nzFdSQYr5TtK/TSa/v9HPoe3bkRCo3uoGkmQw6MSRxoOTktxrL
+> R+SqIs/vdWGA40O3SFdzET14m2k=
+> -----END CERTIFICATE-----
+
+Notes about the 9ece15a -> c9e5618 rebase:
+- resolved conflicts in:
+ OvmfPkg/OvmfPkgIa32.dsc
+ OvmfPkg/OvmfPkgIa32X64.dsc
+ OvmfPkg/OvmfPkgX64.dsc
+ due to OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf having
+ disappeared in upstream (commit 57446bb9).
+
+Notes about the c9e5618 -> b9ffeab rebase:
+- Guid/VariableFormat.h now lives under MdeModulePkg.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- This patch now squashes the following commits:
+ - 014f459c197b OvmfPkg: EnrollDefaultKeys: application for enrolling
+ default keys (RH only)
+ - 18422a18d0e9 OvmfPkg/EnrollDefaultKeys: assign Status before reading
+ it (RH only)
+ - ddb90568e874 OvmfPkg/EnrollDefaultKeys: silence VS2015x86 warning (RH
+ only)
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- This patch now squashes the following commits:
+ - c0b2615a9c0b OvmfPkg: EnrollDefaultKeys: application for enrolling
+ default keys (RH only)
+ - 22f4d33d0168 OvmfPkg/EnrollDefaultKeys: update SignatureOwner GUID for
+ Windows HCK (RH)
+ - ff7f2c1d870d OvmfPkg/EnrollDefaultKeys: expose CertType parameter of
+ EnrollListOfCerts (RH)
+ - aee7b5ba60b4 OvmfPkg/EnrollDefaultKeys: blacklist empty file in dbx
+ for Windows HCK (RH)
+
+- Consequently, OvmfPkg/EnrollDefaultKeys/ is identical to the same
+ directory at the "RHEL-7.4" tag (49d06d386736).
+
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit c0b2615a9c0b4a4be1bffe45681a32915449279d)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c | 1015 +++++++++++++++++
+ .../EnrollDefaultKeys/EnrollDefaultKeys.inf | 52 +
+ OvmfPkg/OvmfPkgIa32.dsc | 4 +
+ OvmfPkg/OvmfPkgIa32X64.dsc | 4 +
+ OvmfPkg/OvmfPkgX64.dsc | 4 +
+ 5 files changed, 1079 insertions(+)
+ create mode 100644 OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
+ create mode 100644 OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+
+diff --git a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
+new file mode 100644
+index 0000000000..dd413df12d
+--- /dev/null
++++ b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
+@@ -0,0 +1,1015 @@
++/** @file
++ Enroll default PK, KEK, DB.
++
++ Copyright (C) 2014, Red Hat, Inc.
++
++ This program and the accompanying materials are licensed and made available
++ under the terms and conditions of the BSD License which accompanies this
++ distribution. The full text of the license may be found at
++ http://opensource.org/licenses/bsd-license .
++
++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
++ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
++**/
++#include <Guid/AuthenticatedVariableFormat.h> // gEfiCustomModeEnableGuid
++#include <Guid/GlobalVariable.h> // EFI_SETUP_MODE_NAME
++#include <Guid/ImageAuthentication.h> // EFI_IMAGE_SECURITY_DATABASE
++#include <Library/BaseMemoryLib.h> // CopyGuid()
++#include <Library/DebugLib.h> // ASSERT()
++#include <Library/MemoryAllocationLib.h> // FreePool()
++#include <Library/ShellCEntryLib.h> // ShellAppMain()
++#include <Library/UefiLib.h> // AsciiPrint()
++#include <Library/UefiRuntimeServicesTableLib.h> // gRT
++
++//
++// We'll use the certificate below as both Platform Key and as first Key
++// Exchange Key.
++//
++// "Red Hat Secure Boot (PK/KEK key 1)/emailAddress=secalert(a)redhat.com"
++// SHA1: fd:fc:7f:3c:7e:f3:e0:57:76:ad:d7:98:78:21:6c:9b:e0:e1:95:97
++//
++STATIC CONST UINT8 RedHatPkKek1[] = {
++ 0x30, 0x82, 0x03, 0xa0, 0x30, 0x82, 0x02, 0x88, 0xa0, 0x03, 0x02, 0x01, 0x02,
++ 0x02, 0x09, 0x00, 0xfe, 0xf5, 0x88, 0xe8, 0xf3, 0x96, 0xc0, 0xf1, 0x30, 0x0d,
++ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
++ 0x30, 0x51, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22,
++ 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72,
++ 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x28, 0x50, 0x4b, 0x2f, 0x4b, 0x45,
++ 0x4b, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x31, 0x29, 0x31, 0x22, 0x30, 0x20, 0x06,
++ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73,
++ 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61,
++ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x30,
++ 0x33, 0x31, 0x31, 0x31, 0x31, 0x35, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x37,
++ 0x31, 0x30, 0x32, 0x35, 0x31, 0x31, 0x31, 0x35, 0x33, 0x37, 0x5a, 0x30, 0x51,
++ 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x52, 0x65,
++ 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
++ 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x28, 0x50, 0x4b, 0x2f, 0x4b, 0x45, 0x4b, 0x20,
++ 0x6b, 0x65, 0x79, 0x20, 0x31, 0x29, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a,
++ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63,
++ 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, 0x2e,
++ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
++ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
++ 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x90, 0x1f, 0x84,
++ 0x7b, 0x8d, 0xbc, 0xeb, 0x97, 0x26, 0x82, 0x6d, 0x88, 0xab, 0x8a, 0xc9, 0x8c,
++ 0x68, 0x70, 0xf9, 0xdf, 0x4b, 0x07, 0xb2, 0x37, 0x83, 0x0b, 0x02, 0xc8, 0x67,
++ 0x68, 0x30, 0x9e, 0xe3, 0xf0, 0xf0, 0x99, 0x4a, 0xb8, 0x59, 0x57, 0xc6, 0x41,
++ 0xf6, 0x38, 0x8b, 0xfe, 0x66, 0x4c, 0x49, 0xe9, 0x37, 0x37, 0x92, 0x2e, 0x98,
++ 0x01, 0x1e, 0x5b, 0x14, 0x50, 0xe6, 0xa8, 0x8d, 0x25, 0x0d, 0xf5, 0x86, 0xe6,
++ 0xab, 0x30, 0xcb, 0x40, 0x16, 0xea, 0x8d, 0x8b, 0x16, 0x86, 0x70, 0x43, 0x37,
++ 0xf2, 0xce, 0xc0, 0x91, 0xdf, 0x71, 0x14, 0x8e, 0x99, 0x0e, 0x89, 0xb6, 0x4c,
++ 0x6d, 0x24, 0x1e, 0x8c, 0xe4, 0x2f, 0x4f, 0x25, 0xd0, 0xba, 0x06, 0xf8, 0xc6,
++ 0xe8, 0x19, 0x18, 0x76, 0x73, 0x1d, 0x81, 0x6d, 0xa8, 0xd8, 0x05, 0xcf, 0x3a,
++ 0xc8, 0x7b, 0x28, 0xc8, 0x36, 0xa3, 0x16, 0x0d, 0x29, 0x8c, 0x99, 0x9a, 0x68,
++ 0xdc, 0xab, 0xc0, 0x4d, 0x8d, 0xbf, 0x5a, 0xbb, 0x2b, 0xa9, 0x39, 0x4b, 0x04,
++ 0x97, 0x1c, 0xf9, 0x36, 0xbb, 0xc5, 0x3a, 0x86, 0x04, 0xae, 0xaf, 0xd4, 0x82,
++ 0x7b, 0xe0, 0xab, 0xde, 0x49, 0x05, 0x68, 0xfc, 0xf6, 0xae, 0x68, 0x1a, 0x6c,
++ 0x90, 0x4d, 0x57, 0x19, 0x3c, 0x64, 0x66, 0x03, 0xf6, 0xc7, 0x52, 0x9b, 0xf7,
++ 0x94, 0xcf, 0x93, 0x6a, 0xa1, 0x68, 0xc9, 0xaa, 0xcf, 0x99, 0x6b, 0xbc, 0xaa,
++ 0x5e, 0x08, 0xe7, 0x39, 0x1c, 0xf7, 0xf8, 0x0f, 0xba, 0x06, 0x7e, 0xf1, 0xcb,
++ 0xe8, 0x76, 0xdd, 0xfe, 0x22, 0xda, 0xad, 0x3a, 0x5e, 0x5b, 0x34, 0xea, 0xb3,
++ 0xc9, 0xe0, 0x4d, 0x04, 0x29, 0x7e, 0xb8, 0x60, 0xb9, 0x05, 0xef, 0xb5, 0xd9,
++ 0x17, 0x58, 0x56, 0x16, 0x60, 0xb9, 0x30, 0x32, 0xf0, 0x36, 0x4a, 0xc3, 0xf2,
++ 0x79, 0x8d, 0x12, 0x40, 0x70, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x7b,
++ 0x30, 0x79, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00,
++ 0x30, 0x2c, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d,
++ 0x04, 0x1f, 0x16, 0x1d, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, 0x4c, 0x20, 0x47,
++ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74,
++ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
++ 0x0e, 0x04, 0x16, 0x04, 0x14, 0x3c, 0xe9, 0x60, 0xe3, 0xff, 0x19, 0xa1, 0x0a,
++ 0x7b, 0xa3, 0x42, 0xf4, 0x8d, 0x42, 0x2e, 0xb4, 0xd5, 0x9c, 0x72, 0xec, 0x30,
++ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x3c,
++ 0xe9, 0x60, 0xe3, 0xff, 0x19, 0xa1, 0x0a, 0x7b, 0xa3, 0x42, 0xf4, 0x8d, 0x42,
++ 0x2e, 0xb4, 0xd5, 0x9c, 0x72, 0xec, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
++ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
++ 0x5c, 0x4d, 0x92, 0x88, 0xb4, 0x82, 0x5f, 0x1d, 0xad, 0x8b, 0x11, 0xec, 0xdf,
++ 0x06, 0xa6, 0x7a, 0xa5, 0x2b, 0x9f, 0x37, 0x55, 0x0c, 0x8d, 0x6e, 0x05, 0x00,
++ 0xad, 0xb7, 0x0c, 0x41, 0x89, 0x69, 0xcf, 0xd6, 0x65, 0x06, 0x9b, 0x51, 0x78,
++ 0xd2, 0xad, 0xc7, 0xbf, 0x9c, 0xdc, 0x05, 0x73, 0x7f, 0xe7, 0x1e, 0x39, 0x13,
++ 0xb4, 0xea, 0xb6, 0x30, 0x7d, 0x40, 0x75, 0xab, 0x9c, 0x43, 0x0b, 0xdf, 0xb0,
++ 0xc2, 0x1b, 0xbf, 0x30, 0xe0, 0xf4, 0xfe, 0xc0, 0xdb, 0x62, 0x21, 0x98, 0xf6,
++ 0xc5, 0xaf, 0xde, 0x3b, 0x4f, 0x49, 0x0a, 0xe6, 0x1e, 0xf9, 0x86, 0xb0, 0x3f,
++ 0x0d, 0xd6, 0xd4, 0x46, 0x37, 0xdb, 0x54, 0x74, 0x5e, 0xff, 0x11, 0xc2, 0x60,
++ 0xc6, 0x70, 0x58, 0xc5, 0x1c, 0x6f, 0xec, 0xb2, 0xd8, 0x6e, 0x6f, 0xc3, 0xbc,
++ 0x33, 0x87, 0x38, 0xa4, 0xf3, 0x44, 0x64, 0x9c, 0x34, 0x3b, 0x28, 0x94, 0x26,
++ 0x78, 0x27, 0x9f, 0x16, 0x17, 0xe8, 0x3b, 0x69, 0x0a, 0x25, 0xa9, 0x73, 0x36,
++ 0x7e, 0x9e, 0x37, 0x5c, 0xec, 0xe8, 0x3f, 0xdb, 0x91, 0xf9, 0x12, 0xb3, 0x3d,
++ 0xce, 0xe7, 0xdd, 0x15, 0xc3, 0xae, 0x8c, 0x05, 0x20, 0x61, 0x9b, 0x95, 0xde,
++ 0x9b, 0xaf, 0xfa, 0xb1, 0x5c, 0x1c, 0xe5, 0x97, 0xe7, 0xc3, 0x34, 0x11, 0x85,
++ 0xf5, 0x8a, 0x27, 0x26, 0xa4, 0x70, 0x36, 0xec, 0x0c, 0xf6, 0x83, 0x3d, 0x90,
++ 0xf7, 0x36, 0xf3, 0xf9, 0xf3, 0x15, 0xd4, 0x90, 0x62, 0xbe, 0x53, 0xb4, 0xaf,
++ 0xd3, 0x49, 0xaf, 0xef, 0xf4, 0x73, 0xe8, 0x7b, 0x76, 0xe4, 0x44, 0x2a, 0x37,
++ 0xba, 0x81, 0xa4, 0x99, 0x0c, 0x3a, 0x31, 0x24, 0x71, 0xa0, 0xe4, 0xe4, 0xb7,
++ 0x1a, 0xcb, 0x47, 0xe4, 0xaa, 0x22, 0xcf, 0xef, 0x75, 0x61, 0x80, 0xe3, 0x43,
++ 0xb7, 0x48, 0x57, 0x73, 0x11, 0x3d, 0x78, 0x9b, 0x69
++};
++
++//
++// Second KEK: "Microsoft Corporation KEK CA 2011".
++// SHA1: 31:59:0b:fd:89:c9:d7:4e:d0:87:df:ac:66:33:4b:39:31:25:4b:30
++//
++// "dbx" updates in "dbxtool" are signed with a key derived from this KEK.
++//
++STATIC CONST UINT8 MicrosoftKEK[] = {
++ 0x30, 0x82, 0x05, 0xe8, 0x30, 0x82, 0x03, 0xd0, 0xa0, 0x03, 0x02, 0x01, 0x02,
++ 0x02, 0x0a, 0x61, 0x0a, 0xd1, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30,
++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
++ 0x00, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
++ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
++ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
++ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
++ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
++ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
++ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3b, 0x30,
++ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x4d, 0x69, 0x63, 0x72, 0x6f,
++ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
++ 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72,
++ 0x74, 0x79, 0x20, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x70, 0x6c, 0x61, 0x63,
++ 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30,
++ 0x36, 0x32, 0x34, 0x32, 0x30, 0x34, 0x31, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x32,
++ 0x36, 0x30, 0x36, 0x32, 0x34, 0x32, 0x30, 0x35, 0x31, 0x32, 0x39, 0x5a, 0x30,
++ 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
++ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
++ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30,
++ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f,
++ 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15,
++ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
++ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2a, 0x30, 0x28, 0x06,
++ 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
++ 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
++ 0x6e, 0x20, 0x4b, 0x45, 0x4b, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31,
++ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
++ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
++ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0xe8, 0xb5, 0x8a, 0xbf, 0xad,
++ 0x57, 0x26, 0xb0, 0x26, 0xc3, 0xea, 0xe7, 0xfb, 0x57, 0x7a, 0x44, 0x02, 0x5d,
++ 0x07, 0x0d, 0xda, 0x4a, 0xe5, 0x74, 0x2a, 0xe6, 0xb0, 0x0f, 0xec, 0x6d, 0xeb,
++ 0xec, 0x7f, 0xb9, 0xe3, 0x5a, 0x63, 0x32, 0x7c, 0x11, 0x17, 0x4f, 0x0e, 0xe3,
++ 0x0b, 0xa7, 0x38, 0x15, 0x93, 0x8e, 0xc6, 0xf5, 0xe0, 0x84, 0xb1, 0x9a, 0x9b,
++ 0x2c, 0xe7, 0xf5, 0xb7, 0x91, 0xd6, 0x09, 0xe1, 0xe2, 0xc0, 0x04, 0xa8, 0xac,
++ 0x30, 0x1c, 0xdf, 0x48, 0xf3, 0x06, 0x50, 0x9a, 0x64, 0xa7, 0x51, 0x7f, 0xc8,
++ 0x85, 0x4f, 0x8f, 0x20, 0x86, 0xce, 0xfe, 0x2f, 0xe1, 0x9f, 0xff, 0x82, 0xc0,
++ 0xed, 0xe9, 0xcd, 0xce, 0xf4, 0x53, 0x6a, 0x62, 0x3a, 0x0b, 0x43, 0xb9, 0xe2,
++ 0x25, 0xfd, 0xfe, 0x05, 0xf9, 0xd4, 0xc4, 0x14, 0xab, 0x11, 0xe2, 0x23, 0x89,
++ 0x8d, 0x70, 0xb7, 0xa4, 0x1d, 0x4d, 0xec, 0xae, 0xe5, 0x9c, 0xfa, 0x16, 0xc2,
++ 0xd7, 0xc1, 0xcb, 0xd4, 0xe8, 0xc4, 0x2f, 0xe5, 0x99, 0xee, 0x24, 0x8b, 0x03,
++ 0xec, 0x8d, 0xf2, 0x8b, 0xea, 0xc3, 0x4a, 0xfb, 0x43, 0x11, 0x12, 0x0b, 0x7e,
++ 0xb5, 0x47, 0x92, 0x6c, 0xdc, 0xe6, 0x04, 0x89, 0xeb, 0xf5, 0x33, 0x04, 0xeb,
++ 0x10, 0x01, 0x2a, 0x71, 0xe5, 0xf9, 0x83, 0x13, 0x3c, 0xff, 0x25, 0x09, 0x2f,
++ 0x68, 0x76, 0x46, 0xff, 0xba, 0x4f, 0xbe, 0xdc, 0xad, 0x71, 0x2a, 0x58, 0xaa,
++ 0xfb, 0x0e, 0xd2, 0x79, 0x3d, 0xe4, 0x9b, 0x65, 0x3b, 0xcc, 0x29, 0x2a, 0x9f,
++ 0xfc, 0x72, 0x59, 0xa2, 0xeb, 0xae, 0x92, 0xef, 0xf6, 0x35, 0x13, 0x80, 0xc6,
++ 0x02, 0xec, 0xe4, 0x5f, 0xcc, 0x9d, 0x76, 0xcd, 0xef, 0x63, 0x92, 0xc1, 0xaf,
++ 0x79, 0x40, 0x84, 0x79, 0x87, 0x7f, 0xe3, 0x52, 0xa8, 0xe8, 0x9d, 0x7b, 0x07,
++ 0x69, 0x8f, 0x15, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x4f, 0x30,
++ 0x82, 0x01, 0x4b, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
++ 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
++ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x62, 0xfc, 0x43, 0xcd, 0xa0, 0x3e, 0xa4,
++ 0xcb, 0x67, 0x12, 0xd2, 0x5b, 0xd9, 0x55, 0xac, 0x7b, 0xcc, 0xb6, 0x8a, 0x5f,
++ 0x30, 0x19, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02,
++ 0x04, 0x0c, 0x1e, 0x0a, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00,
++ 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01,
++ 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
++ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
++ 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0x66, 0x52, 0x43, 0xe1, 0x7e, 0x58, 0x11,
++ 0xbf, 0xd6, 0x4e, 0x9e, 0x23, 0x55, 0x08, 0x3b, 0x3a, 0x22, 0x6a, 0xa8, 0x30,
++ 0x5c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x55, 0x30, 0x53, 0x30, 0x51, 0xa0,
++ 0x4f, 0xa0, 0x4d, 0x86, 0x4b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63,
++ 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e,
++ 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x70,
++ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f,
++ 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f,
++ 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63,
++ 0x72, 0x6c, 0x30, 0x60, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01,
++ 0x01, 0x04, 0x54, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
++ 0x05, 0x07, 0x30, 0x02, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
++ 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x74,
++ 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61,
++ 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d,
++ 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09,
++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
++ 0x02, 0x01, 0x00, 0xd4, 0x84, 0x88, 0xf5, 0x14, 0x94, 0x18, 0x02, 0xca, 0x2a,
++ 0x3c, 0xfb, 0x2a, 0x92, 0x1c, 0x0c, 0xd7, 0xa0, 0xd1, 0xf1, 0xe8, 0x52, 0x66,
++ 0xa8, 0xee, 0xa2, 0xb5, 0x75, 0x7a, 0x90, 0x00, 0xaa, 0x2d, 0xa4, 0x76, 0x5a,
++ 0xea, 0x79, 0xb7, 0xb9, 0x37, 0x6a, 0x51, 0x7b, 0x10, 0x64, 0xf6, 0xe1, 0x64,
++ 0xf2, 0x02, 0x67, 0xbe, 0xf7, 0xa8, 0x1b, 0x78, 0xbd, 0xba, 0xce, 0x88, 0x58,
++ 0x64, 0x0c, 0xd6, 0x57, 0xc8, 0x19, 0xa3, 0x5f, 0x05, 0xd6, 0xdb, 0xc6, 0xd0,
++ 0x69, 0xce, 0x48, 0x4b, 0x32, 0xb7, 0xeb, 0x5d, 0xd2, 0x30, 0xf5, 0xc0, 0xf5,
++ 0xb8, 0xba, 0x78, 0x07, 0xa3, 0x2b, 0xfe, 0x9b, 0xdb, 0x34, 0x56, 0x84, 0xec,
++ 0x82, 0xca, 0xae, 0x41, 0x25, 0x70, 0x9c, 0x6b, 0xe9, 0xfe, 0x90, 0x0f, 0xd7,
++ 0x96, 0x1f, 0xe5, 0xe7, 0x94, 0x1f, 0xb2, 0x2a, 0x0c, 0x8d, 0x4b, 0xff, 0x28,
++ 0x29, 0x10, 0x7b, 0xf7, 0xd7, 0x7c, 0xa5, 0xd1, 0x76, 0xb9, 0x05, 0xc8, 0x79,
++ 0xed, 0x0f, 0x90, 0x92, 0x9c, 0xc2, 0xfe, 0xdf, 0x6f, 0x7e, 0x6c, 0x0f, 0x7b,
++ 0xd4, 0xc1, 0x45, 0xdd, 0x34, 0x51, 0x96, 0x39, 0x0f, 0xe5, 0x5e, 0x56, 0xd8,
++ 0x18, 0x05, 0x96, 0xf4, 0x07, 0xa6, 0x42, 0xb3, 0xa0, 0x77, 0xfd, 0x08, 0x19,
++ 0xf2, 0x71, 0x56, 0xcc, 0x9f, 0x86, 0x23, 0xa4, 0x87, 0xcb, 0xa6, 0xfd, 0x58,
++ 0x7e, 0xd4, 0x69, 0x67, 0x15, 0x91, 0x7e, 0x81, 0xf2, 0x7f, 0x13, 0xe5, 0x0d,
++ 0x8b, 0x8a, 0x3c, 0x87, 0x84, 0xeb, 0xe3, 0xce, 0xbd, 0x43, 0xe5, 0xad, 0x2d,
++ 0x84, 0x93, 0x8e, 0x6a, 0x2b, 0x5a, 0x7c, 0x44, 0xfa, 0x52, 0xaa, 0x81, 0xc8,
++ 0x2d, 0x1c, 0xbb, 0xe0, 0x52, 0xdf, 0x00, 0x11, 0xf8, 0x9a, 0x3d, 0xc1, 0x60,
++ 0xb0, 0xe1, 0x33, 0xb5, 0xa3, 0x88, 0xd1, 0x65, 0x19, 0x0a, 0x1a, 0xe7, 0xac,
++ 0x7c, 0xa4, 0xc1, 0x82, 0x87, 0x4e, 0x38, 0xb1, 0x2f, 0x0d, 0xc5, 0x14, 0x87,
++ 0x6f, 0xfd, 0x8d, 0x2e, 0xbc, 0x39, 0xb6, 0xe7, 0xe6, 0xc3, 0xe0, 0xe4, 0xcd,
++ 0x27, 0x84, 0xef, 0x94, 0x42, 0xef, 0x29, 0x8b, 0x90, 0x46, 0x41, 0x3b, 0x81,
++ 0x1b, 0x67, 0xd8, 0xf9, 0x43, 0x59, 0x65, 0xcb, 0x0d, 0xbc, 0xfd, 0x00, 0x92,
++ 0x4f, 0xf4, 0x75, 0x3b, 0xa7, 0xa9, 0x24, 0xfc, 0x50, 0x41, 0x40, 0x79, 0xe0,
++ 0x2d, 0x4f, 0x0a, 0x6a, 0x27, 0x76, 0x6e, 0x52, 0xed, 0x96, 0x69, 0x7b, 0xaf,
++ 0x0f, 0xf7, 0x87, 0x05, 0xd0, 0x45, 0xc2, 0xad, 0x53, 0x14, 0x81, 0x1f, 0xfb,
++ 0x30, 0x04, 0xaa, 0x37, 0x36, 0x61, 0xda, 0x4a, 0x69, 0x1b, 0x34, 0xd8, 0x68,
++ 0xed, 0xd6, 0x02, 0xcf, 0x6c, 0x94, 0x0c, 0xd3, 0xcf, 0x6c, 0x22, 0x79, 0xad,
++ 0xb1, 0xf0, 0xbc, 0x03, 0xa2, 0x46, 0x60, 0xa9, 0xc4, 0x07, 0xc2, 0x21, 0x82,
++ 0xf1, 0xfd, 0xf2, 0xe8, 0x79, 0x32, 0x60, 0xbf, 0xd8, 0xac, 0xa5, 0x22, 0x14,
++ 0x4b, 0xca, 0xc1, 0xd8, 0x4b, 0xeb, 0x7d, 0x3f, 0x57, 0x35, 0xb2, 0xe6, 0x4f,
++ 0x75, 0xb4, 0xb0, 0x60, 0x03, 0x22, 0x53, 0xae, 0x91, 0x79, 0x1d, 0xd6, 0x9b,
++ 0x41, 0x1f, 0x15, 0x86, 0x54, 0x70, 0xb2, 0xde, 0x0d, 0x35, 0x0f, 0x7c, 0xb0,
++ 0x34, 0x72, 0xba, 0x97, 0x60, 0x3b, 0xf0, 0x79, 0xeb, 0xa2, 0xb2, 0x1c, 0x5d,
++ 0xa2, 0x16, 0xb8, 0x87, 0xc5, 0xe9, 0x1b, 0xf6, 0xb5, 0x97, 0x25, 0x6f, 0x38,
++ 0x9f, 0xe3, 0x91, 0xfa, 0x8a, 0x79, 0x98, 0xc3, 0x69, 0x0e, 0xb7, 0xa3, 0x1c,
++ 0x20, 0x05, 0x97, 0xf8, 0xca, 0x14, 0xae, 0x00, 0xd7, 0xc4, 0xf3, 0xc0, 0x14,
++ 0x10, 0x75, 0x6b, 0x34, 0xa0, 0x1b, 0xb5, 0x99, 0x60, 0xf3, 0x5c, 0xb0, 0xc5,
++ 0x57, 0x4e, 0x36, 0xd2, 0x32, 0x84, 0xbf, 0x9e
++};
++
++//
++// First DB entry: "Microsoft Windows Production PCA 2011"
++// SHA1: 58:0a:6f:4c:c4:e4:b6:69:b9:eb:dc:1b:2b:3e:08:7b:80:d0:67:8d
++//
++// Windows 8 and Windows Server 2012 R2 boot loaders are signed with a chain
++// rooted in this certificate.
++//
++STATIC CONST UINT8 MicrosoftPCA[] = {
++ 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02,
++ 0x02, 0x0a, 0x61, 0x07, 0x76, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30,
++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
++ 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
++ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
++ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
++ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
++ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
++ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
++ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x32, 0x30,
++ 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x4d, 0x69, 0x63, 0x72, 0x6f,
++ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72,
++ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
++ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1e, 0x17,
++ 0x0d, 0x31, 0x31, 0x31, 0x30, 0x31, 0x39, 0x31, 0x38, 0x34, 0x31, 0x34, 0x32,
++ 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x31, 0x30, 0x31, 0x39, 0x31, 0x38, 0x35, 0x31,
++ 0x34, 0x32, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
++ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
++ 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f,
++ 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52,
++ 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
++ 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
++ 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31,
++ 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x4d, 0x69, 0x63,
++ 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77,
++ 0x73, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
++ 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30,
++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
++ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,
++ 0x01, 0x00, 0xdd, 0x0c, 0xbb, 0xa2, 0xe4, 0x2e, 0x09, 0xe3, 0xe7, 0xc5, 0xf7,
++ 0x96, 0x69, 0xbc, 0x00, 0x21, 0xbd, 0x69, 0x33, 0x33, 0xef, 0xad, 0x04, 0xcb,
++ 0x54, 0x80, 0xee, 0x06, 0x83, 0xbb, 0xc5, 0x20, 0x84, 0xd9, 0xf7, 0xd2, 0x8b,
++ 0xf3, 0x38, 0xb0, 0xab, 0xa4, 0xad, 0x2d, 0x7c, 0x62, 0x79, 0x05, 0xff, 0xe3,
++ 0x4a, 0x3f, 0x04, 0x35, 0x20, 0x70, 0xe3, 0xc4, 0xe7, 0x6b, 0xe0, 0x9c, 0xc0,
++ 0x36, 0x75, 0xe9, 0x8a, 0x31, 0xdd, 0x8d, 0x70, 0xe5, 0xdc, 0x37, 0xb5, 0x74,
++ 0x46, 0x96, 0x28, 0x5b, 0x87, 0x60, 0x23, 0x2c, 0xbf, 0xdc, 0x47, 0xa5, 0x67,
++ 0xf7, 0x51, 0x27, 0x9e, 0x72, 0xeb, 0x07, 0xa6, 0xc9, 0xb9, 0x1e, 0x3b, 0x53,
++ 0x35, 0x7c, 0xe5, 0xd3, 0xec, 0x27, 0xb9, 0x87, 0x1c, 0xfe, 0xb9, 0xc9, 0x23,
++ 0x09, 0x6f, 0xa8, 0x46, 0x91, 0xc1, 0x6e, 0x96, 0x3c, 0x41, 0xd3, 0xcb, 0xa3,
++ 0x3f, 0x5d, 0x02, 0x6a, 0x4d, 0xec, 0x69, 0x1f, 0x25, 0x28, 0x5c, 0x36, 0xff,
++ 0xfd, 0x43, 0x15, 0x0a, 0x94, 0xe0, 0x19, 0xb4, 0xcf, 0xdf, 0xc2, 0x12, 0xe2,
++ 0xc2, 0x5b, 0x27, 0xee, 0x27, 0x78, 0x30, 0x8b, 0x5b, 0x2a, 0x09, 0x6b, 0x22,
++ 0x89, 0x53, 0x60, 0x16, 0x2c, 0xc0, 0x68, 0x1d, 0x53, 0xba, 0xec, 0x49, 0xf3,
++ 0x9d, 0x61, 0x8c, 0x85, 0x68, 0x09, 0x73, 0x44, 0x5d, 0x7d, 0xa2, 0x54, 0x2b,
++ 0xdd, 0x79, 0xf7, 0x15, 0xcf, 0x35, 0x5d, 0x6c, 0x1c, 0x2b, 0x5c, 0xce, 0xbc,
++ 0x9c, 0x23, 0x8b, 0x6f, 0x6e, 0xb5, 0x26, 0xd9, 0x36, 0x13, 0xc3, 0x4f, 0xd6,
++ 0x27, 0xae, 0xb9, 0x32, 0x3b, 0x41, 0x92, 0x2c, 0xe1, 0xc7, 0xcd, 0x77, 0xe8,
++ 0xaa, 0x54, 0x4e, 0xf7, 0x5c, 0x0b, 0x04, 0x87, 0x65, 0xb4, 0x43, 0x18, 0xa8,
++ 0xb2, 0xe0, 0x6d, 0x19, 0x77, 0xec, 0x5a, 0x24, 0xfa, 0x48, 0x03, 0x02, 0x03,
++ 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x43, 0x30, 0x82, 0x01, 0x3f, 0x30, 0x10,
++ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03,
++ 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
++ 0x14, 0xa9, 0x29, 0x02, 0x39, 0x8e, 0x16, 0xc4, 0x97, 0x78, 0xcd, 0x90, 0xf9,
++ 0x9e, 0x4f, 0x9a, 0xe1, 0x7c, 0x55, 0xaf, 0x53, 0x30, 0x19, 0x06, 0x09, 0x2b,
++ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0c, 0x1e, 0x0a, 0x00,
++ 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03,
++ 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03,
++ 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
++ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
++ 0xd5, 0xf6, 0x56, 0xcb, 0x8f, 0xe8, 0xa2, 0x5c, 0x62, 0x68, 0xd1, 0x3d, 0x94,
++ 0x90, 0x5b, 0xd7, 0xce, 0x9a, 0x18, 0xc4, 0x30, 0x56, 0x06, 0x03, 0x55, 0x1d,
++ 0x1f, 0x04, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0xa0, 0x49, 0xa0, 0x47, 0x86, 0x45,
++ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69,
++ 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70,
++ 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
++ 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x52, 0x6f, 0x6f, 0x43, 0x65, 0x72, 0x41,
++ 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x33,
++ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x5a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
++ 0x07, 0x01, 0x01, 0x04, 0x4e, 0x30, 0x4c, 0x30, 0x4a, 0x06, 0x08, 0x2b, 0x06,
++ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74, 0x74, 0x70, 0x3a,
++ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
++ 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65,
++ 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x52, 0x6f, 0x6f, 0x43, 0x65, 0x72,
++ 0x41, 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x32,
++ 0x33, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
++ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x14,
++ 0xfc, 0x7c, 0x71, 0x51, 0xa5, 0x79, 0xc2, 0x6e, 0xb2, 0xef, 0x39, 0x3e, 0xbc,
++ 0x3c, 0x52, 0x0f, 0x6e, 0x2b, 0x3f, 0x10, 0x13, 0x73, 0xfe, 0xa8, 0x68, 0xd0,
++ 0x48, 0xa6, 0x34, 0x4d, 0x8a, 0x96, 0x05, 0x26, 0xee, 0x31, 0x46, 0x90, 0x61,
++ 0x79, 0xd6, 0xff, 0x38, 0x2e, 0x45, 0x6b, 0xf4, 0xc0, 0xe5, 0x28, 0xb8, 0xda,
++ 0x1d, 0x8f, 0x8a, 0xdb, 0x09, 0xd7, 0x1a, 0xc7, 0x4c, 0x0a, 0x36, 0x66, 0x6a,
++ 0x8c, 0xec, 0x1b, 0xd7, 0x04, 0x90, 0xa8, 0x18, 0x17, 0xa4, 0x9b, 0xb9, 0xe2,
++ 0x40, 0x32, 0x36, 0x76, 0xc4, 0xc1, 0x5a, 0xc6, 0xbf, 0xe4, 0x04, 0xc0, 0xea,
++ 0x16, 0xd3, 0xac, 0xc3, 0x68, 0xef, 0x62, 0xac, 0xdd, 0x54, 0x6c, 0x50, 0x30,
++ 0x58, 0xa6, 0xeb, 0x7c, 0xfe, 0x94, 0xa7, 0x4e, 0x8e, 0xf4, 0xec, 0x7c, 0x86,
++ 0x73, 0x57, 0xc2, 0x52, 0x21, 0x73, 0x34, 0x5a, 0xf3, 0xa3, 0x8a, 0x56, 0xc8,
++ 0x04, 0xda, 0x07, 0x09, 0xed, 0xf8, 0x8b, 0xe3, 0xce, 0xf4, 0x7e, 0x8e, 0xae,
++ 0xf0, 0xf6, 0x0b, 0x8a, 0x08, 0xfb, 0x3f, 0xc9, 0x1d, 0x72, 0x7f, 0x53, 0xb8,
++ 0xeb, 0xbe, 0x63, 0xe0, 0xe3, 0x3d, 0x31, 0x65, 0xb0, 0x81, 0xe5, 0xf2, 0xac,
++ 0xcd, 0x16, 0xa4, 0x9f, 0x3d, 0xa8, 0xb1, 0x9b, 0xc2, 0x42, 0xd0, 0x90, 0x84,
++ 0x5f, 0x54, 0x1d, 0xff, 0x89, 0xea, 0xba, 0x1d, 0x47, 0x90, 0x6f, 0xb0, 0x73,
++ 0x4e, 0x41, 0x9f, 0x40, 0x9f, 0x5f, 0xe5, 0xa1, 0x2a, 0xb2, 0x11, 0x91, 0x73,
++ 0x8a, 0x21, 0x28, 0xf0, 0xce, 0xde, 0x73, 0x39, 0x5f, 0x3e, 0xab, 0x5c, 0x60,
++ 0xec, 0xdf, 0x03, 0x10, 0xa8, 0xd3, 0x09, 0xe9, 0xf4, 0xf6, 0x96, 0x85, 0xb6,
++ 0x7f, 0x51, 0x88, 0x66, 0x47, 0x19, 0x8d, 0xa2, 0xb0, 0x12, 0x3d, 0x81, 0x2a,
++ 0x68, 0x05, 0x77, 0xbb, 0x91, 0x4c, 0x62, 0x7b, 0xb6, 0xc1, 0x07, 0xc7, 0xba,
++ 0x7a, 0x87, 0x34, 0x03, 0x0e, 0x4b, 0x62, 0x7a, 0x99, 0xe9, 0xca, 0xfc, 0xce,
++ 0x4a, 0x37, 0xc9, 0x2d, 0xa4, 0x57, 0x7c, 0x1c, 0xfe, 0x3d, 0xdc, 0xb8, 0x0f,
++ 0x5a, 0xfa, 0xd6, 0xc4, 0xb3, 0x02, 0x85, 0x02, 0x3a, 0xea, 0xb3, 0xd9, 0x6e,
++ 0xe4, 0x69, 0x21, 0x37, 0xde, 0x81, 0xd1, 0xf6, 0x75, 0x19, 0x05, 0x67, 0xd3,
++ 0x93, 0x57, 0x5e, 0x29, 0x1b, 0x39, 0xc8, 0xee, 0x2d, 0xe1, 0xcd, 0xe4, 0x45,
++ 0x73, 0x5b, 0xd0, 0xd2, 0xce, 0x7a, 0xab, 0x16, 0x19, 0x82, 0x46, 0x58, 0xd0,
++ 0x5e, 0x9d, 0x81, 0xb3, 0x67, 0xaf, 0x6c, 0x35, 0xf2, 0xbc, 0xe5, 0x3f, 0x24,
++ 0xe2, 0x35, 0xa2, 0x0a, 0x75, 0x06, 0xf6, 0x18, 0x56, 0x99, 0xd4, 0x78, 0x2c,
++ 0xd1, 0x05, 0x1b, 0xeb, 0xd0, 0x88, 0x01, 0x9d, 0xaa, 0x10, 0xf1, 0x05, 0xdf,
++ 0xba, 0x7e, 0x2c, 0x63, 0xb7, 0x06, 0x9b, 0x23, 0x21, 0xc4, 0xf9, 0x78, 0x6c,
++ 0xe2, 0x58, 0x17, 0x06, 0x36, 0x2b, 0x91, 0x12, 0x03, 0xcc, 0xa4, 0xd9, 0xf2,
++ 0x2d, 0xba, 0xf9, 0x94, 0x9d, 0x40, 0xed, 0x18, 0x45, 0xf1, 0xce, 0x8a, 0x5c,
++ 0x6b, 0x3e, 0xab, 0x03, 0xd3, 0x70, 0x18, 0x2a, 0x0a, 0x6a, 0xe0, 0x5f, 0x47,
++ 0xd1, 0xd5, 0x63, 0x0a, 0x32, 0xf2, 0xaf, 0xd7, 0x36, 0x1f, 0x2a, 0x70, 0x5a,
++ 0xe5, 0x42, 0x59, 0x08, 0x71, 0x4b, 0x57, 0xba, 0x7e, 0x83, 0x81, 0xf0, 0x21,
++ 0x3c, 0xf4, 0x1c, 0xc1, 0xc5, 0xb9, 0x90, 0x93, 0x0e, 0x88, 0x45, 0x93, 0x86,
++ 0xe9, 0xb1, 0x20, 0x99, 0xbe, 0x98, 0xcb, 0xc5, 0x95, 0xa4, 0x5d, 0x62, 0xd6,
++ 0xa0, 0x63, 0x08, 0x20, 0xbd, 0x75, 0x10, 0x77, 0x7d, 0x3d, 0xf3, 0x45, 0xb9,
++ 0x9f, 0x97, 0x9f, 0xcb, 0x57, 0x80, 0x6f, 0x33, 0xa9, 0x04, 0xcf, 0x77, 0xa4,
++ 0x62, 0x1c, 0x59, 0x7e
++};
++
++//
++// Second DB entry: "Microsoft Corporation UEFI CA 2011"
++// SHA1: 46:de:f6:3b:5c:e6:1c:f8:ba:0d:e2:e6:63:9c:10:19:d0:ed:14:f3
++//
++// To verify the "shim" binary and PCI expansion ROMs with.
++//
++STATIC CONST UINT8 MicrosoftUefiCA[] = {
++ 0x30, 0x82, 0x06, 0x10, 0x30, 0x82, 0x03, 0xf8, 0xa0, 0x03, 0x02, 0x01, 0x02,
++ 0x02, 0x0a, 0x61, 0x08, 0xd3, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30,
++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
++ 0x00, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
++ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
++ 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31,
++ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
++ 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
++ 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43,
++ 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3b, 0x30,
++ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x4d, 0x69, 0x63, 0x72, 0x6f,
++ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
++ 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72,
++ 0x74, 0x79, 0x20, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x70, 0x6c, 0x61, 0x63,
++ 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30,
++ 0x36, 0x32, 0x37, 0x32, 0x31, 0x32, 0x32, 0x34, 0x35, 0x5a, 0x17, 0x0d, 0x32,
++ 0x36, 0x30, 0x36, 0x32, 0x37, 0x32, 0x31, 0x33, 0x32, 0x34, 0x35, 0x5a, 0x30,
++ 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
++ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
++ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30,
++ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f,
++ 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15,
++ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
++ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2b, 0x30, 0x29, 0x06,
++ 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
++ 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
++ 0x6e, 0x20, 0x55, 0x45, 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31,
++ 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
++ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
++ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0x08, 0x6c, 0x4c, 0xc7,
++ 0x45, 0x09, 0x6a, 0x4b, 0x0c, 0xa4, 0xc0, 0x87, 0x7f, 0x06, 0x75, 0x0c, 0x43,
++ 0x01, 0x54, 0x64, 0xe0, 0x16, 0x7f, 0x07, 0xed, 0x92, 0x7d, 0x0b, 0xb2, 0x73,
++ 0xbf, 0x0c, 0x0a, 0xc6, 0x4a, 0x45, 0x61, 0xa0, 0xc5, 0x16, 0x2d, 0x96, 0xd3,
++ 0xf5, 0x2b, 0xa0, 0xfb, 0x4d, 0x49, 0x9b, 0x41, 0x80, 0x90, 0x3c, 0xb9, 0x54,
++ 0xfd, 0xe6, 0xbc, 0xd1, 0x9d, 0xc4, 0xa4, 0x18, 0x8a, 0x7f, 0x41, 0x8a, 0x5c,
++ 0x59, 0x83, 0x68, 0x32, 0xbb, 0x8c, 0x47, 0xc9, 0xee, 0x71, 0xbc, 0x21, 0x4f,
++ 0x9a, 0x8a, 0x7c, 0xff, 0x44, 0x3f, 0x8d, 0x8f, 0x32, 0xb2, 0x26, 0x48, 0xae,
++ 0x75, 0xb5, 0xee, 0xc9, 0x4c, 0x1e, 0x4a, 0x19, 0x7e, 0xe4, 0x82, 0x9a, 0x1d,
++ 0x78, 0x77, 0x4d, 0x0c, 0xb0, 0xbd, 0xf6, 0x0f, 0xd3, 0x16, 0xd3, 0xbc, 0xfa,
++ 0x2b, 0xa5, 0x51, 0x38, 0x5d, 0xf5, 0xfb, 0xba, 0xdb, 0x78, 0x02, 0xdb, 0xff,
++ 0xec, 0x0a, 0x1b, 0x96, 0xd5, 0x83, 0xb8, 0x19, 0x13, 0xe9, 0xb6, 0xc0, 0x7b,
++ 0x40, 0x7b, 0xe1, 0x1f, 0x28, 0x27, 0xc9, 0xfa, 0xef, 0x56, 0x5e, 0x1c, 0xe6,
++ 0x7e, 0x94, 0x7e, 0xc0, 0xf0, 0x44, 0xb2, 0x79, 0x39, 0xe5, 0xda, 0xb2, 0x62,
++ 0x8b, 0x4d, 0xbf, 0x38, 0x70, 0xe2, 0x68, 0x24, 0x14, 0xc9, 0x33, 0xa4, 0x08,
++ 0x37, 0xd5, 0x58, 0x69, 0x5e, 0xd3, 0x7c, 0xed, 0xc1, 0x04, 0x53, 0x08, 0xe7,
++ 0x4e, 0xb0, 0x2a, 0x87, 0x63, 0x08, 0x61, 0x6f, 0x63, 0x15, 0x59, 0xea, 0xb2,
++ 0x2b, 0x79, 0xd7, 0x0c, 0x61, 0x67, 0x8a, 0x5b, 0xfd, 0x5e, 0xad, 0x87, 0x7f,
++ 0xba, 0x86, 0x67, 0x4f, 0x71, 0x58, 0x12, 0x22, 0x04, 0x22, 0x22, 0xce, 0x8b,
++ 0xef, 0x54, 0x71, 0x00, 0xce, 0x50, 0x35, 0x58, 0x76, 0x95, 0x08, 0xee, 0x6a,
++ 0xb1, 0xa2, 0x01, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x76,
++ 0x30, 0x82, 0x01, 0x72, 0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01,
++ 0x82, 0x37, 0x15, 0x01, 0x04, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x23,
++ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x02, 0x04, 0x16,
++ 0x04, 0x14, 0xf8, 0xc1, 0x6b, 0xb7, 0x7f, 0x77, 0x53, 0x4a, 0xf3, 0x25, 0x37,
++ 0x1d, 0x4e, 0xa1, 0x26, 0x7b, 0x0f, 0x20, 0x70, 0x80, 0x30, 0x1d, 0x06, 0x03,
++ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x13, 0xad, 0xbf, 0x43, 0x09, 0xbd,
++ 0x82, 0x70, 0x9c, 0x8c, 0xd5, 0x4f, 0x31, 0x6e, 0xd5, 0x22, 0x98, 0x8a, 0x1b,
++ 0xd4, 0x30, 0x19, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14,
++ 0x02, 0x04, 0x0c, 0x1e, 0x0a, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43,
++ 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02,
++ 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
++ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
++ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0x66, 0x52, 0x43, 0xe1, 0x7e, 0x58,
++ 0x11, 0xbf, 0xd6, 0x4e, 0x9e, 0x23, 0x55, 0x08, 0x3b, 0x3a, 0x22, 0x6a, 0xa8,
++ 0x30, 0x5c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x55, 0x30, 0x53, 0x30, 0x51,
++ 0xa0, 0x4f, 0xa0, 0x4d, 0x86, 0x4b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
++ 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f,
++ 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43,
++ 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f,
++ 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e,
++ 0x63, 0x72, 0x6c, 0x30, 0x60, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
++ 0x01, 0x01, 0x04, 0x54, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, 0x06, 0x01,
++ 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66,
++ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65, 0x72,
++ 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x43, 0x6f, 0x72, 0x54, 0x68, 0x69, 0x50,
++ 0x61, 0x72, 0x4d, 0x61, 0x72, 0x52, 0x6f, 0x6f, 0x5f, 0x32, 0x30, 0x31, 0x30,
++ 0x2d, 0x31, 0x30, 0x2d, 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06,
++ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
++ 0x82, 0x02, 0x01, 0x00, 0x35, 0x08, 0x42, 0xff, 0x30, 0xcc, 0xce, 0xf7, 0x76,
++ 0x0c, 0xad, 0x10, 0x68, 0x58, 0x35, 0x29, 0x46, 0x32, 0x76, 0x27, 0x7c, 0xef,
++ 0x12, 0x41, 0x27, 0x42, 0x1b, 0x4a, 0xaa, 0x6d, 0x81, 0x38, 0x48, 0x59, 0x13,
++ 0x55, 0xf3, 0xe9, 0x58, 0x34, 0xa6, 0x16, 0x0b, 0x82, 0xaa, 0x5d, 0xad, 0x82,
++ 0xda, 0x80, 0x83, 0x41, 0x06, 0x8f, 0xb4, 0x1d, 0xf2, 0x03, 0xb9, 0xf3, 0x1a,
++ 0x5d, 0x1b, 0xf1, 0x50, 0x90, 0xf9, 0xb3, 0x55, 0x84, 0x42, 0x28, 0x1c, 0x20,
++ 0xbd, 0xb2, 0xae, 0x51, 0x14, 0xc5, 0xc0, 0xac, 0x97, 0x95, 0x21, 0x1c, 0x90,
++ 0xdb, 0x0f, 0xfc, 0x77, 0x9e, 0x95, 0x73, 0x91, 0x88, 0xca, 0xbd, 0xbd, 0x52,
++ 0xb9, 0x05, 0x50, 0x0d, 0xdf, 0x57, 0x9e, 0xa0, 0x61, 0xed, 0x0d, 0xe5, 0x6d,
++ 0x25, 0xd9, 0x40, 0x0f, 0x17, 0x40, 0xc8, 0xce, 0xa3, 0x4a, 0xc2, 0x4d, 0xaf,
++ 0x9a, 0x12, 0x1d, 0x08, 0x54, 0x8f, 0xbd, 0xc7, 0xbc, 0xb9, 0x2b, 0x3d, 0x49,
++ 0x2b, 0x1f, 0x32, 0xfc, 0x6a, 0x21, 0x69, 0x4f, 0x9b, 0xc8, 0x7e, 0x42, 0x34,
++ 0xfc, 0x36, 0x06, 0x17, 0x8b, 0x8f, 0x20, 0x40, 0xc0, 0xb3, 0x9a, 0x25, 0x75,
++ 0x27, 0xcd, 0xc9, 0x03, 0xa3, 0xf6, 0x5d, 0xd1, 0xe7, 0x36, 0x54, 0x7a, 0xb9,
++ 0x50, 0xb5, 0xd3, 0x12, 0xd1, 0x07, 0xbf, 0xbb, 0x74, 0xdf, 0xdc, 0x1e, 0x8f,
++ 0x80, 0xd5, 0xed, 0x18, 0xf4, 0x2f, 0x14, 0x16, 0x6b, 0x2f, 0xde, 0x66, 0x8c,
++ 0xb0, 0x23, 0xe5, 0xc7, 0x84, 0xd8, 0xed, 0xea, 0xc1, 0x33, 0x82, 0xad, 0x56,
++ 0x4b, 0x18, 0x2d, 0xf1, 0x68, 0x95, 0x07, 0xcd, 0xcf, 0xf0, 0x72, 0xf0, 0xae,
++ 0xbb, 0xdd, 0x86, 0x85, 0x98, 0x2c, 0x21, 0x4c, 0x33, 0x2b, 0xf0, 0x0f, 0x4a,
++ 0xf0, 0x68, 0x87, 0xb5, 0x92, 0x55, 0x32, 0x75, 0xa1, 0x6a, 0x82, 0x6a, 0x3c,
++ 0xa3, 0x25, 0x11, 0xa4, 0xed, 0xad, 0xd7, 0x04, 0xae, 0xcb, 0xd8, 0x40, 0x59,
++ 0xa0, 0x84, 0xd1, 0x95, 0x4c, 0x62, 0x91, 0x22, 0x1a, 0x74, 0x1d, 0x8c, 0x3d,
++ 0x47, 0x0e, 0x44, 0xa6, 0xe4, 0xb0, 0x9b, 0x34, 0x35, 0xb1, 0xfa, 0xb6, 0x53,
++ 0xa8, 0x2c, 0x81, 0xec, 0xa4, 0x05, 0x71, 0xc8, 0x9d, 0xb8, 0xba, 0xe8, 0x1b,
++ 0x44, 0x66, 0xe4, 0x47, 0x54, 0x0e, 0x8e, 0x56, 0x7f, 0xb3, 0x9f, 0x16, 0x98,
++ 0xb2, 0x86, 0xd0, 0x68, 0x3e, 0x90, 0x23, 0xb5, 0x2f, 0x5e, 0x8f, 0x50, 0x85,
++ 0x8d, 0xc6, 0x8d, 0x82, 0x5f, 0x41, 0xa1, 0xf4, 0x2e, 0x0d, 0xe0, 0x99, 0xd2,
++ 0x6c, 0x75, 0xe4, 0xb6, 0x69, 0xb5, 0x21, 0x86, 0xfa, 0x07, 0xd1, 0xf6, 0xe2,
++ 0x4d, 0xd1, 0xda, 0xad, 0x2c, 0x77, 0x53, 0x1e, 0x25, 0x32, 0x37, 0xc7, 0x6c,
++ 0x52, 0x72, 0x95, 0x86, 0xb0, 0xf1, 0x35, 0x61, 0x6a, 0x19, 0xf5, 0xb2, 0x3b,
++ 0x81, 0x50, 0x56, 0xa6, 0x32, 0x2d, 0xfe, 0xa2, 0x89, 0xf9, 0x42, 0x86, 0x27,
++ 0x18, 0x55, 0xa1, 0x82, 0xca, 0x5a, 0x9b, 0xf8, 0x30, 0x98, 0x54, 0x14, 0xa6,
++ 0x47, 0x96, 0x25, 0x2f, 0xc8, 0x26, 0xe4, 0x41, 0x94, 0x1a, 0x5c, 0x02, 0x3f,
++ 0xe5, 0x96, 0xe3, 0x85, 0x5b, 0x3c, 0x3e, 0x3f, 0xbb, 0x47, 0x16, 0x72, 0x55,
++ 0xe2, 0x25, 0x22, 0xb1, 0xd9, 0x7b, 0xe7, 0x03, 0x06, 0x2a, 0xa3, 0xf7, 0x1e,
++ 0x90, 0x46, 0xc3, 0x00, 0x0d, 0xd6, 0x19, 0x89, 0xe3, 0x0e, 0x35, 0x27, 0x62,
++ 0x03, 0x71, 0x15, 0xa6, 0xef, 0xd0, 0x27, 0xa0, 0xa0, 0x59, 0x37, 0x60, 0xf8,
++ 0x38, 0x94, 0xb8, 0xe0, 0x78, 0x70, 0xf8, 0xba, 0x4c, 0x86, 0x87, 0x94, 0xf6,
++ 0xe0, 0xae, 0x02, 0x45, 0xee, 0x65, 0xc2, 0xb6, 0xa3, 0x7e, 0x69, 0x16, 0x75,
++ 0x07, 0x92, 0x9b, 0xf5, 0xa6, 0xbc, 0x59, 0x83, 0x58
++};
++
++//
++// The Microsoft.UefiSecureBootLogo.Tests.OutOfBoxConfirmDBXisPresent test case
++// of the Secure Boot Logo Test in the Microsoft Hardware Certification Kit
++// expects that the "dbx" variable exist.
++//
++// The article at <https://technet.microsoft.com/en-us/library/dn747883.aspx >
++// writes (excerpt):
++//
++// Windows 8.1 Secure Boot Key Creation and Management Guidance
++// 1. Secure Boot, Windows 8.1 and Key Management
++// 1.4 Signature Databases (Db and Dbx)
++// 1.4.3 Forbidden Signature Database (dbx)
++//
++// The contents of EFI_IMAGE_SIGNATURE_DATABASE1 dbx must be checked when
++// verifying images before checking db and any matches must prevent the
++// image from executing. The database may contain multiple certificates,
++// keys, and hashes in order to identify forbidden images. The Windows
++// Hardware Certification Requirements state that a dbx must be present, so
++// any dummy value, such as the SHA-256 hash of 0, may be used as a safe
++// placeholder until such time as Microsoft begins delivering dbx updates.
++//
++// The byte array below captures the SHA256 checksum of the empty file,
++// blacklisting it for loading & execution. This qualifies as a dummy, since
++// the empty file is not a valid UEFI binary anyway.
++//
++// Technically speaking, we could also capture an official (although soon to be
++// obsolete) dbx update from <http://www.uefi.org/revocationlistfile >. However,
++// the terms and conditions on distributing that binary aren't exactly light
++// reading, so let's best steer clear of it, and follow the "dummy entry"
++// practice recommended -- in natural English langauge -- in the
++// above-referenced TechNet article.
++//
++STATIC CONST UINT8 mSha256OfDevNull[] = {
++ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99,
++ 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95,
++ 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
++};
++
++//
++// The following test cases of the Secure Boot Logo Test in the Microsoft
++// Hardware Certification Kit:
++//
++// - Microsoft.UefiSecureBootLogo.Tests.OutOfBoxVerifyMicrosoftKEKpresent
++// - Microsoft.UefiSecureBootLogo.Tests.OutOfBoxConfirmMicrosoftSignatureInDB
++//
++// expect the EFI_SIGNATURE_DATA.SignatureOwner GUID to be
++// 77FA9ABD-0359-4D32-BD60-28F4E78F784B, when the
++// EFI_SIGNATURE_DATA.SignatureData field carries any of the following X509
++// certificates:
++//
++// - "Microsoft Corporation KEK CA 2011" (in KEK)
++// - "Microsoft Windows Production PCA 2011" (in db)
++// - "Microsoft Corporation UEFI CA 2011" (in db)
++//
++// This is despite the fact that the UEFI specification requires
++// EFI_SIGNATURE_DATA.SignatureOwner to reflect the agent (i.e., OS,
++// application or driver) that enrolled and therefore owns
++// EFI_SIGNATURE_DATA.SignatureData, and not the organization that issued
++// EFI_SIGNATURE_DATA.SignatureData.
++//
++STATIC CONST EFI_GUID mMicrosoftOwnerGuid = {
++ 0x77fa9abd, 0x0359, 0x4d32,
++ { 0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b },
++};
++
++//
++// The most important thing about the variable payload is that it is a list of
++// lists, where the element size of any given *inner* list is constant.
++//
++// Since X509 certificates vary in size, each of our *inner* lists will contain
++// one element only (one X.509 certificate). This is explicitly mentioned in
++// the UEFI specification, in "28.4.1 Signature Database", in a Note.
++//
++// The list structure looks as follows:
++//
++// struct EFI_VARIABLE_AUTHENTICATION_2 { |
++// struct EFI_TIME { |
++// UINT16 Year; |
++// UINT8 Month; |
++// UINT8 Day; |
++// UINT8 Hour; |
++// UINT8 Minute; |
++// UINT8 Second; |
++// UINT8 Pad1; |
++// UINT32 Nanosecond; |
++// INT16 TimeZone; |
++// UINT8 Daylight; |
++// UINT8 Pad2; |
++// } TimeStamp; |
++// |
++// struct WIN_CERTIFICATE_UEFI_GUID { | |
++// struct WIN_CERTIFICATE { | |
++// UINT32 dwLength; ----------------------------------------+ |
++// UINT16 wRevision; | |
++// UINT16 wCertificateType; | |
++// } Hdr; | +- DataSize
++// | |
++// EFI_GUID CertType; | |
++// UINT8 CertData[1] = { <--- "struct hack" | |
++// struct EFI_SIGNATURE_LIST { | | |
++// EFI_GUID SignatureType; | | |
++// UINT32 SignatureListSize; -------------------------+ | |
++// UINT32 SignatureHeaderSize; | | |
++// UINT32 SignatureSize; ---------------------------+ | | |
++// UINT8 SignatureHeader[SignatureHeaderSize]; | | | |
++// v | | |
++// struct EFI_SIGNATURE_DATA { | | | |
++// EFI_GUID SignatureOwner; | | | |
++// UINT8 SignatureData[1] = { <--- "struct hack" | | | |
++// X.509 payload | | | |
++// } | | | |
++// } Signatures[]; | | |
++// } SigLists[]; | |
++// }; | |
++// } AuthInfo; | |
++// }; |
++//
++// Given that the "struct hack" invokes undefined behavior (which is why C99
++// introduced the flexible array member), and because subtracting those pesky
++// sizes of 1 is annoying, and because the format is fully specified in the
++// UEFI specification, we'll introduce two matching convenience structures that
++// are customized for our X.509 purposes.
++//
++#pragma pack(1)
++typedef struct {
++ EFI_TIME TimeStamp;
++
++ //
++ // dwLength covers data below
++ //
++ UINT32 dwLength;
++ UINT16 wRevision;
++ UINT16 wCertificateType;
++ EFI_GUID CertType;
++} SINGLE_HEADER;
++
++typedef struct {
++ //
++ // SignatureListSize covers data below
++ //
++ EFI_GUID SignatureType;
++ UINT32 SignatureListSize;
++ UINT32 SignatureHeaderSize; // constant 0
++ UINT32 SignatureSize;
++
++ //
++ // SignatureSize covers data below
++ //
++ EFI_GUID SignatureOwner;
++
++ //
++ // X.509 certificate follows
++ //
++} REPEATING_HEADER;
++#pragma pack()
++
++/**
++ Enroll a set of certificates in a global variable, overwriting it.
++
++ The variable will be rewritten with NV+BS+RT+AT attributes.
++
++ @param[in] VariableName The name of the variable to overwrite.
++
++ @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to
++ overwrite.
++
++ @param[in] CertType The GUID determining the type of all the
++ certificates in the set that is passed in. For
++ example, gEfiCertX509Guid stands for DER-encoded
++ X.509 certificates, while gEfiCertSha256Guid stands
++ for SHA256 image hashes.
++
++ @param[in] ... A list of
++
++ IN CONST UINT8 *Cert,
++ IN UINTN CertSize,
++ IN CONST EFI_GUID *OwnerGuid
++
++ triplets. If the first component of a triplet is
++ NULL, then the other two components are not
++ accessed, and processing is terminated. The list of
++ certificates is enrolled in the variable specified,
++ overwriting it. The OwnerGuid component identifies
++ the agent installing the certificate.
++
++ @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert
++ value is NULL), or one of the CertSize values
++ is 0, or one of the CertSize values would
++ overflow the accumulated UINT32 data size.
++
++ @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable
++ payload.
++
++ @retval EFI_SUCCESS Enrollment successful; the variable has been
++ overwritten (or created).
++
++ @return Error codes from gRT->GetTime() and
++ gRT->SetVariable().
++**/
++STATIC
++EFI_STATUS
++EFIAPI
++EnrollListOfCerts (
++ IN CHAR16 *VariableName,
++ IN EFI_GUID *VendorGuid,
++ IN EFI_GUID *CertType,
++ ...
++ )
++{
++ UINTN DataSize;
++ SINGLE_HEADER *SingleHeader;
++ REPEATING_HEADER *RepeatingHeader;
++ VA_LIST Marker;
++ CONST UINT8 *Cert;
++ EFI_STATUS Status;
++ UINT8 *Data;
++ UINT8 *Position;
++
++ Status = EFI_SUCCESS;
++
++ //
++ // compute total size first, for UINT32 range check, and allocation
++ //
++ DataSize = sizeof *SingleHeader;
++ VA_START (Marker, CertType);
++ for (Cert = VA_ARG (Marker, CONST UINT8 *);
++ Cert != NULL;
++ Cert = VA_ARG (Marker, CONST UINT8 *)) {
++ UINTN CertSize;
++
++ CertSize = VA_ARG (Marker, UINTN);
++ (VOID)VA_ARG (Marker, CONST EFI_GUID *);
++
++ if (CertSize == 0 ||
++ CertSize > MAX_UINT32 - sizeof *RepeatingHeader ||
++ DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) {
++ Status = EFI_INVALID_PARAMETER;
++ break;
++ }
++ DataSize += sizeof *RepeatingHeader + CertSize;
++ }
++ VA_END (Marker);
++
++ if (DataSize == sizeof *SingleHeader) {
++ Status = EFI_INVALID_PARAMETER;
++ }
++ if (EFI_ERROR (Status)) {
++ goto Out;
++ }
++
++ Data = AllocatePool (DataSize);
++ if (Data == NULL) {
++ Status = EFI_OUT_OF_RESOURCES;
++ goto Out;
++ }
++
++ Position = Data;
++
++ SingleHeader = (SINGLE_HEADER *)Position;
++ Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL);
++ if (EFI_ERROR (Status)) {
++ goto FreeData;
++ }
++ SingleHeader->TimeStamp.Pad1 = 0;
++ SingleHeader->TimeStamp.Nanosecond = 0;
++ SingleHeader->TimeStamp.TimeZone = 0;
++ SingleHeader->TimeStamp.Daylight = 0;
++ SingleHeader->TimeStamp.Pad2 = 0;
++#if 0
++ SingleHeader->dwLength = DataSize - sizeof SingleHeader->TimeStamp;
++#else
++ //
++ // This looks like a bug in edk2. According to the UEFI specification,
++ // dwLength is "The length of the entire certificate, including the length of
++ // the header, in bytes". That shouldn't stop right after CertType -- it
++ // should include everything below it.
++ //
++ SingleHeader->dwLength = sizeof *SingleHeader
++ - sizeof SingleHeader->TimeStamp;
++#endif
++ SingleHeader->wRevision = 0x0200;
++ SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID;
++ CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid);
++ Position += sizeof *SingleHeader;
++
++ VA_START (Marker, CertType);
++ for (Cert = VA_ARG (Marker, CONST UINT8 *);
++ Cert != NULL;
++ Cert = VA_ARG (Marker, CONST UINT8 *)) {
++ UINTN CertSize;
++ CONST EFI_GUID *OwnerGuid;
++
++ CertSize = VA_ARG (Marker, UINTN);
++ OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *);
++
++ RepeatingHeader = (REPEATING_HEADER *)Position;
++ CopyGuid (&RepeatingHeader->SignatureType, CertType);
++ RepeatingHeader->SignatureListSize =
++ (UINT32)(sizeof *RepeatingHeader + CertSize);
++ RepeatingHeader->SignatureHeaderSize = 0;
++ RepeatingHeader->SignatureSize =
++ (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize);
++ CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid);
++ Position += sizeof *RepeatingHeader;
++
++ CopyMem (Position, Cert, CertSize);
++ Position += CertSize;
++ }
++ VA_END (Marker);
++
++ ASSERT (Data + DataSize == Position);
++
++ Status = gRT->SetVariable (VariableName, VendorGuid,
++ (EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS |
++ EFI_VARIABLE_RUNTIME_ACCESS |
++ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
++ DataSize, Data);
++
++FreeData:
++ FreePool (Data);
++
++Out:
++ if (EFI_ERROR (Status)) {
++ AsciiPrint ("error: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName,
++ VendorGuid, Status);
++ }
++ return Status;
++}
++
++
++STATIC
++EFI_STATUS
++EFIAPI
++GetExact (
++ IN CHAR16 *VariableName,
++ IN EFI_GUID *VendorGuid,
++ OUT VOID *Data,
++ IN UINTN DataSize,
++ IN BOOLEAN AllowMissing
++ )
++{
++ UINTN Size;
++ EFI_STATUS Status;
++
++ Size = DataSize;
++ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data);
++ if (EFI_ERROR (Status)) {
++ if (Status == EFI_NOT_FOUND && AllowMissing) {
++ ZeroMem (Data, DataSize);
++ return EFI_SUCCESS;
++ }
++
++ AsciiPrint ("error: GetVariable(\"%s\", %g): %r\n", VariableName,
++ VendorGuid, Status);
++ return Status;
++ }
++
++ if (Size != DataSize) {
++ AsciiPrint ("error: GetVariable(\"%s\", %g): expected size 0x%Lx, "
++ "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size);
++ return EFI_PROTOCOL_ERROR;
++ }
++
++ return EFI_SUCCESS;
++}
++
++typedef struct {
++ UINT8 SetupMode;
++ UINT8 SecureBoot;
++ UINT8 SecureBootEnable;
++ UINT8 CustomMode;
++ UINT8 VendorKeys;
++} SETTINGS;
++
++STATIC
++EFI_STATUS
++EFIAPI
++GetSettings (
++ OUT SETTINGS *Settings
++ )
++{
++ EFI_STATUS Status;
++
++ Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,
++ &Settings->SetupMode, sizeof Settings->SetupMode, FALSE);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
++ Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,
++ &Settings->SecureBoot, sizeof Settings->SecureBoot, FALSE);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
++ Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME,
++ &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable,
++ sizeof Settings->SecureBootEnable, TRUE);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
++ Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
++ &Settings->CustomMode, sizeof Settings->CustomMode, FALSE);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
++ Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid,
++ &Settings->VendorKeys, sizeof Settings->VendorKeys, FALSE);
++ return Status;
++}
++
++STATIC
++VOID
++EFIAPI
++PrintSettings (
++ IN CONST SETTINGS *Settings
++ )
++{
++ AsciiPrint ("info: SetupMode=%d SecureBoot=%d SecureBootEnable=%d "
++ "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot,
++ Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys);
++}
++
++
++INTN
++EFIAPI
++ShellAppMain (
++ IN UINTN Argc,
++ IN CHAR16 **Argv
++ )
++{
++ EFI_STATUS Status;
++ SETTINGS Settings;
++
++ Status = GetSettings (&Settings);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++ PrintSettings (&Settings);
++
++ if (Settings.SetupMode != 1) {
++ AsciiPrint ("error: already in User Mode\n");
++ return 1;
++ }
++
++ if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {
++ Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE;
++ Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
++ (EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS),
++ sizeof Settings.CustomMode, &Settings.CustomMode);
++ if (EFI_ERROR (Status)) {
++ AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
++ &gEfiCustomModeEnableGuid, Status);
++ return 1;
++ }
++ }
++
++ Status = EnrollListOfCerts (
++ EFI_IMAGE_SECURITY_DATABASE,
++ &gEfiImageSecurityDatabaseGuid,
++ &gEfiCertX509Guid,
++ MicrosoftPCA, sizeof MicrosoftPCA, &mMicrosoftOwnerGuid,
++ MicrosoftUefiCA, sizeof MicrosoftUefiCA, &mMicrosoftOwnerGuid,
++ NULL);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++
++ Status = EnrollListOfCerts (
++ EFI_IMAGE_SECURITY_DATABASE1,
++ &gEfiImageSecurityDatabaseGuid,
++ &gEfiCertSha256Guid,
++ mSha256OfDevNull, sizeof mSha256OfDevNull, &gEfiCallerIdGuid,
++ NULL);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++
++ Status = EnrollListOfCerts (
++ EFI_KEY_EXCHANGE_KEY_NAME,
++ &gEfiGlobalVariableGuid,
++ &gEfiCertX509Guid,
++ RedHatPkKek1, sizeof RedHatPkKek1, &gEfiCallerIdGuid,
++ MicrosoftKEK, sizeof MicrosoftKEK, &mMicrosoftOwnerGuid,
++ NULL);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++
++ Status = EnrollListOfCerts (
++ EFI_PLATFORM_KEY_NAME,
++ &gEfiGlobalVariableGuid,
++ &gEfiCertX509Guid,
++ RedHatPkKek1, sizeof RedHatPkKek1, &gEfiGlobalVariableGuid,
++ NULL);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++
++ Settings.CustomMode = STANDARD_SECURE_BOOT_MODE;
++ Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,
++ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
++ sizeof Settings.CustomMode, &Settings.CustomMode);
++ if (EFI_ERROR (Status)) {
++ AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,
++ &gEfiCustomModeEnableGuid, Status);
++ return 1;
++ }
++
++ Status = GetSettings (&Settings);
++ if (EFI_ERROR (Status)) {
++ return 1;
++ }
++ PrintSettings (&Settings);
++
++ if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 ||
++ Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 ||
++ Settings.VendorKeys != 0) {
++ AsciiPrint ("error: unexpected\n");
++ return 1;
++ }
++
++ AsciiPrint ("info: success\n");
++ return 0;
++}
+diff --git a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+new file mode 100644
+index 0000000000..0ad86a2843
+--- /dev/null
++++ b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+@@ -0,0 +1,52 @@
++## @file
++# Enroll default PK, KEK, DB.
++#
++# Copyright (C) 2014, Red Hat, Inc.
++#
++# This program and the accompanying materials are licensed and made available
++# under the terms and conditions of the BSD License which accompanies this
++# distribution. The full text of the license may be found at
++# http://opensource.org/licenses/bsd-license .
++#
++# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
++# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
++# IMPLIED.
++##
++
++[Defines]
++ INF_VERSION = 0x00010006
++ BASE_NAME = EnrollDefaultKeys
++ FILE_GUID = D5C1DF0B-1BAC-4EDF-BA48-08834009CA5A
++ MODULE_TYPE = UEFI_APPLICATION
++ VERSION_STRING = 0.1
++ ENTRY_POINT = ShellCEntryLib
++
++#
++# VALID_ARCHITECTURES = IA32 X64
++#
++
++[Sources]
++ EnrollDefaultKeys.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++ MdeModulePkg/MdeModulePkg.dec
++ SecurityPkg/SecurityPkg.dec
++ ShellPkg/ShellPkg.dec
++
++[Guids]
++ gEfiCertPkcs7Guid
++ gEfiCertSha256Guid
++ gEfiCertX509Guid
++ gEfiCustomModeEnableGuid
++ gEfiGlobalVariableGuid
++ gEfiImageSecurityDatabaseGuid
++ gEfiSecureBootEnableDisableGuid
++
++[LibraryClasses]
++ BaseMemoryLib
++ DebugLib
++ MemoryAllocationLib
++ ShellCEntryLib
++ UefiLib
++ UefiRuntimeServicesTableLib
+diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
+index 8dc3ad2be4..518f6db2c6 100644
+--- a/OvmfPkg/OvmfPkgIa32.dsc
++++ b/OvmfPkg/OvmfPkgIa32.dsc
+@@ -876,6 +876,10 @@
+
+ !if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
++ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
++ <LibraryClasses>
++ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
++ }
+ !endif
+
+ OvmfPkg/PlatformDxe/Platform.inf
+diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
+index d81cd865d5..ed2f876e7e 100644
+--- a/OvmfPkg/OvmfPkgIa32X64.dsc
++++ b/OvmfPkg/OvmfPkgIa32X64.dsc
+@@ -885,6 +885,10 @@
+
+ !if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
++ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
++ <LibraryClasses>
++ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
++ }
+ !endif
+
+ OvmfPkg/PlatformDxe/Platform.inf
+diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
+index 85bd8d4bf6..a12905f882 100644
+--- a/OvmfPkg/OvmfPkgX64.dsc
++++ b/OvmfPkg/OvmfPkgX64.dsc
+@@ -883,6 +883,10 @@
+
+ !if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
++ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf {
++ <LibraryClasses>
++ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
++ }
+ !endif
+
+ OvmfPkg/PlatformDxe/Platform.inf
diff --git a/0014-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch b/0014-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch
new file mode 100644
index 0000000..3c9f001
--- /dev/null
+++ b/0014-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch
@@ -0,0 +1,55 @@
+From 6f89eae9f2abe20e35058848e7cc10a69a6b05ec Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 14 Oct 2015 13:49:43 +0200
+Subject: [PATCH] ArmPlatformPkg: introduce fixed PCD for early hello message
+ (RH only)
+
+Drew has proposed that ARM|AARCH64 platform firmware (especially virtual
+machine firmware) print a reasonably early, simple hello message to the
+serial port, regardless of debug mask settings. This should inform
+interactive users, and provide some rough help in localizing boot
+problems, even with restrictive debug masks.
+
+If a platform doesn't want this feature, it should stick with the default
+empty string.
+
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279
+Downstream only:
+<http://thread.gmane.org/gmane.comp.bios.edk2.devel/2996/focus=3433 >.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Suggested-by: Drew Jones <drjones(a)redhat.com>
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 7ce97b06421434c82095f01a1753a8c9c546cc30)
+(cherry picked from commit 20b1f1cbd0590aa71c6d99d35e23cf08e0707750)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmPlatformPkg/ArmPlatformPkg.dec | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec
+index 5f67e74154..2956d3e2d8 100644
+--- a/ArmPlatformPkg/ArmPlatformPkg.dec
++++ b/ArmPlatformPkg/ArmPlatformPkg.dec
+@@ -113,6 +113,13 @@
+ ## If set, this will swap settings for HDLCD RED_SELECT and BLUE_SELECT registers
+ gArmPlatformTokenSpaceGuid.PcdArmHdLcdSwapBlueRedSelect|FALSE|BOOLEAN|0x00000045
+
++ #
++ # Early hello message (ASCII string), printed to the serial port.
++ # If set to the empty string, nothing is printed.
++ # Otherwise, a trailing CRLF should be specified explicitly.
++ #
++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage|""|VOID*|0x00000100
++
+ [PcdsFixedAtBuild.common,PcdsDynamic.common]
+ ## PL031 RealTimeClock
+ gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0|UINT32|0x00000024
diff --git a/0015-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch b/0015-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch
new file mode 100644
index 0000000..32ce0b3
--- /dev/null
+++ b/0015-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch
@@ -0,0 +1,103 @@
+From e6c0f362edd5834b0d891fc44cd6873566bb0df4 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 14 Oct 2015 13:59:20 +0200
+Subject: [PATCH] ArmPlatformPkg: PrePeiCore: write early hello message to the
+ serial port (RH)
+
+The FixedPcdGetSize() macro expands to an integer constant, therefore an
+optimizing compiler can eliminate the new code, if the platform DSC
+doesn't override the empty string (size=1) default of
+PcdEarlyHelloMessage.
+
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279
+Downstream only:
+<http://thread.gmane.org/gmane.comp.bios.edk2.devel/2996/focus=3433 >.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit b16c4c505ce0e27305235533eac9236aa66f132e)
+(cherry picked from commit 742e5bf6d5ce5a1e73879d6e5c0dd00feda7a9ac)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmPlatformPkg/PrePeiCore/MainMPCore.c | 5 +++++
+ ArmPlatformPkg/PrePeiCore/MainUniCore.c | 5 +++++
+ ArmPlatformPkg/PrePeiCore/PrePeiCore.h | 1 +
+ ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf | 2 ++
+ ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf | 2 ++
+ 5 files changed, 15 insertions(+)
+
+diff --git a/ArmPlatformPkg/PrePeiCore/MainMPCore.c b/ArmPlatformPkg/PrePeiCore/MainMPCore.c
+index dc47adbaff..cbd72232c7 100644
+--- a/ArmPlatformPkg/PrePeiCore/MainMPCore.c
++++ b/ArmPlatformPkg/PrePeiCore/MainMPCore.c
+@@ -117,6 +117,11 @@ PrimaryMain (
+ UINTN TemporaryRamBase;
+ UINTN TemporaryRamSize;
+
++ if (FixedPcdGetSize (PcdEarlyHelloMessage) > 1) {
++ SerialPortWrite (FixedPcdGetPtr (PcdEarlyHelloMessage),
++ FixedPcdGetSize (PcdEarlyHelloMessage) - 1);
++ }
++
+ CreatePpiList (&PpiListSize, &PpiList);
+
+ // Enable the GIC Distributor
+diff --git a/ArmPlatformPkg/PrePeiCore/MainUniCore.c b/ArmPlatformPkg/PrePeiCore/MainUniCore.c
+index 134a469427..af39fc017c 100644
+--- a/ArmPlatformPkg/PrePeiCore/MainUniCore.c
++++ b/ArmPlatformPkg/PrePeiCore/MainUniCore.c
+@@ -35,6 +35,11 @@ PrimaryMain (
+ UINTN TemporaryRamBase;
+ UINTN TemporaryRamSize;
+
++ if (FixedPcdGetSize (PcdEarlyHelloMessage) > 1) {
++ SerialPortWrite (FixedPcdGetPtr (PcdEarlyHelloMessage),
++ FixedPcdGetSize (PcdEarlyHelloMessage) - 1);
++ }
++
+ CreatePpiList (&PpiListSize, &PpiList);
+
+ // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at
+diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCore.h b/ArmPlatformPkg/PrePeiCore/PrePeiCore.h
+index 160894620c..bf843d7768 100644
+--- a/ArmPlatformPkg/PrePeiCore/PrePeiCore.h
++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCore.h
+@@ -21,6 +21,7 @@
+ #include <Library/DebugLib.h>
+ #include <Library/IoLib.h>
+ #include <Library/PcdLib.h>
++#include <Library/SerialPortLib.h>
+
+ #include <PiPei.h>
+ #include <Ppi/TemporaryRamSupport.h>
+diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
+index e3a31fa7c6..1bc0c45420 100644
+--- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
+@@ -72,6 +72,8 @@
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage
++
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gArmTokenSpaceGuid.PcdGicSgiIntId
+diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
+index ec83cec2d8..20698fcfac 100644
+--- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
+@@ -71,3 +71,5 @@
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
++
++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage
diff --git a/0016-ArmVirtPkg-set-early-hello-message-RH-only.patch b/0016-ArmVirtPkg-set-early-hello-message-RH-only.patch
new file mode 100644
index 0000000..35303e7
--- /dev/null
+++ b/0016-ArmVirtPkg-set-early-hello-message-RH-only.patch
@@ -0,0 +1,40 @@
+From e777f7d03c8a8d56e08926ecf0b17e1338837093 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 14 Oct 2015 14:07:17 +0200
+Subject: [PATCH] ArmVirtPkg: set early hello message (RH only)
+
+Print a friendly banner on QEMU, regardless of debug mask settings.
+
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279
+Downstream only:
+<http://thread.gmane.org/gmane.comp.bios.edk2.devel/2996/focus=3433 >.
+
+Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase:
+
+- no changes
+
+Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase:
+
+- no changes
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+(cherry picked from commit 5d4a15b9019728b2d96322bc679099da49916925)
+(cherry picked from commit 179df76dbb0d199bd905236e98775b4059c6502a)
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+---
+ ArmVirtPkg/ArmVirtQemu.dsc | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
+index 86d5d5a666..ffe4ba8092 100644
+--- a/ArmVirtPkg/ArmVirtQemu.dsc
++++ b/ArmVirtPkg/ArmVirtQemu.dsc
+@@ -87,6 +87,7 @@
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+
+ [PcdsFixedAtBuild.common]
++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage|"UEFI firmware starting.\r\n"
+ gArmPlatformTokenSpaceGuid.PcdCoreCount|1
+ !if $(ARCH) == AARCH64
+ gArmTokenSpaceGuid.PcdVFPEnabled|1
diff --git a/0017-BaseTools-footer.makefile-expand-BUILD_CFLAGS-last-f.patch b/0017-BaseTools-footer.makefile-expand-BUILD_CFLAGS-last-f.patch
new file mode 100644
index 0000000..a1e5144
--- /dev/null
+++ b/0017-BaseTools-footer.makefile-expand-BUILD_CFLAGS-last-f.patch
@@ -0,0 +1,35 @@
+From eebbf279b59afa3787d11734d9707cc7ab24d651 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 25 Jul 2018 22:27:53 +0200
+Subject: [PATCH] BaseTools/footer.makefile: expand BUILD_CFLAGS last for C
+ files too
+
+BUILD_CPPFLAGS should be expanded before BUILD_CFLAGS. (The rule for C++
+source files already does this, with BUILD_CPPFLAGS and BUILD_CXXFLAGS.)
+
+This patch doesn't change behavior.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit 67983484a4430c5f82bb5f1397e010c759136321)
+---
+ BaseTools/Source/C/Makefiles/footer.makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/BaseTools/Source/C/Makefiles/footer.makefile b/BaseTools/Source/C/Makefiles/footer.makefile
+index 0926aa9645..5bda9e4e36 100644
+--- a/BaseTools/Source/C/Makefiles/footer.makefile
++++ b/BaseTools/Source/C/Makefiles/footer.makefile
+@@ -24,7 +24,7 @@ $(LIBRARY): $(OBJECTS)
+ $(BUILD_AR) crs $@ $^
+
+ %.o : %.c
+- $(BUILD_CC) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< -o $@
++ $(BUILD_CC) -c $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) $< -o $@
+
+ %.o : %.cpp
+ $(BUILD_CXX) -c $(BUILD_CPPFLAGS) $(BUILD_CXXFLAGS) $< -o $@
diff --git a/0018-BaseTools-header.makefile-remove-c-from-BUILD_CFLAGS.patch b/0018-BaseTools-header.makefile-remove-c-from-BUILD_CFLAGS.patch
new file mode 100644
index 0000000..0942d9e
--- /dev/null
+++ b/0018-BaseTools-header.makefile-remove-c-from-BUILD_CFLAGS.patch
@@ -0,0 +1,40 @@
+From 0af592dfa9a6d1a3379db1331344f411f7774bea Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 25 Jul 2018 22:40:09 +0200
+Subject: [PATCH] BaseTools/header.makefile: remove "-c" from BUILD_CFLAGS
+
+Option "-c" is a mode selection flag (choosing between compiling and
+linking); it should not be in BUILD_CFLAGS, which applies only to
+compiling anyway. The compilation rule for C source files, in
+"footer.makefile", already includes "-c" -- currently we have double "-c"
+options.
+
+This patch doesn't change behavior.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit 03252ae287c4a61983b3793ff71baeabe2ff3df7)
+---
+ BaseTools/Source/C/Makefiles/header.makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile
+index db436773cf..08421ba24c 100644
+--- a/BaseTools/Source/C/Makefiles/header.makefile
++++ b/BaseTools/Source/C/Makefiles/header.makefile
+@@ -71,9 +71,9 @@ INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKE
+ BUILD_CPPFLAGS = $(INCLUDE) -O2
+ ifeq ($(DARWIN),Darwin)
+ # assume clang or clang compatible flags on OS X
+-BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -c -g
++BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g
+ else
+-BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict -Wno-unused-result -nostdlib -c -g
++BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict -Wno-unused-result -nostdlib -g
+ endif
+ BUILD_LFLAGS =
+ BUILD_CXXFLAGS = -Wno-unused-result
diff --git a/0019-BaseTools-Source-C-split-O2-to-BUILD_OPTFLAGS.patch b/0019-BaseTools-Source-C-split-O2-to-BUILD_OPTFLAGS.patch
new file mode 100644
index 0000000..52528d9
--- /dev/null
+++ b/0019-BaseTools-Source-C-split-O2-to-BUILD_OPTFLAGS.patch
@@ -0,0 +1,87 @@
+From 67c8bbaf89bbb4015f0b915fed6fb2f35efd282f Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Wed, 25 Jul 2018 22:59:57 +0200
+Subject: [PATCH] BaseTools/Source/C: split "-O2" to BUILD_OPTFLAGS
+
+The option "-O2" is not a preprocessor flag, but a code generation
+(compilation) flag. Move it from BUILD_CPPFLAGS to BUILD_CFLAGS and
+BUILD_CXXFLAGS.
+
+Because "VfrCompile/GNUmakefile" uses "-O2" through BUILD_CPPFLAGS, and
+because it doesn't use BUILD_CXXFLAGS, we have to introduce BUILD_OPTFLAGS
+separately, so that "VfrCompile/GNUmakefile" can continue using just this
+flag.
+
+This patch doesn't change behavior.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit b8a66170264395edeaa61e6d22930a58e576a685)
+---
+ BaseTools/Source/C/Makefiles/header.makefile | 6 +++++-
+ BaseTools/Source/C/VfrCompile/GNUmakefile | 11 +++++++----
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile
+index 08421ba24c..498c6cf48b 100644
+--- a/BaseTools/Source/C/Makefiles/header.makefile
++++ b/BaseTools/Source/C/Makefiles/header.makefile
+@@ -68,7 +68,8 @@ $(error Bad HOST_ARCH)
+ endif
+
+ INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE)
+-BUILD_CPPFLAGS = $(INCLUDE) -O2
++BUILD_CPPFLAGS = $(INCLUDE)
++BUILD_OPTFLAGS = -O2
+ ifeq ($(DARWIN),Darwin)
+ # assume clang or clang compatible flags on OS X
+ BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g
+@@ -91,6 +92,9 @@ ifeq ($(DARWIN),Darwin)
+ endif
+ endif
+
++# keep BUILD_OPTFLAGS last
++BUILD_CFLAGS += $(BUILD_OPTFLAGS)
++BUILD_CXXFLAGS += $(BUILD_OPTFLAGS)
+
+ .PHONY: all
+ .PHONY: install
+diff --git a/BaseTools/Source/C/VfrCompile/GNUmakefile b/BaseTools/Source/C/VfrCompile/GNUmakefile
+index c4ec61aa6c..bbe562cbc5 100644
+--- a/BaseTools/Source/C/VfrCompile/GNUmakefile
++++ b/BaseTools/Source/C/VfrCompile/GNUmakefile
+@@ -25,6 +25,9 @@ OBJECTS = AParser.o DLexerBase.o ATokenBuffer.o EfiVfrParser.o VfrLexer.o VfrSyn
+
+ VFR_CPPFLAGS = -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS)
+
++# keep BUILD_OPTFLAGS last
++VFR_CXXFLAGS = $(BUILD_OPTFLAGS)
++
+ LINKER = $(BUILD_CXX)
+
+ EXTRA_CLEAN_OBJECTS = EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h VfrLexer.cpp VfrLexer.h VfrSyntax.cpp tokens.h
+@@ -58,16 +61,16 @@ Pccts/dlg/dlg:
+ BIN_DIR='.' $(MAKE) -C Pccts/dlg
+
+ ATokenBuffer.o: Pccts/h/ATokenBuffer.cpp
+- $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@
++ $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@
+
+ DLexerBase.o: Pccts/h/DLexerBase.cpp
+- $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@
++ $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@
+
+ AParser.o: Pccts/h/AParser.cpp
+- $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@
++ $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@
+
+ VfrSyntax.o: VfrSyntax.cpp
+- $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@
++ $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@
+
+ clean: localClean
+
diff --git a/0020-BaseTools-Source-C-take-EXTRA_OPTFLAGS-from-the-call.patch b/0020-BaseTools-Source-C-take-EXTRA_OPTFLAGS-from-the-call.patch
new file mode 100644
index 0000000..f61aebe
--- /dev/null
+++ b/0020-BaseTools-Source-C-take-EXTRA_OPTFLAGS-from-the-call.patch
@@ -0,0 +1,37 @@
+From 26296351f9a6b6dad0604f8ed62ce5de0f41ac2c Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Thu, 26 Jul 2018 00:04:26 +0200
+Subject: [PATCH] BaseTools/Source/C: take EXTRA_OPTFLAGS from the caller
+
+Allow the caller of the top-level makefile either to set EXTRA_OPTFLAGS in
+the environment or to pass EXTRA_OPTFLAGS as a macro definition on the
+command line. EXTRA_OPTFLAGS extends (and potentially overrides) default C
+compilation flags set in the makefiles.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit b0ca5dae78ff71397a8ef568f1914da7668ff5a9)
+---
+ BaseTools/Source/C/Makefiles/header.makefile | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile
+index 498c6cf48b..1b4cad5497 100644
+--- a/BaseTools/Source/C/Makefiles/header.makefile
++++ b/BaseTools/Source/C/Makefiles/header.makefile
+@@ -69,7 +69,10 @@ endif
+
+ INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE)
+ BUILD_CPPFLAGS = $(INCLUDE)
+-BUILD_OPTFLAGS = -O2
++
++# keep EXTRA_OPTFLAGS last
++BUILD_OPTFLAGS = -O2 $(EXTRA_OPTFLAGS)
++
+ ifeq ($(DARWIN),Darwin)
+ # assume clang or clang compatible flags on OS X
+ BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g
diff --git a/0021-BaseTools-Source-C-take-EXTRA_LDFLAGS-from-the-calle.patch b/0021-BaseTools-Source-C-take-EXTRA_LDFLAGS-from-the-calle.patch
new file mode 100644
index 0000000..ed987d0
--- /dev/null
+++ b/0021-BaseTools-Source-C-take-EXTRA_LDFLAGS-from-the-calle.patch
@@ -0,0 +1,35 @@
+From c1a087a76d91665433f190d0468be2b33da443cd Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Thu, 26 Jul 2018 01:24:40 +0200
+Subject: [PATCH] BaseTools/Source/C: take EXTRA_LDFLAGS from the caller
+
+Allow the caller of the top-level makefile either to set EXTRA_LDFLAGS in
+the environment or to pass EXTRA_LDFLAGS as a macro definition on the
+command line. EXTRA_LDFLAGS extends (and potentially overrides) default
+link-editing flags set in the makefiles.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit 81502cee20ac4046f08bb4aec754c7091c8808dc)
+---
+ BaseTools/Source/C/Makefiles/header.makefile | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile
+index 1b4cad5497..7f283d6464 100644
+--- a/BaseTools/Source/C/Makefiles/header.makefile
++++ b/BaseTools/Source/C/Makefiles/header.makefile
+@@ -99,6 +99,9 @@ endif
+ BUILD_CFLAGS += $(BUILD_OPTFLAGS)
+ BUILD_CXXFLAGS += $(BUILD_OPTFLAGS)
+
++# keep EXTRA_LDFLAGS last
++BUILD_LFLAGS += $(EXTRA_LDFLAGS)
++
+ .PHONY: all
+ .PHONY: install
+ .PHONY: clean
diff --git a/0022-BaseTools-VfrCompile-honor-EXTRA_LDFLAGS.patch b/0022-BaseTools-VfrCompile-honor-EXTRA_LDFLAGS.patch
new file mode 100644
index 0000000..a3e89c5
--- /dev/null
+++ b/0022-BaseTools-VfrCompile-honor-EXTRA_LDFLAGS.patch
@@ -0,0 +1,69 @@
+From d30cba687d657a68bf83b8dd54db63b3e2e6cb54 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek(a)redhat.com>
+Date: Thu, 16 Aug 2018 19:38:02 -0700
+Subject: [PATCH] BaseTools/VfrCompile: honor EXTRA_LDFLAGS
+
+In commit 81502cee20ac ("BaseTools/Source/C: take EXTRA_LDFLAGS from the
+caller", 2018-08-16), I missed that "VfrCompile/GNUmakefile" does not use
+BUILD_LFLAGS in the APPLICATION linking rule, unlike "app.makefile" does.
+Instead, "VfrCompile/GNUmakefile" uses the (undefined) LFLAGS macro.
+Therefore commit 81502cee20ac did not cover the linking step of
+VfrCompile.
+
+Thankfully, the structure of the linking rules is the same, between
+"app.makefile" and "VfrCompile/GNUmakefile". Rename the undefined LFLAGS
+macro in "VfrCompile/GNUmakefile" to VFR_LFLAGS (for consistency with
+VFR_CXXFLAGS), and set it to EXTRA_LDFLAGS.
+
+As a result, we have:
+
+ | compilation | linking
+ -----------+--------------------------------+----------------------
+ VfrCompile | VFR_CXXFLAGS = | VFR_LFLAGS =
+ | BUILD_OPTFLAGS = | EXTRA_LDFLAGS
+ | '-O2' + EXTRA_OPTFLAGS |
+ -----------+--------------------------------+----------------------
+ other apps | BUILD_CFLAGS/BUILD_CXXFLAGS = | BUILD_LFLAGS =
+ | [...] + BUILD_OPTFLAGS = | [...] + EXTRA_LDFLAGS
+ | [...] + '-O2' + EXTRA_OPTFLAGS |
+
+This table shows
+- that the VfrCompile compilation and linking flags are always a subset of
+ the corresponding flags used by the other apps,
+- and that the EXTRA flags are always at the end.
+
+Cc: Liming Gao <liming.gao(a)intel.com>
+Cc: Yonghong Zhu <yonghong.zhu(a)intel.com>
+Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1540244
+Fixes: 81502cee20ac4046f08bb4aec754c7091c8808dc
+Contributed-under: TianoCore Contribution Agreement 1.1
+Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
+Reviewed-by: Liming Gao <liming.gao(a)intel.com>
+(cherry picked from commit aa4e0df1f0c7ffdff07d7e382c9da89cbe207cdb)
+---
+ BaseTools/Source/C/VfrCompile/GNUmakefile | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/BaseTools/Source/C/VfrCompile/GNUmakefile b/BaseTools/Source/C/VfrCompile/GNUmakefile
+index bbe562cbc5..9273589ff8 100644
+--- a/BaseTools/Source/C/VfrCompile/GNUmakefile
++++ b/BaseTools/Source/C/VfrCompile/GNUmakefile
+@@ -28,6 +28,9 @@ VFR_CPPFLAGS = -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS)
+ # keep BUILD_OPTFLAGS last
+ VFR_CXXFLAGS = $(BUILD_OPTFLAGS)
+
++# keep EXTRA_LDFLAGS last
++VFR_LFLAGS = $(EXTRA_LDFLAGS)
++
+ LINKER = $(BUILD_CXX)
+
+ EXTRA_CLEAN_OBJECTS = EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h VfrLexer.cpp VfrLexer.h VfrSyntax.cpp tokens.h
+@@ -42,7 +45,7 @@ APPLICATION = $(MAKEROOT)/bin/$(APPNAME)
+ all: $(MAKEROOT)/bin $(APPLICATION)
+
+ $(APPLICATION): $(OBJECTS)
+- $(LINKER) -o $(APPLICATION) $(LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS)
++ $(LINKER) -o $(APPLICATION) $(VFR_LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS)
+
+ VfrCompiler.o: ../Include/Common/BuildVersion.h
+
diff --git a/0099-Tweak-the-tools_def-to-support-cross-compiling.patch b/0099-Tweak-the-tools_def-to-support-cross-compiling.patch
new file mode 100644
index 0000000..bada25f
--- /dev/null
+++ b/0099-Tweak-the-tools_def-to-support-cross-compiling.patch
@@ -0,0 +1,75 @@
+From 0784bdc810bcbd275a78ceb0c2cf04f2f0f68061 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini(a)redhat.com>
+Date: Thu, 16 Aug 2018 15:45:47 -0400
+Subject: [PATCH] Tweak the tools_def to support cross-compiling.
+
+These files are meant for customization, so this is not upstream.
+
+Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
+Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
+---
+ BaseTools/Conf/tools_def.template | 44 +++++++++++++++----------------
+ 1 file changed, 22 insertions(+), 22 deletions(-)
+
+diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
+index a22b96c0b8..8b134ca93f 100755
+--- a/BaseTools/Conf/tools_def.template
++++ b/BaseTools/Conf/tools_def.template
+@@ -5068,17 +5068,17 @@ RELEASE_GCC49_AARCH64_DLINK_FLAGS = DEF(GCC49_AARCH64_DLINK_FLAGS)
+ ##################
+ # GCC5 IA32 definitions
+ ##################
+-*_GCC5_IA32_OBJCOPY_PATH = DEF(GCC5_IA32_PREFIX)objcopy
+-*_GCC5_IA32_CC_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_SLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc-ar
+-*_GCC5_IA32_DLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_ASLDLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_ASM_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_PP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_VFRPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_ASLCC_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_ASLPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+-*_GCC5_IA32_RC_PATH = DEF(GCC5_IA32_PREFIX)objcopy
++*_GCC5_IA32_OBJCOPY_PATH = ENV(GCC5_IA32_PREFIX)objcopy
++*_GCC5_IA32_CC_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_SLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc-ar
++*_GCC5_IA32_DLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_ASLDLINK_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_ASM_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_PP_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_VFRPP_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_ASLCC_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_ASLPP_PATH = ENV(GCC5_IA32_PREFIX)gcc
++*_GCC5_IA32_RC_PATH = ENV(GCC5_IA32_PREFIX)objcopy
+
+ *_GCC5_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto
+ *_GCC5_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 -no-pie
+@@ -5100,17 +5100,17 @@ RELEASE_GCC5_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,
+ ##################
+ # GCC5 X64 definitions
+ ##################
+-*_GCC5_X64_OBJCOPY_PATH = DEF(GCC5_X64_PREFIX)objcopy
+-*_GCC5_X64_CC_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_SLINK_PATH = DEF(GCC5_X64_PREFIX)gcc-ar
+-*_GCC5_X64_DLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_ASLDLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_ASM_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_PP_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_VFRPP_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_ASLCC_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_ASLPP_PATH = DEF(GCC5_X64_PREFIX)gcc
+-*_GCC5_X64_RC_PATH = DEF(GCC5_X64_PREFIX)objcopy
++*_GCC5_X64_OBJCOPY_PATH = ENV(GCC5_X64_PREFIX)objcopy
++*_GCC5_X64_CC_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_SLINK_PATH = ENV(GCC5_X64_PREFIX)gcc-ar
++*_GCC5_X64_DLINK_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_ASLDLINK_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_ASM_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_PP_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_VFRPP_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_ASLCC_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_ASLPP_PATH = ENV(GCC5_X64_PREFIX)gcc
++*_GCC5_X64_RC_PATH = ENV(GCC5_X64_PREFIX)objcopy
+
+ *_GCC5_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto
+ *_GCC5_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
diff --git a/EDKII_openssl-1.0.2j-no-srp.patch b/EDKII_openssl-1.0.2j-no-srp.patch
deleted file mode 100644
index 0735b73..0000000
--- a/EDKII_openssl-1.0.2j-no-srp.patch
+++ /dev/null
@@ -1,2028 +0,0 @@
-diff --git a/Configure b/Configure
-index c39f71a..98dd1d0 100755
---- a/Configure
-+++ b/Configure
-@@ -609,6 +609,9 @@ my %table=(
- # with itself, Applink is never engaged and can as well be omitted.
- "mingw64", "gcc:-mno-cygwin -DL_ENDIAN -O3 -Wall -DWIN32_LEAN_AND_MEAN -DUNICODE -D_UNICODE::-D_MT:MINGW64:-lws2_32 -lgdi32 -lcrypt32:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:${x86_64_asm}:mingw64:win32:cygwin-shared:-D_WINDLL:-mno-cygwin:.dll.a",
-
-+# UEFI
-+"UEFI", "cc:-DL_ENDIAN -O:::UEFI::::",
-+
- # UWIN
- "UWIN", "cc:-DTERMIOS -DL_ENDIAN -O -Wall:::UWIN::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:win32",
-
-@@ -1083,7 +1086,7 @@ if (defined($disabled{"md5"}) || defined($disabled{"sha"})
- }
-
- if (defined($disabled{"ec"}) || defined($disabled{"dsa"})
-- || defined($disabled{"dh"}))
-+ || defined($disabled{"dh"}) || defined($disabled{"stdio"}))
- {
- $disabled{"gost"} = "forced";
- }
-diff --git a/apps/apps.c b/apps/apps.c
-index 9fdc3e0..6c183b0 100644
---- a/apps/apps.c
-+++ b/apps/apps.c
-@@ -2375,6 +2375,8 @@ int args_verify(char ***pargs, int *pargc,
- flags |= X509_V_FLAG_PARTIAL_CHAIN;
- else if (!strcmp(arg, "-no_alt_chains"))
- flags |= X509_V_FLAG_NO_ALT_CHAINS;
-+ else if (!strcmp(arg, "-no_check_time"))
-+ flags |= X509_V_FLAG_NO_CHECK_TIME;
- else if (!strcmp(arg, "-allow_proxy_certs"))
- flags |= X509_V_FLAG_ALLOW_PROXY_CERTS;
- else
-diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
-index 2d562f9..91203b7 100644
---- a/crypto/asn1/a_strex.c
-+++ b/crypto/asn1/a_strex.c
-@@ -104,6 +104,7 @@ static int send_bio_chars(void *arg, const void *buf, int len)
- return 1;
- }
-
-+#ifndef OPENSSL_NO_FP_API
- static int send_fp_chars(void *arg, const void *buf, int len)
- {
- if (!arg)
-@@ -112,6 +113,7 @@ static int send_fp_chars(void *arg, const void *buf, int len)
- return 0;
- return 1;
- }
-+#endif
-
- typedef int char_io (void *arg, const void *buf, int len);
-
-diff --git a/crypto/asn1/asn1_mac.h b/crypto/asn1/asn1_mac.h
-index abc6dc3..3a672e9 100644
---- a/crypto/asn1/asn1_mac.h
-+++ b/crypto/asn1/asn1_mac.h
-@@ -70,7 +70,7 @@ extern "C" {
- # endif
-
- # define ASN1_MAC_H_err(f,r,line) \
-- ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
-+ ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),OPENSSL_FILE,(line))
-
- # define M_ASN1_D2I_vars(a,type,func) \
- ASN1_const_CTX c; \
-@@ -81,7 +81,7 @@ extern "C" {
- c.error=ERR_R_NESTED_ASN1_ERROR; \
- if ((a == NULL) || ((*a) == NULL)) \
- { if ((ret=(type)func()) == NULL) \
-- { c.line=__LINE__; goto err; } } \
-+ { c.line=OPENSSL_LINE; goto err; } } \
- else ret=(*a);
-
- # define M_ASN1_D2I_Init() \
-@@ -90,7 +90,7 @@ extern "C" {
-
- # define M_ASN1_D2I_Finish_2(a) \
- if (!asn1_const_Finish(&c)) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- *(const unsigned char **)pp=c.p; \
- if (a != NULL) (*a)=ret; \
- return(ret);
-@@ -105,7 +105,7 @@ err:\
-
- # define M_ASN1_D2I_start_sequence() \
- if (!asn1_GetSequence(&c,&length)) \
-- { c.line=__LINE__; goto err; }
-+ { c.line=OPENSSL_LINE; goto err; }
- /* Begin reading ASN1 without a surrounding sequence */
- # define M_ASN1_D2I_begin() \
- c.slen = length;
-@@ -129,21 +129,21 @@ err:\
- # define M_ASN1_D2I_get(b, func) \
- c.q=c.p; \
- if (func(&(b),&c.p,c.slen) == NULL) \
-- {c.line=__LINE__; goto err; } \
-+ {c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- /* Don't use this with d2i_ASN1_BOOLEAN() */
- # define M_ASN1_D2I_get_x(type,b,func) \
- c.q=c.p; \
- if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
-- {c.line=__LINE__; goto err; } \
-+ {c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- /* use this instead () */
- # define M_ASN1_D2I_get_int(b,func) \
- c.q=c.p; \
- if (func(&(b),&c.p,c.slen) < 0) \
-- {c.line=__LINE__; goto err; } \
-+ {c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- # define M_ASN1_D2I_get_opt(b,func,type) \
-@@ -164,7 +164,7 @@ err:\
- M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
- c.q=c.p; \
- if (func(&(b),&c.p,c.slen) == NULL) \
-- {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
-+ {c.line=OPENSSL_LINE; M_ASN1_next_prev = _tmp; goto err; } \
- c.slen-=(c.p-c.q);\
- M_ASN1_next_prev=_tmp;
-
-@@ -258,20 +258,20 @@ err:\
- c.q=c.p; \
- if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
- (void (*)())free_func,a,b) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- # define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
- c.q=c.p; \
- if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
- free_func,a,b) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- # define M_ASN1_D2I_get_set_strings(r,func,a,b) \
- c.q=c.p; \
- if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- c.slen-=(c.p-c.q);
-
- # define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
-@@ -285,16 +285,16 @@ err:\
- Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
- if (Tinf & 0x80) \
- { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
- Tlen = c.slen - (c.p - c.q) - 2; \
- if (func(&(r),&c.p,Tlen) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
- Tlen = c.slen - (c.p - c.q); \
- if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
- { c.error=ERR_R_MISSING_ASN1_EOS; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- }\
- c.slen-=(c.p-c.q); \
- }
-@@ -310,18 +310,18 @@ err:\
- Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
- if (Tinf & 0x80) \
- { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
- Tlen = c.slen - (c.p - c.q) - 2; \
- if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
- (void (*)())free_func, \
- b,V_ASN1_UNIVERSAL) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
- Tlen = c.slen - (c.p - c.q); \
- if(!ASN1_check_infinite_end(&c.p, Tlen)) \
- { c.error=ERR_R_MISSING_ASN1_EOS; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- }\
- c.slen-=(c.p-c.q); \
- }
-@@ -337,17 +337,17 @@ err:\
- Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
- if (Tinf & 0x80) \
- { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
- Tlen = c.slen - (c.p - c.q) - 2; \
- if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
- free_func,b,V_ASN1_UNIVERSAL) == NULL) \
-- { c.line=__LINE__; goto err; } \
-+ { c.line=OPENSSL_LINE; goto err; } \
- if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
- Tlen = c.slen - (c.p - c.q); \
- if(!ASN1_check_infinite_end(&c.p, Tlen)) \
- { c.error=ERR_R_MISSING_ASN1_EOS; \
-- c.line=__LINE__; goto err; } \
-+ c.line=OPENSSL_LINE; goto err; } \
- }\
- c.slen-=(c.p-c.q); \
- }
-@@ -355,7 +355,7 @@ err:\
- /* New macros */
- # define M_ASN1_New_Malloc(ret,type) \
- if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
-- { c.line=__LINE__; goto err2; }
-+ { c.line=OPENSSL_LINE; goto err2; }
-
- # define M_ASN1_New(arg,func) \
- if (((arg)=func()) == NULL) return(NULL)
-diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c
-index d5a5514..bede55c 100644
---- a/crypto/asn1/n_pkey.c
-+++ b/crypto/asn1/n_pkey.c
-@@ -193,7 +193,12 @@ int i2d_RSA_NET(const RSA *a, unsigned char **pp,
- OPENSSL_cleanse(pkey->private_key->data, rsalen);
-
- if (cb == NULL)
-+#ifndef OPENSSL_NO_UI
- cb = EVP_read_pw_string;
-+#else
-+ i = 1;
-+ else
-+#endif
- i = cb((char *)buf, 256, "Enter Private Key password:", 1);
- if (i != 0) {
- ASN1err(ASN1_F_I2D_RSA_NET, ASN1_R_BAD_PASSWORD_READ);
-@@ -264,7 +269,11 @@ RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
- goto err;
- }
- if (cb == NULL)
-+#ifndef OPENSSL_NO_UI
- cb = EVP_read_pw_string;
-+#else
-+ goto err;
-+#endif
- if ((ret = d2i_RSA_NET_2(a, enckey->enckey->digest, cb, sgckey)) == NULL)
- goto err;
-
-diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
-index 1d25687..ad641c3 100644
---- a/crypto/bn/bn_prime.c
-+++ b/crypto/bn/bn_prime.c
-@@ -131,7 +131,7 @@
- static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
- const BIGNUM *a1_odd, int k, BN_CTX *ctx,
- BN_MONT_CTX *mont);
--static int probable_prime(BIGNUM *rnd, int bits);
-+static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods);
- static int probable_prime_dh(BIGNUM *rnd, int bits,
- const BIGNUM *add, const BIGNUM *rem,
- BN_CTX *ctx);
-@@ -166,9 +166,13 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
- BIGNUM *t;
- int found = 0;
- int i, j, c1 = 0;
-- BN_CTX *ctx;
-+ BN_CTX *ctx = NULL;
-+ prime_t *mods = NULL;
- int checks = BN_prime_checks_for_size(bits);
-
-+ mods = OPENSSL_malloc(sizeof(*mods) * NUMPRIMES);
-+ if (mods == NULL)
-+ goto err;
- ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
-@@ -179,7 +183,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
- loop:
- /* make a random number and set the top and bottom bits */
- if (add == NULL) {
-- if (!probable_prime(ret, bits))
-+ if (!probable_prime(ret, bits, mods))
- goto err;
- } else {
- if (safe) {
-@@ -230,6 +234,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
- /* we have a prime :-) */
- found = 1;
- err:
-+ OPENSSL_free(mods);
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
-@@ -375,10 +380,9 @@ static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
- return 1;
- }
-
--static int probable_prime(BIGNUM *rnd, int bits)
-+static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods)
- {
- int i;
-- prime_t mods[NUMPRIMES];
- BN_ULONG delta, maxdelta;
-
- again:
-diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h
-index 8d926d5..c29e97d 100644
---- a/crypto/conf/conf.h
-+++ b/crypto/conf/conf.h
-@@ -118,8 +118,10 @@ typedef void conf_finish_func (CONF_IMODULE *md);
-
- int CONF_set_default_method(CONF_METHOD *meth);
- void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash);
-+# ifndef OPENSSL_NO_STDIO
- LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
- long *eline);
-+# endif
- # ifndef OPENSSL_NO_FP_API
- LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
- long *eline);
-@@ -133,7 +135,9 @@ char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
- long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
- const char *name);
- void CONF_free(LHASH_OF(CONF_VALUE) *conf);
-+# ifndef OPENSSL_NO_FP_API
- int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
-+# endif
- int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
-
- void OPENSSL_config(const char *config_name);
-@@ -160,7 +164,9 @@ CONF_METHOD *NCONF_XML(void);
- void NCONF_free(CONF *conf);
- void NCONF_free_data(CONF *conf);
-
-+# ifndef OPENSSL_NO_STDIO
- int NCONF_load(CONF *conf, const char *file, long *eline);
-+# endif
- # ifndef OPENSSL_NO_FP_API
- int NCONF_load_fp(CONF *conf, FILE *fp, long *eline);
- # endif
-@@ -170,7 +176,9 @@ STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,
- char *NCONF_get_string(const CONF *conf, const char *group, const char *name);
- int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
- long *result);
-+# ifndef OPENSSL_NO_FP_API
- int NCONF_dump_fp(const CONF *conf, FILE *out);
-+# endif
- int NCONF_dump_bio(const CONF *conf, BIO *out);
-
- # if 0 /* The following function has no error
-@@ -184,8 +192,10 @@ long NCONF_get_number(CONF *conf, char *group, char *name);
-
- int CONF_modules_load(const CONF *cnf, const char *appname,
- unsigned long flags);
-+# ifndef OPENSSL_NO_STDIO
- int CONF_modules_load_file(const char *filename, const char *appname,
- unsigned long flags);
-+# endif
- void CONF_modules_unload(int all);
- void CONF_modules_finish(void);
- void CONF_modules_free(void);
-diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
-index 68c77ce..3d308c7 100644
---- a/crypto/conf/conf_def.c
-+++ b/crypto/conf/conf_def.c
-@@ -182,6 +182,10 @@ static int def_destroy_data(CONF *conf)
-
- static int def_load(CONF *conf, const char *name, long *line)
- {
-+#ifdef OPENSSL_NO_STDIO
-+ CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB);
-+ return 0;
-+#else
- int ret;
- BIO *in = NULL;
-
-@@ -202,6 +206,7 @@ static int def_load(CONF *conf, const char *name, long *line)
- BIO_free(in);
-
- return ret;
-+#endif
- }
-
- static int def_load_bio(CONF *conf, BIO *in, long *line)
-diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
-index 5281384..952b545 100644
---- a/crypto/conf/conf_lib.c
-+++ b/crypto/conf/conf_lib.c
-@@ -90,6 +90,7 @@ int CONF_set_default_method(CONF_METHOD *meth)
- return 1;
- }
-
-+#ifndef OPENSSL_NO_STDIO
- LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
- long *eline)
- {
-@@ -111,6 +112,7 @@ LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
-
- return ltmp;
- }
-+#endif
-
- #ifndef OPENSSL_NO_FP_API
- LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
-@@ -255,6 +257,7 @@ void NCONF_free_data(CONF *conf)
- conf->meth->destroy_data(conf);
- }
-
-+#ifndef OPENSSL_NO_STDIO
- int NCONF_load(CONF *conf, const char *file, long *eline)
- {
- if (conf == NULL) {
-@@ -264,6 +267,7 @@ int NCONF_load(CONF *conf, const char *file, long *eline)
-
- return conf->meth->load(conf, file, eline);
- }
-+#endif
-
- #ifndef OPENSSL_NO_FP_API
- int NCONF_load_fp(CONF *conf, FILE *fp, long *eline)
-diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
-index e0c9a67..13d93ea 100644
---- a/crypto/conf/conf_mod.c
-+++ b/crypto/conf/conf_mod.c
-@@ -159,6 +159,7 @@ int CONF_modules_load(const CONF *cnf, const char *appname,
-
- }
-
-+#ifndef OPENSSL_NO_STDIO
- int CONF_modules_load_file(const char *filename, const char *appname,
- unsigned long flags)
- {
-@@ -194,6 +195,7 @@ int CONF_modules_load_file(const char *filename, const char *appname,
-
- return ret;
- }
-+#endif
-
- static int module_run(const CONF *cnf, char *name, char *value,
- unsigned long flags)
-diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c
-index c042cf2..a25b636 100644
---- a/crypto/conf/conf_sap.c
-+++ b/crypto/conf/conf_sap.c
-@@ -87,9 +87,11 @@ void OPENSSL_config(const char *config_name)
- ENGINE_load_builtin_engines();
- #endif
- ERR_clear_error();
-+#ifndef OPENSSL_NO_STDIO
- CONF_modules_load_file(NULL, config_name,
- CONF_MFLAGS_DEFAULT_SECTION |
- CONF_MFLAGS_IGNORE_MISSING_FILE);
-+#endif
- openssl_configured = 1;
- }
-
-diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
-index 1925428..da4b34d 100644
---- a/crypto/cryptlib.c
-+++ b/crypto/cryptlib.c
-@@ -263,7 +263,7 @@ int CRYPTO_get_new_dynlockid(void)
- return (0);
- }
- pointer->references = 1;
-- pointer->data = dynlock_create_callback(__FILE__, __LINE__);
-+ pointer->data = dynlock_create_callback(OPENSSL_FILE, OPENSSL_LINE);
- if (pointer->data == NULL) {
- OPENSSL_free(pointer);
- CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
-@@ -289,7 +289,7 @@ int CRYPTO_get_new_dynlockid(void)
- CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
- if (i == -1) {
-- dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
-+ dynlock_destroy_callback(pointer->data, OPENSSL_FILE, OPENSSL_LINE);
- OPENSSL_free(pointer);
- } else
- i += 1; /* to avoid 0 */
-@@ -328,7 +328,7 @@ void CRYPTO_destroy_dynlockid(int i)
- CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
- if (pointer) {
-- dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
-+ dynlock_destroy_callback(pointer->data, OPENSSL_FILE, OPENSSL_LINE);
- OPENSSL_free(pointer);
- }
- }
-@@ -670,6 +670,7 @@ unsigned long *OPENSSL_ia32cap_loc(void)
- }
-
- # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
-+#include <stdio.h>
- # define OPENSSL_CPUID_SETUP
- # if defined(_WIN32)
- typedef unsigned __int64 IA32CAP;
-@@ -980,11 +981,13 @@ void OPENSSL_showfatal(const char *fmta, ...)
- #else
- void OPENSSL_showfatal(const char *fmta, ...)
- {
-+#ifndef OPENSSL_NO_STDIO
- va_list ap;
-
- va_start(ap, fmta);
- vfprintf(stderr, fmta, ap);
- va_end(ap);
-+#endif
- }
-
- int OPENSSL_isservice(void)
-@@ -1011,10 +1014,12 @@ void OpenSSLDie(const char *file, int line, const char *assertion)
- #endif
- }
-
-+#ifndef OPENSSL_NO_STDIO
- void *OPENSSL_stderr(void)
- {
- return stderr;
- }
-+#endif
-
- int CRYPTO_memcmp(const volatile void *in_a, const volatile void *in_b, size_t len)
- {
-diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h
-index fba180a..3e3ea5e 100644
---- a/crypto/cryptlib.h
-+++ b/crypto/cryptlib.h
-@@ -101,7 +101,9 @@ extern "C" {
- void OPENSSL_cpuid_setup(void);
- extern unsigned int OPENSSL_ia32cap_P[];
- void OPENSSL_showfatal(const char *fmta, ...);
-+#ifndef OPENSSL_NO_STDIO
- void *OPENSSL_stderr(void);
-+#endif
- extern int OPENSSL_NONPIC_relocated;
-
- #ifdef __cplusplus
-diff --git a/crypto/crypto.h b/crypto/crypto.h
-index 6c644ce..bea4ca1 100644
---- a/crypto/crypto.h
-+++ b/crypto/crypto.h
-@@ -235,15 +235,15 @@ typedef struct openssl_item_st {
- # ifndef OPENSSL_NO_LOCKING
- # ifndef CRYPTO_w_lock
- # define CRYPTO_w_lock(type) \
-- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
- # define CRYPTO_w_unlock(type) \
-- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
- # define CRYPTO_r_lock(type) \
-- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
- # define CRYPTO_r_unlock(type) \
-- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
- # define CRYPTO_add(addr,amount,type) \
-- CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
-+ CRYPTO_add_lock(addr,amount,type,OPENSSL_FILE,OPENSSL_LINE)
- # endif
- # else
- # define CRYPTO_w_lock(a)
-@@ -378,19 +378,19 @@ int CRYPTO_is_mem_check_on(void);
- # define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
- # define is_MemCheck_on() CRYPTO_is_mem_check_on()
-
--# define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
--# define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__)
-+# define OPENSSL_malloc(num) CRYPTO_malloc((int)num,OPENSSL_FILE,OPENSSL_LINE)
-+# define OPENSSL_strdup(str) CRYPTO_strdup((str),OPENSSL_FILE,OPENSSL_LINE)
- # define OPENSSL_realloc(addr,num) \
-- CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
-+ CRYPTO_realloc((char *)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE)
- # define OPENSSL_realloc_clean(addr,old_num,num) \
-- CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
-+ CRYPTO_realloc_clean(addr,old_num,num,OPENSSL_FILE,OPENSSL_LINE)
- # define OPENSSL_remalloc(addr,num) \
-- CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
-+ CRYPTO_remalloc((char **)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE)
- # define OPENSSL_freeFunc CRYPTO_free
- # define OPENSSL_free(addr) CRYPTO_free(addr)
-
- # define OPENSSL_malloc_locked(num) \
-- CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
-+ CRYPTO_malloc_locked((int)num,OPENSSL_FILE,OPENSSL_LINE)
- # define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
-
- const char *SSLeay_version(int type);
-@@ -545,7 +545,7 @@ void CRYPTO_set_mem_debug_options(long bits);
- long CRYPTO_get_mem_debug_options(void);
-
- # define CRYPTO_push_info(info) \
-- CRYPTO_push_info_(info, __FILE__, __LINE__);
-+ CRYPTO_push_info_(info, OPENSSL_FILE, OPENSSL_LINE);
- int CRYPTO_push_info_(const char *info, const char *file, int line);
- int CRYPTO_pop_info(void);
- int CRYPTO_remove_all_info(void);
-@@ -588,7 +588,7 @@ void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
-
- /* die if we have to */
- void OpenSSLDie(const char *file, int line, const char *assertion);
--# define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
-+# define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(OPENSSL_FILE, OPENSSL_LINE, #e),1))
-
- unsigned long *OPENSSL_ia32cap_loc(void);
- # define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
-@@ -605,14 +605,14 @@ void OPENSSL_init(void);
- # define fips_md_init_ctx(alg, cx) \
- int alg##_Init(cx##_CTX *c) \
- { \
-- if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \
-+ if (FIPS_mode()) OpenSSLDie(OPENSSL_FILE, OPENSSL_LINE, \
- "Low level API call to digest " #alg " forbidden in FIPS mode!"); \
- return private_##alg##_Init(c); \
- } \
- int private_##alg##_Init(cx##_CTX *c)
-
- # define fips_cipher_abort(alg) \
-- if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \
-+ if (FIPS_mode()) OpenSSLDie(OPENSSL_FILE, OPENSSL_LINE, \
- "Low level API call to cipher " #alg " forbidden in FIPS mode!")
-
- # else
-diff --git a/crypto/des/read2pwd.c b/crypto/des/read2pwd.c
-index 01e275f..7633139 100644
---- a/crypto/des/read2pwd.c
-+++ b/crypto/des/read2pwd.c
-@@ -114,6 +114,10 @@
- #include <openssl/ui.h>
- #include <openssl/crypto.h>
-
-+#ifndef BUFSIZ
-+#define BUFSIZ 256
-+#endif
-+
- int DES_read_password(DES_cblock *key, const char *prompt, int verify)
- {
- int ok;
-diff --git a/crypto/dh/Makefile b/crypto/dh/Makefile
-index 46fa5ac..cc366ec 100644
---- a/crypto/dh/Makefile
-+++ b/crypto/dh/Makefile
-@@ -134,7 +134,7 @@ dh_gen.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
- dh_gen.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
- dh_gen.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
- dh_gen.o: ../cryptlib.h dh_gen.c
--dh_kdf.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
-+dh_kdf.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
- dh_kdf.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h
- dh_kdf.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
- dh_kdf.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
-diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
-index a5bd901..6488879 100644
---- a/crypto/dh/dh.h
-+++ b/crypto/dh/dh.h
-@@ -240,11 +240,13 @@ DH *DH_get_1024_160(void);
- DH *DH_get_2048_224(void);
- DH *DH_get_2048_256(void);
-
-+# ifndef OPENSSL_NO_CMS
- /* RFC2631 KDF */
- int DH_KDF_X9_42(unsigned char *out, size_t outlen,
- const unsigned char *Z, size_t Zlen,
- ASN1_OBJECT *key_oid,
- const unsigned char *ukm, size_t ukmlen, const EVP_MD *md);
-+# endif
-
- # define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
-@@ -337,7 +339,9 @@ int DH_KDF_X9_42(unsigned char *out, size_t outlen,
-
- /* KDF types */
- # define EVP_PKEY_DH_KDF_NONE 1
-+# ifndef OPENSSL_NO_CMS
- # define EVP_PKEY_DH_KDF_X9_42 2
-+# endif
-
- /* BEGIN ERROR CODES */
- /*
-diff --git a/crypto/dh/dh_kdf.c b/crypto/dh/dh_kdf.c
-index a882cb2..aace5fb 100644
---- a/crypto/dh/dh_kdf.c
-+++ b/crypto/dh/dh_kdf.c
-@@ -51,6 +51,9 @@
- * ====================================================================
- */
-
-+#include <e_os.h>
-+
-+#ifndef OPENSSL_NO_CMS
- #include <string.h>
- #include <openssl/dh.h>
- #include <openssl/evp.h>
-@@ -58,6 +61,7 @@
- #include <openssl/cms.h>
-
- /* Key derivation from X9.42/RFC2631 */
-+/* Uses CMS functions, hence the #ifdef wrapper. */
-
- #define DH_KDF_MAX (1L << 30)
-
-@@ -185,3 +189,4 @@ int DH_KDF_X9_42(unsigned char *out, size_t outlen,
- EVP_MD_CTX_cleanup(&mctx);
- return rv;
- }
-+#endif
-diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
-index b58e3fa..926be98 100644
---- a/crypto/dh/dh_pmeth.c
-+++ b/crypto/dh/dh_pmeth.c
-@@ -207,7 +207,11 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
- case EVP_PKEY_CTRL_DH_KDF_TYPE:
- if (p1 == -2)
- return dctx->kdf_type;
-+#ifdef OPENSSL_NO_CMS
-+ if (p1 != EVP_PKEY_DH_KDF_NONE)
-+#else
- if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
-+#endif
- return -2;
- dctx->kdf_type = p1;
- return 1;
-@@ -448,7 +452,9 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- return ret;
- *keylen = ret;
- return 1;
-- } else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
-+ }
-+#ifndef OPENSSL_NO_CMS
-+ else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
- unsigned char *Z = NULL;
- size_t Zlen = 0;
- if (!dctx->kdf_outlen || !dctx->kdf_oid)
-@@ -479,7 +485,8 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- }
- return ret;
- }
-- return 1;
-+#endif
-+ return 0;
- }
-
- const EVP_PKEY_METHOD dh_pkey_meth = {
-diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
-index 46f163b..b4a72a0 100644
---- a/crypto/engine/eng_int.h
-+++ b/crypto/engine/eng_int.h
-@@ -88,7 +88,7 @@ extern "C" {
- (unsigned int)(e), (isfunct ? "funct" : "struct"), \
- ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \
- ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \
-- (__FILE__), (__LINE__));
-+ (OPENSSL_FILE), (OPENSSL_LINE));
-
- # else
-
-@@ -136,7 +136,7 @@ ENGINE *engine_table_select(ENGINE_TABLE **table, int nid);
- # else
- ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
- int l);
--# define engine_table_select(t,n) engine_table_select_tmp(t,n,__FILE__,__LINE__)
-+# define engine_table_select(t,n) engine_table_select_tmp(t,n,OPENSSL_FILE,OPENSSL_LINE)
- # endif
- typedef void (engine_table_doall_cb) (int nid, STACK_OF(ENGINE) *sk,
- ENGINE *def, void *arg);
-diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c
-index 34b0029..cf622bb 100644
---- a/crypto/engine/eng_openssl.c
-+++ b/crypto/engine/eng_openssl.c
-@@ -86,7 +86,9 @@
- * this is no longer automatic in ENGINE_load_builtin_engines().
- */
- #define TEST_ENG_OPENSSL_RC4
-+#ifndef OPENSSL_NO_FP_API
- #define TEST_ENG_OPENSSL_PKEY
-+#endif
- /* #define TEST_ENG_OPENSSL_RC4_OTHERS */
- #define TEST_ENG_OPENSSL_RC4_P_INIT
- /* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */
-diff --git a/crypto/err/err.h b/crypto/err/err.h
-index 585aa8b..04c6cfc 100644
---- a/crypto/err/err.h
-+++ b/crypto/err/err.h
-@@ -200,39 +200,39 @@ typedef struct err_state_st {
-
- # define ERR_LIB_USER 128
-
--# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__)
--# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__)
--# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__)
--# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__)
--# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__)
--# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__)
--# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__)
--# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__)
--# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__)
--# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__)
--# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__)
--# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__)
--# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__)
--# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__)
--# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__)
--# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__)
--# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__)
--# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__)
--# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__)
--# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__)
--# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__)
--# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__)
--# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__)
--# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__)
--# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__)
--# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
--# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
--# define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
--# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__)
--# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
--# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__)
--# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__)
--# define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
-+# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-+# define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /*
- * Borland C seems too stupid to be able to shift and do longs in the
-diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
-index 39ab793..ad1e350 100644
---- a/crypto/evp/evp.h
-+++ b/crypto/evp/evp.h
-@@ -602,11 +602,13 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
- int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
- int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
-
-+#ifndef OPENSSL_NO_UI
- int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
- int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
- const char *prompt, int verify);
- void EVP_set_pw_prompt(const char *prompt);
- char *EVP_get_pw_prompt(void);
-+#endif
-
- int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
- const unsigned char *salt, const unsigned char *data,
-diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c
-index 5be9e33..63c8866 100644
---- a/crypto/evp/evp_key.c
-+++ b/crypto/evp/evp_key.c
-@@ -63,6 +63,7 @@
- #include <openssl/evp.h>
- #include <openssl/ui.h>
-
-+#ifndef OPENSSL_NO_UI
- /* should be init to zeros. */
- static char prompt_string[80];
-
-@@ -117,6 +118,7 @@ int EVP_read_pw_string_min(char *buf, int min, int len, const char *prompt,
- OPENSSL_cleanse(buff, BUFSIZ);
- return ret;
- }
-+#endif /* OPENSSL_NO_UI */
-
- int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
- const unsigned char *salt, const unsigned char *data,
-diff --git a/crypto/opensslconf.h.in b/crypto/opensslconf.h.in
-index 7a1c85d..7162c0f 100644
---- a/crypto/opensslconf.h.in
-+++ b/crypto/opensslconf.h.in
-@@ -1,5 +1,15 @@
- /* crypto/opensslconf.h.in */
-
-+#ifndef OPENSSL_FILE
-+#ifdef OPENSSL_NO_FILENAMES
-+#define OPENSSL_FILE ""
-+#define OPENSSL_LINE 0
-+#else
-+#define OPENSSL_FILE __FILE__
-+#define OPENSSL_LINE __LINE__
-+#endif
-+#endif
-+
- /* Generate 80386 code? */
- #undef I386_ONLY
-
-@@ -56,7 +66,7 @@
- #endif
- #endif
-
--#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
-+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) && !defined(OPENSSL_SYSNAME_UEFI)
- #define CONFIG_HEADER_BN_H
- #undef BN_LLONG
-
-diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
-index aac72fb..d271ec8 100644
---- a/crypto/pem/pem.h
-+++ b/crypto/pem/pem.h
-@@ -324,6 +324,7 @@ int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
-
- # define DECLARE_PEM_read_fp(name, type) /**/
- # define DECLARE_PEM_write_fp(name, type) /**/
-+# define DECLARE_PEM_write_fp_const(name, type) /**/
- # define DECLARE_PEM_write_cb_fp(name, type) /**/
- # else
-
-@@ -417,6 +418,7 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
- pem_password_cb *cd, void *u);
- # endif
-
-+#ifndef OPENSSL_NO_FP_API
- int PEM_read(FILE *fp, char **name, char **header,
- unsigned char **data, long *len);
- int PEM_write(FILE *fp, const char *name, const char *hdr,
-@@ -428,6 +430,7 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
- int klen, pem_password_cb *callback, void *u);
- STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
- pem_password_cb *cb, void *u);
-+#endif
-
- int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
- EVP_MD *md_type, unsigned char **ek, int *ekl,
-@@ -494,6 +497,7 @@ int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
- EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
- void *u);
-
-+#ifndef OPENSSL_NO_FP_API
- int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u);
-@@ -510,6 +514,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
- int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cd,
- void *u);
-+#endif
-
- EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
- int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x);
-diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
-index c82b3c0..56c77b1 100644
---- a/crypto/pem/pem_lib.c
-+++ b/crypto/pem/pem_lib.c
-@@ -84,7 +84,7 @@ int pem_check_suffix(const char *pem_str, const char *suffix);
-
- int PEM_def_callback(char *buf, int num, int w, void *key)
- {
--#ifdef OPENSSL_NO_FP_API
-+#if defined(OPENSSL_NO_FP_API) || defined(OPENSSL_NO_UI)
- /*
- * We should not ever call the default callback routine from windows.
- */
-diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c
-index 5747c73..9edca4d 100644
---- a/crypto/pem/pem_pk8.c
-+++ b/crypto/pem/pem_pk8.c
-@@ -69,9 +69,11 @@
- static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder,
- int nid, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u);
-+#ifndef OPENSSL_NO_FP_API
- static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
- int nid, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u);
-+#endif
-
- /*
- * These functions write a private key in PKCS#8 format: it is a "drop in"
-diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
-index dc9b484..e75c4b2 100644
---- a/crypto/pkcs7/pk7_smime.c
-+++ b/crypto/pkcs7/pk7_smime.c
-@@ -64,6 +64,8 @@
- #include <openssl/x509.h>
- #include <openssl/x509v3.h>
-
-+#define BUFFERSIZE 4096
-+
- static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
-
- PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
-@@ -254,7 +256,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
- STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
- PKCS7_SIGNER_INFO *si;
- X509_STORE_CTX cert_ctx;
-- char buf[4096];
-+ char *buf = NULL;
- int i, j = 0, k, ret = 0;
- BIO *p7bio = NULL;
- BIO *tmpin = NULL, *tmpout = NULL;
-@@ -373,8 +375,12 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
- tmpout = out;
-
- /* We now have to 'read' from p7bio to calculate digests etc. */
-+ if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
-+ PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
-+ goto err;
-+ }
- for (;;) {
-- i = BIO_read(p7bio, buf, sizeof(buf));
-+ i = BIO_read(p7bio, buf, BUFFERSIZE);
- if (i <= 0)
- break;
- if (tmpout)
-@@ -405,6 +411,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
- ret = 1;
-
- err:
-+ OPENSSL_free(buf);
- if (tmpin == indata) {
- if (indata)
- BIO_pop(p7bio);
-@@ -523,7 +530,7 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
- {
- BIO *tmpmem;
- int ret, i;
-- char buf[4096];
-+ char *buf = NULL;
-
- if (!p7) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_INVALID_NULL_POINTER);
-@@ -567,24 +574,30 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
- }
- BIO_free_all(bread);
- return ret;
-- } else {
-- for (;;) {
-- i = BIO_read(tmpmem, buf, sizeof(buf));
-- if (i <= 0) {
-- ret = 1;
-- if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
-- if (!BIO_get_cipher_status(tmpmem))
-- ret = 0;
-- }
--
-- break;
-- }
-- if (BIO_write(data, buf, i) != i) {
-- ret = 0;
-- break;
-+ }
-+ if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
-+ PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
-+ goto err;
-+ }
-+ for (;;) {
-+ i = BIO_read(tmpmem, buf, BUFFERSIZE);
-+ if (i <= 0) {
-+ ret = 1;
-+ if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
-+ if (!BIO_get_cipher_status(tmpmem))
-+ ret = 0;
- }
-+
-+ break;
-+ }
-+ if (BIO_write(data, buf, i) != i) {
-+ ret = 0;
-+ break;
- }
-- BIO_free_all(tmpmem);
-- return ret;
- }
-+
-+err:
-+ OPENSSL_free(buf);
-+ BIO_free_all(tmpmem);
-+ return ret;
- }
-diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c
-index 737aebf..f23f348 100644
---- a/crypto/rand/rand_egd.c
-+++ b/crypto/rand/rand_egd.c
-@@ -95,7 +95,7 @@
- * RAND_egd() is a wrapper for RAND_egd_bytes() with numbytes=255.
- */
-
--#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_BEOS)
-+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_BEOS) || defined(OPENSSL_SYS_UEFI)
- int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
- {
- return (-1);
-diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
-index 6c5b65d..11ee152 100644
---- a/crypto/rand/rand_unix.c
-+++ b/crypto/rand/rand_unix.c
-@@ -116,7 +116,7 @@
- #include <openssl/rand.h>
- #include "rand_lcl.h"
-
--#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE))
-+#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_UEFI))
-
- # include <sys/types.h>
- # include <sys/time.h>
-@@ -439,7 +439,7 @@ int RAND_poll(void)
- * defined(OPENSSL_SYS_VXWORKS) ||
- * defined(OPENSSL_SYS_NETWARE)) */
-
--#if defined(OPENSSL_SYS_VXWORKS)
-+#if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
- int RAND_poll(void)
- {
- return 0;
-diff --git a/crypto/ts/ts.h b/crypto/ts/ts.h
-index 2daa1b2..5205bc5 100644
---- a/crypto/ts/ts.h
-+++ b/crypto/ts/ts.h
-@@ -281,8 +281,10 @@ TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length);
-
- TS_REQ *TS_REQ_dup(TS_REQ *a);
-
-+#ifndef OPENSSL_NO_FP_API
- TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a);
- int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a);
-+#endif
- TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a);
- int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a);
-
-@@ -294,10 +296,12 @@ TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a,
-
- TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a);
-
-+#ifndef OPENSSL_NO_FP_API
- TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a);
- int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a);
--TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT **a);
--int i2d_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT *a);
-+#endif
-+TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT **a);
-+int i2d_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT *a);
-
- TS_RESP *TS_RESP_new(void);
- void TS_RESP_free(TS_RESP *a);
-@@ -306,10 +310,12 @@ TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length);
- TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token);
- TS_RESP *TS_RESP_dup(TS_RESP *a);
-
-+#ifndef OPENSSL_NO_FP_API
- TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a);
- int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a);
--TS_RESP *d2i_TS_RESP_bio(BIO *fp, TS_RESP **a);
--int i2d_TS_RESP_bio(BIO *fp, TS_RESP *a);
-+#endif
-+TS_RESP *d2i_TS_RESP_bio(BIO *bio, TS_RESP **a);
-+int i2d_TS_RESP_bio(BIO *bio, TS_RESP *a);
-
- TS_STATUS_INFO *TS_STATUS_INFO_new(void);
- void TS_STATUS_INFO_free(TS_STATUS_INFO *a);
-@@ -325,10 +331,12 @@ TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp,
- long length);
- TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a);
-
-+#ifndef OPENSSL_NO_FP_API
- TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a);
- int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a);
--TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO **a);
--int i2d_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO *a);
-+#endif
-+TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO **a);
-+int i2d_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO *a);
-
- TS_ACCURACY *TS_ACCURACY_new(void);
- void TS_ACCURACY_free(TS_ACCURACY *a);
-@@ -731,15 +739,18 @@ int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *msg);
- * ts/ts_conf.c
- */
-
-+#ifndef OPENSSL_NO_STDIO
- X509 *TS_CONF_load_cert(const char *file);
- STACK_OF(X509) *TS_CONF_load_certs(const char *file);
- EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass);
-+#endif
- const char *TS_CONF_get_tsa_section(CONF *conf, const char *section);
- int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb,
- TS_RESP_CTX *ctx);
- int TS_CONF_set_crypto_device(CONF *conf, const char *section,
- const char *device);
- int TS_CONF_set_default_engine(const char *name);
-+#ifndef OPENSSL_NO_STDIO
- int TS_CONF_set_signer_cert(CONF *conf, const char *section,
- const char *cert, TS_RESP_CTX *ctx);
- int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs,
-@@ -747,6 +758,7 @@ int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs,
- int TS_CONF_set_signer_key(CONF *conf, const char *section,
- const char *key, const char *pass,
- TS_RESP_CTX *ctx);
-+#endif
- int TS_CONF_set_def_policy(CONF *conf, const char *section,
- const char *policy, TS_RESP_CTX *ctx);
- int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx);
-@@ -787,6 +799,11 @@ void ERR_load_TS_strings(void);
- # define TS_F_TS_CHECK_SIGNING_CERTS 103
- # define TS_F_TS_CHECK_STATUS_INFO 104
- # define TS_F_TS_COMPUTE_IMPRINT 145
-+# define TS_F_TS_CONF_INVALID 151
-+# define TS_F_TS_CONF_LOAD_CERT 153
-+# define TS_F_TS_CONF_LOAD_CERTS 154
-+# define TS_F_TS_CONF_LOAD_KEY 155
-+# define TS_F_TS_CONF_LOOKUP_FAIL 152
- # define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146
- # define TS_F_TS_GET_STATUS_TEXT 105
- # define TS_F_TS_MSG_IMPRINT_SET_ALGO 118
-@@ -825,6 +842,8 @@ void ERR_load_TS_strings(void);
- /* Reason codes. */
- # define TS_R_BAD_PKCS7_TYPE 132
- # define TS_R_BAD_TYPE 133
-+# define TS_R_CANNOT_LOAD_CERT 137
-+# define TS_R_CANNOT_LOAD_KEY 138
- # define TS_R_CERTIFICATE_VERIFY_ERROR 100
- # define TS_R_COULD_NOT_SET_ENGINE 127
- # define TS_R_COULD_NOT_SET_TIME 115
-@@ -857,6 +876,8 @@ void ERR_load_TS_strings(void);
- # define TS_R_UNACCEPTABLE_POLICY 125
- # define TS_R_UNSUPPORTED_MD_ALGORITHM 126
- # define TS_R_UNSUPPORTED_VERSION 113
-+# define TS_R_VAR_BAD_VALUE 135
-+# define TS_R_VAR_LOOKUP_FAILURE 136
- # define TS_R_WRONG_CONTENT_TYPE 114
-
- #ifdef __cplusplus
-diff --git a/crypto/ts/ts_conf.c b/crypto/ts/ts_conf.c
-index 4716b23..c4416ba 100644
---- a/crypto/ts/ts_conf.c
-+++ b/crypto/ts/ts_conf.c
-@@ -92,6 +92,7 @@
-
- /* Function definitions for certificate and key loading. */
-
-+#ifndef OPENSSL_NO_STDIO
- X509 *TS_CONF_load_cert(const char *file)
- {
- BIO *cert = NULL;
-@@ -102,7 +103,7 @@ X509 *TS_CONF_load_cert(const char *file)
- x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
- end:
- if (x == NULL)
-- fprintf(stderr, "unable to load certificate: %s\n", file);
-+ TSerr(TS_F_TS_CONF_LOAD_CERT, TS_R_CANNOT_LOAD_CERT);
- BIO_free(cert);
- return x;
- }
-@@ -129,7 +130,7 @@ STACK_OF(X509) *TS_CONF_load_certs(const char *file)
- }
- end:
- if (othercerts == NULL)
-- fprintf(stderr, "unable to load certificates: %s\n", file);
-+ TSerr(TS_F_TS_CONF_LOAD_CERTS, TS_R_CANNOT_LOAD_CERT);
- sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
- BIO_free(certs);
- return othercerts;
-@@ -145,21 +146,24 @@ EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass)
- pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *)pass);
- end:
- if (pkey == NULL)
-- fprintf(stderr, "unable to load private key: %s\n", file);
-+ TSerr(TS_F_TS_CONF_LOAD_KEY, TS_R_CANNOT_LOAD_KEY);
- BIO_free(key);
- return pkey;
- }
-+#endif /* !OPENSSL_NO_STDIO */
-
- /* Function definitions for handling configuration options. */
-
- static void TS_CONF_lookup_fail(const char *name, const char *tag)
- {
-- fprintf(stderr, "variable lookup failed for %s::%s\n", name, tag);
-+ TSerr(TS_F_TS_CONF_LOOKUP_FAIL, TS_R_VAR_LOOKUP_FAILURE);
-+ ERR_add_error_data(3, name, "::", tag);
- }
-
- static void TS_CONF_invalid(const char *name, const char *tag)
- {
-- fprintf(stderr, "invalid variable value for %s::%s\n", name, tag);
-+ TSerr(TS_F_TS_CONF_INVALID, TS_R_VAR_BAD_VALUE);
-+ ERR_add_error_data(3, name, "::", tag);
- }
-
- const char *TS_CONF_get_tsa_section(CONF *conf, const char *section)
-@@ -237,6 +241,7 @@ int TS_CONF_set_default_engine(const char *name)
-
- #endif
-
-+#ifndef OPENSSL_NO_STDIO
- int TS_CONF_set_signer_cert(CONF *conf, const char *section,
- const char *cert, TS_RESP_CTX *ctx)
- {
-@@ -302,6 +307,7 @@ int TS_CONF_set_signer_key(CONF *conf, const char *section,
- EVP_PKEY_free(key_obj);
- return ret;
- }
-+#endif /* !OPENSSL_NO_STDIO */
-
- int TS_CONF_set_def_policy(CONF *conf, const char *section,
- const char *policy, TS_RESP_CTX *ctx)
-diff --git a/crypto/ts/ts_err.c b/crypto/ts/ts_err.c
-index ff1abf4..3f5b78f 100644
---- a/crypto/ts/ts_err.c
-+++ b/crypto/ts/ts_err.c
-@@ -1,6 +1,6 @@
- /* crypto/ts/ts_err.c */
- /* ====================================================================
-- * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
-+ * Copyright (c) 1999-2015 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
-@@ -87,6 +87,11 @@ static ERR_STRING_DATA TS_str_functs[] = {
- {ERR_FUNC(TS_F_TS_CHECK_SIGNING_CERTS), "TS_CHECK_SIGNING_CERTS"},
- {ERR_FUNC(TS_F_TS_CHECK_STATUS_INFO), "TS_CHECK_STATUS_INFO"},
- {ERR_FUNC(TS_F_TS_COMPUTE_IMPRINT), "TS_COMPUTE_IMPRINT"},
-+ {ERR_FUNC(TS_F_TS_CONF_INVALID), "ts_CONF_invalid"},
-+ {ERR_FUNC(TS_F_TS_CONF_LOAD_CERT), "TS_CONF_load_cert"},
-+ {ERR_FUNC(TS_F_TS_CONF_LOAD_CERTS), "TS_CONF_load_certs"},
-+ {ERR_FUNC(TS_F_TS_CONF_LOAD_KEY), "TS_CONF_load_key"},
-+ {ERR_FUNC(TS_F_TS_CONF_LOOKUP_FAIL), "ts_CONF_lookup_fail"},
- {ERR_FUNC(TS_F_TS_CONF_SET_DEFAULT_ENGINE), "TS_CONF_set_default_engine"},
- {ERR_FUNC(TS_F_TS_GET_STATUS_TEXT), "TS_GET_STATUS_TEXT"},
- {ERR_FUNC(TS_F_TS_MSG_IMPRINT_SET_ALGO), "TS_MSG_IMPRINT_set_algo"},
-@@ -132,6 +137,8 @@ static ERR_STRING_DATA TS_str_functs[] = {
- static ERR_STRING_DATA TS_str_reasons[] = {
- {ERR_REASON(TS_R_BAD_PKCS7_TYPE), "bad pkcs7 type"},
- {ERR_REASON(TS_R_BAD_TYPE), "bad type"},
-+ {ERR_REASON(TS_R_CANNOT_LOAD_CERT), "cannot load certificate"},
-+ {ERR_REASON(TS_R_CANNOT_LOAD_KEY), "cannot load private key"},
- {ERR_REASON(TS_R_CERTIFICATE_VERIFY_ERROR), "certificate verify error"},
- {ERR_REASON(TS_R_COULD_NOT_SET_ENGINE), "could not set engine"},
- {ERR_REASON(TS_R_COULD_NOT_SET_TIME), "could not set time"},
-@@ -170,6 +177,8 @@ static ERR_STRING_DATA TS_str_reasons[] = {
- {ERR_REASON(TS_R_UNACCEPTABLE_POLICY), "unacceptable policy"},
- {ERR_REASON(TS_R_UNSUPPORTED_MD_ALGORITHM), "unsupported md algorithm"},
- {ERR_REASON(TS_R_UNSUPPORTED_VERSION), "unsupported version"},
-+ {ERR_REASON(TS_R_VAR_BAD_VALUE), "var bad value"},
-+ {ERR_REASON(TS_R_VAR_LOOKUP_FAILURE), "cannot find config variable"},
- {ERR_REASON(TS_R_WRONG_CONTENT_TYPE), "wrong content type"},
- {0, NULL}
- };
-diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c
-index 0f29011..80dd40e 100644
---- a/crypto/ui/ui_util.c
-+++ b/crypto/ui/ui_util.c
-@@ -56,6 +56,10 @@
- #include <string.h>
- #include "ui_locl.h"
-
-+#ifndef BUFSIZ
-+#define BUFSIZ 256
-+#endif
-+
- int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
- int verify)
- {
-diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
-index bbc3189..29695f9 100644
---- a/crypto/x509/by_dir.c
-+++ b/crypto/x509/by_dir.c
-@@ -69,6 +69,8 @@
- # include <sys/stat.h>
- #endif
-
-+#ifndef OPENSSL_NO_STDIO
-+
- #include <openssl/lhash.h>
- #include <openssl/x509.h>
-
-@@ -438,3 +440,5 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
- BUF_MEM_free(b);
- return (ok);
- }
-+
-+#endif /* OPENSSL_NO_STDIO */
-diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
-index 8334b3f..d075f66 100644
---- a/crypto/x509/x509_vfy.c
-+++ b/crypto/x509/x509_vfy.c
-@@ -1064,6 +1064,8 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
- ctx->current_crl = crl;
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
- ptime = &ctx->param->check_time;
-+ else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
-+ return 1;
- else
- ptime = NULL;
-
-@@ -1805,6 +1807,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
-
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
- ptime = &ctx->param->check_time;
-+ else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
-+ return 1;
- else
- ptime = NULL;
-
-diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
-index 5062682..e90d931 100644
---- a/crypto/x509/x509_vfy.h
-+++ b/crypto/x509/x509_vfy.h
-@@ -443,6 +443,8 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
- * will force the behaviour to match that of previous versions.
- */
- # define X509_V_FLAG_NO_ALT_CHAINS 0x100000
-+/* Do not check certificate/CRL validity against current time */
-+# define X509_V_FLAG_NO_CHECK_TIME 0x200000
-
- # define X509_VP_FLAG_DEFAULT 0x1
- # define X509_VP_FLAG_OVERWRITE 0x2
-@@ -496,8 +498,10 @@ X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx);
-
- X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
-
-+#ifndef OPENSSL_NO_STDIO
- X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
- X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
-+#endif
-
- int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
- int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
-diff --git a/crypto/x509v3/ext_dat.h b/crypto/x509v3/ext_dat.h
-index c3a6fce..09ebbca 100644
---- a/crypto/x509v3/ext_dat.h
-+++ b/crypto/x509v3/ext_dat.h
-@@ -127,8 +127,10 @@ static const X509V3_EXT_METHOD *standard_exts[] = {
- &v3_idp,
- &v3_alt[2],
- &v3_freshest_crl,
-+#ifndef OPENSSL_NO_SCT
- &v3_ct_scts[0],
- &v3_ct_scts[1],
-+#endif
- };
-
- /* Number of standard extensions */
-diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509v3/v3_pci.c
-index 34cad53..12f12a7 100644
---- a/crypto/x509v3/v3_pci.c
-+++ b/crypto/x509v3/v3_pci.c
-@@ -149,6 +149,7 @@ static int process_pci_value(CONF_VALUE *val,
- goto err;
- }
- OPENSSL_free(tmp_data2);
-+#ifndef OPENSSL_NO_STDIO
- } else if (strncmp(val->value, "file:", 5) == 0) {
- unsigned char buf[2048];
- int n;
-@@ -181,6 +182,7 @@ static int process_pci_value(CONF_VALUE *val,
- X509V3_conf_err(val);
- goto err;
- }
-+#endif /* !OPENSSL_NO_STDIO */
- } else if (strncmp(val->value, "text:", 5) == 0) {
- val_len = strlen(val->value + 5);
- tmp_data = OPENSSL_realloc((*policy)->data,
-diff --git a/crypto/x509v3/v3_scts.c b/crypto/x509v3/v3_scts.c
-index 0b7c681..1895b8f 100644
---- a/crypto/x509v3/v3_scts.c
-+++ b/crypto/x509v3/v3_scts.c
-@@ -61,6 +61,7 @@
- #include <openssl/asn1.h>
- #include <openssl/x509v3.h>
-
-+#ifndef OPENSSL_NO_SCT
- /* Signature and hash algorithms from RFC 5246 */
- #define TLSEXT_hash_sha256 4
-
-@@ -332,3 +333,4 @@ static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
-
- return 1;
- }
-+#endif
-diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
-index f5c6156..a2e78aa 100644
---- a/crypto/x509v3/x509v3.h
-+++ b/crypto/x509v3/x509v3.h
-@@ -688,8 +688,9 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
- int ml);
- int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
- int indent);
-+#ifndef OPENSSL_NO_FP_API
- int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
--
-+#endif
- int X509V3_extensions_print(BIO *out, char *title,
- STACK_OF(X509_EXTENSION) *exts,
- unsigned long flag, int indent);
-diff --git a/demos/engines/cluster_labs/hw_cluster_labs_err.h b/demos/engines/cluster_labs/hw_cluster_labs_err.h
-index 3300e11..e9e58d5 100644
---- a/demos/engines/cluster_labs/hw_cluster_labs_err.h
-+++ b/demos/engines/cluster_labs/hw_cluster_labs_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_CL_strings(void);
- static void ERR_unload_CL_strings(void);
- static void ERR_CL_error(int function, int reason, char *file, int line);
--# define CLerr(f,r) ERR_CL_error((f),(r),__FILE__,__LINE__)
-+# define CLerr(f,r) ERR_CL_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the CL functions. */
-
-diff --git a/demos/engines/ibmca/hw_ibmca_err.h b/demos/engines/ibmca/hw_ibmca_err.h
-index c17e0c9..10d0212 100644
---- a/demos/engines/ibmca/hw_ibmca_err.h
-+++ b/demos/engines/ibmca/hw_ibmca_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_IBMCA_strings(void);
- static void ERR_unload_IBMCA_strings(void);
- static void ERR_IBMCA_error(int function, int reason, char *file, int line);
--# define IBMCAerr(f,r) ERR_IBMCA_error((f),(r),__FILE__,__LINE__)
-+# define IBMCAerr(f,r) ERR_IBMCA_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the IBMCA functions. */
-
-diff --git a/demos/engines/rsaref/rsaref_err.h b/demos/engines/rsaref/rsaref_err.h
-index 4356815..598836f 100644
---- a/demos/engines/rsaref/rsaref_err.h
-+++ b/demos/engines/rsaref/rsaref_err.h
-@@ -68,7 +68,7 @@ extern "C" {
- static void ERR_load_RSAREF_strings(void);
- static void ERR_unload_RSAREF_strings(void);
- static void ERR_RSAREF_error(int function, int reason, char *file, int line);
--# define RSAREFerr(f,r) ERR_RSAREF_error((f),(r),__FILE__,__LINE__)
-+# define RSAREFerr(f,r) ERR_RSAREF_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
- /* Error codes for the RSAREF functions. */
-
- /* Function codes. */
-diff --git a/demos/engines/zencod/hw_zencod_err.h b/demos/engines/zencod/hw_zencod_err.h
-index f4a8358..94d3293 100644
---- a/demos/engines/zencod/hw_zencod_err.h
-+++ b/demos/engines/zencod/hw_zencod_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_ZENCOD_strings(void);
- static void ERR_unload_ZENCOD_strings(void);
- static void ERR_ZENCOD_error(int function, int reason, char *file, int line);
--# define ZENCODerr(f,r) ERR_ZENCOD_error((f),(r),__FILE__,__LINE__)
-+# define ZENCODerr(f,r) ERR_ZENCOD_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the ZENCOD functions. */
-
-diff --git a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
-index 44792f9..7f95d58 100644
---- a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
-+++ b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
-@@ -203,6 +203,10 @@ chain found is not trusted, then OpenSSL will continue to check to see if an
- alternative chain can be found that is trusted. With this flag set the behaviour
- will match that of OpenSSL versions prior to 1.0.2b.
-
-+The B<X509_V_FLAG_NO_CHECK_TIME> flag suppresses checking the validity period
-+of certificates and CRLs against the current time. If X509_VERIFY_PARAM_set_time()
-+is used to specify a verification time, the check is not suppressed.
-+
- =head1 NOTES
-
- The above functions should be used to manipulate verification parameters
-diff --git a/doc/crypto/threads.pod b/doc/crypto/threads.pod
-index dc0e939..fe123bb 100644
---- a/doc/crypto/threads.pod
-+++ b/doc/crypto/threads.pod
-@@ -51,15 +51,15 @@ CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
- void CRYPTO_lock(int mode, int n, const char *file, int line);
-
- #define CRYPTO_w_lock(type) \
-- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
- #define CRYPTO_w_unlock(type) \
-- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
- #define CRYPTO_r_lock(type) \
-- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
- #define CRYPTO_r_unlock(type) \
-- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
-+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
- #define CRYPTO_add(addr,amount,type) \
-- CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
-+ CRYPTO_add_lock(addr,amount,type,OPENSSL_FILE,OPENSSL_LINE)
-
- =head1 DESCRIPTION
-
-diff --git a/e_os.h b/e_os.h
-index 1fa36c1..3e9dae2 100644
---- a/e_os.h
-+++ b/e_os.h
-@@ -136,7 +136,7 @@ extern "C" {
- # define MSDOS
- # endif
-
--# if defined(MSDOS) && !defined(GETPID_IS_MEANINGLESS)
-+# if (defined(MSDOS) || defined(OPENSSL_SYS_UEFI)) && !defined(GETPID_IS_MEANINGLESS)
- # define GETPID_IS_MEANINGLESS
- # endif
-
-diff --git a/e_os2.h b/e_os2.h
-index 7be9989..909e22f 100644
---- a/e_os2.h
-+++ b/e_os2.h
-@@ -97,7 +97,14 @@ extern "C" {
- * For 32 bit environment, there seems to be the CygWin environment and then
- * all the others that try to do the same thing Microsoft does...
- */
--# if defined(OPENSSL_SYSNAME_UWIN)
-+/*
-+ * UEFI lives here because it might be built with a Microsoft toolchain and
-+ * we need to avoid the false positive match on Windows.
-+ */
-+# if defined(OPENSSL_SYSNAME_UEFI)
-+# undef OPENSSL_SYS_UNIX
-+# define OPENSSL_SYS_UEFI
-+# elif defined(OPENSSL_SYSNAME_UWIN)
- # undef OPENSSL_SYS_UNIX
- # define OPENSSL_SYS_WIN32_UWIN
- # else
-diff --git a/engines/ccgost/e_gost_err.h b/engines/ccgost/e_gost_err.h
-index a2018ec..9eacdcf 100644
---- a/engines/ccgost/e_gost_err.h
-+++ b/engines/ccgost/e_gost_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- void ERR_load_GOST_strings(void);
- void ERR_unload_GOST_strings(void);
- void ERR_GOST_error(int function, int reason, char *file, int line);
--# define GOSTerr(f,r) ERR_GOST_error((f),(r),__FILE__,__LINE__)
-+# define GOSTerr(f,r) ERR_GOST_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the GOST functions. */
-
-diff --git a/engines/e_4758cca_err.h b/engines/e_4758cca_err.h
-index 2f29d96..47a2635 100644
---- a/engines/e_4758cca_err.h
-+++ b/engines/e_4758cca_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_CCA4758_strings(void);
- static void ERR_unload_CCA4758_strings(void);
- static void ERR_CCA4758_error(int function, int reason, char *file, int line);
--# define CCA4758err(f,r) ERR_CCA4758_error((f),(r),__FILE__,__LINE__)
-+# define CCA4758err(f,r) ERR_CCA4758_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the CCA4758 functions. */
-
-diff --git a/engines/e_aep_err.h b/engines/e_aep_err.h
-index 2ed0114..1f8fa5b 100644
---- a/engines/e_aep_err.h
-+++ b/engines/e_aep_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_AEPHK_strings(void);
- static void ERR_unload_AEPHK_strings(void);
- static void ERR_AEPHK_error(int function, int reason, char *file, int line);
--# define AEPHKerr(f,r) ERR_AEPHK_error((f),(r),__FILE__,__LINE__)
-+# define AEPHKerr(f,r) ERR_AEPHK_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the AEPHK functions. */
-
-diff --git a/engines/e_atalla_err.h b/engines/e_atalla_err.h
-index 7b71eff..d958496 100644
---- a/engines/e_atalla_err.h
-+++ b/engines/e_atalla_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_ATALLA_strings(void);
- static void ERR_unload_ATALLA_strings(void);
- static void ERR_ATALLA_error(int function, int reason, char *file, int line);
--# define ATALLAerr(f,r) ERR_ATALLA_error((f),(r),__FILE__,__LINE__)
-+# define ATALLAerr(f,r) ERR_ATALLA_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the ATALLA functions. */
-
-diff --git a/engines/e_capi_err.h b/engines/e_capi_err.h
-index b5d06dc..cfe46b1 100644
---- a/engines/e_capi_err.h
-+++ b/engines/e_capi_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_CAPI_strings(void);
- static void ERR_unload_CAPI_strings(void);
- static void ERR_CAPI_error(int function, int reason, char *file, int line);
--# define CAPIerr(f,r) ERR_CAPI_error((f),(r),__FILE__,__LINE__)
-+# define CAPIerr(f,r) ERR_CAPI_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the CAPI functions. */
-
-diff --git a/engines/e_chil_err.h b/engines/e_chil_err.h
-index d86a4ce..3d961b9 100644
---- a/engines/e_chil_err.h
-+++ b/engines/e_chil_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_HWCRHK_strings(void);
- static void ERR_unload_HWCRHK_strings(void);
- static void ERR_HWCRHK_error(int function, int reason, char *file, int line);
--# define HWCRHKerr(f,r) ERR_HWCRHK_error((f),(r),__FILE__,__LINE__)
-+# define HWCRHKerr(f,r) ERR_HWCRHK_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the HWCRHK functions. */
-
-diff --git a/engines/e_cswift_err.h b/engines/e_cswift_err.h
-index fde3a82..7c20691 100644
---- a/engines/e_cswift_err.h
-+++ b/engines/e_cswift_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_CSWIFT_strings(void);
- static void ERR_unload_CSWIFT_strings(void);
- static void ERR_CSWIFT_error(int function, int reason, char *file, int line);
--# define CSWIFTerr(f,r) ERR_CSWIFT_error((f),(r),__FILE__,__LINE__)
-+# define CSWIFTerr(f,r) ERR_CSWIFT_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the CSWIFT functions. */
-
-diff --git a/engines/e_gmp_err.h b/engines/e_gmp_err.h
-index 637abbc..ccaf3da 100644
---- a/engines/e_gmp_err.h
-+++ b/engines/e_gmp_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_GMP_strings(void);
- static void ERR_unload_GMP_strings(void);
- static void ERR_GMP_error(int function, int reason, char *file, int line);
--# define GMPerr(f,r) ERR_GMP_error((f),(r),__FILE__,__LINE__)
-+# define GMPerr(f,r) ERR_GMP_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the GMP functions. */
-
-diff --git a/engines/e_nuron_err.h b/engines/e_nuron_err.h
-index aa7849c..e607d3e 100644
---- a/engines/e_nuron_err.h
-+++ b/engines/e_nuron_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_NURON_strings(void);
- static void ERR_unload_NURON_strings(void);
- static void ERR_NURON_error(int function, int reason, char *file, int line);
--# define NURONerr(f,r) ERR_NURON_error((f),(r),__FILE__,__LINE__)
-+# define NURONerr(f,r) ERR_NURON_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the NURON functions. */
-
-diff --git a/engines/e_sureware_err.h b/engines/e_sureware_err.h
-index bef8623..54f2848 100644
---- a/engines/e_sureware_err.h
-+++ b/engines/e_sureware_err.h
-@@ -68,7 +68,7 @@ static void ERR_load_SUREWARE_strings(void);
- static void ERR_unload_SUREWARE_strings(void);
- static void ERR_SUREWARE_error(int function, int reason, char *file,
- int line);
--# define SUREWAREerr(f,r) ERR_SUREWARE_error((f),(r),__FILE__,__LINE__)
-+# define SUREWAREerr(f,r) ERR_SUREWARE_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the SUREWARE functions. */
-
-diff --git a/engines/e_ubsec_err.h b/engines/e_ubsec_err.h
-index c8aec7c..67110ed 100644
---- a/engines/e_ubsec_err.h
-+++ b/engines/e_ubsec_err.h
-@@ -67,7 +67,7 @@ extern "C" {
- static void ERR_load_UBSEC_strings(void);
- static void ERR_unload_UBSEC_strings(void);
- static void ERR_UBSEC_error(int function, int reason, char *file, int line);
--# define UBSECerr(f,r) ERR_UBSEC_error((f),(r),__FILE__,__LINE__)
-+# define UBSECerr(f,r) ERR_UBSEC_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- /* Error codes for the UBSEC functions. */
-
-diff --git a/makevms.com b/makevms.com
-index f6b3ff2..1dcbe36 100755
---- a/makevms.com
-+++ b/makevms.com
-@@ -293,6 +293,7 @@ $ CONFIG_LOGICALS := AES,-
- RFC3779,-
- RIPEMD,-
- RSA,-
-+ SCT,-
- SCTP,-
- SEED,-
- SHA,-
-diff --git a/ssl/d1_both.c b/ssl/d1_both.c
-index 9bc6153..b5648eb 100644
---- a/ssl/d1_both.c
-+++ b/ssl/d1_both.c
-@@ -1068,7 +1068,7 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
- int dtls1_read_failed(SSL *s, int code)
- {
- if (code > 0) {
-- fprintf(stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
-+ fprintf(stderr, "dtls1_read_failed(); invalid state reached\n");
- return 1;
- }
-
-diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
-index 499f0e8..5672f99 100644
---- a/ssl/ssl_asn1.c
-+++ b/ssl/ssl_asn1.c
-@@ -418,7 +418,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
- if (ssl_version == SSL2_VERSION) {
- if (os.length != 3) {
- c.error = SSL_R_CIPHER_CODE_WRONG_LENGTH;
-- c.line = __LINE__;
-+ c.line = OPENSSL_LINE;
- goto err;
- }
- id = 0x02000000L |
-@@ -429,14 +429,14 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
- || ssl_version == DTLS1_BAD_VER) {
- if (os.length != 2) {
- c.error = SSL_R_CIPHER_CODE_WRONG_LENGTH;
-- c.line = __LINE__;
-+ c.line = OPENSSL_LINE;
- goto err;
- }
- id = 0x03000000L |
- ((unsigned long)os.data[0] << 8L) | (unsigned long)os.data[1];
- } else {
- c.error = SSL_R_UNKNOWN_SSL_VERSION;
-- c.line = __LINE__;
-+ c.line = OPENSSL_LINE;
- goto err;
- }
-
-@@ -526,7 +526,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
- if (os.data != NULL) {
- if (os.length > SSL_MAX_SID_CTX_LENGTH) {
- c.error = SSL_R_BAD_LENGTH;
-- c.line = __LINE__;
-+ c.line = OPENSSL_LINE;
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
-diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
-index f48ebae..ac4f08c 100644
---- a/ssl/ssl_cert.c
-+++ b/ssl/ssl_cert.c
-@@ -857,12 +857,12 @@ int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
- return (add_client_CA(&(ctx->client_CA), x));
- }
-
-+#ifndef OPENSSL_NO_STDIO
- static int xname_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
- {
- return (X509_NAME_cmp(*a, *b));
- }
-
--#ifndef OPENSSL_NO_STDIO
- /**
- * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
- * it doesn't really have anything to do with clients (except that a common use
-@@ -930,7 +930,6 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
- ERR_clear_error();
- return (ret);
- }
--#endif
-
- /**
- * Add a file of certs to a stack.
-@@ -1050,6 +1049,7 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
- CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
- return ret;
- }
-+#endif /* !OPENSSL_NO_STDIO */
-
- /* Add a certificate to a BUF_MEM structure */
-
-diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
-index 8d3709d..2bb403b 100644
---- a/ssl/ssl_conf.c
-+++ b/ssl/ssl_conf.c
-@@ -370,6 +370,7 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
- return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
- }
-
-+#ifndef OPENSSL_NO_STDIO
- static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
- {
- int rv = 1;
-@@ -436,7 +437,9 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
- BIO_free(in);
- return rv > 0;
- }
--#endif
-+#endif /* !OPENSSL_NO_DH */
-+#endif /* !OPENSSL_NO_STDIO */
-+
- typedef struct {
- int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
- const char *str_file;
-@@ -462,12 +465,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
- SSL_CONF_CMD_STRING(CipherString, "cipher"),
- SSL_CONF_CMD_STRING(Protocol, NULL),
- SSL_CONF_CMD_STRING(Options, NULL),
-+#ifndef OPENSSL_NO_STDIO
- SSL_CONF_CMD(Certificate, "cert", SSL_CONF_TYPE_FILE),
- SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_TYPE_FILE),
- SSL_CONF_CMD(ServerInfoFile, NULL, SSL_CONF_TYPE_FILE),
- #ifndef OPENSSL_NO_DH
- SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_TYPE_FILE)
- #endif
-+#endif
- };
-
- static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
-diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
-index b6d1ee9..75f38cd 100644
---- a/ssl/t1_enc.c
-+++ b/ssl/t1_enc.c
-@@ -779,9 +779,7 @@ int tls1_enc(SSL *s, int send)
- * we can't write into the input stream: Can this ever
- * happen?? (steve)
- */
-- fprintf(stderr,
-- "%s:%d: rec->data != rec->input\n",
-- __FILE__, __LINE__);
-+ fprintf(stderr, "tls1_enc: rec->data != rec->input\n");
- else if (RAND_bytes(rec->input, ivlen) <= 0)
- return -1;
- }
-diff --git a/test/cms-test.pl b/test/cms-test.pl
-index baa3b59..1ee3f02 100644
---- a/test/cms-test.pl
-+++ b/test/cms-test.pl
-@@ -100,6 +100,13 @@ my $no_ec2m;
- my $no_ecdh;
- my $ossl8 = `$ossl_path version -v` =~ /0\.9\.8/;
-
-+system ("$ossl_path no-cms > $null_path");
-+if ($? == 0)
-+ {
-+ print "CMS disabled\n";
-+ exit 0;
-+ }
-+
- system ("$ossl_path no-ec > $null_path");
- if ($? == 0)
- {
-diff --git a/util/libeay.num b/util/libeay.num
-index 2094ab3..992abb2 100755
---- a/util/libeay.num
-+++ b/util/libeay.num
-@@ -4370,7 +4370,7 @@ DH_compute_key_padded 4732 EXIST::FUNCTION:DH
- ECDSA_METHOD_set_sign 4733 EXIST::FUNCTION:ECDSA
- CMS_RecipientEncryptedKey_cert_cmp 4734 EXIST:!VMS:FUNCTION:CMS
- CMS_RecipEncryptedKey_cert_cmp 4734 EXIST:VMS:FUNCTION:CMS
--DH_KDF_X9_42 4735 EXIST::FUNCTION:DH
-+DH_KDF_X9_42 4735 EXIST::FUNCTION:CMS,DH
- RSA_OAEP_PARAMS_free 4736 EXIST::FUNCTION:RSA
- EVP_des_ede3_wrap 4737 EXIST::FUNCTION:DES
- RSA_OAEP_PARAMS_it 4738 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RSA
-diff --git a/util/mkdef.pl b/util/mkdef.pl
-index b9b159a..9841498 100755
---- a/util/mkdef.pl
-+++ b/util/mkdef.pl
-@@ -97,6 +97,8 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
- "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM",
- # Engines
- "STATIC_ENGINE", "ENGINE", "HW", "GMP",
-+ # X.509v3 Signed Certificate Timestamps
-+ "SCT",
- # RFC3779
- "RFC3779",
- # TLS
-@@ -144,7 +146,7 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
- my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
- my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
- my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
--my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
-+my $no_sct; my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
- my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc;
- my $no_nextprotoneg; my $no_sctp; my $no_srtp; my $no_ssl_trace;
- my $no_unit_test; my $no_ssl3_method; my $no_ssl2_method;
-@@ -235,6 +237,7 @@ foreach (@ARGV, split(/ /, $options))
- elsif (/^no-engine$/) { $no_engine=1; }
- elsif (/^no-hw$/) { $no_hw=1; }
- elsif (/^no-gmp$/) { $no_gmp=1; }
-+ elsif (/^no-sct$/) { $no_sct=1; }
- elsif (/^no-rfc3779$/) { $no_rfc3779=1; }
- elsif (/^no-tlsext$/) { $no_tlsext=1; }
- elsif (/^no-cms$/) { $no_cms=1; }
-@@ -1209,6 +1212,7 @@ sub is_valid
- if ($keyword eq "FP_API" && $no_fp_api) { return 0; }
- if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
- if ($keyword eq "GMP" && $no_gmp) { return 0; }
-+ if ($keyword eq "SCT" && $no_sct) { return 0; }
- if ($keyword eq "RFC3779" && $no_rfc3779) { return 0; }
- if ($keyword eq "TLSEXT" && $no_tlsext) { return 0; }
- if ($keyword eq "PSK" && $no_psk) { return 0; }
-diff --git a/util/mkerr.pl b/util/mkerr.pl
-index c197f3a..97b295c 100644
---- a/util/mkerr.pl
-+++ b/util/mkerr.pl
-@@ -89,7 +89,7 @@ Options:
- void ERR_load_<LIB>_strings(void);
- void ERR_unload_<LIB>_strings(void);
- void ERR_<LIB>_error(int f, int r, char *fn, int ln);
-- #define <LIB>err(f,r) ERR_<LIB>_error(f,r,__FILE__,__LINE__)
-+ #define <LIB>err(f,r) ERR_<LIB>_error(f,r,OPENSSL_FILE,OPENSSL_LINE)
- while the code facilitates the use of these in an environment
- where the error support routines are dynamically loaded at
- runtime.
-@@ -482,7 +482,7 @@ EOF
- ${staticloader}void ERR_load_${lib}_strings(void);
- ${staticloader}void ERR_unload_${lib}_strings(void);
- ${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
--# define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__)
-+# define ${lib}err(f,r) ERR_${lib}_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
- EOF
- }
diff --git a/build-iso.sh b/build-iso.sh
index 4643e16..413c119 100644
--- a/build-iso.sh
+++ b/build-iso.sh
@@ -6,25 +6,21 @@ dir="$1"
# cfg
shell="$dir/Shell.efi"
enroll="$dir/EnrollDefaultKeys.efi"
+root="$dir/image"
vfat="$dir/shell.img"
iso="$dir/UefiShell.iso"
-export MTOOLS_SKIP_CHECK=1
-# calc size
-s1=$(stat --format=%s -- $shell)
-s2=$(stat --format=%s -- $enroll)
-size=$(( ($s1 + $s2) * 11 / 10 ))
-set -x
-
-# create non-partitioned FAT image
-/usr/sbin/mkdosfs -C "$vfat" -n UEFI_SHELL -- "$(( $size / 1024 ))"
-mmd -i "$vfat" ::efi
-mmd -i "$vfat" ::efi/boot
-mcopy -i "$vfat" "$shell" ::efi/boot/bootx64.efi
-mcopy -i "$vfat" "$enroll" ::
-#mdir -i "$vfat" -/ ::
+# create non-partitioned (1.44 MB floppy disk) FAT image
+mkdir "$root"
+mkdir "$root"/efi
+mkdir "$root"/efi/boot
+cp "$shell" "$root"/efi/boot/bootx64.efi
+cp "$enroll" "$root"
+qemu-img convert --image-opts \
+ driver=vvfat,floppy=on,fat-type=12,label=UEFI_SHELL,dir="$root/" \
+ $vfat
# build ISO with FAT image file as El Torito EFI boot image
genisoimage -input-charset ASCII -J -rational-rock \
-efi-boot "${vfat##*/}" -no-emul-boot -o "$iso" -- "$vfat"
-rm -f "$vfat"
+rm -rf "$root/" "$vfat"
diff --git a/edk2.spec b/edk2.spec
index 644df30..5e2a6ca 100644
--- a/edk2.spec
+++ b/edk2.spec
@@ -1,11 +1,21 @@
-%global edk2_date 20170209
-%global edk2_githash 296153c5
-%global openssl_version 1.0.2j
+%global edk2_date 20180815
+%global edk2_githash cb5f4f45ce
+%global openssl_version 1.1.0h
+%global qosb_version 1.1.3
+%define qosb_testing 0
+
+%ifarch x86_64
+%define qosb_testing 1
+%endif
+%if 0%{?fedora:1}
%define cross 1
+%endif
%ifarch %{ix86} x86_64
+%if 0%{?fedora:1}
%define build_ovmf_ia32 1
+%endif
%ifarch x86_64
%define build_ovmf_x64 1
%endif
@@ -25,48 +35,61 @@
Name: edk2
Version: %{edk2_date}git%{edk2_githash}
-Release: 7%{dist}
+Release: 1%{dist}
Summary: EFI Development Kit II
Group: Applications/Emulators
License: BSD
URL: http://www.tianocore.org/edk2/
+
+# Tarball generated from git object update-tarball.sh script
Source0: edk2-%{edk2_date}-%{edk2_githash}.tar.xz
-# We have to remove certain patented algorithms from the openssl source
-# tarball with the hobble-openssl script which is included below.
-# The original openssl upstream tarball cannot be shipped in the .src.rpm.
Source1: openssl-%{openssl_version}-hobbled.tar.xz
-Source2: hobble-openssl
-Source3: build-iso.sh
-Source9: update-tarball.sh
-
-# This is the version of the OpenSSL patch that EDK2 applies, but
-# with all changes to srp.* files removed.
-Source10: EDKII_openssl-1.0.2j-no-srp.patch
-
-# Debug output tweaks, not for upstream
+Source2: ovmf-whitepaper-c770f8c.txt
+Source3: https://github.com/puiterwijk/qemu-ovmf-secureboot/archive/v%{qosb_version}…
+Source10: hobble-openssl
+Source11: build-iso.sh
+Source12: update-tarball.sh
+Source13: openssl-patch-to-tarball.sh
+
+# non-upstream patches
Patch0001: 0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch
Patch0002: 0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch
Patch0003: 0003-OvmfPkg-enable-DEBUG_VERBOSE.patch
Patch0004: 0004-OvmfPkg-increase-max-debug-message-length-to-512.patch
-Patch0005: 0005-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
-# Exclude EFI shell from firmware, suggested by pjones re: secureboot.
-# Not for upstream, see bug 1325023#c16
-Patch0006: 0006-EXCLUDE_SHELL_FROM_FD.patch
-# Ship EnrollDefaultKeys application.
-# Not for upstream, see bug 1325023#c16
-Patch0007: 0007-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
-# More text console resolutions. Upstreaming attempted, but failed
-Patch0008: 0008-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
+Patch0005: 0005-advertise-OpenSSL-on-TianoCore-splash-screen-boot-lo.patch
+Patch0006: 0006-OvmfPkg-QemuVideoDxe-enable-debug-messages-in-VbeShi.patch
+Patch0007: 0007-MdeModulePkg-TerminalDxe-add-other-text-resolutions.patch
+Patch0008: 0008-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch
+Patch0009: 0009-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch
+Patch0010: 0010-ArmVirtPkg-QemuFwCfgLib-allow-UEFI_DRIVER-client-mod.patch
+Patch0011: 0011-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch
+Patch0012: 0012-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch
+Patch0013: 0013-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch
+Patch0014: 0014-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch
+Patch0015: 0015-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch
+Patch0016: 0016-ArmVirtPkg-set-early-hello-message-RH-only.patch
+# Fix passing through RPM build flags (bz 1540244)
+Patch0017: 0017-BaseTools-footer.makefile-expand-BUILD_CFLAGS-last-f.patch
+Patch0018: 0018-BaseTools-header.makefile-remove-c-from-BUILD_CFLAGS.patch
+Patch0019: 0019-BaseTools-Source-C-split-O2-to-BUILD_OPTFLAGS.patch
+Patch0020: 0020-BaseTools-Source-C-take-EXTRA_OPTFLAGS-from-the-call.patch
+Patch0021: 0021-BaseTools-Source-C-take-EXTRA_LDFLAGS-from-the-calle.patch
+Patch0022: 0022-BaseTools-VfrCompile-honor-EXTRA_LDFLAGS.patch
+
%if 0%{?cross:1}
# Tweak the tools_def to support cross-compiling.
-# These files are meant for customization, so this is not upstream.
-Patch0009: 0009-Tweak-the-tools_def-to-support-cross-compiling.patch
+# These files are meant for customization, so this is not upstream too.
+Patch0099: 0099-Tweak-the-tools_def-to-support-cross-compiling.patch
%endif
-# fix for build failure, sent upstream
-Patch0010: 0010-VfrCompile-fix-invalid-comparison-between-pointer-an.patch
+# openssl patches from Fedora
+Patch1021: openssl-1.1.0-issuer-hash.patch
+Patch1039: openssl-1.1.0-cc-reqs.patch
+Patch1040: openssl-1.1.0-disable-ssl3.patch
+Patch1044: openssl-1.1.0-bio-fd-preserve-nl.patch
+%if 0%{?fedora:1}
#
# actual firmware builds support cross-compiling. edk2-tools
# in theory should build everywhere without much trouble, but
@@ -74,7 +97,11 @@ Patch0010: 0010-VfrCompile-fix-invalid-comparison-between-pointer-an.patch
# (such as ppc), so lets limit things to the known-good ones.
#
ExclusiveArch: %{ix86} x86_64 %{arm} aarch64
+%else
+ExclusiveArch: x86_64 aarch64
+%endif
+BuildRequires: gcc gcc-c++
BuildRequires: python
BuildRequires: libuuid-devel
%if 0%{?cross:1}
@@ -84,10 +111,22 @@ BuildRequires: gcc-x86_64-linux-gnu
%endif
BuildRequires: iasl
BuildRequires: nasm
-BuildRequires: dosfstools
-BuildRequires: mtools
+BuildRequires: qemu-img
BuildRequires: genisoimage
+# These are for QOSB
+BuildRequires: python3-requests
+BuildRequires: qemu-system-x86
+%if %{?qosb_testing}
+# This is used for testing the enrollment: builds are run in a chroot, lacking
+# a kernel. The testing is only performed on x86_64 for now, but we can't make
+# the BuildRequires only on a specific arch, as that'd come through in the SRPM
+# NOTE: The actual enrollment needs to happen in all builds for all architectures,
+# because OVMF is built as noarch, which means that koji enforces that the build
+# results don't actually differ per arch, and then it picks a random arches' build
+# for the actual RPM.
+BuildRequires: kernel-core
+%endif
%description
EDK II is a development code base for creating UEFI drivers, applications
@@ -119,10 +158,22 @@ BuildArch: noarch
This package documents the tools that are needed to
build EFI executables and ROMs using the GNU tools.
+%package qosb
+Summary: Tool to enroll secureboot
+Group: Development/Tools
+Buildarch: noarch
+%description qosb
+This package contains QOSB (QEMU OVMF Secure Boot), which can enroll OVMF
+variable files to enforce Secure Boot.
+
+
%if 0%{?build_ovmf_x64:1}
%package ovmf
Summary: Open Virtual Machine Firmware
+# OVMF includes the Secure Boot and IPv6 features; it has a builtin OpenSSL
+# library.
License: BSD and OpenSSL
+Provides: bundled(openssl)
Provides: OVMF = %{version}-%{release}
Obsoletes: OVMF < %{version}-%{release}
BuildArch: noarch
@@ -134,7 +185,10 @@ Open Virtual Machine Firmware (x64)
%if 0%{?build_ovmf_ia32:1}
%package ovmf-ia32
Summary: Open Virtual Machine Firmware
+# OVMF includes the Secure Boot and IPv6 features; it has a builtin OpenSSL
+# library.
License: BSD and OpenSSL
+Provides: bundled(openssl)
BuildArch: noarch
%description ovmf-ia32
EFI Development Kit II
@@ -147,6 +201,9 @@ Summary: AARCH64 Virtual Machine Firmware
Provides: AAVMF = %{version}-%{release}
Obsoletes: AAVMF < %{version}-%{release}
BuildArch: noarch
+# No Secure Boot for AAVMF yet, but we include OpenSSL for the IPv6 stack.
+License: BSD and OpenSSL
+Provides: bundled(openssl)
%description aarch64
EFI Development Kit II
AARCH64 UEFI Firmware
@@ -164,24 +221,32 @@ armv7 UEFI Firmware
%prep
%setup -q -n tianocore-%{name}-%{edk2_githash}
-%autopatch -p1
-# replace upstream patch with ours
-cp %{SOURCE10} CryptoPkg/Library/OpensslLib/EDKII_openssl-%{openssl_version}.patch
-# add openssl
-tar -C CryptoPkg/Library/OpensslLib -xf %{SOURCE1}
-(cd CryptoPkg/Library/OpensslLib/openssl-%{openssl_version};
- patch -p1 < ../EDKII_openssl-%{openssl_version}.patch)
-(cd CryptoPkg/Library/OpensslLib; ./Install.sh)
-cp CryptoPkg/Library/OpensslLib/openssl-*/LICENSE LICENSE.openssl
+# Ensure old shell and binary packages are not used
+rm -rf EdkShellBinPkg
+rm -rf EdkShellPkg
+rm -rf FatBinPkg
+rm -rf ShellBinPkg
+# copy whitepaper into place
+cp -a -- %{SOURCE2} .
+# extract openssl into place
+tar -xvf %{SOURCE1} --strip-components=1
+
+# Extract QOSB
+tar -xvf %{SOURCE3}
+mv qemu-ovmf-secureboot-%{qosb_version}/README.md README.qosb
+mv qemu-ovmf-secureboot-%{qosb_version}/LICENSE LICENSE.qosb
+
+%autopatch -p1
+base64 --decode < MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64 > MdeModulePkg/Logo/Logo-OpenSSL.bmp
%build
source ./edksetup.sh
# compiler
-CC_FLAGS="-t GCC49"
+CC_FLAGS="-t GCC5"
# parallel builds
JOBS="%{?_smp_mflags}"
@@ -191,11 +256,13 @@ if test "$JOBS" != ""; then
fi
# common features
-CC_FLAGS="${CC_FLAGS} -b DEBUG"
-CC_FLAGS="${CC_FLAGS} --cmd-len=65536"
+CC_FLAGS="$CC_FLAGS --cmd-len=65536 -t %{TOOLCHAIN} -b DEBUG --hash"
+CC_FLAGS="$CC_FLAGS -D NETWORK_IP6_ENABLE"
+CC_FLAGS="$CC_FLAGS -D TPM2_ENABLE"
# ovmf features
OVMF_FLAGS="${CC_FLAGS}"
+OVMF_FLAGS="${OVMF_FLAGS} -D TLS_ENABLE"
OVMF_FLAGS="${OVMF_FLAGS} -D HTTP_BOOT_ENABLE"
OVMF_FLAGS="${OVMF_FLAGS} -D NETWORK_IP6_ENABLE"
OVMF_FLAGS="${OVMF_FLAGS} -D FD_SIZE_2MB"
@@ -211,15 +278,17 @@ ARM_FLAGS="${CC_FLAGS}"
ARM_FLAGS="${ARM_FLAGS} -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F"
unset MAKEFLAGS
-make -C BaseTools #%{?_smp_mflags}
+make -C BaseTools %{?_smp_mflags} \
+ EXTRA_OPTFLAGS="%{optflags}" \
+ EXTRA_LDFLAGS="%{__global_ldflags}"
sed -i -e 's/-Werror//' Conf/tools_def.txt
%if 0%{?cross:1}
-export GCC49_IA32_PREFIX="x86_64-linux-gnu-"
-export GCC49_X64_PREFIX="x86_64-linux-gnu-"
-export GCC49_AARCH64_PREFIX="aarch64-linux-gnu-"
-export GCC49_ARM_PREFIX="arm-linux-gnu-"
+export GCC5_IA32_PREFIX="x86_64-linux-gnu-"
+export GCC5_X64_PREFIX="x86_64-linux-gnu-"
+export GCC5_AARCH64_PREFIX="aarch64-linux-gnu-"
+export GCC5_ARM_PREFIX="arm-linux-gnu-"
%endif
# build ovmf (x64)
@@ -237,7 +306,15 @@ cp Build/Ovmf3264/*/FV/OVMF_CODE.fd ovmf/OVMF_CODE.secboot.fd
cp Build/Ovmf3264/*/X64/Shell.efi ovmf/
cp Build/Ovmf3264/*/X64/EnrollDefaultKeys.efi ovmf
sh %{_sourcedir}/build-iso.sh ovmf/
-unset GCC49_X64_PREFIX
+
+# Build enrolled VARS file
+python3 qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator \
+ --qemu-binary /usr/bin/qemu-system-x86_64 \
+ --skip-testing \
+ --ovmf-binary ovmf/OVMF_CODE.secboot.fd \
+ --ovmf-template-vars ovmf/OVMF_VARS.fd \
+ --uefi-shell-iso ovmf/UefiShell.iso \
+ ovmf/OVMF_VARS.secboot.fd
%endif
@@ -256,7 +333,6 @@ cp Build/OvmfIa32/*/FV/OVMF_CODE.fd ovmf-ia32/OVMF_CODE.secboot.fd
cp Build/OvmfIa32/*/IA32/Shell.efi ovmf-ia32/Shell.efi
cp Build/OvmfIa32/*/IA32/EnrollDefaultKeys.efi ovmf-ia32/EnrollDefaultKeys.efi
sh %{_sourcedir}/build-iso.sh ovmf-ia32/
-unset GCC49_IA32_PREFIX
%endif
@@ -268,7 +344,6 @@ cp Build/ArmVirtQemu-AARCH64/DEBUG_*/FV/*.fd aarch64
dd of="aarch64/QEMU_EFI-pflash.raw" if="/dev/zero" bs=1M count=64
dd of="aarch64/QEMU_EFI-pflash.raw" if="aarch64/QEMU_EFI.fd" conv=notrunc
dd of="aarch64/vars-template-pflash.raw" if="/dev/zero" bs=1M count=64
-unset GCC49_AARCH64_PREFIX
%endif
@@ -280,10 +355,27 @@ cp Build/ArmVirtQemu-ARM/DEBUG_*/FV/*.fd arm
dd of="arm/QEMU_EFI-pflash.raw" if="/dev/zero" bs=1M count=64
dd of="arm/QEMU_EFI-pflash.raw" if="arm/QEMU_EFI.fd" conv=notrunc
dd of="arm/vars-template-pflash.raw" if="/dev/zero" bs=1M count=64
-unset GCC49_ARM_PREFIX
+%endif
+
+%check
+%if 0%{?build_ovmf_x64:1}
+%if 0%{?qosb_testing}
+# Verify enrolled VARS file
+python3 qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator \
+ --qemu-binary /usr/bin/qemu-system-x86_64 \
+ --skip-enrollment \
+ --print-output \
+ --ovmf-binary ovmf/OVMF_CODE.secboot.fd \
+ --ovmf-template-vars ovmf/OVMF_VARS.fd \
+ --uefi-shell-iso ovmf/UefiShell.iso \
+ --no-download \
+ --kernel-path `rpm -ql kernel-core | grep "\/vmlinuz$" -m 1` \
+ ovmf/OVMF_VARS.secboot.fd
+%endif
%endif
%install
+cp CryptoPkg/Library/OpensslLib/openssl/LICENSE LICENSE.openssl
mkdir -p %{buildroot}%{_bindir} \
%{buildroot}%{_datadir}/%{name}/Conf \
%{buildroot}%{_datadir}/%{name}/Scripts
@@ -314,6 +406,7 @@ mkdir %{buildroot}/usr/share/OVMF
ln -sf ../%{name}/ovmf/OVMF_CODE.fd %{buildroot}/usr/share/OVMF
ln -sf ../%{name}/ovmf/OVMF_CODE.secboot.fd %{buildroot}/usr/share/OVMF
ln -sf ../%{name}/ovmf/OVMF_VARS.fd %{buildroot}/usr/share/OVMF
+ln -sf ../%{name}/ovmf/OVMF_VARS.secboot.fd %{buildroot}/usr/share/OVMF
ln -sf ../%{name}/ovmf/UefiShell.iso %{buildroot}/usr/share/OVMF
%endif
%if 0%{?build_ovmf_ia32:1}
@@ -331,9 +424,15 @@ cp -a arm %{buildroot}/usr/share/%{name}
ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/AAVMF32_CODE.fd
%endif
+install qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator %{buildroot}%{_bindir}
+
%files tools
+%license License.txt
+%license LICENSE.openssl
%{_bindir}/BootSectImage
+%{_bindir}/Brotli
+%{_bindir}/DevicePath
%{_bindir}/EfiLdrImage
%{_bindir}/EfiRom
%{_bindir}/GenCrc32
@@ -372,11 +471,17 @@ ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/
%files tools-doc
%doc BaseTools/UserManuals/*.rtf
+%files qosb
+%license LICENSE.qosb
+%doc README.qosb
+%{_bindir}/ovmf-vars-generator
+
%if 0%{?build_ovmf_x64:1}
%files ovmf
%license OvmfPkg/License.txt
%license LICENSE.openssl
%doc OvmfPkg/README
+%doc ovmf-whitepaper-c770f8c.txt
%dir /usr/share/%{name}
%dir /usr/share/%{name}/ovmf
/usr/share/%{name}/ovmf/OVMF*.fd
@@ -390,6 +495,7 @@ ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/
%license OvmfPkg/License.txt
%license LICENSE.openssl
%doc OvmfPkg/README
+%doc ovmf-whitepaper-c770f8c.txt
%dir /usr/share/%{name}
%dir /usr/share/%{name}/ovmf-ia32
/usr/share/%{name}/ovmf-ia32/OVMF*.fd
@@ -399,7 +505,8 @@ ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/
%if 0%{?build_aavmf_aarch64:1}
%files aarch64
-%license ArmVirtPkg/License.txt
+%license OvmfPkg/License.txt
+%license LICENSE.openssl
%dir /usr/share/%{name}
%dir /usr/share/%{name}/aarch64
/usr/share/%{name}/aarch64/QEMU*.fd
@@ -409,7 +516,8 @@ ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/
%if 0%{?build_aavmf_arm:1}
%files arm
-%license ArmVirtPkg/License.txt
+%license OvmfPkg/License.txt
+%license LICENSE.openssl
%dir /usr/share/%{name}
%dir /usr/share/%{name}/arm
/usr/share/%{name}/arm/QEMU*.fd
@@ -419,6 +527,9 @@ ln -sf ../%{name}/arm/QEMU_EFI-pflash.raw %{buildroot}/usr/share/AAVMF/
%changelog
+* Fri Aug 31 2018 Cole Robinson <crobinso(a)redhat.com> - 20180815gitcb5f4f45ce-1
+- Update to edk2 git cb5f4f45ce, edk2-stable201808
+
* Mon Nov 13 2017 Paolo Bonzini <pbonzini(a)redhat.com> - 20170209git296153c5-6
- Allow non-cross builds
- Install /usr/share/OVMF and /usr/share/AAVMF
diff --git a/openssl-1.1.0-bio-fd-preserve-nl.patch b/openssl-1.1.0-bio-fd-preserve-nl.patch
new file mode 100644
index 0000000..5d71291
--- /dev/null
+++ b/openssl-1.1.0-bio-fd-preserve-nl.patch
@@ -0,0 +1,34 @@
+diff --git a/CryptoPkg/Library/OpensslLib/openssl/crypto/bio/bss_fd.c b/CryptoPkg/Library/OpensslLib/openssl/crypto/bio/bss_fd.c
+index 2bd3517..a886655 100644
+--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/bio/bss_fd.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/bio/bss_fd.c
+@@ -204,8 +204,10 @@ static int fd_gets(BIO *bp, char *buf, int size)
+ char *ptr = buf;
+ char *end = buf + size - 1;
+
+- while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n'))
+- ptr++;
++ while (ptr < end && fd_read(bp, ptr, 1) > 0) {
++ if (*ptr++ == '\n')
++ break;
++ }
+
+ ptr[0] = '\0';
+
+diff --git a/CryptoPkg/Library/OpensslLib/openssl/doc/crypto/BIO_read.pod b/CryptoPkg/Library/OpensslLib/openssl/doc/crypto/BIO_read.pod
+index 45871c1..fe70e9f 100644
+--- a/CryptoPkg/Library/OpensslLib/openssl/doc/crypto/BIO_read.pod
++++ b/CryptoPkg/Library/OpensslLib/openssl/doc/crypto/BIO_read.pod
+@@ -23,7 +23,8 @@ in B<buf>. Usually this operation will attempt to read a line of data
+ from the BIO of maximum length B<len-1>. There are exceptions to this,
+ however; for example, BIO_gets() on a digest BIO will calculate and
+ return the digest and other BIOs may not support BIO_gets() at all.
+-The returned string is always NUL-terminated.
++The returned string is always NUL-terminated and the '\n' is preserved
++if present in the input data.
+
+ BIO_write() attempts to write B<len> bytes from B<buf> to BIO B<b>.
+
+--
+2.17.0
+
diff --git a/openssl-1.1.0-cc-reqs.patch b/openssl-1.1.0-cc-reqs.patch
new file mode 100644
index 0000000..b62e75f
--- /dev/null
+++ b/openssl-1.1.0-cc-reqs.patch
@@ -0,0 +1,29 @@
+--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_gen.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_gen.c
+@@ -86,6 +86,12 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
+ if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
+ goto err;
+
++ /* prepare minimum p and q difference */
++ if (!BN_one(r3))
++ goto err;
++ if (bitsp > 100 && !BN_lshift(r3, r3, bitsp - 100))
++ goto err;
++
+ if (BN_copy(rsa->e, e_value) == NULL)
+ goto err;
+
+@@ -118,7 +124,9 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
+ do {
+ if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
+ goto err;
+- } while (BN_cmp(rsa->p, rsa->q) == 0);
++ if (!BN_sub(r2, rsa->q, rsa->p))
++ goto err;
++ } while (BN_ucmp(r2, r3) <= 0);
+ if (!BN_sub(r2, rsa->q, BN_value_one()))
+ goto err;
+ ERR_set_mark();
+--
+2.17.0
+
diff --git a/openssl-1.1.0-disable-ssl3.patch b/openssl-1.1.0-disable-ssl3.patch
new file mode 100644
index 0000000..1e61659
--- /dev/null
+++ b/openssl-1.1.0-disable-ssl3.patch
@@ -0,0 +1,65 @@
+diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c
+index 8a190d2..6b4c5ae 100644
+--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c
+@@ -2653,6 +2653,13 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
+ * or by using the SSL_CONF library.
+ */
+ ret->options |= SSL_OP_NO_COMPRESSION;
++ /*
++ * Disable SSLv3 by default. Applications can
++ * re-enable it by configuring
++ * SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv3);
++ * or by using the SSL_CONF library.
++ */
++ ret->options |= SSL_OP_NO_SSLv3;
+
+ ret->tlsext_status_type = -1;
+
+diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/ssl_test.c b/CryptoPkg/Library/OpensslLib/openssl/test/ssl_test.c
+index 2cbbddd..1a409d1 100644
+--- a/CryptoPkg/Library/OpensslLib/openssl/test/ssl_test.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/test/ssl_test.c
+@@ -277,6 +277,7 @@ static int execute_test(SSL_TEST_FIXTURE fixture)
+ SSL_TEST_SERVERNAME_CB_NONE) {
+ server2_ctx = SSL_CTX_new(TLS_server_method());
+ TEST_check(server2_ctx != NULL);
++ SSL_CTX_clear_options(server2_ctx, SSL_OP_NO_SSLv3);
+ }
+ client_ctx = SSL_CTX_new(TLS_client_method());
+ TEST_check(SSL_CTX_set_max_proto_version(client_ctx, TLS_MAX_VERSION));
+@@ -290,11 +291,15 @@ static int execute_test(SSL_TEST_FIXTURE fixture)
+ TLS_MAX_VERSION));
+ TEST_check(resume_server_ctx != NULL);
+ TEST_check(resume_client_ctx != NULL);
++ SSL_CTX_clear_options(resume_server_ctx, SSL_OP_NO_SSLv3);
++ SSL_CTX_clear_options(resume_client_ctx, SSL_OP_NO_SSLv3);
+ }
+ }
+
+ TEST_check(server_ctx != NULL);
+ TEST_check(client_ctx != NULL);
++ SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3);
++ SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3);
+
+ TEST_check(CONF_modules_load(conf, fixture.test_app, 0) > 0);
+
+diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/ssltest_old.c b/CryptoPkg/Library/OpensslLib/openssl/test/ssltest_old.c
+index e77c692..e586072 100644
+--- a/CryptoPkg/Library/OpensslLib/openssl/test/ssltest_old.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/test/ssltest_old.c
+@@ -1460,6 +1460,11 @@ int main(int argc, char *argv[])
+ ERR_print_errors(bio_err);
+ goto end;
+ }
++
++ SSL_CTX_clear_options(c_ctx, SSL_OP_NO_SSLv3);
++ SSL_CTX_clear_options(s_ctx, SSL_OP_NO_SSLv3);
++ SSL_CTX_clear_options(s_ctx2, SSL_OP_NO_SSLv3);
++
+ /*
+ * Since we will use low security ciphersuites and keys for testing set
+ * security level to zero by default. Tests can override this by adding
+--
+2.17.0
+
diff --git a/openssl-1.1.0-issuer-hash.patch b/openssl-1.1.0-issuer-hash.patch
new file mode 100644
index 0000000..74087f3
--- /dev/null
+++ b/openssl-1.1.0-issuer-hash.patch
@@ -0,0 +1,13 @@
+--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/x509/x509_cmp.c
++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/x509/x509_cmp.c
+@@ -39,6 +39,7 @@ unsigned long X509_issuer_and_serial_hash(X509 *a)
+
+ if (ctx == NULL)
+ goto err;
++ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
+ if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL))
+ goto err;
+--
+2.17.0
+
diff --git a/openssl-patch-to-tarball.sh b/openssl-patch-to-tarball.sh
new file mode 100644
index 0000000..5b327ca
--- /dev/null
+++ b/openssl-patch-to-tarball.sh
@@ -0,0 +1,63 @@
+#! /bin/sh
+
+: << \EOF
+ For importing the hobbled OpenSSL tarball from Fedora, the following
+ steps are necessary. Note that both the "sources" file format and the
+ pkgs.fedoraproject.org directory structure have changed, accommodating
+ SHA512 checksums.
+
+ # in a separate directory
+ fedpkg clone -a openssl
+ cd openssl
+ fedpkg switch-branch master
+ gitk -- sources
+
+ # the commit that added the 1.1.0h hobbled tarball is 6eb8f620273
+ # subject "update to upstream version 1.1.0h"
+ git checkout 6eb8f620273
+
+ # fetch the hobbled tarball and verify the checksum
+ (
+ set -e
+ while read HASH_TYPE FN EQ HASH; do
+ # remove leading and trailing parens
+ FN="${FN#(*}"
+ FN="${FN%*)}"
+ wget \
+ http://pkgs.fedoraproject.org/repo/pkgs/openssl/$FN/sha512/$HASH/$FN
+ done <sources
+ sha512sum -c sources
+ )
+
+ # unpack the hobbled tarball into edk2, according to
+ # "OpenSSL-HOWTO.txt"; WORKSPACE stands for the root of the edk2 project
+ # tree
+ tar -x --xz -f openssl-1.1.0h-hobbled.tar.xz
+ mv -- openssl-1.1.0h "$WORKSPACE"/CryptoPkg/Library/OpensslLib/openssl
+
+ # update the INF files as described in "OpenSSL-HOWTO.txt", then save
+ # the results as a single commit
+ (cd "$WORKSPACE"/CryptoPkg/Library/OpensslLib && perl process_files.pl)
+ git rm --cached CryptoPkg/Library/OpensslLib/openssl
+ git commit -m'remove openssl submodule'
+ git add -A CryptoPkg/Library/OpensslLib/openssl
+ git commit -m'add openssl 1.1.0h'
+ git format-patch -1
+
+Then run the patch through this script which will build a new tar file.
+EOF
+
+set -e
+edk2_githash=$(awk '/^%global edk2_githash/ {print $3}' edk2.spec)
+openssl_version=$(awk '/^%global openssl_version/ {print $3}' edk2.spec)
+mkdir -p tianocore-openssl-${openssl_version}
+(exec 3> openssl-${openssl_version}-hobbled.tar.xz
+ cd tianocore-openssl-${openssl_version}
+ git init .
+ git config core.whitespace cr-at-eol
+ git config am.keepcr true
+ git am
+ git archive --format=tar --prefix=tianocore-edk2-${edk2_githash}/ \
+ HEAD CryptoPkg/Library/OpensslLib/ | \
+ xz -9ev >&3) < $1
+rm -rf tianocore-openssl-${openssl_version}
diff --git a/ovmf-whitepaper-c770f8c.txt b/ovmf-whitepaper-c770f8c.txt
new file mode 100644
index 0000000..ba727b4
--- /dev/null
+++ b/ovmf-whitepaper-c770f8c.txt
@@ -0,0 +1,2422 @@
+Open Virtual Machine Firmware (OVMF) Status Report
+July 2014 (with updates in August 2014 - January 2015)
+
+Author: Laszlo Ersek <lersek(a)redhat.com>
+Copyright (C) 2014-2015, Red Hat, Inc.
+CC BY-SA 4.0 <http://creativecommons.org/licenses/by-sa/4.0/ >
+
+Abstract
+--------
+
+The Unified Extensible Firmware Interface (UEFI) is a specification that
+defines a software interface between an operating system and platform firmware.
+UEFI is designed to replace the Basic Input/Output System (BIOS) firmware
+interface.
+
+Hardware platform vendors have been increasingly adopting the UEFI
+Specification to govern their boot firmware developments. OVMF (Open Virtual
+Machine Firmware), a sub-project of Intel's EFI Development Kit II (edk2),
+enables UEFI support for Ia32 and X64 Virtual Machines.
+
+This paper reports on the status of the OVMF project, treats features and
+limitations, gives end-user hints, and examines some areas in-depth.
+
+Keywords: ACPI, boot options, CSM, edk2, firmware, flash, fw_cfg, KVM, memory
+map, non-volatile variables, OVMF, PCD, QEMU, reset vector, S3, Secure Boot,
+Smbios, SMM, TianoCore, UEFI, VBE shim, Virtio
+
+Table of Contents
+-----------------
+
+- Motivation
+- Scope
+- Example qemu invocation
+- Installation of OVMF guests with virt-manager and virt-install
+- Supported guest operating systems
+- Compatibility Support Module (CSM)
+- Phases of the boot process
+- Project structure
+- Platform Configuration Database (PCD)
+- Firmware image structure
+- S3 (suspend to RAM and resume)
+- A comprehensive memory map of OVMF
+- Known Secure Boot limitations
+- Variable store and LockBox in SMRAM
+- Select features
+ - X64-specific reset vector for OVMF
+ - Client library for QEMU's firmware configuration interface
+ - Guest ACPI tables
+ - Guest SMBIOS tables
+ - Platform-specific boot policy
+ - Virtio drivers
+ - Platform Driver
+ - Video driver
+- Afterword
+
+Motivation
+----------
+
+OVMF extends the usual benefits of virtualization to UEFI. Reasons to use OVMF
+include:
+
+- Legacy-free guests. A UEFI-based environment eliminates dependencies on
+ legacy address spaces and devices. This is especially beneficial when used
+ with physically assigned devices where the legacy operating mode is
+ troublesome to support, ex. assigned graphics cards operating in legacy-free,
+ non-VGA mode in the guest.
+
+- Future proof guests. The x86 market is steadily moving towards a legacy-free
+ platform and guest operating systems may eventually require a UEFI
+ environment. OVMF provides that next generation firmware support for such
+ applications.
+
+- GUID partition tables (GPTs). MBR partition tables represent partition
+ offsets and sizes with 32-bit integers, in units of 512 byte sectors. This
+ limits the addressable portion of the disk to 2 TB. GPT represents logical
+ block addresses with 64 bits.
+
+- Liberating boot loader binaries from residing in contested and poorly defined
+ space between the partition table and the partitions.
+
+- Support for booting off disks (eg. pass-through physical SCSI devices) with a
+ 4kB physical and logical sector size, i.e. which don't have 512-byte block
+ emulation.
+
+- Development and testing of Secure Boot-related features in guest operating
+ systems. Although OVMF's Secure Boot implementation is currently not secure
+ against malicious UEFI drivers, UEFI applications, and guest kernels,
+ trusted guest code that only uses standard UEFI interfaces will find a valid
+ Secure Boot environment under OVMF, with working key enrollment and signature
+ validation. This enables development and testing of portable, Secure
+ Boot-related guest code.
+
+- Presence of non-volatile UEFI variables. This furthers development and
+ testing of OS installers, UEFI boot loaders, and unique, dependent guest OS
+ features. For example, an efivars-backed pstore (persistent storage)
+ file system works under Linux.
+
+- Altogether, a near production-level UEFI environment for virtual machines
+ when Secure Boot is not required.
+
+Scope
+-----
+
+UEFI and especially Secure Boot have been topics fraught with controversy and
+political activism. This paper sidesteps these aspects and strives to focus on
+use cases, hands-on information for end users, and technical details.
+
+Unless stated otherwise, the expression "X supports Y" means "X is technically
+compatible with interfaces provided or required by Y". It does not imply
+support as an activity performed by natural persons or companies.
+
+We discuss the status of OVMF at a state no earlier than edk2 SVN revision
+16158. The paper concentrates on upstream projects and communities, but
+occasionally it pans out about OVMF as it is planned to be shipped (as
+Technical Preview) in Red Hat Enterprise Linux 7.1. Such digressions are marked
+with the [RHEL] margin notation.
+
+Although other VMMs and accelerators are known to support (or plan to support)
+OVMF to various degrees -- for example, VirtualBox, Xen, BHyVe --, we'll
+emphasize OVMF on qemu/KVM, because QEMU and KVM have always been Red Hat's
+focus wrt. OVMF.
+
+The recommended upstream QEMU version is 2.1+. The recommended host Linux
+kernel (KVM) version is 3.10+. The recommended QEMU machine type is
+"qemu-system-x86_64 -M pc-i440fx-2.1" or later.
+
+The term "TianoCore" is used interchangeably with "edk2" in this paper.
+
+Example qemu invocation
+-----------------------
+
+The following commands give a quick foretaste of installing a UEFI operating
+system on OVMF, relying only on upstream edk2 and qemu.
+
+- Clone and build OVMF:
+
+ git clone https://github.com/tianocore/edk2.git
+ cd edk2
+ nice OvmfPkg/build.sh -a X64 -n $(getconf _NPROCESSORS_ONLN)
+
+ (Note that this ad-hoc build will not include the Secure Boot feature.)
+
+- The build output file, "OVMF.fd", includes not only the executable firmware
+ code, but the non-volatile variable store as well. For this reason, make a
+ VM-specific copy of the build output (the variable store should be private to
+ the virtual machine):
+
+ cp Build/OvmfX64/DEBUG_GCC4?/FV/OVMF.fd fedora.flash
+
+ (The variable store and the firmware executable are also available in the
+ build output as separate files: "OVMF_VARS.fd" and "OVMF_CODE.fd". This
+ enables central management and updates of the firmware executable, while each
+ virtual machine can retain its own variable store.)
+
+- Download a Fedora LiveCD:
+
+ wget https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Live/x86_64/Fedor…
+
+- Create a virtual disk (qcow2 format, 20 GB in size):
+
+ qemu-img create -f qcow2 fedora.img 20G
+
+- Create the following qemu wrapper script under the name "fedora.sh":
+
+ # Basic virtual machine properties: a recent i440fx machine type, KVM
+ # acceleration, 2048 MB RAM, two VCPUs.
+ OPTS="-M pc-i440fx-2.1 -enable-kvm -m 2048 -smp 2"
+
+ # The OVMF binary, including the non-volatile variable store, appears as a
+ # "normal" qemu drive on the host side, and it is exposed to the guest as a
+ # persistent flash device.
+ OPTS="$OPTS -drive if=pflash,format=raw,file=fedora.flash"
+
+ # The hard disk is exposed to the guest as a virtio-block device. OVMF has a
+ # driver stack that supports such a disk. We specify this disk as first boot
+ # option. OVMF recognizes the boot order specification.
+ OPTS="$OPTS -drive id=disk0,if=none,format=qcow2,file=fedora.img"
+ OPTS="$OPTS -device virtio-blk-pci,drive=disk0,bootindex=0"
+
+ # The Fedora installer disk appears as an IDE CD-ROM in the guest. This is
+ # the 2nd boot option.
+ OPTS="$OPTS -drive id=cd0,if=none,format=raw,readonly"
+ OPTS="$OPTS,file=Fedora-Live-Xfce-x86_64-20-1.iso"
+ OPTS="$OPTS -device ide-cd,bus=ide.1,drive=cd0,bootindex=1"
+
+ # The following setting enables S3 (suspend to RAM). OVMF supports S3
+ # suspend/resume.
+ OPTS="$OPTS -global PIIX4_PM.disable_s3=0"
+
+ # OVMF emits a number of info / debug messages to the QEMU debug console, at
+ # ioport 0x402. We configure qemu so that the debug console is indeed
+ # available at that ioport. We redirect the host side of the debug console to
+ # a file.
+ OPTS="$OPTS -global isa-debugcon.iobase=0x402 -debugcon file:fedora.ovmf.log"
+
+ # QEMU accepts various commands and queries from the user on the monitor
+ # interface. Connect the monitor with the qemu process's standard input and
+ # output.
+ OPTS="$OPTS -monitor stdio"
+
+ # A USB tablet device in the guest allows for accurate pointer tracking
+ # between the host and the guest.
+ OPTS="$OPTS -device piix3-usb-uhci -device usb-tablet"
+
+ # Provide the guest with a virtual network card (virtio-net).
+ #
+ # Normally, qemu provides the guest with a UEFI-conformant network driver
+ # from the iPXE project, in the form of a PCI expansion ROM. For this test,
+ # we disable the expansion ROM and allow OVMF's built-in virtio-net driver to
+ # take effect.
+ #
+ # On the host side, we use the SLIRP ("user") network backend, which has
+ # relatively low performance, but it doesn't require extra privileges from
+ # the user executing qemu.
+ OPTS="$OPTS -netdev id=net0,type=user"
+ OPTS="$OPTS -device virtio-net-pci,netdev=net0,romfile="
+
+ # A Spice QXL GPU is recommended as the primary VGA-compatible display
+ # device. It is a full-featured virtual video card, with great operating
+ # system driver support. OVMF supports it too.
+ OPTS="$OPTS -device qxl-vga"
+
+ qemu-system-x86_64 $OPTS
+
+- Start the Fedora guest:
+
+ sh fedora.sh
+
+- The above command can be used for both installation and later boots of the
+ Fedora guest.
+
+- In order to verify basic OVMF network connectivity:
+
+ - Assuming that the non-privileged user running qemu belongs to group G
+ (where G is a numeric identifier), ensure as root on the host that the
+ group range in file "/proc/sys/net/ipv4/ping_group_range" includes G.
+
+ - As the non-privileged user, boot the guest as usual.
+
+ - On the TianoCore splash screen, press ESC.
+
+ - Navigate to Boot Manager | EFI Internal Shell
+
+ - In the UEFI Shell, issue the following commands:
+
+ ifconfig -s eth0 dhcp
+ ping A.B.C.D
+
+ where A.B.C.D is a public IPv4 address in dotted decimal notation that your
+ host can reach.
+
+ - Type "quit" at the (qemu) monitor prompt.
+
+Installation of OVMF guests with virt-manager and virt-install
+--------------------------------------------------------------
+
+(1) Assuming OVMF has been installed on the host with the following files:
+ - /usr/share/OVMF/OVMF_CODE.fd
+ - /usr/share/OVMF/OVMF_VARS.fd
+
+ locate the "nvram" stanza in "/etc/libvirt/qemu.conf", and edit it as
+ follows:
+
+ nvram = [ "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" ]
+
+(2) Restart libvirtd with your Linux distribution's service management tool;
+ for example,
+
+ systemctl restart libvirtd
+
+(3) In virt-manager, proceed with the guest installation as usual:
+ - select File | New Virtual Machine,
+ - advance to Step 5 of 5,
+ - in Step 5, check "Customize configuration before install",
+ - click Finish;
+ - in the customization dialog, select Overview | Firmware, and choose UEFI,
+ - click Apply and Begin Installation.
+
+(4) With virt-install:
+
+ LDR="loader=/usr/share/OVMF/OVMF_CODE.fd,loader_ro=yes,loader_type=pflash"
+ virt-install \
+ --name fedora20 \
+ --memory 2048 \
+ --vcpus 2 \
+ --os-variant fedora20 \
+ --boot hd,cdrom,$LDR \
+ --disk size=20 \
+ --disk path=Fedora-Live-Xfce-x86_64-20-1.iso,device=cdrom,bus=scsi
+
+(5) A popular, distribution-independent, bleeding-edge OVMF package is
+ available under <https://www.kraxel.org/repos/ >, courtesy of Gerd Hoffmann.
+
+ The "edk2.git-ovmf-x64" package provides the following files, among others:
+ - /usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd
+ - /usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd
+
+ When using this package, adapt steps (1) and (4) accordingly.
+
+(6) Additionally, the "edk2.git-ovmf-x64" package seeks to simplify the
+ enablement of Secure Boot in a virtual machine (strictly for development
+ and testing purposes).
+
+ - Boot the virtual machine off the CD-ROM image called
+ "/usr/share/edk2.git/ovmf-x64/UefiShell.iso"; before or after installing
+ the main guest operating system.
+
+ - When the UEFI shell appears, issue the following commands:
+
+ EnrollDefaultKeys.efi
+ reset -s
+
+ - The EnrollDefaultKeys.efi utility enrolls the following keys:
+
+ - A static example X.509 certificate (CN=TestCommonName) as Platform Key
+ and first Key Exchange Key.
+
+ The private key matching this certificate has been destroyed (but you
+ shouldn't trust this statement).
+
+ - "Microsoft Corporation KEK CA 2011" as second Key Exchange Key
+ (SHA1: 31:59:0b:fd:89:c9:d7:4e:d0:87:df:ac:66:33:4b:39:31:25:4b:30).
+
+ - "Microsoft Windows Production PCA 2011" as first DB entry
+ (SHA1: 58:0a:6f:4c:c4:e4:b6:69:b9:eb:dc:1b:2b:3e:08:7b:80:d0:67:8d).
+
+ - "Microsoft Corporation UEFI CA 2011" as second DB entry
+ (SHA1: 46:de:f6:3b:5c:e6:1c:f8:ba:0d:e2:e6:63:9c:10:19:d0:ed:14:f3).
+
+ These keys suffice to boot released versions of popular Linux
+ distributions (through the shim.efi utility), and Windows 8 and Windows
+ Server 2012 R2, in Secure Boot mode.
+
+Supported guest operating systems
+---------------------------------
+
+Upstream OVMF does not favor some guest operating systems over others for
+political or ideological reasons. However, some operating systems are harder to
+obtain and/or technically more difficult to support. The general expectation is
+that recent UEFI OSes should just work. Please consult the "OvmfPkg/README"
+file.
+
+The following guest OSes were tested with OVMF:
+- Red Hat Enterprise Linux 6
+- Red Hat Enterprise Linux 7
+- Fedora 18
+- Fedora 19
+- Fedora 20
+- Windows Server 2008 R2 SP1
+- Windows Server 2012
+- Windows 8
+
+Notes about Windows Server 2008 R2 (paraphrasing the "OvmfPkg/README" file):
+
+- QEMU should be started with one of the "-device qxl-vga" and "-device VGA"
+ options.
+
+- Only one video mode, 1024x768x32, is supported at OS runtime.
+
+ Please refer to the section about QemuVideoDxe (OVMF's built-in video driver)
+ for more details on this limitation.
+
+- The qxl-vga video card is recommended ("-device qxl-vga"). After booting the
+ installed guest OS, select the video card in Device Manager, and upgrade the
+ video driver to the QXL XDDM one.
+
+ The QXL XDDM driver can be downloaded from
+ <http://www.spice-space.org/download.html >, under Guest | Windows binaries.
+
+ This driver enables additional graphics resolutions at OS runtime, and
+ provides S3 (suspend/resume) capability.
+
+Notes about Windows Server 2012 and Windows 8:
+
+- QEMU should be started with the "-device qxl-vga,revision=4" option (or a
+ later revision, if available).
+
+- The guest OS's builtin video driver inherits the video mode / frame buffer
+ from OVMF. There's no way to change the resolution at OS runtime.
+
+ For this reason, a platform driver has been developed for OVMF, which allows
+ users to change the preferred video mode in the firmware. Please refer to the
+ section about PlatformDxe for details.
+
+- It is recommended to upgrade the guest OS's video driver to the QXL WDDM one,
+ via Device Manager.
+
+ Binaries for the QXL WDDM driver can be found at
+ <http://people.redhat.com/~vrozenfe/qxlwddm > (pick a version greater than or
+ equal to 0.6), while the source code resides at
+ <https://github.com/vrozenfe/qxl-dod >.
+
+ This driver enables additional graphics resolutions at OS runtime, and
+ provides S3 (suspend/resume) capability.
+
+Compatibility Support Module (CSM)
+----------------------------------
+
+Collaboration between SeaBIOS and OVMF developers has enabled SeaBIOS to be
+built as a Compatibility Support Module, and OVMF to embed and use it.
+
+Benefits of a SeaBIOS CSM include:
+
+- The ability to boot legacy (non-UEFI) operating systems, such as legacy Linux
+ systems, Windows 7, OpenBSD 5.2, FreeBSD 8/9, NetBSD, DragonflyBSD, Solaris
+ 10/11.
+
+- Legacy (non-UEFI-compliant) PCI expansion ROMs, such as a VGA BIOS, mapped by
+ QEMU in emulated devices' ROM BARs, are loaded and executed by OVMF.
+
+ For example, this grants the Windows Server 2008 R2 SP1 guest's native,
+ legacy video driver access to all modes of all QEMU video cards.
+
+Building the CSM target of the SeaBIOS source tree is out of scope for this
+report. Additionally, upstream OVMF does not enable the CSM by default.
+
+Interested users and developers should look for OVMF's "-D CSM_ENABLE"
+build-time option, and check out the <https://www.kraxel.org/repos/ > continuous
+integration repository, which provides CSM-enabled OVMF builds.
+
+[RHEL] The "OVMF_CODE.fd" firmware image made available on the Red Hat
+ Enterprise Linux 7.1 host does not include a Compatibility Support
+ Module, for the following reasons:
+
+ - Virtual machines running officially supported, legacy guest operating
+ systems should just use the standalone SeaBIOS firmware. Firmware
+ selection is flexible in virtualization, see eg. "Installation of OVMF
+ guests with virt-manager and virt-install" above.
+
+ - The 16-bit thunking interface between OVMF and SeaBIOS is very complex
+ and presents a large debugging and support burden, based on past
+ experience.
+
+ - Secure Boot is incompatible with CSM.
+
+ - Inter-project dependencies should be minimized whenever possible.
+
+ - Using the default QXL video card, the Windows 2008 R2 SP1 guest can be
+ installed with its built-in, legacy video driver. Said driver will
+ select the only available video mode, 1024x768x32. After installation,
+ the video driver can be upgraded to the full-featured QXL XDDM driver.
+
+Phases of the boot process
+--------------------------
+
+The PI and UEFI specifications, and Intel's UEFI and EDK II Learning and
+Development materials provide ample information on PI and UEFI concepts. The
+following is an absolutely minimal, rough glossary that is included only to
+help readers new to PI and UEFI understand references in later, OVMF-specific
+sections. We defer heavily to the official specifications and the training
+materials, and frequently quote them below.
+
+A central concept to mention early is the GUID -- globally unique identifier. A
+GUID is a 128-bit number, written as XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
+where each X stands for a hexadecimal nibble. GUIDs are used to name everything
+in PI and in UEFI. Programmers introduce new GUIDs with the "uuidgen" utility,
+and standards bodies standardize well-known services by positing their GUIDs.
+
+The boot process is roughly divided in the following phases:
+
+- Reset vector code.
+
+- SEC: Security phase. This phase is the root of firmware integrity.
+
+- PEI: Pre-EFI Initialization. This phase performs "minimal processor, chipset
+ and platform configuration for the purpose of discovering memory". Modules in
+ PEI collectively save their findings about the platform in a list of HOBs
+ (hand-off blocks).
+
+ When developing PEI code, the Platform Initialization (PI) specification
+ should be consulted.
+
+- DXE: Driver eXecution Environment, pronounced as "Dixie". This "is the phase
+ where the bulk of the booting occurs: devices are enumerated and initialized,
+ UEFI services are supported, and protocols and drivers are implemented. Also,
+ the tables that create the UEFI interface are produced".
+
+ On the PEI/DXE boundary, the HOBs produced by PEI are consumed. For example,
+ this is how the memory space map is configured initially.
+
+- BDS: Boot Device Selection. It is "responsible for determining how and where
+ you want to boot the operating system".
+
+ When developing DXE and BDS code, it is mainly the UEFI specification that
+ should be consulted. When speaking about DXE, BDS is frequently considered to
+ be a part of it.
+
+The following concepts are tied to specific boot process phases:
+
+- PEIM: a PEI Module (pronounced "PIM"). A binary module running in the PEI
+ phase, consuming some PPIs and producing other PPIs, and producing HOBs.
+
+- PPI: PEIM-to-PEIM interface. A structure of function pointers and related
+ data members that establishes a PEI service, or an instance of a PEI service.
+ PPIs are identified by GUID.
+
+ An example is EFI_PEI_S3_RESUME2_PPI (6D582DBC-DB85-4514-8FCC-5ADF6227B147).
+
+- DXE driver: a binary module running in the DXE and BDS phases, consuming some
+ protocols and producing other protocols.
+
+- Protocol: A structure of function pointers and related data members that
+ establishes a DXE service, or an instance of a DXE service. Protocols are
+ identified by GUID.
+
+ An example is EFI_BLOCK_IO_PROTOCOL (964E5B21-6459-11D2-8E39-00A0C969723B).
+
+- Architectural protocols: a set of standard protocols that are foundational to
+ the working of a UEFI system. Each architectural protocol has at most one
+ instance. Architectural protocols are implemented by a subset of DXE drivers.
+ DXE drivers explicitly list the set of protocols (including architectural
+ protocols) that they need to work. UEFI drivers can only be loaded once all
+ architectural protocols have become available during the DXE phase.
+
+ An example is EFI_VARIABLE_WRITE_ARCH_PROTOCOL
+ (6441F818-6362-4E44-B570-7DBA31DD2453).
+
+Project structure
+-----------------
+
+The term "OVMF" usually denotes the project (community and development effort)
+that provide and maintain the subject matter UEFI firmware for virtual
+machines. However the term is also frequently applied to the firmware binary
+proper that a virtual machine executes.
+
+OVMF emerges as a compilation of several modules from the edk2 source
+repository. "edk2" stands for EFI Development Kit II; it is a "modern,
+feature-rich, cross-platform firmware development environment for the UEFI and
+PI specifications".
+
+The composition of OVMF is dictated by the following build control files:
+
+ OvmfPkg/OvmfPkgIa32.dsc
+ OvmfPkg/OvmfPkgIa32.fdf
+
+ OvmfPkg/OvmfPkgIa32X64.dsc
+ OvmfPkg/OvmfPkgIa32X64.fdf
+
+ OvmfPkg/OvmfPkgX64.dsc
+ OvmfPkg/OvmfPkgX64.fdf
+
+The format of these files is described in the edk2 DSC and FDF specifications.
+Roughly, the DSC file determines:
+- library instance resolutions for library class requirements presented by the
+ modules to be compiled,
+- the set of modules to compile.
+
+The FDF file roughly determines:
+- what binary modules (compilation output files, precompiled binaries, graphics
+ image files, verbatim binary sections) to include in the firmware image,
+- how to lay out the firmware image.
+
+The Ia32 flavor of these files builds a firmware where both PEI and DXE phases
+are 32-bit. The Ia32X64 flavor builds a firmware where the PEI phase consists
+of 32-bit modules, and the DXE phase is 64-bit. The X64 flavor builds a purely
+64-bit firmware.
+
+The word size of the DXE phase must match the word size of the runtime OS -- a
+32-bit DXE can't cooperate with a 64-bit OS, and a 64-bit DXE can't work a
+32-bit OS.
+
+OVMF pulls together modules from across the edk2 tree. For example:
+
+- common drivers and libraries that are platform independent are usually
+ located under MdeModulePkg and MdePkg,
+
+- common but hardware-specific drivers and libraries that match QEMU's
+ pc-i440fx-* machine type are pulled in from IntelFrameworkModulePkg,
+ PcAtChipsetPkg and UefiCpuPkg,
+
+- the platform independent UEFI Shell is built from ShellPkg,
+
+- OvmfPkg includes drivers and libraries that are useful for virtual machines
+ and may or may not be specific to QEMU's pc-i440fx-* machine type.
+
+Platform Configuration Database (PCD)
+-------------------------------------
+
+Like the "Phases of the boot process" section, this one introduces a concept in
+very raw form. We defer to the PCD related edk2 specifications, and we won't
+discuss implementation details here. Our purpose is only to offer the reader a
+usable (albeit possibly inaccurate) definition, so that we can refer to PCDs
+later on.
+
+Colloquially, when we say "PCD", we actually mean "PCD entry"; that is, an
+entry stored in the Platform Configuration Database.
+
+The Platform Configuration Database is
+- a firmware-wide
+- name-value store
+- of scalars and buffers
+- where each entry may be
+ - build-time constant, or
+ - run-time dynamic, or
+ - theoretically, a middle option: patchable in the firmware file itself,
+ using a dedicated tool. (OVMF does not utilize externally patchable
+ entries.)
+
+A PCD entry is declared in the DEC file of the edk2 top-level Package directory
+whose modules (drivers and libraries) are the primary consumers of the PCD
+entry. (See for example OvmfPkg/OvmfPkg.dec). Basically, a PCD in a DEC file
+exposes a simple customization point.
+
+Interest in a PCD entry is communicated to the build system by naming the PCD
+entry in the INF file of the interested module (application, driver or
+library). The module may read and -- dependent on the PCD entry's category --
+write the PCD entry.
+
+Let's investigate the characteristics of the Database and the PCD entries.
+
+- Firmware-wide: technically, all modules may access all entries they are
+ interested in, assuming they advertise their interest in their INF files.
+ With careful design, PCDs enable inter-driver propagation of (simple) system
+ configuration. PCDs are available in both PEI and DXE.
+
+ (UEFI drivers meant to be portable (ie. from third party vendors) are not
+ supposed to use PCDs, since PCDs qualify internal to the specific edk2
+ firmware in question.)
+
+- Name-value store of scalars and buffers: each PCD has a symbolic name, and a
+ fixed scalar type (UINT16, UINT32 etc), or VOID* for buffers. Each PCD entry
+ belongs to a namespace, where a namespace is (obviously) a GUID, defined in
+ the DEC file.
+
+- A DEC file can permit several categories for a PCD:
+ - build-time constant ("FixedAtBuild"),
+ - patchable in the firmware image ("PatchableInModule", unused in OVMF),
+ - runtime modifiable ("Dynamic").
+
+The platform description file (DSC) of a top-level Package directory may choose
+the exact category for a given PCD entry that its modules wish to use, and
+assign a default (or constant) initial value to it.
+
+In addition, the edk2 build system too can initialize PCD entries to values
+that it calculates while laying out the flash device image. Such PCD
+assignments are described in the FDF control file.
+
+Firmware image structure
+------------------------
+
+(We assume the common X64 choice for both PEI and DXE, and the default DEBUG
+build target.)
+
+The OvmfPkg/OvmfPkgX64.fdf file defines the following layout for the flash
+device image "OVMF.fd":
+
+ Description Compression type Size
+ ------------------------------ ---------------------- -------
+ Non-volatile data storage open-coded binary data 128 KB
+ Variable store 56 KB
+ Event log 4 KB
+ Working block 4 KB
+ Spare area 64 KB
+
+ FVMAIN_COMPACT uncompressed 1712 KB
+ FV Firmware File System file LZMA compressed
+ PEIFV uncompressed 896 KB
+ individual PEI modules uncompressed
+ DXEFV uncompressed 8192 KB
+ individual DXE modules uncompressed
+
+ SECFV uncompressed 208 KB
+ SEC driver
+ reset vector code
+
+The top-level image consists of three regions (three firmware volumes):
+- non-volatile data store (128 KB),
+- main firmware volume (FVMAIN_COMPACT, 1712 KB),
+- firmware volume containing the reset vector code and the SEC phase code (208
+ KB).
+
+In total, the OVMF.fd file has size 128 KB + 1712 KB + 208 KB == 2 MB.
+
+(1) The firmware volume with non-volatile data store (128 KB) has the following
+ internal structure, in blocks of 4 KB:
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ L: event log
+ LIVE | varstore |L|W| W: working block
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ SPARE | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The first half of this firmware volume is "live", while the second half is
+ "spare". The spare half is important when the variable driver reclaims
+ unused storage and reorganizes the variable store.
+
+ The live half dedicates 14 blocks (56 KB) to the variable store itself. On
+ top of those, one block is set aside for an event log, and one block is
+ used as the working block of the fault tolerant write protocol. Fault
+ tolerant writes are used to recover from an occasional (virtual) power loss
+ during variable updates.
+
+ The blocks in this firmware volume are accessed, in stacking order from
+ least abstract to most abstract, by:
+
+ - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL (provided by
+ OvmfPkg/QemuFlashFvbServicesRuntimeDxe),
+
+ - EFI_FAULT_TOLERANT_WRITE_PROTOCOL (provided by
+ MdeModulePkg/Universal/FaultTolerantWriteDxe),
+
+ - architectural protocols instrumental to the runtime UEFI variable
+ services:
+ - EFI_VARIABLE_ARCH_PROTOCOL,
+ - EFI_VARIABLE_WRITE_ARCH_PROTOCOL.
+
+ In a non-secure boot build, the DXE driver providing these architectural
+ protocols is MdeModulePkg/Universal/Variable/RuntimeDxe. In a secure boot
+ build, where authenticated variables are available, the DXE driver
+ offering these protocols is SecurityPkg/VariableAuthenticated/RuntimeDxe.
+
+(2) The main firmware volume (FVMAIN_COMPACT, 1712 KB) embeds further firmware
+ volumes. The outermost layer is a Firmware File System (FFS), carrying a
+ single file. This file holds an LZMA-compressed section, which embeds two
+ firmware volumes: PEIFV (896 KB) with PEIMs, and DXEFV (8192 KB) with DXE
+ and UEFI drivers.
+
+ This scheme enables us to build 896 KB worth of PEI drivers and 8192 KB
+ worth of DXE and UEFI drivers, compress them all with LZMA in one go, and
+ store the compressed result in 1712 KB, saving room in the flash device.
+
+(3) The SECFV firmware volume (208 KB) is not compressed. It carries the
+ "volume top file" with the reset vector code, to end at 4 GB in
+ guest-physical address space, and the SEC phase driver (OvmfPkg/Sec).
+
+ The last 16 bytes of the volume top file (mapped directly under 4 GB)
+ contain a NOP slide and a jump instruction. This is where QEMU starts
+ executing the firmware, at address 0xFFFF_FFF0. The reset vector and the
+ SEC driver run from flash directly.
+
+ The SEC driver locates FVMAIN_COMPACT in the flash, and decompresses the
+ main firmware image to RAM. The rest of OVMF (PEI, DXE, BDS phases) run
+ from RAM.
+
+As already mentioned, the OVMF.fd file is mapped by qemu's
+"hw/block/pflash_cfi01.c" device just under 4 GB in guest-physical address
+space, according to the command line option
+
+ -drive if=pflash,format=raw,file=fedora.flash
+
+(refer to the Example qemu invocation). This is a "ROMD device", which can
+switch out of "ROMD mode" and back into it.
+
+Namely, in the default ROMD mode, the guest-physical address range backed by
+the flash device reads and executes as ROM (it does not trap from KVM to QEMU).
+The first write access in this mode traps to QEMU, and flips the device out of
+ROMD mode.
+
+In non-ROMD mode, the flash chip is programmed by storing CFI (Common Flash
+Interface) command values at the flash-covered addresses; both reads and writes
+trap to QEMU, and the flash contents are modified and synchronized to the
+host-side file. A special CFI command flips the flash device back to ROMD mode.
+
+Qemu implements the above based on the KVM_CAP_READONLY_MEM / KVM_MEM_READONLY
+KVM features, and OVMF puts it to use in its EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
+implementation, under "OvmfPkg/QemuFlashFvbServicesRuntimeDxe".
+
+IMPORTANT: Never pass OVMF.fd to qemu with the -bios option. That option maps
+the firmware image as ROM into the guest's address space, and forces OVMF to
+emulate non-volatile variables with a fallback driver that is bound to have
+insufficient and confusing semantics.
+
+The 128 KB firmware volume with the variable store, discussed under (1), is
+also built as a separate host-side file, named "OVMF_VARS.fd". The "rest" is
+built into a third file, "OVMF_CODE.fd", which is only 1920 KB in size. The
+variable store is mapped into its usual location, at 4 GB - 2 MB = 0xFFE0_0000,
+through the following qemu options:
+
+ -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd \
+ -drive if=pflash,format=raw,file=fedora.varstore.fd
+
+This way qemu configures two flash chips consecutively, with start addresses
+growing downwards, which is transparent to OVMF.
+
+[RHEL] Red Hat Enterprise Linux 7.1 ships a Secure Boot-enabled, X64, DEBUG
+ firmware only. Furthermore, only the split files ("OVMF_VARS.fd" and
+ "OVMF_CODE.fd") are available.
+
+S3 (suspend to RAM and resume)
+------------------------------
+
+As noted in Example qemu invocation, the
+
+ -global PIIX4_PM.disable_s3=0
+
+command line option tells qemu and OVMF if the user would like to enable S3
+support. (This is corresponds to the /domain/pm/suspend-to-mem/@enabled libvirt
+domain XML attribute.)
+
+Implementing / orchestrating S3 was a considerable community effort in OVMF. A
+detailed description exceeds the scope of this report; we only make a few
+statements.
+
+(1) S3-related PPIs and protocols are well documented in the PI specification.
+
+(2) Edk2 contains most modules that are needed to implement S3 on a given
+ platform. One abstraction that is central to the porting / extending of the
+ S3-related modules to a new platform is the LockBox library interface,
+ which a specific platform can fill in by implementing its own LockBox
+ library instance.
+
+ The LockBox library provides a privileged name-value store (to be addressed
+ by GUIDs). The privilege separation stretches between the firmware and the
+ operating system. That is, the S3-related machinery of the firmware saves
+ some items in the LockBox securely, under well-known GUIDs, before booting
+ the operating system. During resume (which is a form of warm reset), the
+ firmware is activated again, and retrieves items from the LockBox. Before
+ jumping to the OS's resume vector, the LockBox is secured again.
+
+ We'll return to this later when we separately discuss SMRAM and SMM.
+
+(3) During resume, the DXE and later phases are never reached; only the reset
+ vector, and the SEC and PEI phases of the firmware run. The platform is
+ supposed to detect a resume in progress during PEI, and to store that fact
+ in the BootMode field of the Phase Handoff Information Table (PHIT) HOB.
+ OVMF keys this off the CMOS, see OvmfPkg/PlatformPei.
+
+ At the end of PEI, the DXE IPL PEIM (Initial Program Load PEI Module, see
+ MdeModulePkg/Core/DxeIplPeim) examines the Boot Mode, and if it says "S3
+ resume in progress", then the IPL branches to the PEIM that exports
+ EFI_PEI_S3_RESUME2_PPI (provided by UefiCpuPkg/Universal/Acpi/S3Resume2Pei)
+ rather than loading the DXE core.
+
+ S3Resume2Pei executes the technical steps of the resumption, relying on the
+ contents of the LockBox.
+
+(4) During first boot (or after a normal platform reset), when DXE does run,
+ hardware drivers in the DXE phase are encouraged to "stash" their hardware
+ configuration steps (eg. accesses to PCI config space, I/O ports, memory
+ mapped addresses, and so on) in a centrally maintained, so called "S3 boot
+ script". Hardware accesses are represented with opcodes of a special binary
+ script language.
+
+ This boot script is to be replayed during resume, by S3Resume2Pei. The
+ general goal is to bring back hardware devices -- which have been powered
+ off during suspend -- to their original after-first-boot state, and in
+ particular, to do so quickly.
+
+ At the moment, OVMF saves only one opcode in the S3 resume boot script: an
+ INFORMATION opcode, with contents 0xDEADBEEF (in network byte order). The
+ consensus between Linux developers seems to be that boot firmware is only
+ responsible for restoring basic chipset state, which OVMF does during PEI
+ anyway, independently of S3 vs. normal reset. (One example is the power
+ management registers of the i440fx chipset.) Device and peripheral state is
+ the responsibility of the runtime operating system.
+
+ Although an experimental OVMF S3 boot script was at one point captured for
+ the virtual Cirrus VGA card, such a boot script cannot follow eg. video
+ mode changes effected by the OS. Hence the operating system can never avoid
+ restoring device state, and most Linux display drivers (eg. stdvga, QXL)
+ already cover S3 resume fully.
+
+ The XDDM and WDDM driver models used under Windows OSes seem to recognize
+ this notion of runtime OS responsibility as well. (See the list of OSes
+ supported by OVMF in a separate section.)
+
+(5) The S3 suspend/resume data flow in OVMF is included here tersely, for
+ interested developers.
+
+ (a) BdsLibBootViaBootOption()
+ EFI_ACPI_S3_SAVE_PROTOCOL [AcpiS3SaveDxe]
+ - saves ACPI S3 Context to LockBox ---------------------+
+ (including FACS address -- FACS ACPI table |
+ contains OS waking vector) |
+ |
+ - prepares boot script: |
+ EFI_S3_SAVE_STATE_PROTOCOL.Write() [S3SaveStateDxe] |
+ S3BootScriptLib [PiDxeS3BootScriptLib] |
+ - opcodes & arguments are saved in NVS. --+ |
+ | |
+ - issues a notification by installing | |
+ EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL | |
+ | |
+ (b) EFI_S3_SAVE_STATE_PROTOCOL [S3SaveStateDxe] | |
+ S3BootScriptLib [PiDxeS3BootScriptLib] | |
+ - closes script with special opcode <---------+ |
+ - script is available in non-volatile memory |
+ via PcdS3BootScriptTablePrivateDataPtr --+ |
+ | |
+ BootScriptExecutorDxe | |
+ S3BootScriptLib [PiDxeS3BootScriptLib] | |
+ - Knows about boot script location by <----+ |
+ synchronizing with the other library |
+ instance via |
+ PcdS3BootScriptTablePrivateDataPtr. |
+ - Copies relocated image of itself to |
+ reserved memory. --------------------------------+ |
+ - Saved image contains pointer to boot script. ---|--+ |
+ | | |
+ Runtime: | | |
+ | | |
+ (c) OS is booted, writes OS waking vector to FACS, | | |
+ suspends machine | | |
+ | | |
+ S3 Resume (PEI): | | |
+ | | |
+ (d) PlatformPei sets S3 Boot Mode based on CMOS | | |
+ | | |
+ (e) DXE core is skipped and EFI_PEI_S3_RESUME2 is | | |
+ called as last step of PEI | | |
+ | | |
+ (f) S3Resume2Pei retrieves from LockBox: | | |
+ - ACPI S3 Context (path to FACS) <------------------|--|--+
+ | | |
+ +------------------|--|--+
+ - Boot Script Executor Image <----------------------+ | |
+ | |
+ (g) BootScriptExecutorDxe | |
+ S3BootScriptLib [PiDxeS3BootScriptLib] | |
+ - executes boot script <-----------------------------+ |
+ |
+ (h) OS waking vector available from ACPI S3 Context / FACS <--+
+ is called
+
+A comprehensive memory map of OVMF
+----------------------------------
+
+The following section gives a detailed analysis of memory ranges below 4 GB
+that OVMF statically uses.
+
+In the rightmost column, the PCD entry is identified by which the source refers
+to the address or size in question.
+
+The flash-covered range has been discussed previously in "Firmware image
+structure", therefore we include it only for completeness. Due to the fact that
+this range is always backed by a memory mapped device (and never RAM), it is
+unaffected by S3 (suspend to RAM and resume).
+
++--------------------------+ 4194304 KB
+| |
+| SECFV | size: 208 KB
+| |
++--------------------------+ 4194096 KB
+| |
+| FVMAIN_COMPACT | size: 1712 KB
+| |
++--------------------------+ 4192384 KB
+| |
+| variable store | size: 64 KB PcdFlashNvStorageFtwSpareSize
+| spare area |
+| |
++--------------------------+ 4192320 KB PcdOvmfFlashNvStorageFtwSpareBase
+| |
+| FTW working block | size: 4 KB PcdFlashNvStorageFtwWorkingSize
+| |
++--------------------------+ 4192316 KB PcdOvmfFlashNvStorageFtwWorkingBase
+| |
+| Event log of | size: 4 KB PcdOvmfFlashNvStorageEventLogSize
+| non-volatile storage |
+| |
++--------------------------+ 4192312 KB PcdOvmfFlashNvStorageEventLogBase
+| |
+| variable store | size: 56 KB PcdFlashNvStorageVariableSize
+| |
++--------------------------+ 4192256 KB PcdOvmfFlashNvStorageVariableBase
+
+The flash-mapped image of OVMF.fd covers the entire structure above (2048 KB).
+
+When using the split files, the address 4192384 KB
+(PcdOvmfFlashNvStorageFtwSpareBase + PcdFlashNvStorageFtwSpareSize) is the
+boundary between the mapped images of OVMF_VARS.fd (56 KB + 4 KB + 4 KB + 64 KB
+= 128 KB) and OVMF_CODE.fd (1712 KB + 208 KB = 1920 KB).
+
+With regard to RAM that is statically used by OVMF, S3 (suspend to RAM and
+resume) complicates matters. Many ranges have been introduced only to support
+S3, hence for all ranges below, the following questions will be audited:
+
+(a) when and how a given range is initialized after first boot of the VM,
+(b) how it is protected from memory allocations during DXE,
+(c) how it is protected from the OS,
+(d) how it is accessed on the S3 resume path,
+(e) how it is accessed on the warm reset path.
+
+Importantly, the term "protected" is meant as protection against inadvertent
+reallocations and overwrites by co-operating DXE and OS modules. It does not
+imply security against malicious code.
+
++--------------------------+ 17408 KB
+| |
+|DXEFV from FVMAIN_COMPACT | size: 8192 KB PcdOvmfDxeMemFvSize
+| decompressed firmware |
+| volume with DXE modules |
+| |
++--------------------------+ 9216 KB PcdOvmfDxeMemFvBase
+| |
+|PEIFV from FVMAIN_COMPACT | size: 896 KB PcdOvmfPeiMemFvSize
+| decompressed firmware |
+| volume with PEI modules |
+| |
++--------------------------+ 8320 KB PcdOvmfPeiMemFvBase
+| |
+| permanent PEI memory for | size: 32 KB PcdS3AcpiReservedMemorySize
+| the S3 resume path |
+| |
++--------------------------+ 8288 KB PcdS3AcpiReservedMemoryBase
+| |
+| temporary SEC/PEI heap | size: 32 KB PcdOvmfSecPeiTempRamSize
+| and stack |
+| |
++--------------------------+ 8256 KB PcdOvmfSecPeiTempRamBase
+| |
+| unused | size: 32 KB
+| |
++--------------------------+ 8224 KB
+| |
+| SEC's table of | size: 4 KB PcdGuidedExtractHandlerTableSize
+| GUIDed section handlers |
+| |
++--------------------------+ 8220 KB PcdGuidedExtractHandlerTableAddress
+| |
+| LockBox storage | size: 4 KB PcdOvmfLockBoxStorageSize
+| |
++--------------------------+ 8216 KB PcdOvmfLockBoxStorageBase
+| |
+| early page tables on X64 | size: 24 KB PcdOvmfSecPageTablesSize
+| |
++--------------------------+ 8192 KB PcdOvmfSecPageTablesBase
+
+(1) Early page tables on X64:
+
+ (a) when and how it is initialized after first boot of the VM
+
+ The range is filled in during the SEC phase
+ [OvmfPkg/ResetVector/Ia32/PageTables64.asm]. The CR3 register is verified
+ against the base address in SecCoreStartupWithStack()
+ [OvmfPkg/Sec/SecMain.c].
+
+ (b) how it is protected from memory allocations during DXE
+
+ If S3 was enabled on the QEMU command line (see "-global
+ PIIX4_PM.disable_s3=0" earlier), then InitializeRamRegions()
+ [OvmfPkg/PlatformPei/MemDetect.c] protects the range with an AcpiNVS memory
+ allocation HOB, in PEI.
+
+ If S3 was disabled, then this range is not protected. DXE's own page tables
+ are first built while still in PEI (see HandOffToDxeCore()
+ [MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c]). Those tables are located
+ in permanent PEI memory. After CR3 is switched over to them (which occurs
+ before jumping to the DXE core entry point), we don't have to preserve the
+ initial tables.
+
+ (c) how it is protected from the OS
+
+ If S3 is enabled, then (1b) reserves it from the OS too.
+
+ If S3 is disabled, then the range needs no protection.
+
+ (d) how it is accessed on the S3 resume path
+
+ It is rewritten same as in (1a), which is fine because (1c) reserved it.
+
+ (e) how it is accessed on the warm reset path
+
+ It is rewritten same as in (1a).
+
+(2) LockBox storage:
+
+ (a) when and how it is initialized after first boot of the VM
+
+ InitializeRamRegions() [OvmfPkg/PlatformPei/MemDetect.c] zeroes out the
+ area during PEI. This is correct but not strictly necessary, since on first
+ boot the area is zero-filled anyway.
+
+ The LockBox signature of the area is filled in by the PEI module or DXE
+ driver that has been linked against OVMF's LockBoxLib and is run first. The
+ signature is written in LockBoxLibInitialize()
+ [OvmfPkg/Library/LockBoxLib/LockBoxLib.c].
+
+ Any module calling SaveLockBox() [OvmfPkg/Library/LockBoxLib/LockBoxLib.c]
+ will co-populate this area.
+
+ (b) how it is protected from memory allocations during DXE
+
+ If S3 is enabled, then InitializeRamRegions()
+ [OvmfPkg/PlatformPei/MemDetect.c] protects the range as AcpiNVS.
+
+ Otherwise, the range is covered with a BootServicesData memory allocation
+ HOB.
+
+ (c) how it is protected from the OS
+
+ If S3 is enabled, then (2b) protects it sufficiently.
+
+ Otherwise the range requires no runtime protection, and the
+ BootServicesData allocation type from (2b) ensures that the range will be
+ released to the OS.
+
+ (d) how it is accessed on the S3 resume path
+
+ The S3 Resume PEIM restores data from the LockBox, which has been correctly
+ protected in (2c).
+
+ (e) how it is accessed on the warm reset path
+
+ InitializeRamRegions() [OvmfPkg/PlatformPei/MemDetect.c] zeroes out the
+ range during PEI, effectively emptying the LockBox. Modules will
+ re-populate the LockBox as described in (2a).
+
+(3) SEC's table of GUIDed section handlers
+
+ (a) when and how it is initialized after first boot of the VM
+
+ The following two library instances are linked into SecMain:
+ - IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib,
+ - MdePkg/Library/BaseExtractGuidedSectionLib.
+
+ The first library registers its LZMA decompressor plugin (which is a called
+ a "section handler") by calling the second library:
+
+ LzmaDecompressLibConstructor() [GuidedSectionExtraction.c]
+ ExtractGuidedSectionRegisterHandlers() [BaseExtractGuidedSectionLib.c]
+
+ The second library maintains its table of registered "section handlers", to
+ be indexed by GUID, in this fixed memory area, independently of S3
+ enablement.
+
+ (The decompression of FVMAIN_COMPACT's FFS file section that contains the
+ PEIFV and DXEFV firmware volumes occurs with the LZMA decompressor
+ registered above. See (6) and (7) below.)
+
+ (b) how it is protected from memory allocations during DXE
+
+ There is no need to protect this area from DXE: because nothing else in
+ OVMF links against BaseExtractGuidedSectionLib, the area loses its
+ significance as soon as OVMF progresses from SEC to PEI, therefore DXE is
+ allowed to overwrite the region.
+
+ (c) how it is protected from the OS
+
+ When S3 is enabled, we cover the range with an AcpiNVS memory allocation
+ HOB in InitializeRamRegions().
+
+ When S3 is disabled, the range is not protected.
+
+ (d) how it is accessed on the S3 resume path
+
+ The table of registered section handlers is again managed by
+ BaseExtractGuidedSectionLib linked into SecMain exclusively. Section
+ handler registrations update the table in-place (based on GUID matches).
+
+ (e) how it is accessed on the warm reset path
+
+ If S3 is enabled, then the OS won't damage the table (due to (3c)), thus
+ see (3d).
+
+ If S3 is disabled, then the OS has most probably overwritten the range with
+ its own data, hence (3a) -- complete reinitialization -- will come into
+ effect, based on the table signature check in BaseExtractGuidedSectionLib.
+
+(4) temporary SEC/PEI heap and stack
+
+ (a) when and how it is initialized after first boot of the VM
+
+ The range is configured in [OvmfPkg/Sec/X64/SecEntry.S] and
+ SecCoreStartupWithStack() [OvmfPkg/Sec/SecMain.c]. The stack half is read &
+ written by the CPU transparently. The heap half is used for memory
+ allocations during PEI.
+
+ Data is migrated out (to permanent PEI stack & memory) in (or soon after)
+ PublishPeiMemory() [OvmfPkg/PlatformPei/MemDetect.c].
+
+ (b) how it is protected from memory allocations during DXE
+
+ It is not necessary to protect this range during DXE because its use ends
+ still in PEI.
+
+ (c) how it is protected from the OS
+
+ If S3 is enabled, then InitializeRamRegions()
+ [OvmfPkg/PlatformPei/MemDetect.c] reserves it as AcpiNVS.
+
+ If S3 is disabled, then the range doesn't require protection.
+
+ (d) how it is accessed on the S3 resume path
+
+ Same as in (4a), except the target area of the migration triggered by
+ PublishPeiMemory() [OvmfPkg/PlatformPei/MemDetect.c] is different -- see
+ (5).
+
+ (e) how it is accessed on the warm reset path
+
+ Same as in (4a). The stack and heap halves both may contain garbage, but it
+ doesn't matter.
+
+(5) permanent PEI memory for the S3 resume path
+
+ (a) when and how it is initialized after first boot of the VM
+
+ No particular initialization or use.
+
+ (b) how it is protected from memory allocations during DXE
+
+ We don't need to protect this area during DXE.
+
+ (c) how it is protected from the OS
+
+ When S3 is enabled, InitializeRamRegions()
+ [OvmfPkg/PlatformPei/MemDetect.c] makes sure the OS stays away by covering
+ the range with an AcpiNVS memory allocation HOB.
+
+ When S3 is disabled, the range needs no protection.
+
+ (d) how it is accessed on the S3 resume path
+
+ PublishPeiMemory() installs the range as permanent RAM for PEI. The range
+ will serve as stack and will satisfy allocation requests during the rest of
+ PEI. OS data won't overlap due to (5c).
+
+ (e) how it is accessed on the warm reset path
+
+ Same as (5a).
+
+(6) PEIFV -- decompressed firmware volume with PEI modules
+
+ (a) when and how it is initialized after first boot of the VM
+
+ DecompressMemFvs() [OvmfPkg/Sec/SecMain.c] populates the area, by
+ decompressing the flash-mapped FVMAIN_COMPACT volume's contents. (Refer to
+ "Firmware image structure".)
+
+ (b) how it is protected from memory allocations during DXE
+
+ When S3 is disabled, PeiFvInitialization() [OvmfPkg/PlatformPei/Fv.c]
+ covers the range with a BootServicesData memory allocation HOB.
+
+ When S3 is enabled, the same is coverage is ensured, just with the stronger
+ AcpiNVS memory allocation type.
+
+ (c) how it is protected from the OS
+
+ When S3 is disabled, it is not necessary to keep the range from the OS.
+
+ Otherwise the AcpiNVS type allocation from (6b) provides coverage.
+
+ (d) how it is accessed on the S3 resume path
+
+ Rather than decompressing it again from FVMAIN_COMPACT, GetS3ResumePeiFv()
+ [OvmfPkg/Sec/SecMain.c] reuses the protected area for parsing / execution
+ from (6c).
+
+ (e) how it is accessed on the warm reset path
+
+ Same as (6a).
+
+(7) DXEFV -- decompressed firmware volume with DXE modules
+
+ (a) when and how it is initialized after first boot of the VM
+
+ Same as (6a).
+
+ (b) how it is protected from memory allocations during DXE
+
+ PeiFvInitialization() [OvmfPkg/PlatformPei/Fv.c] covers the range with a
+ BootServicesData memory allocation HOB.
+
+ (c) how it is protected from the OS
+
+ The OS is allowed to release and reuse this range.
+
+ (d) how it is accessed on the S3 resume path
+
+ It's not; DXE never runs during S3 resume.
+
+ (e) how it is accessed on the warm reset path
+
+ Same as in (7a).
+
+Known Secure Boot limitations
+-----------------------------
+
+Under "Motivation" we've mentioned that OVMF's Secure Boot implementation is
+not suitable for production use yet -- it's only good for development and
+testing of standards-conformant, non-malicious guest code (UEFI and operating
+system alike).
+
+Now that we've examined the persistent flash device, the workings of S3, and
+the memory map, we can discuss two currently known shortcomings of OVMF's
+Secure Boot that in fact make it insecure. (Clearly problems other than these
+two might exist; the set of issues considered here is not meant to be
+exhaustive.)
+
+One trait of Secure Boot is tamper-evidence. Secure Boot may not prevent
+malicious modification of software components (for example, operating system
+drivers), but by being the root of integrity on a platform, it can catch (or
+indirectly contribute to catching) unauthorized changes, by way of signature
+and certificate checks at the earliest phases of boot.
+
+If an attacker can tamper with key material stored in authenticated and/or
+boot-time only persistent variables (for example, PK, KEK, db, dbt, dbx), then
+the intended security of this scheme is compromised. The UEFI 2.4A
+specification says
+
+- in section 28.3.4:
+
+ Platform Keys:
+
+ The public key must be stored in non-volatile storage which is tamper and
+ delete resistant.
+
+ Key Exchange Keys:
+
+ The public key must be stored in non-volatile storage which is tamper
+ resistant.
+
+- in section 28.6.1:
+
+ The signature database variables db, dbt, and dbx must be stored in
+ tamper-resistant non-volatile storage.
+
+(1) The combination of QEMU, KVM, and OVMF does not provide this kind of
+ resistance. The variable store in the emulated flash chip is directly
+ accessible to, and reprogrammable by, UEFI drivers, applications, and
+ operating systems.
+
+(2) Under "S3 (suspend to RAM and resume)" we pointed out that the LockBox
+ storage must be similarly secure and tamper-resistant.
+
+ On the S3 resume path, the PEIM providing EFI_PEI_S3_RESUME2_PPI
+ (UefiCpuPkg/Universal/Acpi/S3Resume2Pei) restores and interprets data from
+ the LockBox that has been saved there during boot. This PEIM, being part of
+ the firmware, has full access to the platform. If an operating system can
+ tamper with the contents of the LockBox, then at the next resume the
+ platform's integrity might be subverted.
+
+ OVMF stores the LockBox in normal guest RAM (refer to the memory map
+ section above). Operating systems and third party UEFI drivers and UEFI
+ applications that respect the UEFI memory map will not inadvertently
+ overwrite the LockBox storage, but there's nothing to prevent eg. a
+ malicious kernel from modifying the LockBox.
+
+One means to address these issues is SMM and SMRAM (System Management Mode and
+System Management RAM).
+
+During boot and resume, the firmware can enter and leave SMM and access SMRAM.
+Before the DXE phase is left, and control is transferred to the BDS phase (when
+third party UEFI drivers and applications can be loaded, and an operating
+system can be loaded), SMRAM is locked in hardware, and subsequent modules
+cannot access it directly. (See EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL.)
+
+Once SMRAM has been locked, UEFI drivers and the operating system can enter SMM
+by raising a System Management Interrupt (SMI), at which point trusted code
+(part of the platform firmware) takes control. SMRAM is also unlocked by
+platform reset, at which point the boot firmware takes control again.
+
+Variable store and LockBox in SMRAM
+-----------------------------------
+
+Edk2 provides almost all components to implement the variable store and the
+LockBox in SMRAM. In this section we summarize ideas for utilizing those
+facilities.
+
+The SMRAM and SMM infrastructure in edk2 is built up as follows:
+
+(1) The platform hardware provides SMM / SMI / SMRAM.
+
+ Qemu/KVM doesn't support these features currently and should implement them
+ in the longer term.
+
+(2) The platform vendor (in this case, OVMF developers) implement device
+ drivers for the platform's System Management Mode:
+
+ - EFI_SMM_CONTROL2_PROTOCOL: for raising a synchronous (and/or) periodic
+ SMI(s); that is, for entering SMM.
+
+ - EFI_SMM_ACCESS2_PROTOCOL: for describing and accessing SMRAM.
+
+ These protocols are documented in the PI Specification, Volume 4.
+
+(3) The platform DSC file is to include the following platform-independent
+ modules:
+
+ - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf: SMM Initial Program Load
+ - MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf: SMM Core
+
+(4) At this point, modules of type DXE_SMM_DRIVER can be loaded.
+
+ Such drivers are privileged. They run in SMM, have access to SMRAM, and are
+ separated and switched from other drivers through SMIs. Secure
+ communication between unprivileged (non-SMM) and privileged (SMM) drivers
+ happens through EFI_SMM_COMMUNICATION_PROTOCOL (implemented by the SMM
+ Core, see (3)).
+
+ DXE_SMM_DRIVER modules must sanitize their input (coming from unprivileged
+ drivers) carefully.
+
+(5) The authenticated runtime variable services driver (for Secure Boot builds)
+ is located under "SecurityPkg/VariableAuthenticated/RuntimeDxe". OVMF
+ currently builds the driver (a DXE_RUNTIME_DRIVER module) with the
+ "VariableRuntimeDxe.inf" control file (refer to "OvmfPkg/OvmfPkgX64.dsc"),
+ which does not use SMM.
+
+ The directory includes two more INF files:
+
+ - VariableSmm.inf -- module type: DXE_SMM_DRIVER. A privileged driver that
+ runs in SMM and has access to SMRAM.
+
+ - VariableSmmRuntimeDxe.inf -- module type: DXE_RUNTIME_DRIVER. A
+ non-privileged driver that implements the variable runtime services
+ (replacing the current "VariableRuntimeDxe.inf" file) by communicating
+ with the above privileged SMM half via EFI_SMM_COMMUNICATION_PROTOCOL.
+
+(6) An SMRAM-based LockBox implementation needs to be discussed in two parts,
+ because the LockBox is accessed in both PEI and DXE.
+
+ (a) During DXE, drivers save data in the LockBox. A save operation is
+ layered as follows:
+
+ - The unprivileged driver wishing to store data in the LockBox links
+ against the "MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf"
+ library instance.
+
+ The library allows the unprivileged driver to format requests for the
+ privileged SMM LockBox driver (see below), and to parse responses.
+
+ - The privileged SMM LockBox driver is built from
+ "MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf". This
+ driver has module type DXE_SMM_DRIVER and can access SMRAM.
+
+ The driver delegates command parsing and response formatting to
+ "MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf".
+
+ - The above two halves (unprivileged and privileged) mirror what we've
+ seen in case of the variable service drivers, under (5).
+
+ (b) In PEI, the S3 Resume PEIM (UefiCpuPkg/Universal/Acpi/S3Resume2Pei)
+ retrieves data from the LockBox.
+
+ Presumably, S3Resume2Pei should be considered an "unprivileged PEIM",
+ and the SMRAM access should be layered as seen in DXE. Unfortunately,
+ edk2 does not implement all of the layers in PEI -- the code either
+ doesn't exist, or it is not open source:
+
+ role | DXE: protocol/module | PEI: PPI/module
+ -------------+--------------------------------+------------------------------
+ unprivileged | any | S3Resume2Pei.inf
+ driver | |
+ -------------+--------------------------------+------------------------------
+ command | LIBRARY_CLASS = LockBoxLib | LIBRARY_CLASS = LockBoxLib
+ formatting | |
+ and response | SmmLockBoxDxeLib.inf | SmmLockBoxPeiLib.inf
+ parsing | |
+ -------------+--------------------------------+------------------------------
+ privilege | EFI_SMM_COMMUNICATION_PROTOCOL | EFI_PEI_SMM_COMMUNICATION_PPI
+ separation | |
+ | PiSmmCore.inf | missing!
+ -------------+--------------------------------+------------------------------
+ platform SMM | EFI_SMM_CONTROL2_PROTOCOL | PEI_SMM_CONTROL_PPI
+ and SMRAM | EFI_SMM_ACCESS2_PROTOCOL | PEI_SMM_ACCESS_PPI
+ access | |
+ | to be done in OVMF | to be done in OVMF
+ -------------+--------------------------------+------------------------------
+ command | LIBRARY_CLASS = LockBoxLib | LIBRARY_CLASS = LockBoxLib
+ parsing and | |
+ response | SmmLockBoxSmmLib.inf | missing!
+ formatting | |
+ -------------+--------------------------------+------------------------------
+ privileged | SmmLockBox.inf | missing!
+ LockBox | |
+ driver | |
+
+ Alternatively, in the future OVMF might be able to provide a LockBoxLib
+ instance (an SmmLockBoxPeiLib substitute) for S3Resume2Pei that
+ accesses SMRAM directly, eliminating the need for deeper layers in the
+ stack (that is, EFI_PEI_SMM_COMMUNICATION_PPI and deeper).
+
+ In fact, a "thin" EFI_PEI_SMM_COMMUNICATION_PPI implementation whose
+ sole Communicate() member invariably returns EFI_NOT_STARTED would
+ cause the current SmmLockBoxPeiLib library instance to directly perform
+ full-depth SMRAM access and LockBox search, obviating the "missing"
+ cells. (With reference to A Tour Beyond BIOS: Implementing S3 Resume
+ with EDK2, by Jiewen Yao and Vincent Zimmer, October 2014.)
+
+Select features
+---------------
+
+In this section we'll browse the top-level "OvmfPkg" package directory, and
+discuss the more interesting drivers and libraries that have not been mentioned
+thus far.
+
+X64-specific reset vector for OVMF
+..................................
+
+The "OvmfPkg/ResetVector" directory customizes the reset vector (found in
+"UefiCpuPkg/ResetVector/Vtf0") for "OvmfPkgX64.fdf", that is, when the SEC/PEI
+phases run in 64-bit (ie. long) mode.
+
+The reset vector's control flow looks roughly like:
+
+ resetVector [Ia16/ResetVectorVtf0.asm]
+ EarlyBspInitReal16 [Ia16/Init16.asm]
+ Main16 [Main.asm]
+ EarlyInit16 [Ia16/Init16.asm]
+
+ ; Transition the processor from
+ ; 16-bit real mode to 32-bit flat mode
+ TransitionFromReal16To32BitFlat [Ia16/Real16ToFlat32.asm]
+
+ ; Search for the
+ ; Boot Firmware Volume (BFV)
+ Flat32SearchForBfvBase [Ia32/SearchForBfvBase.asm]
+
+ ; Search for the SEC entry point
+ Flat32SearchForSecEntryPoint [Ia32/SearchForSecEntry.asm]
+
+ %ifdef ARCH_IA32
+ ; Jump to the 32-bit SEC entry point
+ %else
+ ; Transition the processor
+ ; from 32-bit flat mode
+ ; to 64-bit flat mode
+ Transition32FlatTo64Flat [Ia32/Flat32ToFlat64.asm]
+
+ SetCr3ForPageTables64 [Ia32/PageTables64.asm]
+ ; set CR3 to page tables
+ ; built into the ROM image
+
+ ; enable PAE
+ ; set LME
+ ; enable paging
+
+ ; Jump to the 64-bit SEC entry point
+ %endif
+
+On physical platforms, the initial page tables referenced by
+SetCr3ForPageTables64 are built statically into the flash device image, and are
+present in ROM at runtime. This is fine on physical platforms because the
+pre-built page table entries have the Accessed and Dirty bits set from the
+start.
+
+Accordingly, for OVMF running in long mode on qemu/KVM, the initial page tables
+were mapped as a KVM_MEM_READONLY slot, as part of QEMU's pflash device (refer
+to "Firmware image structure" above).
+
+In spite of the Accessed and Dirty bits being pre-set in the read-only,
+in-flash PTEs, in a virtual machine attempts are made to update said PTE bits,
+differently from physical hardware. The component attempting to update the
+read-only PTEs can be one of the following:
+
+- The processor itself, if it supports nested paging, and the user enables that
+ processor feature,
+
+- KVM code implementing shadow paging, otherwise.
+
+The first case presents no user-visible symptoms, but the second case (KVM,
+shadow paging) used to cause a triple fault, prior to Linux commit ba6a354
+("KVM: mmu: allow page tables to be in read-only slots").
+
+For compatibility with earlier KVM versions, the OvmfPkg/ResetVector directory
+adapts the generic reset vector code as follows:
+
+ Transition32FlatTo64Flat [UefiCpuPkg/.../Ia32/Flat32ToFlat64.asm]
+
+ SetCr3ForPageTables64 [OvmfPkg/ResetVector/Ia32/PageTables64.asm]
+
+ ; dynamically build the initial page tables in RAM, at address
+ ; PcdOvmfSecPageTablesBase (refer to the memory map above),
+ ; identity-mapping the first 4 GB of address space
+
+ ; set CR3 to PcdOvmfSecPageTablesBase
+
+ ; enable PAE
+ ; set LME
+ ; enable paging
+
+This way the PTEs that earlier KVM versions try to update (during shadow
+paging) are located in a read-write memory slot, and the write attempts
+succeed.
+
+Client library for QEMU's firmware configuration interface
+..........................................................
+
+QEMU provides a write-only, 16-bit wide control port, and a read-write, 8-bit
+wide data port for exchanging configuration elements with the firmware.
+
+The firmware writes a selector (a key) to the control port (0x510), and then
+reads the corresponding configuration data (produced by QEMU) from the data
+port (0x511).
+
+If the selected entry is writable, the firmware may overwrite it. If QEMU has
+associated a callback with the entry, then when the entry is completely
+rewritten, QEMU runs the callback. (OVMF does not rewrite any entries at the
+moment.)
+
+A number of selector values (keys) are predefined. In particular, key 0x19
+selects (returns) a directory of { name, selector, size } triplets, roughly
+speaking.
+
+The firmware can request configuration elements by well-known name as well, by
+looking up the selector value first in the directory, by name, and then writing
+the selector to the control port. The number of bytes to read subsequently from
+the data port is known from the directory entry's "size" field.
+
+By convention, directory entries (well-known symbolic names of configuration
+elements) are formatted as POSIX pathnames. For example, the array selected by
+the "etc/system-states" name indicates (among other things) whether the user
+enabled S3 support in QEMU.
+
+The above interface is called "fw_cfg".
+
+The binary data associated with a symbolic name is called an "fw_cfg file".
+
+OVMF's fw_cfg client library is found in "OvmfPkg/Library/QemuFwCfgLib". OVMF
+discovers many aspects of the virtual system with it; we refer to a few
+examples below.
+
+Guest ACPI tables
+.................
+
+An operating system discovers a good amount of its hardware by parsing ACPI
+tables, and by interpreting ACPI objects and methods. On physical hardware, the
+platform vendor's firmware installs ACPI tables in memory that match both the
+hardware present in the system and the user's firmware configuration ("BIOS
+setup").
+
+Under qemu/KVM, the owner of the (virtual) hardware configuration is QEMU.
+Hardware can easily be reconfigured on the command line. Furthermore, features
+like CPU hotplug, PCI hotplug, memory hotplug are continuously developed for
+QEMU, and operating systems need direct ACPI support to exploit these features.
+
+For this reason, QEMU builds its own ACPI tables dynamically, in a
+self-descriptive manner, and exports them to the firmware through a complex,
+multi-file fw_cfg interface. It is rooted in the "etc/table-loader" fw_cfg
+file. (Further details of this interface are out of scope for this report.)
+
+OVMF's AcpiPlatformDxe driver fetches the ACPI tables, and installs them for
+the guest OS with the EFI_ACPI_TABLE_PROTOCOL (which is in turn provided by the
+generic "MdeModulePkg/Universal/Acpi/AcpiTableDxe" driver).
+
+For earlier QEMU versions and machine types (which we generally don't recommend
+for OVMF; see "Scope"), the "OvmfPkg/AcpiTables" directory contains a few
+static ACPI table templates. When the "etc/table-loader" fw_cfg file is
+unavailable, AcpiPlatformDxe installs these default tables (with a little bit
+of dynamic patching).
+
+When OVMF runs in a Xen domU, AcpiTableDxe also installs ACPI tables that
+originate from the hypervisor's environment.
+
+Guest SMBIOS tables
+...................
+
+Quoting the SMBIOS Reference Specification,
+
+ [...] the System Management BIOS Reference Specification addresses how
+ motherboard and system vendors present management information about their
+ products in a standard format [...]
+
+In practice SMBIOS tables are just another set of tables that the platform
+vendor's firmware installs in RAM for the operating system, and, importantly,
+for management applications running on the OS. Without rehashing the "Guest
+ACPI tables" section in full, let's map the OVMF roles seen there from ACPI to
+SMBIOS:
+
+ role | ACPI | SMBIOS
+ -------------------------+-------------------------+-------------------------
+ fw_cfg file | etc/table-loader | etc/smbios/smbios-tables
+ -------------------------+-------------------------+-------------------------
+ OVMF driver | AcpiPlatformDxe | SmbiosPlatformDxe
+ under "OvmfPkg" | |
+ -------------------------+-------------------------+-------------------------
+ Underlying protocol, | EFI_ACPI_TABLE_PROTOCOL | EFI_SMBIOS_PROTOCOL
+ implemented by generic | |
+ driver under | Acpi/AcpiTableDxe | SmbiosDxe
+ "MdeModulePkg/Universal" | |
+ -------------------------+-------------------------+-------------------------
+ default tables available | yes | [RHEL] yes, Type0 and
+ for earlier QEMU machine | | Type1 tables
+ types, with hot-patching | |
+ -------------------------+-------------------------+-------------------------
+ tables fetched in Xen | yes | yes
+ domUs | |
+
+Platform-specific boot policy
+.............................
+
+OVMF's BDS (Boot Device Selection) phase is implemented by
+IntelFrameworkModulePkg/Universal/BdsDxe. Roughly speaking, this large driver:
+
+- provides the EFI BDS architectural protocol (which DXE transfers control to
+ after dispatching all DXE drivers),
+
+- connects drivers to devices,
+
+- enumerates boot devices,
+
+- auto-generates boot options,
+
+- provides "BIOS setup" screens, such as:
+
+ - Boot Manager, for booting an option,
+
+ - Boot Maintenance Manager, for adding, deleting, and reordering boot
+ options, changing console properties etc,
+
+ - Device Manager, where devices can register configuration forms, including
+
+ - Secure Boot configuration forms,
+
+ - OVMF's Platform Driver form (see under PlatformDxe).
+
+Firmware that includes the "IntelFrameworkModulePkg/Universal/BdsDxe" driver
+can customize its behavior by providing an instance of the PlatformBdsLib
+library class. The driver links against this platform library, and the
+platform library can call Intel's BDS utility functions from
+"IntelFrameworkModulePkg/Library/GenericBdsLib".
+
+OVMF's PlatformBdsLib instance can be found in
+"OvmfPkg/Library/PlatformBdsLib". The main function where the BdsDxe driver
+enters the library is PlatformBdsPolicyBehavior(). We mention two OVMF
+particulars here.
+
+(1) OVMF is capable of loading kernel images directly from fw_cfg, matching
+ QEMU's -kernel, -initrd, and -append command line options. This feature is
+ useful for rapid, repeated Linux kernel testing, and is implemented in the
+ following call tree:
+
+ PlatformBdsPolicyBehavior() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
+ TryRunningQemuKernel() [OvmfPkg/Library/PlatformBdsLib/QemuKernel.c]
+ LoadLinux*() [OvmfPkg/Library/LoadLinuxLib/Linux.c]
+
+ OvmfPkg/Library/LoadLinuxLib ports the efilinux bootloader project into
+ OvmfPkg.
+
+(2) OVMF seeks to comply with the boot order specification passed down by QEMU
+ over fw_cfg.
+
+ (a) About Boot Modes
+
+ During the PEI phase, OVMF determines and stores the Boot Mode in the
+ PHIT HOB (already mentioned in "S3 (suspend to RAM and resume)"). The
+ boot mode is supposed to influence the rest of the system, for example it
+ distinguishes S3 resume (BOOT_ON_S3_RESUME) from a "normal" boot.
+
+ In general, "normal" boots can be further differentiated from each other;
+ for example for speed reasons. When the firmware can tell during PEI that
+ the chassis has not been opened since last power-up, then it might want
+ to save time by not connecting all devices and not enumerating all boot
+ options from scratch; it could just rely on the stored results of the
+ last enumeration. The matching BootMode value, to be set during PEI,
+ would be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES.
+
+ OVMF only sets one of the following two boot modes, based on CMOS
+ contents:
+ - BOOT_ON_S3_RESUME,
+ - BOOT_WITH_FULL_CONFIGURATION.
+
+ For BOOT_ON_S3_RESUME, please refer to "S3 (suspend to RAM and resume)".
+ The other boot mode supported by OVMF, BOOT_WITH_FULL_CONFIGURATION, is
+ an appropriate "catch-all" for a virtual machine, where hardware can
+ easily change from boot to boot.
+
+ (b) Auto-generation of boot options
+
+ Accordingly, when not resuming from S3 sleep (*), OVMF always connects
+ all devices, and enumerates all bootable devices as new boot options
+ (non-volatile variables called Boot####).
+
+ (*) During S3 resume, DXE is not reached, hence BDS isn't either.
+
+ The auto-enumerated boot options are stored in the BootOrder non-volatile
+ variable after any preexistent options. (Boot options may exist before
+ auto-enumeration eg. because the user added them manually with the Boot
+ Maintenance Manager or the efibootmgr utility. They could also originate
+ from an earlier auto-enumeration.)
+
+ PlatformBdsPolicyBehavior() [OvmfPkg/.../BdsPlatform.c]
+ TryRunningQemuKernel() [OvmfPkg/.../QemuKernel.c]
+ BdsLibConnectAll() [IntelFrameworkModulePkg/.../BdsConnect.c]
+ BdsLibEnumerateAllBootOption() [IntelFrameworkModulePkg/.../BdsBoot.c]
+ BdsLibBuildOptionFromHandle() [IntelFrameworkModulePkg/.../BdsBoot.c]
+ BdsLibRegisterNewOption() [IntelFrameworkModulePkg/.../BdsMisc.c]
+ //
+ // Append the new option number to the original option order
+ //
+
+ (c) Relative UEFI device paths in boot options
+
+ The handling of relative ("short-form") UEFI device paths is best
+ demonstrated through an example, and by quoting the UEFI 2.4A
+ specification.
+
+ A short-form hard drive UEFI device path could be (displaying each device
+ path node on a separate line for readability):
+
+ HD(1,GPT,14DD1CC5-D576-4BBF-8858-BAF877C8DF61,0x800,0x64000)/
+ \EFI\fedora\shim.efi
+
+ This device path lacks prefix nodes (eg. hardware or messaging type
+ nodes) that would lead to the hard drive. During load option processing,
+ the above short-form or relative device path could be matched against the
+ following absolute device path:
+
+ PciRoot(0x0)/
+ Pci(0x4,0x0)/
+ HD(1,GPT,14DD1CC5-D576-4BBF-8858-BAF877C8DF61,0x800,0x64000)/
+ \EFI\fedora\shim.efi
+
+ The motivation for this type of device path matching / completion is to
+ allow the user to move around the hard drive (for example, to plug a
+ controller in a different PCI slot, or to expose the block device on a
+ different iSCSI path) and still enable the firmware to find the hard
+ drive.
+
+ The UEFI specification says,
+
+ 9.3.6 Media Device Path
+ 9.3.6.1 Hard Drive
+
+ [...] Section 3.1.2 defines special rules for processing the Hard
+ Drive Media Device Path. These special rules enable a disk's location
+ to change and still have the system boot from the disk. [...]
+
+ 3.1.2 Load Option Processing
+
+ [...] The boot manager must [...] support booting from a short-form
+ device path that starts with the first element being a hard drive
+ media device path [...]. The boot manager must use the GUID or
+ signature and partition number in the hard drive device path to match
+ it to a device in the system. If the drive supports the GPT
+ partitioning scheme the GUID in the hard drive media device path is
+ compared with the UniquePartitionGuid field of the GUID Partition
+ Entry [...]. If the drive supports the PC-AT MBR scheme the signature
+ in the hard drive media device path is compared with the
+ UniqueMBRSignature in the Legacy Master Boot Record [...]. If a
+ signature match is made, then the partition number must also be
+ matched. The hard drive device path can be appended to the matching
+ hardware device path and normal boot behavior can then be used. If
+ more than one device matches the hard drive device path, the boot
+ manager will pick one arbitrarily. Thus the operating system must
+ ensure the uniqueness of the signatures on hard drives to guarantee
+ deterministic boot behavior.
+
+ Edk2 implements and exposes the device path completion logic in the
+ already referenced "IntelFrameworkModulePkg/Library/GenericBdsLib"
+ library, in the BdsExpandPartitionPartialDevicePathToFull() function.
+
+ (d) Filtering and reordering the boot options based on fw_cfg
+
+ Once we have an "all-inclusive", partly preexistent, partly freshly
+ auto-generated boot option list from bullet (b), OVMF loads QEMU's
+ requested boot order from fw_cfg, and filters and reorders the list from
+ (b) with it:
+
+ PlatformBdsPolicyBehavior() [OvmfPkg/.../BdsPlatform.c]
+ TryRunningQemuKernel() [OvmfPkg/.../QemuKernel.c]
+ BdsLibConnectAll() [IntelFrameworkModulePkg/.../BdsConnect.c]
+ BdsLibEnumerateAllBootOption() [IntelFrameworkModulePkg/.../BdsBoot.c]
+ SetBootOrderFromQemu() [OvmfPkg/.../QemuBootOrder.c]
+
+ According to the (preferred) "-device ...,bootindex=N" and the (legacy)
+ '-boot order=drives' command line options, QEMU requests a boot order
+ from the firmware through the "bootorder" fw_cfg file. (For a bootindex
+ example, refer to the "Example qemu invocation" section.)
+
+ This fw_cfg file consists of OpenFirmware (OFW) device paths -- note: not
+ UEFI device paths! --, one per line. An example list is:
+
+ /pci@i0cf8/scsi@4/disk@0,0
+ /pci@i0cf8/ide@1,1/drive@1/disk@0
+ /pci@i0cf8/ethernet@3/ethernet-phy@0
+
+ OVMF filters and reorders the boot option list from bullet (b) with the
+ following nested loops algorithm:
+
+ new_uefi_order := <empty>
+ for each qemu_ofw_path in QEMU's OpenFirmware device path list:
+ qemu_uefi_path_prefix := translate(qemu_ofw_path)
+
+ for each boot_option in current_uefi_order:
+ full_boot_option := complete(boot_option)
+
+ if match(qemu_uefi_path_prefix, full_boot_option):
+ append(new_uefi_order, boot_option)
+ break
+
+ for each unmatched boot_option in current_uefi_order:
+ if survives(boot_option):
+ append(new_uefi_order, boot_option)
+
+ current_uefi_order := new_uefi_order
+
+ OVMF iterates over QEMU's OFW device paths in order, translates each to a
+ UEFI device path prefix, tries to match the translated prefix against the
+ UEFI boot options (which are completed from relative form to absolute
+ form for the purpose of prefix matching), and if there's a match, the
+ matching boot option is appended to the new boot order (which starts out
+ empty).
+
+ (We elaborate on the translate() function under bullet (e). The
+ complete() function has been explained in bullet (c).)
+
+ In addition, UEFI boot options that remain unmatched after filtering and
+ reordering are post-processed, and some of them "survive". Due to the
+ fact that OpenFirmware device paths have less expressive power than their
+ UEFI counterparts, some UEFI boot options are simply inexpressible (hence
+ unmatchable) by the nested loops algorithm.
+
+ An important example is the memory-mapped UEFI shell, whose UEFI device
+ path is inexpressible by QEMU's OFW device paths:
+
+ MemoryMapped(0xB,0x900000,0x10FFFFF)/
+ FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
+
+ (Side remark: notice that the address range visible in the MemoryMapped()
+ node corresponds to DXEFV under "comprehensive memory map of OVMF"! In
+ addition, the FvFile() node's GUID originates from the FILE_GUID entry of
+ "ShellPkg/Application/Shell/Shell.inf".)
+
+ The UEFI shell can be booted by pressing ESC in OVMF on the TianoCore
+ splash screen, and navigating to Boot Manager | EFI Internal Shell. If
+ the "survival policy" was not implemented, the UEFI shell's boot option
+ would always be filtered out.
+
+ The current "survival policy" preserves all boot options that start with
+ neither PciRoot() nor HD().
+
+ (e) Translating QEMU's OpenFirmware device paths to UEFI device path
+ prefixes
+
+ In this section we list the (strictly heuristical) mappings currently
+ performed by OVMF.
+
+ The "prefix only" nature of the translation output is rooted minimally in
+ the fact that QEMU's OpenFirmware device paths cannot carry pathnames
+ within filesystems. There's no way to specify eg.
+
+ \EFI\fedora\shim.efi
+
+ in an OFW device path, therefore a UEFI device path translated from an
+ OFW device path can at best be a prefix (not a full match) of a UEFI
+ device path that ends with "\EFI\fedora\shim.efi".
+
+ - IDE disk, IDE CD-ROM:
+
+ OpenFirmware device path:
+
+ /pci@i0cf8/ide@1,1/drive@0/disk@0
+ ^ ^ ^ ^ ^
+ | | | | master or slave
+ | | | primary or secondary
+ | PCI slot & function holding IDE controller
+ PCI root at system bus port, PIO
+
+ UEFI device path prefix:
+
+ PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
+ ^
+ fixed LUN
+
+ - Floppy disk:
+
+ OpenFirmware device path:
+
+ /pci@i0cf8/isa@1/fdc@03f0/floppy@0
+ ^ ^ ^ ^
+ | | | A: or B:
+ | | ISA controller io-port (hex)
+ | PCI slot holding ISA controller
+ PCI root at system bus port, PIO
+
+ UEFI device path prefix:
+
+ PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x0)
+ ^
+ ACPI UID (A: or B:)
+
+ - Virtio-block disk:
+
+ OpenFirmware device path:
+
+ /pci@i0cf8/scsi@6[,3]/disk@0,0
+ ^ ^ ^ ^ ^
+ | | | fixed
+ | | PCI function corresponding to disk (optional)
+ | PCI slot holding disk
+ PCI root at system bus port, PIO
+
+ UEFI device path prefixes (dependent on the presence of a nonzero PCI
+ function in the OFW device path):
+
+ PciRoot(0x0)/Pci(0x6,0x0)/HD(
+ PciRoot(0x0)/Pci(0x6,0x3)/HD(
+
+ - Virtio-scsi disk and virtio-scsi passthrough:
+
+ OpenFirmware device path:
+
+ /pci@i0cf8/scsi@7[,3]/channel@0/disk@2,3
+ ^ ^ ^ ^ ^
+ | | | | LUN
+ | | | target
+ | | channel (unused, fixed 0)
+ | PCI slot[, function] holding SCSI controller
+ PCI root at system bus port, PIO
+
+ UEFI device path prefixes (dependent on the presence of a nonzero PCI
+ function in the OFW device path):
+
+ PciRoot(0x0)/Pci(0x7,0x0)/Scsi(0x2,0x3)
+ PciRoot(0x0)/Pci(0x7,0x3)/Scsi(0x2,0x3)
+
+ - Emulated and passed-through (physical) network cards:
+
+ OpenFirmware device path:
+
+ /pci@i0cf8/ethernet@3[,2]
+ ^ ^
+ | PCI slot[, function] holding Ethernet card
+ PCI root at system bus port, PIO
+
+ UEFI device path prefixes (dependent on the presence of a nonzero PCI
+ function in the OFW device path):
+
+ PciRoot(0x0)/Pci(0x3,0x0)
+ PciRoot(0x0)/Pci(0x3,0x2)
+
+Virtio drivers
+..............
+
+UEFI abstracts various types of hardware resources into protocols, and allows
+firmware developers to implement those protocols in device drivers. The Virtio
+Specification defines various types of virtual hardware for virtual machines.
+Connecting the two specifications, OVMF provides UEFI drivers for QEMU's
+virtio-block, virtio-scsi, and virtio-net devices.
+
+The following diagram presents the protocol and driver stack related to Virtio
+devices in edk2 and OVMF. Each node in the graph identifies a protocol and/or
+the edk2 driver that produces it. Nodes on the top are more abstract.
+
+ EFI_BLOCK_IO_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL
+ [OvmfPkg/VirtioBlkDxe] [OvmfPkg/VirtioNetDxe]
+ | |
+ | EFI_EXT_SCSI_PASS_THRU_PROTOCOL |
+ | [OvmfPkg/VirtioScsiDxe] |
+ | | |
+ +------------------------+--------------------------+
+ |
+ VIRTIO_DEVICE_PROTOCOL
+ |
+ +---------------------+---------------------+
+ | |
+ [OvmfPkg/VirtioPciDeviceDxe] [custom platform drivers]
+ | |
+ | |
+ EFI_PCI_IO_PROTOCOL [OvmfPkg/Library/VirtioMmioDeviceLib]
+ [MdeModulePkg/Bus/Pci/PciBusDxe] direct MMIO register access
+
+The top three drivers produce standard UEFI abstractions: the Block IO
+Protocol, the Extended SCSI Pass Thru Protocol, and the Simple Network
+Protocol, for virtio-block, virtio-scsi, and virtio-net devices, respectively.
+
+Comparing these device-specific virtio drivers to each other, we can determine:
+
+- They all conform to the UEFI Driver Model. This means that their entry point
+ functions don't immediately start to search for devices and to drive them,
+ they only register instances of the EFI_DRIVER_BINDING_PROTOCOL. The UEFI
+ Driver Model then enumerates devices and chains matching drivers
+ automatically.
+
+- They are as minimal as possible, while remaining correct (refer to source
+ code comments for details). For example, VirtioBlkDxe and VirtioScsiDxe both
+ support only one request in flight.
+
+ In theory, VirtioBlkDxe could implement EFI_BLOCK_IO2_PROTOCOL, which allows
+ queueing. Similarly, VirtioScsiDxe does not support the non-blocking mode of
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). (Which is permitted by the UEFI
+ specification.) Both VirtioBlkDxe and VirtioScsiDxe delegate synchronous
+ request handling to "OvmfPkg/Library/VirtioLib". This limitation helps keep
+ the implementation simple, and testing thus far seems to imply satisfactory
+ performance, for a virtual boot firmware.
+
+ VirtioNetDxe cannot avoid queueing, because EFI_SIMPLE_NETWORK_PROTOCOL
+ requires it on the interface level. Consequently, VirtioNetDxe is
+ significantly more complex than VirtioBlkDxe and VirtioScsiDxe. Technical
+ notes are provided in "OvmfPkg/VirtioNetDxe/TechNotes.txt".
+
+- None of these drivers access hardware directly. Instead, the Virtio Device
+ Protocol (OvmfPkg/Include/Protocol/VirtioDevice.h) collects / extracts virtio
+ operations defined in the Virtio Specification, and these backend-independent
+ virtio device drivers go through the abstract VIRTIO_DEVICE_PROTOCOL.
+
+ IMPORTANT: the VIRTIO_DEVICE_PROTOCOL is not a standard UEFI protocol. It is
+ internal to edk2 and not described in the UEFI specification. It should only
+ be used by drivers and applications that live inside the edk2 source tree.
+
+Currently two providers exist for VIRTIO_DEVICE_PROTOCOL:
+
+- The first one is the "more traditional" virtio-pci backend, implemented by
+ OvmfPkg/VirtioPciDeviceDxe. This driver also complies with the UEFI Driver
+ Model. It consumes an instance of the EFI_PCI_IO_PROTOCOL, and, if the PCI
+ device/function under probing appears to be a virtio device, it produces a
+ Virtio Device Protocol instance for it. The driver translates abstract virtio
+ operations to PCI accesses.
+
+- The second provider, the virtio-mmio backend, is a library, not a driver,
+ living in OvmfPkg/Library/VirtioMmioDeviceLib. This library translates
+ abstract virtio operations to MMIO accesses.
+
+ The virtio-mmio backend is only a library -- rather than a standalone, UEFI
+ Driver Model-compliant driver -- because the type of resource it consumes, an
+ MMIO register block base address, is not enumerable.
+
+ In other words, while the PCI root bridge driver and the PCI bus driver
+ produce instances of EFI_PCI_IO_PROTOCOL automatically, thereby enabling the
+ UEFI Driver Model to probe devices and stack up drivers automatically, no
+ such enumeration exists for MMIO register blocks.
+
+ For this reason, VirtioMmioDeviceLib needs to be linked into thin, custom
+ platform drivers that dispose over this kind of information. As soon as a
+ driver knows about the MMIO register block base addresses, it can pass each
+ to the library, and then the VIRTIO_DEVICE_PROTOCOL will be instantiated
+ (assuming a valid virtio-mmio register block of course). From that point on
+ the UEFI Driver Model again takes care of the chaining.
+
+ Typically, such a custom driver does not conform to the UEFI Driver Model
+ (because that would presuppose auto-enumeration for MMIO register blocks).
+ Hence it has the following responsibilities:
+
+ - it shall behave as a "wrapper" UEFI driver around the library,
+
+ - it shall know virtio-mmio base addresses,
+
+ - in its entry point function, it shall create a new UEFI handle with an
+ instance of the EFI_DEVICE_PATH_PROTOCOL for each virtio-mmio device it
+ knows the base address for,
+
+ - it shall call VirtioMmioInstallDevice() on those handles, with the
+ corresponding base addresses.
+
+ OVMF itself does not employ VirtioMmioDeviceLib. However, the library is used
+ (or has been tested as Proof-of-Concept) in the following 64-bit and 32-bit
+ ARM emulator setups:
+
+ - in "RTSM_VE_FOUNDATIONV8_EFI.fd" and "FVP_AARCH64_EFI.fd", on ARM Holdings'
+ ARM(R) v8-A Foundation Model and ARM(R) AEMv8-A Base Platform FVP
+ emulators, respectively:
+
+ EFI_BLOCK_IO_PROTOCOL
+ [OvmfPkg/VirtioBlkDxe]
+ |
+ VIRTIO_DEVICE_PROTOCOL
+ [ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf]
+ |
+ [OvmfPkg/Library/VirtioMmioDeviceLib]
+ direct MMIO register access
+
+ - in "RTSM_VE_CORTEX-A15_EFI.fd" and "RTSM_VE_CORTEX-A15_MPCORE_EFI.fd", on
+ "qemu-system-arm -M vexpress-a15":
+
+ EFI_BLOCK_IO_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL
+ [OvmfPkg/VirtioBlkDxe] [OvmfPkg/VirtioNetDxe]
+ | |
+ +------------------+---------------+
+ |
+ VIRTIO_DEVICE_PROTOCOL
+ [ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf]
+ |
+ [OvmfPkg/Library/VirtioMmioDeviceLib]
+ direct MMIO register access
+
+ In the above ARM / VirtioMmioDeviceLib configurations, VirtioBlkDxe was
+ tested with booting Linux distributions, while VirtioNetDxe was tested with
+ pinging public IPv4 addresses from the UEFI shell.
+
+Platform Driver
+...............
+
+Sometimes, elements of persistent firmware configuration are best exposed to
+the user in a friendly way. OVMF's platform driver (OvmfPkg/PlatformDxe)
+presents such settings on the "OVMF Platform Configuration" dialog:
+
+- Press ESC on the TianoCore splash screen,
+- Navigate to Device Manager | OVMF Platform Configuration.
+
+At the moment, OVMF's platform driver handles only one setting: the preferred
+graphics resolution. This is useful for two purposes:
+
+- Some UEFI shell commands, like DRIVERS and DEVICES, benefit from a wide
+ display. Using the MODE shell command, the user can switch to a larger text
+ resolution (limited by the graphics resolution), and see the command output
+ in a more easily consumable way.
+
+ [RHEL] The list of text modes available to the MODE command is also limited
+ by ConSplitterDxe (found under MdeModulePkg/Universal/Console).
+ ConSplitterDxe builds an intersection of text modes that are
+ simultaneously supported by all consoles that ConSplitterDxe
+ multiplexes console output to.
+
+ In practice, the strongest text mode restriction comes from
+ TerminalDxe, which provides console I/O on serial ports. TerminalDxe
+ has a very limited built-in list of text modes, heavily pruning the
+ intersection built by ConSplitterDxe, and made available to the MODE
+ command.
+
+ On the Red Hat Enterprise Linux 7.1 host, TerminalDxe's list of modes
+ has been extended with text resolutions that match the Spice QXL GPU's
+ common graphics resolutions. This way a "full screen" text mode should
+ always be available in the MODE command.
+
+- The other advantage of controlling the graphics resolution lies with UEFI
+ operating systems that don't (yet) have a native driver for QEMU's virtual
+ video cards -- eg. the Spice QXL GPU. Such OSes may choose to inherit the
+ properties of OVMF's EFI_GRAPHICS_OUTPUT_PROTOCOL (provided by
+ OvmfPkg/QemuVideoDxe, see later).
+
+ Although the display can be used at runtime in such cases, by direct
+ framebuffer access, its properties, for example, the resolution, cannot be
+ modified. The platform driver allows the user to select the preferred GOP
+ resolution, reboot, and let the guest OS inherit that preferred resolution.
+
+The platform driver has three access points: the "normal" driver entry point, a
+set of HII callbacks, and a GOP installation callback.
+
+(1) Driver entry point: the PlatformInit() function.
+
+ (a) First, this function loads any available settings, and makes them take
+ effect. For the preferred graphics resolution in particular, this means
+ setting the following PCDs:
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+
+ These PCDs influence the GraphicsConsoleDxe driver (located under
+ MdeModulePkg/Universal/Console), which switches to the preferred
+ graphics mode, and produces EFI_SIMPLE_TEXT_OUTPUT_PROTOCOLs on GOPs:
+
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ [MdeModulePkg/Universal/Console/GraphicsConsoleDxe]
+ |
+ EFI_GRAPHICS_OUTPUT_PROTOCOL
+ [OvmfPkg/QemuVideoDxe]
+ |
+ EFI_PCI_IO_PROTOCOL
+ [MdeModulePkg/Bus/Pci/PciBusDxe]
+
+ (b) Second, the driver entry point registers the user interface, including
+ HII callbacks.
+
+ (c) Third, the driver entry point registers a GOP installation callback.
+
+(2) HII callbacks and the user interface.
+
+ The Human Interface Infrastructure (HII) "is a set of protocols that allow
+ a UEFI driver to provide the ability to register user interface and
+ configuration content with the platform firmware".
+
+ OVMF's platform driver:
+
+ - provides a static, basic, visual form (PlatformForms.vfr), written in the
+ Visual Forms Representation language,
+
+ - includes a UCS-16 encoded message catalog (Platform.uni),
+
+ - includes source code that dynamically populates parts of the form, with
+ the help of MdeModulePkg/Library/UefiHiiLib -- this library simplifies
+ the handling of IFR (Internal Forms Representation) opcodes,
+
+ - processes form actions that the user takes (Callback() function),
+
+ - loads and saves platform configuration in a private, non-volatile
+ variable (ExtractConfig() and RouteConfig() functions).
+
+ The ExtractConfig() HII callback implements the following stack of
+ conversions, for loading configuration and presenting it to the user:
+
+ MultiConfigAltResp -- form engine / HII communication
+ ^
+ |
+ [BlockToConfig]
+ |
+ MAIN_FORM_STATE -- binary representation of form/widget
+ ^ state
+ |
+ [PlatformConfigToFormState]
+ |
+ PLATFORM_CONFIG -- accessible to DXE and UEFI drivers
+ ^
+ |
+ [PlatformConfigLoad]
+ |
+ UEFI non-volatile variable -- accessible to external utilities
+
+ The layers are very similar for the reverse direction, ie. when taking
+ input from the user, and saving the configuration (RouteConfig() HII
+ callback):
+
+ ConfigResp -- form engine / HII communication
+ |
+ [ConfigToBlock]
+ |
+ v
+ MAIN_FORM_STATE -- binary representation of form/widget
+ | state
+ [FormStateToPlatformConfig]
+ |
+ v
+ PLATFORM_CONFIG -- accessible to DXE and UEFI drivers
+ |
+ [PlatformConfigSave]
+ |
+ v
+ UEFI non-volatile variable -- accessible to external utilities
+
+(3) When the platform driver starts, a GOP may not be available yet. Thus the
+ driver entry point registers a callback (the GopInstalled() function) for
+ GOP installations.
+
+ When the first GOP is produced (usually by QemuVideoDxe, or potentially by
+ a third party video driver), PlatformDxe retrieves the list of graphics
+ modes the GOP supports, and dynamically populates the drop-down list of
+ available resolutions on the form. The GOP installation callback is then
+ removed.
+
+Video driver
+............
+
+OvmfPkg/QemuVideoDxe is OVMF's built-in video driver. We can divide its
+services in two parts: graphics output protocol (primary), and Int10h (VBE)
+shim (secondary).
+
+(1) QemuVideoDxe conforms to the UEFI Driver Model; it produces an instance of
+ the EFI_GRAPHICS_OUTPUT_PROTOCOL (GOP) on each PCI display that it supports
+ and is connected to:
+
+ EFI_GRAPHICS_OUTPUT_PROTOCOL
+ [OvmfPkg/QemuVideoDxe]
+ |
+ EFI_PCI_IO_PROTOCOL
+ [MdeModulePkg/Bus/Pci/PciBusDxe]
+
+ It supports the following QEMU video cards:
+
+ - Cirrus 5430 ("-device cirrus-vga"),
+ - Standard VGA ("-device VGA"),
+ - QXL VGA ("-device qxl-vga", "-device qxl").
+
+ For Cirrus the following resolutions and color depths are available:
+ 640x480x32, 800x600x32, 1024x768x24. On stdvga and QXL a long list of
+ resolutions is available. The list is filtered against the frame buffer
+ size during initialization.
+
+ The size of the QXL VGA compatibility framebuffer can be changed with the
+
+ -device qxl-vga,vgamem_mb=$NUM_MB
+
+ QEMU option. If $NUM_MB exceeds 32, then the following is necessary
+ instead:
+
+ -device qxl-vga,vgamem_mb=$NUM_MB,ram_size_mb=$((NUM_MB*2))
+
+ because the compatibility framebuffer can't cover more than half of PCI BAR
+ #0. The latter defaults to 64MB in size, and is controlled by the
+ "ram_size_mb" property.
+
+(2) When QemuVideoDxe binds the first Standard VGA or QXL VGA device, and there
+ is no real VGA BIOS present in the C to F segments (which could originate
+ from a legacy PCI option ROM -- refer to "Compatibility Support Module
+ (CSM)"), then QemuVideoDxe installs a minimal, "fake" VGA BIOS -- an Int10h
+ (VBE) "shim".
+
+ The shim is implemented in 16-bit assembly in
+ "OvmfPkg/QemuVideoDxe/VbeShim.asm". The "VbeShim.sh" shell script assembles
+ it and formats it as a C array ("VbeShim.h") with the help of the "nasm"
+ utility. The driver's InstallVbeShim() function copies the shim in place
+ (the C segment), and fills in the VBE Info and VBE Mode Info structures.
+ The real-mode 10h interrupt vector is pointed to the shim's handler.
+
+ The shim is (correctly) irrelevant and invisible for all UEFI operating
+ systems we know about -- except Windows Server 2008 R2 and other Windows
+ operating systems in that family.
+
+ Namely, the Windows 2008 R2 SP1 (and Windows 7) UEFI guest's default video
+ driver dereferences the real mode Int10h vector, loads the pointed-to
+ handler code, and executes what it thinks to be VGA BIOS services in an
+ internal real-mode emulator. Consequently, video mode switching used not to
+ work in Windows 2008 R2 SP1 when it ran on the "pure UEFI" build of OVMF,
+ making the guest uninstallable. Hence the (otherwise optional, non-default)
+ Compatibility Support Module (CSM) ended up a requirement for running such
+ guests.
+
+ The hard dependency on the sophisticated SeaBIOS CSM and the complex
+ supporting edk2 infrastructure, for enabling this family of guests, was
+ considered suboptimal by some members of the upstream community,
+
+ [RHEL] and was certainly considered a serious maintenance disadvantage for
+ Red Hat Enterprise Linux 7.1 hosts.
+
+ Thus, the shim has been collaboratively developed for the Windows 7 /
+ Windows Server 2008 R2 family. The shim provides a real stdvga / QXL
+ implementation for the few services that are in fact necessary for the
+ Windows 2008 R2 SP1 (and Windows 7) UEFI guest, plus some "fakes" that the
+ guest invokes but whose effect is not important. The only supported mode is
+ 1024x768x32, which is enough to install the guest and then upgrade its
+ video driver to the full-featured QXL XDDM one.
+
+ The C segment is not present in the UEFI memory map prepared by OVMF.
+ Memory space that would cover it is never added (either in PEI, in the form
+ of memory resource descriptor HOBs, or in DXE, via gDS->AddMemorySpace()).
+ This way the handler body is invisible to all other UEFI guests, and the
+ rest of edk2.
+
+ The Int10h real-mode IVT entry is covered with a Boot Services Code page,
+ making that too inaccessible to the rest of edk2. Due to the allocation
+ type, UEFI guest OSes different from the Windows Server 2008 family can
+ reclaim the page at zero. (The Windows 2008 family accesses that page
+ regardless of the allocation type.)
+
+Afterword
+---------
+
+After the bulk of this document was written in July 2014, OVMF development has
+not stopped. To name two significant code contributions from the community: in
+January 2015, OVMF runs on the "q35" machine type of QEMU, and it features a
+driver for Xen paravirtual block devices (and another for the underlying Xen
+bus).
+
+Furthermore, a dedicated virtualization platform has been contributed to
+ArmPlatformPkg that plays a role parallel to OvmfPkg's. It targets the "virt"
+machine type of qemu-system-arm and qemu-system-aarch64. Parts of OvmfPkg are
+being refactored and modularized so they can be reused in
+"ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc".
diff --git a/sources b/sources
index 03dfd2b..993de36 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,3 @@
-SHA512 (openssl-1.0.2j-hobbled.tar.xz) = 87c7c4e45f83c49b36154f4c66d3799fdc63286f9841b4dd71d4bdc3b26206be6009e33462533f0c1cc0efd9ef6aa05b772728ed0ee3e88f952586cdcf513003
-SHA512 (edk2-20170209-296153c5.tar.xz) = b9b1936bde197712fe0f5dc3cf227095c08803486866967703959f4adc131c48b1b5f3bcdd8a4a40fe234eba5a7fdf887087d4d522db01a0920eb85cc7ab9454
+SHA512 (qemu-ovmf-secureboot-1.1.3.tar.gz) = f830a525f66379e8e3c61d006fab49547e6709f7aa0f95e70f23c7d26407cc804a0ced9dcfd26af63391d603e9cb5a0714c222c7cdca8599e41852e22e13be80
+SHA512 (openssl-1.1.0h-hobbled.tar.xz) = 6b544a5560a0a3d59b368e3f216284e79389112c87bb34289f8f6644a2454407161a1755b292e8045ff7c172237b070973b03610fd1da3d5204f4118a8644724
+SHA512 (edk2-20180815-cb5f4f45ce.tar.xz) = 2912bb30b5be1d7efc1b7aa6d337fd1403fc9ea7cfc580c22dd770d82273ce4c801eba2d60a6f2fda4bc1c6e49747be606de4acfdcca286c10e44b11369cde9d
diff --git a/update-tarball.sh b/update-tarball.sh
index b61d758..e414329 100644
--- a/update-tarball.sh
+++ b/update-tarball.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
user="tianocore"
repo="edk2"
@@ -8,21 +8,30 @@ uri="https://github.com/${user}/${repo} "
api="${uri/github.com/api.github.com/repos}"
tar="${uri/github.com/codeload.github.com}/legacy.tar.gz"
-hash=$(curl -s "${api}/git/refs/heads/${branch}" | grep '"sha"' | cut -d'"' -f4)
-if test "$hash" = ""; then
+if test $# -ge 1; then
+ hash=$1
+ short=$1
+else
+ hash=$(curl -s "${api}/git/refs/heads/${branch}" | grep '"sha"' | cut -d'"' -f4)
+ if test "$hash" = ""; then
echo "# failed to fetch $branch hash"
exit 1
+ fi
+ short=$(echo $hash | sed -e 's/^\(.......\).*/\1/')
fi
-short=$(echo $hash | sed -e 's/^\(.......\).*/\1/')
-date=$(curl -s "${api}/git/commits/$hash" | awk '
- /"committer"/ { c=1 }
- /"date"/ { if (c) { print } }
-' | cut -d'"' -f4)
-date="${date%T*}"
-date="${date//-/}"
+if test $# = 2; then
+ date=$2
+else
+ date=$(curl -s "${api}/git/commits/$hash" | awk '
+ /"committer"/ { c=1 }
+ /"date"/ { if (c) { print } }
+ ' | cut -d'"' -f4)
+ date="${date%T*}"
+ date="${date//-/}"
+fi
-name="${repo}-${date}-${short}.tar.gz"
+name="${repo}-${date}-${short}.tar.xz"
if test -f "$name"; then
echo "# exists: $name"
@@ -41,5 +50,5 @@ echo
echo "# cleanup ..."
rm -vf ${repo}-*.tar*
echo "# fetching $name ..."
-curl "$tar/$hash" > "$name"
+curl "$tar/$hash" | zcat | xz -9e > "$name"
exit 0
The package rpms/racket.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/racket.git/commit/?id=f241dafce9084… .
Change:
+ExcludeArch: s390x armv7hl
Thanks.
Full change:
============
commit f241dafce908418595fbb717060cbbefb6867e61
Author: dbenoit <dbenoit(a)redhat.com>
Date: Fri Aug 31 14:25:40 2018 -0400
add spec and patches
diff --git a/racket-6.12-fix-doc-open-url.patch b/racket-6.12-fix-doc-open-url.patch
new file mode 100644
index 0000000..7c497f5
--- /dev/null
+++ b/racket-6.12-fix-doc-open-url.patch
@@ -0,0 +1,69 @@
+diff -urN racket-6.12-wbsvr/share/pkgs/scribble-lib/help/search.rkt racket-6.12/share/pkgs/scribble-lib/help/search.rkt
+--- racket-6.12-wbsvr/share/pkgs/scribble-lib/help/search.rkt 2018-03-19 17:14:56.017273013 -0400
++++ racket-6.12/share/pkgs/scribble-lib/help/search.rkt 2018-03-19 17:15:37.839113929 -0400
+@@ -17,33 +17,38 @@
+ #:notify [notify void])
+ (define open-url (get-doc-open-url))
+ (cond
+- [open-url
+- (define dest-url (let ([u (string->url open-url)])
+- (combine-url/relative
+- u
+- (string-join
+- (for/list ([s (explode-path sub)])
+- (if (path? s)
+- (path-element->string s)
+- (format "~a" s)))
+- "/"))))
+- (notify (url->string dest-url))
+- (send-url (url->string
+- (struct-copy url dest-url
+- [fragment (or fragment
+- (url-fragment dest-url))]
+- [query (append
+- (url-query dest-url)
+- (if query
+- (url-query
+- (string->url
+- (format "q?~a" query)))
+- null))])))]
+- [else
+- (let* ([path (build-path (find-user-doc-dir) sub)]
+- [path (if (file-exists? path) path (build-path (find-doc-dir) sub))])
+- (notify path)
+- (send-url/file path #:fragment fragment #:query query))]))
++ [open-url
++ (define dest-url (let ([u (string->url open-url)])
++ (combine-url/relative
++ u
++ (string-join
++ (for/list ([s (explode-path sub)])
++ (if (path? s)
++ (path-element->string s)
++ (format "~a" s)))
++ "/"))))
++ (notify (url->string dest-url))
++ (send-url (url->string
++ (struct-copy url dest-url
++ [fragment (or fragment
++ (url-fragment dest-url))]
++ [query (append
++ (url-query dest-url)
++ (if query
++ (url-query
++ (string->url
++ (format "q?~a" query)))
++ null))])))]
++ [else
++ (let* ([path (build-path (find-user-doc-dir) sub)]
++ [path (if (file-exists? path) path (build-path (find-doc-dir) sub))])
++ (notify path)
++ (if (file-exists? path)
++ (send-url/file path #:fragment fragment #:query query)
++ (let ([part (lambda (pfx x) (if x (string-append pfx x) ""))])
++ (send-url (string-append
++ "https://docs.racket-lang.org/ "
++ sub (part "#" fragment) (part "?" query))))))]))
+
+ ;; This is an example of changing this code to use the online manuals.
+ ;; Normally, it's better to set `doc-open-url` in "etc/config.rktd",
diff --git a/racket-6.12-fix-rpaths.patch b/racket-6.12-fix-rpaths.patch
new file mode 100644
index 0000000..f76730e
--- /dev/null
+++ b/racket-6.12-fix-rpaths.patch
@@ -0,0 +1,13 @@
+diff -urN racket-6.12-f/collects/racket/runtime-path.rkt racket-6.12/collects/racket/runtime-path.rkt
+--- racket-6.12-f/collects/racket/runtime-path.rkt 2018-02-06 16:04:29.969878308 -0500
++++ racket-6.12/collects/racket/runtime-path.rkt 2018-02-06 16:07:10.549176282 -0500
+@@ -186,7 +186,8 @@
+ (path-of
+ #,(datum->syntax
+ #'orig-stx
+- `(,#'this-expression-source-file))))
++ `(,#'this-expression-source-file)
++ #'orig-stx)))
+ #'void)])
+ (apply to-values (resolve-paths (#%variable-reference)
+ get-dir
diff --git a/racket-6.12-fix-webserver-rpaths.patch b/racket-6.12-fix-webserver-rpaths.patch
new file mode 100644
index 0000000..78614cf
--- /dev/null
+++ b/racket-6.12-fix-webserver-rpaths.patch
@@ -0,0 +1,35 @@
+diff -urN racket-6.12-rp/share/pkgs/web-server-lib/web-server/formlets/lib.rkt racket-6.12-wbsvr/share/pkgs/web-server-lib/web-server/formlets/lib.rkt
+--- racket-6.12-rp/share/pkgs/web-server-lib/web-server/formlets/lib.rkt 2018-02-22 18:42:06.131455756 -0500
++++ racket-6.12-wbsvr/share/pkgs/web-server-lib/web-server/formlets/lib.rkt 2018-03-20 15:07:09.666222028 -0400
+@@ -7,6 +7,7 @@
+ racket/function
+ racket/serialize
+ syntax/location
++ setup/collects
+ (for-syntax racket/base
+ syntax/parse))
+
+@@ -70,20 +71,20 @@
+ #:range-contracts (map (curry coerce-contract 'formlet/c)
+ contracts)))]))
+ (define quote-this-module-path
+- (quote-module-path))
++ (path->collects-relative (quote-module-path)))
+ (define-syntax formlet/c
+ (syntax-parser
+ [(_ range ...)
+ #:declare range (expr/c #'contract?
+ #:name "range contract argument")
+ #'(formlet/c** (-> listof-binding
+- (values (coerce-contract 'formlet/c range.c) ...)))]
++ (values (coerce-contract 'formlet/c range #;.c) ...)))]
+ [name:id
+ #`(contract
+ (-> contract? (... ...) contract?)
+ dynamic-formlet/c
+ quote-this-module-path
+- (quote-module-path)
++ (path->collects-relative (quote-module-path))
+ "formlet/c"
+ #'name)]))
+
diff --git a/racket-6.12-remove-nonfree.patch b/racket-6.12-remove-nonfree.patch
new file mode 100644
index 0000000..4e72a3e
--- /dev/null
+++ b/racket-6.12-remove-nonfree.patch
@@ -0,0 +1,1124 @@
+diff -urN racket-6.12-nf/share/links.rktd racket-6.12/share/links.rktd
+--- racket-6.12-nf/share/links.rktd 2018-01-31 13:04:06.757393819 -0500
++++ racket-6.12/share/links.rktd 2018-01-31 13:04:25.419309681 -0500
+@@ -133,7 +133,6 @@
+ (root "pkgs/r5rs-doc")
+ (root "pkgs/srfi-lite-lib")
+ (root "pkgs/srfi-lib")
+- (root "pkgs/srfi-lib-nonfree")
+ (root "pkgs/html-doc")
+ (root "pkgs/images-gui-lib")
+ (root "pkgs/images-doc")
+@@ -177,7 +176,6 @@
+ (root "pkgs/slideshow-exe")
+ (root "pkgs/slideshow-plugin")
+ (root "pkgs/srfi-doc")
+- (root "pkgs/srfi-doc-nonfree")
+ (root "pkgs/syntax-color-doc")
+ (root "pkgs/web-server-lib")
+ (root "pkgs/unix-socket-lib")
+diff -urN racket-6.12-nf/share/pkgs/srfi/info.rkt racket-6.12/share/pkgs/srfi/info.rkt
+--- racket-6.12-nf/share/pkgs/srfi/info.rkt 2018-01-31 13:04:07.216391749 -0500
++++ racket-6.12/share/pkgs/srfi/info.rkt 2018-01-31 13:05:32.601025227 -0500
+@@ -3,13 +3,9 @@
+ (define collection 'multi)
+
+ (define deps '("srfi-lib"
+- "srfi-lib-nonfree"
+- "srfi-doc"
+- "srfi-doc-nonfree"))
++ "srfi-doc"))
+ (define implies '("srfi-lib"
+- "srfi-lib-nonfree"
+- "srfi-doc"
+- "srfi-foc-nonfree"))
++ "srfi-doc"))
+
+ (define pkg-desc "Legacy SRFI (Scheme) libraries")
+
+diff -urN racket-6.12-nf/share/pkgs/srfi-doc-nonfree/info.rkt racket-6.12/share/pkgs/srfi-doc-nonfree/info.rkt
+--- racket-6.12-nf/share/pkgs/srfi-doc-nonfree/info.rkt 2018-01-31 13:04:07.221391727 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/info.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,19 +0,0 @@
+-#lang info
+-
+-(define collection 'multi)
+-
+-(define build-deps '("mzscheme-doc"
+- "scheme-lib"
+- "base"
+- "scribble-lib"
+- "srfi-doc"
+- "srfi-lib-nonfree"
+- "racket-doc"
+- "r5rs-doc"
+- "r6rs-doc"
+- "compatibility-lib"))
+-(define update-implies '("srfi-lib-nonfree"))
+-
+-(define pkg-desc "documentation part of \"srfi nonfree\"")
+-
+-(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt
+--- racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt 2018-01-31 13:04:07.221391727 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,3 +0,0 @@
+-#lang info
+-
+-(define scribblings '(("srfi-nf.scrbl" (multi-page) (library 100))))
+diff -urN racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl
+--- racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl 2018-01-31 13:04:07.221391727 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl 1969-12-31 19:00:00.000000000 -0500
+@@ -1,66 +0,0 @@
+-#lang scribble/doc
+-@(require srfi/scribblings/util
+- scribble/manual
+- scribble/eval
+- scriblib/render-cond
+- scribble/core
+- scribble/html-properties
+- (for-syntax scheme/base)
+- (for-label scheme/base
+- racket/stream))
+-
+-@; ----------------------------------------------------------------------
+-
+-@title{SRFI Nonfree Libraries and Documentation}
+-
+-The @link[#:style srfi-std "http://srfi.schemers.org/ "]{Scheme Requests for
+-Implementation} (a.k.a. @deftech{SRFI}) process allows individual
+-members of the Scheme community to propose libraries and extensions to
+-be supported by multiple Scheme implementations.
+-
+-Racket is distributed with implementations of many SRFIs, most of
+-which can be implemented as libraries. To import the bindings of SRFI
+-@math{n}, use
+-
+-@racketblock[
+-(require @#,elem{@racketidfont{srfi/}@math{n}})
+-]
+-
+-This document lists the SRFIs that are supported by Racket and
+-provides a link to the original SRFI specification (which is also
+-distributed as part of Racket's documentation).
+-
+-The following SRFI specification documents are licensed restrictively.
+-
+-@table-of-contents[]
+-
+-
+-@; ----------------------------------------
+-
+-@srfi[5]{A compatible let form with signatures and rest arguments}
+-
+-@redirect[5 '(
+- (let #t "unnamed")
+-)]
+-
+-Racket provides this SRFI in the @racket[srfi-lib-nonfree] package.
+-
+-@; ----------------------------------------
+-
+-@srfi[29]{Localization}
+-
+-@redirect[29 '(
+- (current-language #f "current-language")
+- (current-country #f "current-country")
+- (current-locale-details #f "current-locale-details")
+- (declare-bundle! #f "declare-bundle!")
+- (store-bundle #f "store-bundle")
+- (load-bundle! #f "load-bundle!")
+- (localized-template #f "localized-template")
+-)]
+-
+-Racket provides a free implementation of this SRFI in the @racket[srfi-lib] package. Only the SRFI specification document is nonfree.
+-
+-@; ----------------------------------------
+-
+-@index-section[]
+diff -urN racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html
+--- racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html 2018-01-31 13:04:07.221391727 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,507 +0,0 @@
+-<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN">
+-<html>
+- <head>
+- <meta name="generator" content="HTML Tidy, see www.w3.org ">
+- <title>SRFI 29: Localization</title>
+- <meta name="author" content="Scott G. Miller">
+- <meta name="description" content="Localization">
+- </head>
+- <body>
+- <H1>Title</H1>
+-
+- SRFI 29: Localization
+-
+- <H1>Author</H1>
+-
+- Scott G. Miller
+-
+- <H1>Abstract</H1>
+-
+- This document specifies an interface to retrieving and
+- displaying locale sensitive messages. A Scheme program can
+- register one or more translations of templated messages, and
+- then write Scheme code that can transparently retrieve the
+- appropriate message for the locale under which the Scheme
+- system is running. <br>
+-
+-
+- <H1>Rationale</H1>
+-
+- <p>As any programmer that has ever had to deal with making his
+- or her code readable in more than one locale, the process of
+- sufficiently abstracting program messages from their
+- presentation to the user is non-trivial without help from the
+- programming language. Most modern programming language
+- libraries do provide some mechanism for performing this
+- separation.</p>
+-
+- <p>A portable API that allows a piece of code to run without
+- modification in different countries and under different
+- languages is a must for any non-trivial software project.
+- The interface should separate the logic of a program from
+- the myriad of translations that may be necessary.</p>
+-
+- <p>The interface described in this document provides such
+- functionality. The underlying implementation is also allowed to
+- use whatever datastructures it likes to provide access to the
+- translations in the most efficient manner possible. In
+- addition, the implementation is provided with standardized
+- functions that programs will use for accessing an external,
+- unspecified repository of translations.</p>
+-
+- <p>This interface <i>does not</i> cover all aspects of
+- localization, including support for non-latin characters,
+- number and date formatting, etc. Such functionality is the
+- scope of a future SRFI that may extend this one.</p>
+-
+- <H1>Dependencies</H1>
+-
+- An SRFI-29 conformant implementation must also implement
+- SRFI-28, Basic Format Strings. Message templates are strings
+- that must be processed by the <tt>format</tt> function
+- specified in that SRFI.
+-
+- <H1>Specification</H1>
+-
+- <h3>Message Bundles</h3>
+-
+- <p>A Message Bundle is a set of message templates and their
+- identifying keys. Each bundle contains one or more such
+- key/value pairs. The bundle itself is associated with a
+- <i>bundle specifier</i> which uniquely identifies the
+- bundle.</p>
+-
+- <h3>Bundle Specifiers</h3>
+-
+- <p>A Bundle Specifier is a Scheme list that describes, in order
+- of importance, the package and locale of a message bundle.
+- In most cases, a locale specifier will have between one
+- and three elements. The first element is a symbol denoting the
+- package for which this bundle applies. The second and third
+- elements denote a <i>locale</i>. The second element (first
+- element of the locale) if present, is the two letter, ISO 639-1
+- language code for the bundle. The third element, if present, is
+- a two letter ISO 3166-1 country code. In some cases, a
+- fourth element may be present, specifying the encoding used for
+- the bundle. All bundle specifier elements are Scheme
+- symbols.</p>
+-
+- <p>If only one translation is provided, it should be designated
+- only by a package name, for example <tt>(mathlib)</tt>. This
+- translation is called the <i>default</i> translation.</p>
+-
+- <h3>Bundle Searching</h3>
+-
+- <p>When a message template is retrieved from a bundle, the
+- Scheme implementation will provide the locale under which the
+- system is currently running. When the template is retrieved,
+- the package name will be specified. The Scheme system should
+- construct a Bundle Specifier from the provided package name and
+- the active locale. For example, when retrieving a message
+- template for French Canadian, in the <tt>mathlib</tt> package,
+- the bundle specifier '<tt>(mathlib fr ca)</tt>' is used. A
+- program may also retrieve the elements of the current locale
+- using the no-argument procedures:</p>
+-
+- <p><b><a name="current-language"></a><tt>current-language</tt></b> <tt>->
+- <i>symbol</i></tt><br>
+- <tt><b>current-language</b> <i>symbol</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- When given no arguments, returns the current ISO 639-1
+- language code as a symbol. If provided with an
+- argument, the current language is set to that named by the
+- symbol for the currently executing Scheme thread (or for the
+- entire Scheme system if such a distinction is not possible).
+-
+- </blockquote>
+-
+- <p><b><a name="current-country"></a><tt>current-country</tt></b> <tt>->
+- <i>symbol</i></tt><br>
+- <tt><b>current-country</b> <i>symbol</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- returns the current ISO 3166-1 country code as a symbol.
+- If provided with an argument, the current country is
+- set to that named by the symbol for the currently executing
+- Scheme thread (or for the entire Scheme system if such a
+- distinction is not possible).
+- </blockquote>
+-
+- <p><b><a name="current-locale-details"></a><tt>current-locale-details</tt></b> <tt>-> <i>list of
+- symbol</i></tt>s<br>
+- <tt><b>current-locale-details</b> <i>list-of-symbols</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- Returns a list of additional locale details as a list of
+- symbols. This list may contain information about
+- encodings or other more specific information. If
+- provided with an argument, the current locale details are set
+- to those given in the currently executing Scheme thread (or
+- for the entire Scheme system if such a distinction is not
+- possible).
+- </blockquote>
+-
+- <p>The Scheme System should first check for a bundle with the
+- exact name provided. If no such bundle is found, the last
+- element from the list is removed and a search is tried for a
+- bundle with that name. If no bundle is then found, the list is
+- shortened by removing the last element again. If no message is
+- found and the bundle specifier is now the empty list, an error
+- should be raised.</p>
+-
+- <p>The reason for this search order is to provide the most
+- locale sensitive template possible, but to fall back on more
+- general templates if a translation has not yet been provided
+- for the given locale.</p>
+-
+- <h3>Message Templates</h3>
+-
+- <p>A message template is a localized message that may or may
+- not contain one of a number of formatting codes. A message
+- template is a Scheme string. The string is of a form that can
+- be processed by the <tt>format</tt> procedure found in many
+- Scheme systems and formally specified in SRFI-28 (Basic Format
+- Strings).</p>
+-
+- <p>This SRFI also extends SRFI-28 to provide an additional
+- <tt>format</tt> escape code:</p>
+-
+- <blockquote>
+- <tt>~[n]@*</tt> - Causes a value-requiring escape code that
+- follows this code immediately to reference the [N]'th
+- optional value absolutely, rather than the next unconsumed
+- value. The referenced value is <i>not</i> consumed.
+- </blockquote>
+- This extension allows optional values to be positionally
+- referenced, so that message templates can be constructed that
+- can produce the proper word ordering for a language.
+-
+- <h3>Preparing Bundles</h3>
+- Before a bundle may be used by the Scheme system to retrieve
+- localized template messages, they must be made available to the
+- Scheme system. This SRFI specifies a way to portably
+- define the bundles, as well as store them in and retrieve them
+- from an unspecified system which may be provided by resources
+- outside the Scheme system.<br>
+-
+-
+- <p><b><a name="declare-bundle!"></a><tt>declare-bundle!</tt></b> <tt><i>bundle-specifier
+- association-list</i> -> undefined<br>
+- </tt></p>
+-
+- <blockquote>
+- Declares a new bundle named by the given bundle-specifier.
+- The contents of the bundle are defined by the provided
+- association list. The list contains associations
+- between Scheme symbols and the message templates (Scheme
+- strings) they name. If a bundle already exists with the
+- given name, it is overwritten with the newly declared
+- bundle.<br>
+- </blockquote>
+- <tt><a name="store-bundle"></a><b>store-bundle</b> <i>bundle-specifier</i> ->
+- boolean</tt><br>
+-
+-
+- <blockquote>
+- Attempts to store a bundle named by the given bundle
+- specifier, and previously made available using
+- <tt>declare-bundle!</tt> or <tt>load-bundle!</tt>, in an
+- unspecified mechanism that may be persistent across Scheme
+- system restarts. If successful, a non-false value is
+- returned. If unsuccessful, <tt>#f</tt> is returned.<br>
+- </blockquote>
+- <tt><a name="load-bundle!"></a><b>load-bundle!</b> <i>bundle-specifier</i> ->
+- boolean</tt><br>
+-
+-
+- <blockquote>
+- Attempts to retrieve a bundle from an unspecified mechanism
+- which stores bundles outside the Scheme system. If the
+- bundle was retrieved successfully, the function returns a
+- non-false value, and the bundle is immediately available to
+- the Scheme system. If the bundle could not be found or loaded
+- successfully, the function returns <tt>#f</tt>, and the
+- Scheme system's bundle registry remains unaffected.<br>
+- </blockquote>
+- A compliant Scheme system may choose not to provide any
+- external mechanism to store localized bundles. If it does
+- not, it must still provide implementations for
+- <tt>store-bundle</tt> and <tt>load-bundle!</tt>. In such a
+- case, both functions must return <tt>#f</tt> regardless of the
+- arguments given. Users of this SRFI should recognize that the
+- inability to load or store a localized bundle in an external
+- repository is <i>not</i> a fatal error.<br>
+-
+-
+- <h3>Retrieving Localized Message Templates</h3>
+-
+- <p><a name="localized-template"></a><b><tt>localized-template</tt></b> <i><tt>package-name
+- message-template-name</tt></i> <tt>-> <i>string or #f<br>
+- </i></tt></p>
+-
+- <blockquote>
+- Retrieves a localized message template for the given package
+- name and the given message template name (both symbols).
+- If no such message could be found, false (#f) is
+- returned.<br>
+- <br>
+- </blockquote>
+- After retrieving a template, the calling program can use
+- <tt>format</tt> to produce a string that can be displayed to
+- the user.<br>
+-
+-
+- <h2>Examples</h2>
+- The below example makes use of SRFI-29 to display simple,
+- localized messages. It also defines its bundles in such a
+- way that the Scheme system may store and retrieve the bundles
+- from a more efficient system catalog, if available.<br>
+-
+-<pre>
+-(let ((translations
+- '(((en) . ((time . "Its ~a, ~a.")
+- (goodbye . "Goodbye, ~a.")))
+- ((fr) . ((time . "~1@*~a, c'est ~a.")
+- (goodbye . "Au revoir, ~a."))))))
+- (for-each (lambda (translation)
+- (let ((bundle-name (cons 'hello-program (car translation))))
+- (if (not (load-bundle! bundle-name))
+- (begin
+- (declare-bundle! bundle-name (cdr translation))
+- (store-bundle! bundle-name)))))
+- translations))
+-
+-(define localized-message
+- (lambda (message-name . args)
+- (apply format (cons (localized-template 'hello-program
+- message-name)
+- args))))
+-
+-(let ((myname "Fred"))
+- (display (localized-message 'time "12:00" myname))
+- (display #\newline)
+-
+- (display (localized-message 'goodbye myname))
+- (display #\newline))
+-
+-;; Displays (English):
+-;; Its 12:00, Fred.
+-;; Goodbye, Fred.
+-;;
+-;; French:
+-;; Fred, c'est 12:00.
+-;; Au revoir, Fred.
+-</pre>
+-
+- <H1>Implementation</H1>
+-
+- <p>The implementation requires that the Scheme system provide a
+- definition for <tt>current-language</tt> and
+- <tt>current-country</tt> capable of distinguishing the correct
+- locale present during a Scheme session. The definitions of
+- those functions in the reference implementation are not capable
+- of that distinction. Their implementation is provided only so
+- that the following code can run in any R4RS scheme system.
+- <br>
+- </p>
+-
+- <p>In addition, the below implementation of a compliant
+- <tt>format</tt> requires SRFI-6 (Basic String Ports) and
+- SRFI-23 (Error reporting)</p>
+-<pre>
+-;; The association list in which bundles will be stored
+-(define *localization-bundles* '())
+-
+-;; The current-language and current-country functions provided
+-;; here must be rewritten for each Scheme system to default to the
+-;; actual locale of the session
+-(define current-language
+- (let ((current-language-value 'en))
+- (lambda args
+- (if (null? args)
+- current-language-value
+- (set! current-language-value (car args))))))
+-
+-(define current-country
+- (let ((current-country-value 'us))
+- (lambda args
+- (if (null? args)
+- current-country-value
+- (set! current-country-value (car args))))))
+-
+-;; The load-bundle! and store-bundle! both return #f in this
+-;; reference implementation. A compliant implementation need
+-;; not rewrite these procedures.
+-(define load-bundle!
+- (lambda (bundle-specifier)
+- #f))
+-
+-(define store-bundle!
+- (lambda (bundle-specifier)
+- #f))
+-
+-;; Declare a bundle of templates with a given bundle specifier
+-(define declare-bundle!
+- (letrec ((remove-old-bundle
+- (lambda (specifier bundle)
+- (cond ((null? bundle) '())
+- ((equal? (caar bundle) specifier)
+- (cdr bundle))
+- (else (cons (car bundle)
+- (remove-old-bundle specifier
+- (cdr bundle))))))))
+- (lambda (bundle-specifier bundle-assoc-list)
+- (set! *localization-bundles*
+- (cons (cons bundle-specifier bundle-assoc-list)
+- (remove-old-bundle bundle-specifier
+- *localization-bundles*))))))
+-
+-;;Retrieve a localized template given its package name and a template name
+-(define localized-template
+- (letrec ((rdc
+- (lambda (ls)
+- (if (null? (cdr ls))
+- '()
+- (cons (car ls) (rdc (cdr ls))))))
+- (find-bundle
+- (lambda (specifier template-name)
+- (cond ((assoc specifier *localization-bundles*) =>
+- (lambda (bundle) bundle))
+- ((null? specifier) #f)
+- (else (find-bundle (rdc specifier)
+- template-name))))))
+- (lambda (package-name template-name)
+- (let loop ((specifier (cons package-name
+- (list (current-language)
+- (current-country)))))
+- (and (not (null? specifier))
+- (let ((bundle (find-bundle specifier template-name)))
+- (and bundle
+- (cond ((assq template-name bundle) => cdr)
+- ((null? (cdr specifier)) #f)
+- (else (loop (rdc specifier)))))))))))
+-
+-;;An SRFI-28 and SRFI-29 compliant version of format. It requires
+-;;SRFI-23 for error reporting.
+-(define format
+- (lambda (format-string . objects)
+- (let ((buffer (open-output-string)))
+- (let loop ((format-list (string->list format-string))
+- (objects objects)
+- (object-override #f))
+- (cond ((null? format-list) (get-output-string buffer))
+- ((char=? (car format-list) #\~)
+- (cond ((null? (cdr format-list))
+- (error 'format "Incomplete escape sequence"))
+- ((char-numeric? (cadr format-list))
+- (let posloop ((fl (cddr format-list))
+- (pos (string->number
+- (string (cadr format-list)))))
+- (cond ((null? fl)
+- (error 'format "Incomplete escape sequence"))
+- ((and (eq? (car fl) '#\@)
+- (null? (cdr fl)))
+- (error 'format "Incomplete escape sequence"))
+- ((and (eq? (car fl) '#\@)
+- (eq? (cadr fl) '#\*))
+- (loop (cddr fl) objects (list-ref objects pos)))
+- (else
+- (posloop (cdr fl)
+- (+ (* 10 pos)
+- (string->number
+- (string (car fl)))))))))
+- (else
+- (case (cadr format-list)
+- ((#\a)
+- (cond (object-override
+- (begin
+- (display object-override buffer)
+- (loop (cddr format-list) objects #f)))
+- ((null? objects)
+- (error 'format "No value for escape sequence"))
+- (else
+- (begin
+- (display (car objects) buffer)
+- (loop (cddr format-list)
+- (cdr objects) #f)))))
+- ((#\s)
+- (cond (object-override
+- (begin
+- (display object-override buffer)
+- (loop (cddr format-list) objects #f)))
+- ((null? objects)
+- (error 'format "No value for escape sequence"))
+- (else
+- (begin
+- (write (car objects) buffer)
+- (loop (cddr format-list)
+- (cdr objects) #f)))))
+- ((#\%)
+- (if object-override
+- (error 'format "Escape sequence following positional override does not require a value"))
+- (display #\newline buffer)
+- (loop (cddr format-list) objects #f))
+- ((#\~)
+- (if object-override
+- (error 'format "Escape sequence following positional override does not require a value"))
+- (display #\~ buffer)
+- (loop (cddr format-list) objects #f))
+- (else
+- (error 'format "Unrecognized escape sequence"))))))
+- (else (display (car format-list) buffer)
+- (loop (cdr format-list) objects #f)))))))
+-
+-</pre>
+-
+- <H1>Copyright</H1>
+-
+- Copyright (C) Scott G. Miller (2002). All Rights Reserved.
+-
+- <p>This document and translations of it may be copied and
+- furnished to others, and derivative works that comment on or
+- otherwise explain it or assist in its implementation may be
+- prepared, copied, published and distributed, in whole or in
+- part, without restriction of any kind, provided that the above
+- copyright notice and this paragraph are included on all such
+- copies and derivative works. However, this document itself may
+- not be modified in any way, such as by removing the copyright
+- notice or references to the Scheme Request For Implementation
+- process or editors, except as needed for the purpose of
+- developing SRFIs in which case the procedures for copyrights
+- defined in the SRFI process must be followed, or as required to
+- translate it into languages other than English.</p>
+-
+- <p>The limited permissions granted above are perpetual and will
+- not be revoked by the authors or their successors or
+- assigns.</p>
+-
+- <p>This document and the information contained herein is
+- provided on an "AS IS" basis and THE AUTHOR AND THE SRFI
+- EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES
+- OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>
+- <hr>
+-
+- <address>
+- Editor: <a href="mailto:srfi-editors@srfi.schemers.org">David
+- Rush</a>
+- </address>
+-
+- <address>
+- Author: <a href="mailto:scgmille@freenetproject.org">Scott G.
+- Miller</a>
+- </address>
+- <!-- Created: Tue Sep 29 19:20:08 EDT 1998 -->
+- <!-- hhmts start -->Last modified: Mon Jun 17 12:00:08 Pacific
+- Daylight Time 2002 <!-- hhmts end --> <br>
+- </body>
+-</html>
+-
+diff -urN racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html
+--- racket-6.12-nf/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html 2018-01-31 13:04:07.221391727 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,345 +0,0 @@
+-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+-<html>
+-<head>
+- <title>SRFI 5: A compatible let form with signatures and rest arguments</title>
+-</head>
+-<body>
+-
+-<H1>Title</H1>
+-
+-SRFI-5: A compatible <code>let</code> form with signatures and rest arguments
+-
+-<H1>Author</H1>
+-
+-Andy Gaynor
+-
+-<H1>Status</H1>
+-
+-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html ">here</A>.
+-You can access the discussion on this SRFI via <A HREF="http://srfi.schemers.org/srfi-5/mail-archive/maillist.html ">the archive of the mailing list</A>.
+-<P><UL>
+-<LI>Received: 1999/2/2
+-<LI>Draft: 1999/2/10-1999/04/12
+-<LI>Final: 1999/4/26
+-<LI>Revised reference implementation: 2003/01/27
+-</UL>
+-
+-<H1>Abstract</H1>
+-
+-The <i>named-let</i> incarnation of the <code>let</code> form has two slight
+-inconsistencies with the <code>define</code> form. As defined, the <code>let</code>
+-form makes no accommodation for rest arguments, an issue of functionality
+-and consistency. As defined, the <code>let</code> form does not accommodate
+-signature-style syntax, an issue of aesthetics and consistency. Both
+-issues are addressed here in a manner which is compatible with the traditional
+-<code>let</code> form but for minor extensions.
+-
+-<H1>Rationale</H1>
+-
+-<H2>Signature-style Syntax</H2>
+-
+-Consider the following two equivalent definitions:
+-
+-<p><pre>
+-(define fibonacci
+- (lambda (n i f0 f1)
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1)))))
+-
+-(define (fibonacci n i f0 f1)
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-</pre>
+-
+-Although there is a named-let analog for the former form, there is none
+-for the latter. To wit, suppose one wished to compute the 10th element
+-of the Fibonacci sequence using a named let:
+-
+-<p>
+-<pre>
+-(let fibonacci ((n 10) (i 0) (f0 0) (f1 1))
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-Values: 55
+-</pre>
+-
+-As it stands, one cannot equivalently write
+-
+-<p>
+-<pre>
+-(let (fibonacci (n 10) (i 0) (f0 0) (f1 1))
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-</pre>
+-
+-which is consistent with <code>define</code>'s signature-style form.
+-<p>Those that favor the signature style may prefer this extension.
+-In any case, it may be more appropriate to include all bound names within
+-the binding section. As presented, this straightforward extension
+-introduces no ambiguity or incompatibility with the existing definition
+-of let.
+-
+-<H2>Rest Arguments</H2>
+-
+-As it stands, one cannot write a named let with rest arguments, as in
+-
+-<p>
+-<pre>
+-(let (blast (port (current-output-port)) . (x (+ 1 2) 4 5))
+- (if (null? x)
+- 'just-a-silly-contrived-example
+- (begin
+- (write (car x) port)
+- (apply blast port (cdr x)))))
+-</pre>
+-
+-otherwise equivalent to
+-
+-<p>
+-<pre>
+-(letrec ((blast (lambda (port . x)
+- (if (null? x)
+- 'just-a-silly-contrived-example
+- (begin
+- (write (car x) port)
+- (apply blast port (cdr x)))))))
+- (blast (current-output-port) (+ 1 2) 4 5))
+-</pre>
+-
+-While this example is rather contrived, the functionality is not.
+-There are several times when the author has used this construct in practice.
+-Regardless, there is little reason to deny the <code>let</code> form access to
+-all the features of lambda functionality.
+-
+-<H2>Symbols in Binding Sections</H2>
+-
+-Both the features above rely upon the placement of symbols in <code>let</code>
+-binding lists (this statement is intentially simplistic). The only
+-other apparent use of such symbol placement is to tersely bind variables
+-to unspecified values. For example, one might desire to use
+-<code>(let (foo bar baz) ...)</code>
+-to bind <code>foo</code>, <code>bar</code>, and <code>baz</code> to
+-unspecified values.
+-
+-<p>This usage is considered less important in light of the rationales
+-presented above, and an alternate syntax is immediately apparent, as
+-in <code>(let ((foo) (bar) (baz)) ...)</code> This may even
+-be preferable, consistently parenthesizing normal binding clauses.
+-
+-<H1>Specification</H1>
+-
+-<H2>Syntax</H2>
+-
+-<p>
+-A formal specification of the syntax follows. Below, body, expression,
+-and identifier are free. Each instantiation of binding-name must be
+-unique.
+-</p>
+-
+-<p>
+-<pre>
+- let = "(" "let" let-bindings body ")"
+- expressions = nothing | expression expressions
+- let-bindings = let-name bindings
+- |"(" let-name "." bindings ")"
+- let-name = identifier
+- bindings = "(" ")"
+- | rest-binding
+- | "(" normal-bindings ["." rest-binding] ")"
+-normal-bindings = nothing
+- | normal-binding normal-bindings
+-normal-binding = "(" binding-name expression ")"
+- binding-name = identifier
+- rest-binding = "(" binding-name expressions ")"
+-</pre>
+-
+-<p>
+-For clarity and convenience, an informal specification follows.
+-</p>
+-
+-<ol>
+-<li><a name="unnamed">Unnamed</a>
+-
+-<p><pre>
+-(let ((<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-non-sig">
+-Named, non-signature-style, no rest argument</a>
+-
+-<p><pre>
+-(let <name> ((<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-sig">Named, signature-style, no rest argument</a>
+-
+-<p><pre>
+-(let (<name> (<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-non-sig-rest">Named, non-signature-style, rest argument</a>
+-
+-<p><pre>
+-(let <name> ((<parameter> <argument>)...
+-
+-. (<rest-parameter> <rest-argument>...))
+- <body>...)
+-</pre>
+-
+-<li><a name="named-sig-rest">Named, signature-style, rest argument</a>
+-
+-<p><pre>
+-(let (<name> (<parameter> <argument>)...
+-
+-. (<rest-parameter> <rest-argument>...))
+- <body>...)
+-</pre>
+-</li>
+-</ol>
+-
+-<H2>Semantics</H2>
+-
+-Let <code>$lambda</code> and <code>$letrec</code> be hygienic bindings for the <code>lambda</code>
+-and <code>letrec</code> forms, respectively.
+-
+-<ul>
+-<li>For informal syntax 1:
+-
+-<p><pre>
+-(($lambda (<parameter>...) <body>...) <argument>...)
+-</pre>
+-</li>
+-
+-<li>For informal syntaxes 2 and 3:
+-
+-<p>
+-<pre>
+-($letrec ((<name> ($lambda (<parameter>...) <body>...)))
+- (<name> <argument>...))
+-</pre>
+-</li>
+-
+-<li>For informal syntaxes 4 and 5:
+-
+-<p>
+-<pre>
+-($letrec ((<name> ($lambda (<parameter>...
+-
+-. <rest-parameter>) <body>...)))
+- (<name> <argument>... <rest-argument>...))
+-</pre>
+-</li>
+-</ul>
+-
+-<H1>Implementation</H1>
+-
+-Here is an implementation using <code>SYNTAX-RULES</code>.
+-
+-<p>
+-<pre>
+-;; Use your own standard let.
+-;; Or call a lambda.
+-;; (define-syntax standard-let
+-;;
+-;; (syntax-rules ()
+-;;
+-;; ((let ((var val) ...) body ...)
+-;; ((lambda (var ...) body ...) val ...))))
+-
+-(define-syntax let
+-
+- (syntax-rules ()
+-
+- ;; No bindings: use standard-let.
+- ((let () body ...)
+- (standard-let () body ...))
+- ;; Or call a lambda.
+- ;; ((lambda () body ...))
+-
+- ;; All standard bindings: use standard-let.
+- ((let ((var val) ...) body ...)
+- (standard-let ((var val) ...) body ...))
+- ;; Or call a lambda.
+- ;; ((lambda (var ...) body ...) val ...)
+-
+- ;; One standard binding: loop.
+- ;; The all-standard-bindings clause didn't match,
+- ;; so there must be a rest binding.
+- ((let ((var val) . bindings) body ...)
+- (let-loop #f bindings (var) (val) (body ...)))
+-
+- ;; Signature-style name: loop.
+- ((let (name binding ...) body ...)
+- (let-loop name (binding ...) () () (body ...)))
+-
+- ;; defun-style name: loop.
+- ((let name bindings body ...)
+- (let-loop name bindings () () (body ...)))))
+-
+-(define-syntax let-loop
+-
+- (syntax-rules ()
+-
+- ;; Standard binding: destructure and loop.
+- ((let-loop name ((var0 val0) binding ...) (var ... ) (val ... ) body)
+- (let-loop name ( binding ...) (var ... var0) (val ... val0) body))
+-
+- ;; Rest binding, no name: use standard-let, listing the rest values.
+- ;; Because of let's first clause, there is no "no bindings, no name" clause.
+- ((let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
+- (standard-let ((var val) ... (rest-var (list rest-val ...))) . body))
+- ;; Or call a lambda with a rest parameter on all values.
+- ;; ((lambda (var ... . rest-var) . body) val ... rest-val ...))
+- ;; Or use one of several other reasonable alternatives.
+-
+- ;; No bindings, name: call a letrec'ed lambda.
+- ((let-loop name () (var ...) (val ...) body)
+- ((letrec ((name (lambda (var ...) . body)))
+- name)
+- val ...))
+-
+- ;; Rest binding, name: call a letrec'ed lambda.
+- ((let-loop name (rest-var rest-val ...) (var ...) (val ...) body)
+- ((letrec ((name (lambda (var ... . rest-var) . body)))
+- name)
+- val ... rest-val ...))))
+-</pre>
+-
+-
+-<H1>Copyright</H1>
+-
+-Copyright (C) Andy Gaynor (1999). All Rights Reserved.
+-<p>This document and translations of it may be copied and furnished to
+-others, and derivative works that comment on or otherwise explain it or
+-assist in its implementation may be prepared, copied, published and distributed,
+-in whole or in part, without restriction of any kind, provided that the
+-above copyright notice and this paragraph are included on all such copies
+-and derivative works. However, this document itself may not be modified
+-in any way, such as by removing the copyright notice or references to the
+-Scheme Request For Implementation process or editors, except as needed
+-for the purpose of developing SRFIs in which case the procedures for copyrights
+-defined in the SRFI process must be followed, or as required to translate
+-it into languages other than English.
+-<p>The limited permissions granted above are perpetual and will not be
+-revoked by the authors or their successors or assigns.
+-<p>This document and the information contained herein is provided on an
+-"AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES,
+-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE
+-USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+-WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+-
+- <hr>
+- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address>
+-
+-</body>
+-</html>
+diff -urN racket-6.12-nf/share/pkgs/srfi-lib-nonfree/info.rkt racket-6.12/share/pkgs/srfi-lib-nonfree/info.rkt
+--- racket-6.12-nf/share/pkgs/srfi-lib-nonfree/info.rkt 2018-01-31 13:04:07.236391659 -0500
++++ racket-6.12/share/pkgs/srfi-lib-nonfree/info.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,14 +0,0 @@
+-#lang info
+-
+-(define collection 'multi)
+-
+-(define deps '("scheme-lib"
+- "base"
+- "r6rs-lib"
+- "srfi-lib"
+- "compatibility-lib"))
+-
+-
+-(define pkg-desc "implementation (no documentation) part of \"srfi nonfree\"")
+-
+-(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/%3a5/let.rkt racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/%3a5/let.rkt
+--- racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/%3a5/let.rkt 2018-01-31 13:04:07.236391659 -0500
++++ racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/%3a5/let.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1 +0,0 @@
+-#lang s-exp srfi/provider srfi/%3a5
+diff -urN racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/%3a5.rkt racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/%3a5.rkt
+--- racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/%3a5.rkt 2018-01-31 13:04:07.236391659 -0500
++++ racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/%3a5.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,3 +0,0 @@
+-#lang s-exp srfi/provider srfi/5
+-
+-;; FIXME: "rest arguments" need to generate mutable lists
+diff -urN racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/5/let.rkt racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/5/let.rkt
+--- racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/5/let.rkt 2018-01-31 13:04:07.236391659 -0500
++++ racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/5/let.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,86 +0,0 @@
+-;;;
+-;;; <let.rkt> ---- SRFI 5 A compatible let form with signatures and rest arguments
+-;;; Time-stamp: <03/04/08 09:56:06 solsona>
+-;;;
+-;;; Usually, I would add a copyright notice, and the announce that
+-;;; this code is under the LGPL licence. Nevertheless, I only did the
+-;;; port to PLT Scheme v200, and here is the copyright notice,
+-;;; comments, and licence from the original source:
+-;;;
+-;;; Copyright (C) Andy Gaynor (1999-2003)
+-;;;
+-;;; The version of my-let here was cleaned up by: Paul Schlie <schlie(a)attbi.com>.
+-;;; Renamed to s:let by Eli Barzilay
+-
+-#lang scheme/base
+-(provide s:let)
+-
+-(define-syntax s:let
+- (syntax-rules ()
+- ;; standard
+- ((s:let () body ...)
+- (let () body ...))
+- ((s:let ((var val) ...) body ...)
+- (let ((var val) ...) body ...))
+-
+- ;; rest style
+- ((s:let ((var val) . bindings) body ...)
+- (let-loop #f bindings (var) (val) (body ...)))
+-
+- ;; signature style
+- ((s:let (name bindings ...) body ...)
+- (let-loop name (bindings ...) () () (body ...)))
+-
+- ;; standard named style
+- ((s:let name (bindings ...) body ...)
+- (let-loop name (bindings ...) () () (body ...)))
+-
+- ))
+-
+-;; A loop to walk down the list of bindings.
+-
+-(define-syntax let-loop
+- (syntax-rules ()
+-
+- ;; No more bindings - make a LETREC.
+- ((let-loop name () (vars ...) (vals ...) body)
+- ((letrec ((name (lambda (vars ...) . body)))
+- name)
+- vals ...))
+-
+- ;; Rest binding, no name
+- ((let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
+- (let ((var val) ... (rest-var (list rest-val ...))) . body))
+-
+- ;; Process a (var val) pair.
+- ((let-loop name ((var val) more ...) (vars ...) (vals ...) body)
+- (let-loop name (more ...) (vars ... var) (vals ... val) body))
+-
+- ;; End with a rest variable - make a LETREC.
+- ((let-loop name (rest-var rest-vals ...) (vars ...) (vals ...) body)
+- ((letrec ((name (lambda (vars ... . rest-var) . body)))
+- name)
+- vals ... rest-vals ...))))
+-
+-;; Four loops - normal and `signature-style', each with and without a rest
+-;; binding.
+-;;
+-;;(let fibonacci ((n 10) (i 0) (f0 0) (f1 1))
+-;; (if (= i n)
+-;; f0
+-;; (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-;;
+-;;(let (fibonacci (n 10) (i 0) (f0 0) (f1 1))
+-;; (if (= i n)
+-;; f0
+-;; (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-;;
+-;;(let fibonacci ((n 10) (i 0) . (f 0 1))
+-;; (if (= i n)
+-;; (car f)
+-;; (fibonacci n (+ i 1) (cadr f) (+ (car f) (cadr f)))))
+-;;
+-;;(let (fibonacci (n 10) (i 0) . (f 0 1))
+-;; (if (= i n)
+-;; (car f)
+-;; (fibonacci n (+ i 1) (cadr f) (+ (car f) (cadr f)))))
+diff -urN racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/5.rkt racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/5.rkt
+--- racket-6.12-nf/share/pkgs/srfi-lib-nonfree/srfi/5.rkt 2018-01-31 13:04:07.236391659 -0500
++++ racket-6.12/share/pkgs/srfi-lib-nonfree/srfi/5.rkt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,2 +0,0 @@
+-;; module loader for SRFI-5
+-#lang s-exp srfi/provider srfi/5/let #:unprefix s:
diff --git a/racket-6.12-update-srfi.patch b/racket-6.12-update-srfi.patch
new file mode 100644
index 0000000..1894e32
--- /dev/null
+++ b/racket-6.12-update-srfi.patch
@@ -0,0 +1,4369 @@
+diff -urN racket-6.12-orig/share/links.rktd racket-6.12/share/links.rktd
+--- racket-6.12-orig/share/links.rktd 2018-01-26 16:12:13.000000000 -0500
++++ racket-6.12/share/links.rktd 2018-01-31 12:22:57.600504036 -0500
+@@ -133,6 +133,7 @@
+ (root "pkgs/r5rs-doc")
+ (root "pkgs/srfi-lite-lib")
+ (root "pkgs/srfi-lib")
++ (root "pkgs/srfi-lib-nonfree")
+ (root "pkgs/html-doc")
+ (root "pkgs/images-gui-lib")
+ (root "pkgs/images-doc")
+@@ -176,6 +177,7 @@
+ (root "pkgs/slideshow-exe")
+ (root "pkgs/slideshow-plugin")
+ (root "pkgs/srfi-doc")
++ (root "pkgs/srfi-doc-nonfree")
+ (root "pkgs/syntax-color-doc")
+ (root "pkgs/web-server-lib")
+ (root "pkgs/unix-socket-lib")
+diff -urN racket-6.12-orig/share/pkgs/srfi/info.rkt racket-6.12/share/pkgs/srfi/info.rkt
+--- racket-6.12-orig/share/pkgs/srfi/info.rkt 2018-01-26 16:10:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi/info.rkt 2018-01-31 12:22:58.139502019 -0500
+@@ -1 +1,16 @@
+-(module info setup/infotab (#%module-begin (define package-content-state (quote (built "6.12"))) (define collection (quote multi)) (define deps (quote ("srfi-lib" "srfi-doc"))) (define implies (quote ("srfi-lib" "srfi-doc"))) (define pkg-desc "Legacy SRFI (Scheme) libraries") (define pkg-authors (quote (mflatt noel chongkai jay)))))
++#lang info
++
++(define collection 'multi)
++
++(define deps '("srfi-lib"
++ "srfi-lib-nonfree"
++ "srfi-doc"
++ "srfi-doc-nonfree"))
++(define implies '("srfi-lib"
++ "srfi-lib-nonfree"
++ "srfi-doc"
++ "srfi-foc-nonfree"))
++
++(define pkg-desc "Legacy SRFI (Scheme) libraries")
++
++(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc/info.rkt racket-6.12/share/pkgs/srfi-doc/info.rkt
+--- racket-6.12-orig/share/pkgs/srfi-doc/info.rkt 2018-01-26 16:10:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc/info.rkt 2018-01-31 12:22:58.139502019 -0500
+@@ -1 +1,24 @@
+-(module info setup/infotab (#%module-begin (define package-content-state (quote (built "6.12"))) (define collection (quote multi)) (define build-deps (quote ("mzscheme-doc" "scheme-lib" "base" "scribble-lib" "srfi-lib" "racket-doc" "r5rs-doc" "r6rs-doc" "compatibility-lib"))) (define update-implies (quote ("srfi-lib"))) (define pkg-desc "documentation part of \"srfi\"") (define pkg-authors (quote (mflatt noel chongkai jay)))))
++#lang info
++
++(define collection 'multi)
++
++(define build-deps '("mzscheme-doc"
++ "scheme-lib"
++ "base"
++ "scribble-lib"
++ "srfi-lib"
++ "racket-doc"
++ "r5rs-doc"
++ "r6rs-doc"
++ "compatibility-lib"))
++
++(define deps '("scheme-lib"
++ "base"
++ "scribble-lib"
++ "compatibility-lib"))
++
++(define update-implies '("srfi-lib"))
++
++(define pkg-desc "documentation part of \"srfi\"")
++
++(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi.scrbl racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi.scrbl
+--- racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi.scrbl 2018-01-26 15:34:52.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi.scrbl 2018-01-31 12:22:58.144502000 -0500
+@@ -1,5 +1,6 @@
+ #lang scribble/doc
+-@(require scribble/manual
++@(require srfi/scribblings/util
++ scribble/manual
+ scribble/eval
+ scriblib/render-cond
+ scribble/core
+@@ -8,54 +9,6 @@
+ (for-label scheme/base
+ racket/stream))
+
+-@(define-syntax (srfi stx)
+- (syntax-case stx ()
+- [(_ num #:subdir subdir? . title)
+- (with-syntax ([srfi/n (string->symbol (format "srfi/~a" (syntax-e #'num)))])
+- #'(begin
+- (section #:tag (format "srfi-~a" num)
+- #:style 'unnumbered
+- (format "SRFI ~a: " num)
+- . title)
+- (defmodule srfi/n)
+- "Original specification: "
+- (let* ([label (format "SRFI ~a" num)]
+- [sub (if subdir? (format "srfi-~a/" num) "")]
+- [url ( (b) (format "~a/srfi-std/~asrfi-~a.html" b sub num))])
+- (cond-element
+- [(or latex text) @link[(url "http://docs.racket-lang.org ") label]]
+- [else @link[(url ".") label]]))))]
+- [(_ num . title) #'(srfi num #:subdir #f . title)]))
+-
+-@;{ The `lst' argument is a list of
+- (list sym syntactic-form? html-anchor) }
+-@(define (redirect n lst #:subdir [subdir? #f])
+- (let ([file (if subdir?
+- (format "srfi-~a/srfi-~a.html" n n)
+- (format "srfi-~a.html" n))]
+- [mod-path (string->symbol (format "srfi/~a" n))])
+- (make-binding-redirect-elements mod-path
+- (map (lambda (b)
+- (list (car b) (cadr b)
+- (build-path "srfi-std" file)
+- (caddr b)))
+- lst))))
+-
+-@(define in-core
+- (case-lambda
+- [() (in-core ".")]
+- [(k) @elem{This SRFI's bindings are also available in
+- @racketmodname[racket/base]@|k|}]))
+-
+-@(begin
+- (define-syntax-rule (def-mz mz-if)
+- (begin
+- (require (for-label mzscheme))
+- (define mz-if (racket if))))
+- (def-mz mz-if))
+-
+-@(define srfi-std (style #f (list (install-resource "srfi-std"))))
+-
+ @; ----------------------------------------------------------------------
+
+ @title{SRFIs: Libraries}
+@@ -245,14 +198,6 @@
+
+ @; ----------------------------------------
+
+-@srfi[5]{A compatible let form with signatures and rest arguments}
+-
+-@redirect[5 '(
+- (let #t "unnamed")
+-)]
+-
+-@; ----------------------------------------
+-
+ @srfi[6]{Basic String Ports}
+
+ @redirect[6 '(
+@@ -671,20 +616,6 @@
+
+ @; ----------------------------------------
+
+-@srfi[29]{Localization}
+-
+-@redirect[29 '(
+- (current-language #f "current-language")
+- (current-country #f "current-country")
+- (current-locale-details #f "current-locale-details")
+- (declare-bundle! #f "declare-bundle!")
+- (store-bundle #f "store-bundle")
+- (load-bundle! #f "load-bundle!")
+- (localized-template #f "localized-template")
+-)]
+-
+-@; ----------------------------------------
+-
+ @srfi[30]{Nested Multi-line Comments}
+
+ This SRFI's syntax is part of Racket's default reader.
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html
+--- racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html 2018-01-26 15:34:52.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,507 +0,0 @@
+-<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN">
+-<html>
+- <head>
+- <meta name="generator" content="HTML Tidy, see www.w3.org ">
+- <title>SRFI 29: Localization</title>
+- <meta name="author" content="Scott G. Miller">
+- <meta name="description" content="Localization">
+- </head>
+- <body>
+- <H1>Title</H1>
+-
+- SRFI 29: Localization
+-
+- <H1>Author</H1>
+-
+- Scott G. Miller
+-
+- <H1>Abstract</H1>
+-
+- This document specifies an interface to retrieving and
+- displaying locale sensitive messages. A Scheme program can
+- register one or more translations of templated messages, and
+- then write Scheme code that can transparently retrieve the
+- appropriate message for the locale under which the Scheme
+- system is running. <br>
+-
+-
+- <H1>Rationale</H1>
+-
+- <p>As any programmer that has ever had to deal with making his
+- or her code readable in more than one locale, the process of
+- sufficiently abstracting program messages from their
+- presentation to the user is non-trivial without help from the
+- programming language. Most modern programming language
+- libraries do provide some mechanism for performing this
+- separation.</p>
+-
+- <p>A portable API that allows a piece of code to run without
+- modification in different countries and under different
+- languages is a must for any non-trivial software project.
+- The interface should separate the logic of a program from
+- the myriad of translations that may be necessary.</p>
+-
+- <p>The interface described in this document provides such
+- functionality. The underlying implementation is also allowed to
+- use whatever datastructures it likes to provide access to the
+- translations in the most efficient manner possible. In
+- addition, the implementation is provided with standardized
+- functions that programs will use for accessing an external,
+- unspecified repository of translations.</p>
+-
+- <p>This interface <i>does not</i> cover all aspects of
+- localization, including support for non-latin characters,
+- number and date formatting, etc. Such functionality is the
+- scope of a future SRFI that may extend this one.</p>
+-
+- <H1>Dependencies</H1>
+-
+- An SRFI-29 conformant implementation must also implement
+- SRFI-28, Basic Format Strings. Message templates are strings
+- that must be processed by the <tt>format</tt> function
+- specified in that SRFI.
+-
+- <H1>Specification</H1>
+-
+- <h3>Message Bundles</h3>
+-
+- <p>A Message Bundle is a set of message templates and their
+- identifying keys. Each bundle contains one or more such
+- key/value pairs. The bundle itself is associated with a
+- <i>bundle specifier</i> which uniquely identifies the
+- bundle.</p>
+-
+- <h3>Bundle Specifiers</h3>
+-
+- <p>A Bundle Specifier is a Scheme list that describes, in order
+- of importance, the package and locale of a message bundle.
+- In most cases, a locale specifier will have between one
+- and three elements. The first element is a symbol denoting the
+- package for which this bundle applies. The second and third
+- elements denote a <i>locale</i>. The second element (first
+- element of the locale) if present, is the two letter, ISO 639-1
+- language code for the bundle. The third element, if present, is
+- a two letter ISO 3166-1 country code. In some cases, a
+- fourth element may be present, specifying the encoding used for
+- the bundle. All bundle specifier elements are Scheme
+- symbols.</p>
+-
+- <p>If only one translation is provided, it should be designated
+- only by a package name, for example <tt>(mathlib)</tt>. This
+- translation is called the <i>default</i> translation.</p>
+-
+- <h3>Bundle Searching</h3>
+-
+- <p>When a message template is retrieved from a bundle, the
+- Scheme implementation will provide the locale under which the
+- system is currently running. When the template is retrieved,
+- the package name will be specified. The Scheme system should
+- construct a Bundle Specifier from the provided package name and
+- the active locale. For example, when retrieving a message
+- template for French Canadian, in the <tt>mathlib</tt> package,
+- the bundle specifier '<tt>(mathlib fr ca)</tt>' is used. A
+- program may also retrieve the elements of the current locale
+- using the no-argument procedures:</p>
+-
+- <p><b><a name="current-language"></a><tt>current-language</tt></b> <tt>->
+- <i>symbol</i></tt><br>
+- <tt><b>current-language</b> <i>symbol</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- When given no arguments, returns the current ISO 639-1
+- language code as a symbol. If provided with an
+- argument, the current language is set to that named by the
+- symbol for the currently executing Scheme thread (or for the
+- entire Scheme system if such a distinction is not possible).
+-
+- </blockquote>
+-
+- <p><b><a name="current-country"></a><tt>current-country</tt></b> <tt>->
+- <i>symbol</i></tt><br>
+- <tt><b>current-country</b> <i>symbol</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- returns the current ISO 3166-1 country code as a symbol.
+- If provided with an argument, the current country is
+- set to that named by the symbol for the currently executing
+- Scheme thread (or for the entire Scheme system if such a
+- distinction is not possible).
+- </blockquote>
+-
+- <p><b><a name="current-locale-details"></a><tt>current-locale-details</tt></b> <tt>-> <i>list of
+- symbol</i></tt>s<br>
+- <tt><b>current-locale-details</b> <i>list-of-symbols</i> ->
+- undefined</tt><br>
+- </p>
+-
+- <blockquote>
+- Returns a list of additional locale details as a list of
+- symbols. This list may contain information about
+- encodings or other more specific information. If
+- provided with an argument, the current locale details are set
+- to those given in the currently executing Scheme thread (or
+- for the entire Scheme system if such a distinction is not
+- possible).
+- </blockquote>
+-
+- <p>The Scheme System should first check for a bundle with the
+- exact name provided. If no such bundle is found, the last
+- element from the list is removed and a search is tried for a
+- bundle with that name. If no bundle is then found, the list is
+- shortened by removing the last element again. If no message is
+- found and the bundle specifier is now the empty list, an error
+- should be raised.</p>
+-
+- <p>The reason for this search order is to provide the most
+- locale sensitive template possible, but to fall back on more
+- general templates if a translation has not yet been provided
+- for the given locale.</p>
+-
+- <h3>Message Templates</h3>
+-
+- <p>A message template is a localized message that may or may
+- not contain one of a number of formatting codes. A message
+- template is a Scheme string. The string is of a form that can
+- be processed by the <tt>format</tt> procedure found in many
+- Scheme systems and formally specified in SRFI-28 (Basic Format
+- Strings).</p>
+-
+- <p>This SRFI also extends SRFI-28 to provide an additional
+- <tt>format</tt> escape code:</p>
+-
+- <blockquote>
+- <tt>~[n]@*</tt> - Causes a value-requiring escape code that
+- follows this code immediately to reference the [N]'th
+- optional value absolutely, rather than the next unconsumed
+- value. The referenced value is <i>not</i> consumed.
+- </blockquote>
+- This extension allows optional values to be positionally
+- referenced, so that message templates can be constructed that
+- can produce the proper word ordering for a language.
+-
+- <h3>Preparing Bundles</h3>
+- Before a bundle may be used by the Scheme system to retrieve
+- localized template messages, they must be made available to the
+- Scheme system. This SRFI specifies a way to portably
+- define the bundles, as well as store them in and retrieve them
+- from an unspecified system which may be provided by resources
+- outside the Scheme system.<br>
+-
+-
+- <p><b><a name="declare-bundle!"></a><tt>declare-bundle!</tt></b> <tt><i>bundle-specifier
+- association-list</i> -> undefined<br>
+- </tt></p>
+-
+- <blockquote>
+- Declares a new bundle named by the given bundle-specifier.
+- The contents of the bundle are defined by the provided
+- association list. The list contains associations
+- between Scheme symbols and the message templates (Scheme
+- strings) they name. If a bundle already exists with the
+- given name, it is overwritten with the newly declared
+- bundle.<br>
+- </blockquote>
+- <tt><a name="store-bundle"></a><b>store-bundle</b> <i>bundle-specifier</i> ->
+- boolean</tt><br>
+-
+-
+- <blockquote>
+- Attempts to store a bundle named by the given bundle
+- specifier, and previously made available using
+- <tt>declare-bundle!</tt> or <tt>load-bundle!</tt>, in an
+- unspecified mechanism that may be persistent across Scheme
+- system restarts. If successful, a non-false value is
+- returned. If unsuccessful, <tt>#f</tt> is returned.<br>
+- </blockquote>
+- <tt><a name="load-bundle!"></a><b>load-bundle!</b> <i>bundle-specifier</i> ->
+- boolean</tt><br>
+-
+-
+- <blockquote>
+- Attempts to retrieve a bundle from an unspecified mechanism
+- which stores bundles outside the Scheme system. If the
+- bundle was retrieved successfully, the function returns a
+- non-false value, and the bundle is immediately available to
+- the Scheme system. If the bundle could not be found or loaded
+- successfully, the function returns <tt>#f</tt>, and the
+- Scheme system's bundle registry remains unaffected.<br>
+- </blockquote>
+- A compliant Scheme system may choose not to provide any
+- external mechanism to store localized bundles. If it does
+- not, it must still provide implementations for
+- <tt>store-bundle</tt> and <tt>load-bundle!</tt>. In such a
+- case, both functions must return <tt>#f</tt> regardless of the
+- arguments given. Users of this SRFI should recognize that the
+- inability to load or store a localized bundle in an external
+- repository is <i>not</i> a fatal error.<br>
+-
+-
+- <h3>Retrieving Localized Message Templates</h3>
+-
+- <p><a name="localized-template"></a><b><tt>localized-template</tt></b> <i><tt>package-name
+- message-template-name</tt></i> <tt>-> <i>string or #f<br>
+- </i></tt></p>
+-
+- <blockquote>
+- Retrieves a localized message template for the given package
+- name and the given message template name (both symbols).
+- If no such message could be found, false (#f) is
+- returned.<br>
+- <br>
+- </blockquote>
+- After retrieving a template, the calling program can use
+- <tt>format</tt> to produce a string that can be displayed to
+- the user.<br>
+-
+-
+- <h2>Examples</h2>
+- The below example makes use of SRFI-29 to display simple,
+- localized messages. It also defines its bundles in such a
+- way that the Scheme system may store and retrieve the bundles
+- from a more efficient system catalog, if available.<br>
+-
+-<pre>
+-(let ((translations
+- '(((en) . ((time . "Its ~a, ~a.")
+- (goodbye . "Goodbye, ~a.")))
+- ((fr) . ((time . "~1@*~a, c'est ~a.")
+- (goodbye . "Au revoir, ~a."))))))
+- (for-each (lambda (translation)
+- (let ((bundle-name (cons 'hello-program (car translation))))
+- (if (not (load-bundle! bundle-name))
+- (begin
+- (declare-bundle! bundle-name (cdr translation))
+- (store-bundle! bundle-name)))))
+- translations))
+-
+-(define localized-message
+- (lambda (message-name . args)
+- (apply format (cons (localized-template 'hello-program
+- message-name)
+- args))))
+-
+-(let ((myname "Fred"))
+- (display (localized-message 'time "12:00" myname))
+- (display #\newline)
+-
+- (display (localized-message 'goodbye myname))
+- (display #\newline))
+-
+-;; Displays (English):
+-;; Its 12:00, Fred.
+-;; Goodbye, Fred.
+-;;
+-;; French:
+-;; Fred, c'est 12:00.
+-;; Au revoir, Fred.
+-</pre>
+-
+- <H1>Implementation</H1>
+-
+- <p>The implementation requires that the Scheme system provide a
+- definition for <tt>current-language</tt> and
+- <tt>current-country</tt> capable of distinguishing the correct
+- locale present during a Scheme session. The definitions of
+- those functions in the reference implementation are not capable
+- of that distinction. Their implementation is provided only so
+- that the following code can run in any R4RS scheme system.
+- <br>
+- </p>
+-
+- <p>In addition, the below implementation of a compliant
+- <tt>format</tt> requires SRFI-6 (Basic String Ports) and
+- SRFI-23 (Error reporting)</p>
+-<pre>
+-;; The association list in which bundles will be stored
+-(define *localization-bundles* '())
+-
+-;; The current-language and current-country functions provided
+-;; here must be rewritten for each Scheme system to default to the
+-;; actual locale of the session
+-(define current-language
+- (let ((current-language-value 'en))
+- (lambda args
+- (if (null? args)
+- current-language-value
+- (set! current-language-value (car args))))))
+-
+-(define current-country
+- (let ((current-country-value 'us))
+- (lambda args
+- (if (null? args)
+- current-country-value
+- (set! current-country-value (car args))))))
+-
+-;; The load-bundle! and store-bundle! both return #f in this
+-;; reference implementation. A compliant implementation need
+-;; not rewrite these procedures.
+-(define load-bundle!
+- (lambda (bundle-specifier)
+- #f))
+-
+-(define store-bundle!
+- (lambda (bundle-specifier)
+- #f))
+-
+-;; Declare a bundle of templates with a given bundle specifier
+-(define declare-bundle!
+- (letrec ((remove-old-bundle
+- (lambda (specifier bundle)
+- (cond ((null? bundle) '())
+- ((equal? (caar bundle) specifier)
+- (cdr bundle))
+- (else (cons (car bundle)
+- (remove-old-bundle specifier
+- (cdr bundle))))))))
+- (lambda (bundle-specifier bundle-assoc-list)
+- (set! *localization-bundles*
+- (cons (cons bundle-specifier bundle-assoc-list)
+- (remove-old-bundle bundle-specifier
+- *localization-bundles*))))))
+-
+-;;Retrieve a localized template given its package name and a template name
+-(define localized-template
+- (letrec ((rdc
+- (lambda (ls)
+- (if (null? (cdr ls))
+- '()
+- (cons (car ls) (rdc (cdr ls))))))
+- (find-bundle
+- (lambda (specifier template-name)
+- (cond ((assoc specifier *localization-bundles*) =>
+- (lambda (bundle) bundle))
+- ((null? specifier) #f)
+- (else (find-bundle (rdc specifier)
+- template-name))))))
+- (lambda (package-name template-name)
+- (let loop ((specifier (cons package-name
+- (list (current-language)
+- (current-country)))))
+- (and (not (null? specifier))
+- (let ((bundle (find-bundle specifier template-name)))
+- (and bundle
+- (cond ((assq template-name bundle) => cdr)
+- ((null? (cdr specifier)) #f)
+- (else (loop (rdc specifier)))))))))))
+-
+-;;An SRFI-28 and SRFI-29 compliant version of format. It requires
+-;;SRFI-23 for error reporting.
+-(define format
+- (lambda (format-string . objects)
+- (let ((buffer (open-output-string)))
+- (let loop ((format-list (string->list format-string))
+- (objects objects)
+- (object-override #f))
+- (cond ((null? format-list) (get-output-string buffer))
+- ((char=? (car format-list) #\~)
+- (cond ((null? (cdr format-list))
+- (error 'format "Incomplete escape sequence"))
+- ((char-numeric? (cadr format-list))
+- (let posloop ((fl (cddr format-list))
+- (pos (string->number
+- (string (cadr format-list)))))
+- (cond ((null? fl)
+- (error 'format "Incomplete escape sequence"))
+- ((and (eq? (car fl) '#\@)
+- (null? (cdr fl)))
+- (error 'format "Incomplete escape sequence"))
+- ((and (eq? (car fl) '#\@)
+- (eq? (cadr fl) '#\*))
+- (loop (cddr fl) objects (list-ref objects pos)))
+- (else
+- (posloop (cdr fl)
+- (+ (* 10 pos)
+- (string->number
+- (string (car fl)))))))))
+- (else
+- (case (cadr format-list)
+- ((#\a)
+- (cond (object-override
+- (begin
+- (display object-override buffer)
+- (loop (cddr format-list) objects #f)))
+- ((null? objects)
+- (error 'format "No value for escape sequence"))
+- (else
+- (begin
+- (display (car objects) buffer)
+- (loop (cddr format-list)
+- (cdr objects) #f)))))
+- ((#\s)
+- (cond (object-override
+- (begin
+- (display object-override buffer)
+- (loop (cddr format-list) objects #f)))
+- ((null? objects)
+- (error 'format "No value for escape sequence"))
+- (else
+- (begin
+- (write (car objects) buffer)
+- (loop (cddr format-list)
+- (cdr objects) #f)))))
+- ((#\%)
+- (if object-override
+- (error 'format "Escape sequence following positional override does not require a value"))
+- (display #\newline buffer)
+- (loop (cddr format-list) objects #f))
+- ((#\~)
+- (if object-override
+- (error 'format "Escape sequence following positional override does not require a value"))
+- (display #\~ buffer)
+- (loop (cddr format-list) objects #f))
+- (else
+- (error 'format "Unrecognized escape sequence"))))))
+- (else (display (car format-list) buffer)
+- (loop (cdr format-list) objects #f)))))))
+-
+-</pre>
+-
+- <H1>Copyright</H1>
+-
+- Copyright (C) Scott G. Miller (2002). All Rights Reserved.
+-
+- <p>This document and translations of it may be copied and
+- furnished to others, and derivative works that comment on or
+- otherwise explain it or assist in its implementation may be
+- prepared, copied, published and distributed, in whole or in
+- part, without restriction of any kind, provided that the above
+- copyright notice and this paragraph are included on all such
+- copies and derivative works. However, this document itself may
+- not be modified in any way, such as by removing the copyright
+- notice or references to the Scheme Request For Implementation
+- process or editors, except as needed for the purpose of
+- developing SRFIs in which case the procedures for copyrights
+- defined in the SRFI process must be followed, or as required to
+- translate it into languages other than English.</p>
+-
+- <p>The limited permissions granted above are perpetual and will
+- not be revoked by the authors or their successors or
+- assigns.</p>
+-
+- <p>This document and the information contained herein is
+- provided on an "AS IS" basis and THE AUTHOR AND THE SRFI
+- EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES
+- OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>
+- <hr>
+-
+- <address>
+- Editor: <a href="mailto:srfi-editors@srfi.schemers.org">David
+- Rush</a>
+- </address>
+-
+- <address>
+- Author: <a href="mailto:scgmille@freenetproject.org">Scott G.
+- Miller</a>
+- </address>
+- <!-- Created: Tue Sep 29 19:20:08 EDT 1998 -->
+- <!-- hhmts start -->Last modified: Mon Jun 17 12:00:08 Pacific
+- Daylight Time 2002 <!-- hhmts end --> <br>
+- </body>
+-</html>
+-
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-5.html racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-5.html
+--- racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-5.html 2018-01-26 15:34:52.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/srfi-std/srfi-5.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,345 +0,0 @@
+-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+-<html>
+-<head>
+- <title>SRFI 5: A compatible let form with signatures and rest arguments</title>
+-</head>
+-<body>
+-
+-<H1>Title</H1>
+-
+-SRFI-5: A compatible <code>let</code> form with signatures and rest arguments
+-
+-<H1>Author</H1>
+-
+-Andy Gaynor
+-
+-<H1>Status</H1>
+-
+-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html ">here</A>.
+-You can access the discussion on this SRFI via <A HREF="http://srfi.schemers.org/srfi-5/mail-archive/maillist.html ">the archive of the mailing list</A>.
+-<P><UL>
+-<LI>Received: 1999/2/2
+-<LI>Draft: 1999/2/10-1999/04/12
+-<LI>Final: 1999/4/26
+-<LI>Revised reference implementation: 2003/01/27
+-</UL>
+-
+-<H1>Abstract</H1>
+-
+-The <i>named-let</i> incarnation of the <code>let</code> form has two slight
+-inconsistencies with the <code>define</code> form. As defined, the <code>let</code>
+-form makes no accommodation for rest arguments, an issue of functionality
+-and consistency. As defined, the <code>let</code> form does not accommodate
+-signature-style syntax, an issue of aesthetics and consistency. Both
+-issues are addressed here in a manner which is compatible with the traditional
+-<code>let</code> form but for minor extensions.
+-
+-<H1>Rationale</H1>
+-
+-<H2>Signature-style Syntax</H2>
+-
+-Consider the following two equivalent definitions:
+-
+-<p><pre>
+-(define fibonacci
+- (lambda (n i f0 f1)
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1)))))
+-
+-(define (fibonacci n i f0 f1)
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-</pre>
+-
+-Although there is a named-let analog for the former form, there is none
+-for the latter. To wit, suppose one wished to compute the 10th element
+-of the Fibonacci sequence using a named let:
+-
+-<p>
+-<pre>
+-(let fibonacci ((n 10) (i 0) (f0 0) (f1 1))
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-Values: 55
+-</pre>
+-
+-As it stands, one cannot equivalently write
+-
+-<p>
+-<pre>
+-(let (fibonacci (n 10) (i 0) (f0 0) (f1 1))
+- (if (= i n)
+- f0
+- (fibonacci n (+ i 1) f1 (+ f0 f1))))
+-</pre>
+-
+-which is consistent with <code>define</code>'s signature-style form.
+-<p>Those that favor the signature style may prefer this extension.
+-In any case, it may be more appropriate to include all bound names within
+-the binding section. As presented, this straightforward extension
+-introduces no ambiguity or incompatibility with the existing definition
+-of let.
+-
+-<H2>Rest Arguments</H2>
+-
+-As it stands, one cannot write a named let with rest arguments, as in
+-
+-<p>
+-<pre>
+-(let (blast (port (current-output-port)) . (x (+ 1 2) 4 5))
+- (if (null? x)
+- 'just-a-silly-contrived-example
+- (begin
+- (write (car x) port)
+- (apply blast port (cdr x)))))
+-</pre>
+-
+-otherwise equivalent to
+-
+-<p>
+-<pre>
+-(letrec ((blast (lambda (port . x)
+- (if (null? x)
+- 'just-a-silly-contrived-example
+- (begin
+- (write (car x) port)
+- (apply blast port (cdr x)))))))
+- (blast (current-output-port) (+ 1 2) 4 5))
+-</pre>
+-
+-While this example is rather contrived, the functionality is not.
+-There are several times when the author has used this construct in practice.
+-Regardless, there is little reason to deny the <code>let</code> form access to
+-all the features of lambda functionality.
+-
+-<H2>Symbols in Binding Sections</H2>
+-
+-Both the features above rely upon the placement of symbols in <code>let</code>
+-binding lists (this statement is intentially simplistic). The only
+-other apparent use of such symbol placement is to tersely bind variables
+-to unspecified values. For example, one might desire to use
+-<code>(let (foo bar baz) ...)</code>
+-to bind <code>foo</code>, <code>bar</code>, and <code>baz</code> to
+-unspecified values.
+-
+-<p>This usage is considered less important in light of the rationales
+-presented above, and an alternate syntax is immediately apparent, as
+-in <code>(let ((foo) (bar) (baz)) ...)</code> This may even
+-be preferable, consistently parenthesizing normal binding clauses.
+-
+-<H1>Specification</H1>
+-
+-<H2>Syntax</H2>
+-
+-<p>
+-A formal specification of the syntax follows. Below, body, expression,
+-and identifier are free. Each instantiation of binding-name must be
+-unique.
+-</p>
+-
+-<p>
+-<pre>
+- let = "(" "let" let-bindings body ")"
+- expressions = nothing | expression expressions
+- let-bindings = let-name bindings
+- |"(" let-name "." bindings ")"
+- let-name = identifier
+- bindings = "(" ")"
+- | rest-binding
+- | "(" normal-bindings ["." rest-binding] ")"
+-normal-bindings = nothing
+- | normal-binding normal-bindings
+-normal-binding = "(" binding-name expression ")"
+- binding-name = identifier
+- rest-binding = "(" binding-name expressions ")"
+-</pre>
+-
+-<p>
+-For clarity and convenience, an informal specification follows.
+-</p>
+-
+-<ol>
+-<li><a name="unnamed">Unnamed</a>
+-
+-<p><pre>
+-(let ((<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-non-sig">
+-Named, non-signature-style, no rest argument</a>
+-
+-<p><pre>
+-(let <name> ((<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-sig">Named, signature-style, no rest argument</a>
+-
+-<p><pre>
+-(let (<name> (<parameter> <argument>)...)
+- <body>...)
+-</pre>
+-</li>
+-
+-<li><a name="named-non-sig-rest">Named, non-signature-style, rest argument</a>
+-
+-<p><pre>
+-(let <name> ((<parameter> <argument>)...
+-
+-. (<rest-parameter> <rest-argument>...))
+- <body>...)
+-</pre>
+-
+-<li><a name="named-sig-rest">Named, signature-style, rest argument</a>
+-
+-<p><pre>
+-(let (<name> (<parameter> <argument>)...
+-
+-. (<rest-parameter> <rest-argument>...))
+- <body>...)
+-</pre>
+-</li>
+-</ol>
+-
+-<H2>Semantics</H2>
+-
+-Let <code>$lambda</code> and <code>$letrec</code> be hygienic bindings for the <code>lambda</code>
+-and <code>letrec</code> forms, respectively.
+-
+-<ul>
+-<li>For informal syntax 1:
+-
+-<p><pre>
+-(($lambda (<parameter>...) <body>...) <argument>...)
+-</pre>
+-</li>
+-
+-<li>For informal syntaxes 2 and 3:
+-
+-<p>
+-<pre>
+-($letrec ((<name> ($lambda (<parameter>...) <body>...)))
+- (<name> <argument>...))
+-</pre>
+-</li>
+-
+-<li>For informal syntaxes 4 and 5:
+-
+-<p>
+-<pre>
+-($letrec ((<name> ($lambda (<parameter>...
+-
+-. <rest-parameter>) <body>...)))
+- (<name> <argument>... <rest-argument>...))
+-</pre>
+-</li>
+-</ul>
+-
+-<H1>Implementation</H1>
+-
+-Here is an implementation using <code>SYNTAX-RULES</code>.
+-
+-<p>
+-<pre>
+-;; Use your own standard let.
+-;; Or call a lambda.
+-;; (define-syntax standard-let
+-;;
+-;; (syntax-rules ()
+-;;
+-;; ((let ((var val) ...) body ...)
+-;; ((lambda (var ...) body ...) val ...))))
+-
+-(define-syntax let
+-
+- (syntax-rules ()
+-
+- ;; No bindings: use standard-let.
+- ((let () body ...)
+- (standard-let () body ...))
+- ;; Or call a lambda.
+- ;; ((lambda () body ...))
+-
+- ;; All standard bindings: use standard-let.
+- ((let ((var val) ...) body ...)
+- (standard-let ((var val) ...) body ...))
+- ;; Or call a lambda.
+- ;; ((lambda (var ...) body ...) val ...)
+-
+- ;; One standard binding: loop.
+- ;; The all-standard-bindings clause didn't match,
+- ;; so there must be a rest binding.
+- ((let ((var val) . bindings) body ...)
+- (let-loop #f bindings (var) (val) (body ...)))
+-
+- ;; Signature-style name: loop.
+- ((let (name binding ...) body ...)
+- (let-loop name (binding ...) () () (body ...)))
+-
+- ;; defun-style name: loop.
+- ((let name bindings body ...)
+- (let-loop name bindings () () (body ...)))))
+-
+-(define-syntax let-loop
+-
+- (syntax-rules ()
+-
+- ;; Standard binding: destructure and loop.
+- ((let-loop name ((var0 val0) binding ...) (var ... ) (val ... ) body)
+- (let-loop name ( binding ...) (var ... var0) (val ... val0) body))
+-
+- ;; Rest binding, no name: use standard-let, listing the rest values.
+- ;; Because of let's first clause, there is no "no bindings, no name" clause.
+- ((let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
+- (standard-let ((var val) ... (rest-var (list rest-val ...))) . body))
+- ;; Or call a lambda with a rest parameter on all values.
+- ;; ((lambda (var ... . rest-var) . body) val ... rest-val ...))
+- ;; Or use one of several other reasonable alternatives.
+-
+- ;; No bindings, name: call a letrec'ed lambda.
+- ((let-loop name () (var ...) (val ...) body)
+- ((letrec ((name (lambda (var ...) . body)))
+- name)
+- val ...))
+-
+- ;; Rest binding, name: call a letrec'ed lambda.
+- ((let-loop name (rest-var rest-val ...) (var ...) (val ...) body)
+- ((letrec ((name (lambda (var ... . rest-var) . body)))
+- name)
+- val ... rest-val ...))))
+-</pre>
+-
+-
+-<H1>Copyright</H1>
+-
+-Copyright (C) Andy Gaynor (1999). All Rights Reserved.
+-<p>This document and translations of it may be copied and furnished to
+-others, and derivative works that comment on or otherwise explain it or
+-assist in its implementation may be prepared, copied, published and distributed,
+-in whole or in part, without restriction of any kind, provided that the
+-above copyright notice and this paragraph are included on all such copies
+-and derivative works. However, this document itself may not be modified
+-in any way, such as by removing the copyright notice or references to the
+-Scheme Request For Implementation process or editors, except as needed
+-for the purpose of developing SRFIs in which case the procedures for copyrights
+-defined in the SRFI process must be followed, or as required to translate
+-it into languages other than English.
+-<p>The limited permissions granted above are perpetual and will not be
+-revoked by the authors or their successors or assigns.
+-<p>This document and the information contained herein is provided on an
+-"AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES,
+-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE
+-USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+-WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+-
+- <hr>
+- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address>
+-
+-</body>
+-</html>
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/util.rkt racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/util.rkt
+--- racket-6.12-orig/share/pkgs/srfi-doc/srfi/scribblings/util.rkt 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc/srfi/scribblings/util.rkt 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,61 @@
++#lang scribble/doc
++
++@(require scribble/manual
++ scribble/eval
++ scriblib/render-cond
++ scribble/core
++ scribble/html-properties
++ (for-syntax scheme/base)
++ (for-label scheme/base
++ racket/stream))
++
++@(provide (all-defined-out))
++
++@(define-syntax (srfi stx)
++ (syntax-case stx ()
++ [(_ num #:subdir subdir? . title)
++ (with-syntax ([srfi/n (string->symbol (format "srfi/~a" (syntax-e #'num)))])
++ #'(begin
++ (section #:tag (format "srfi-~a" num)
++ #:style 'unnumbered
++ (format "SRFI ~a: " num)
++ . title)
++ (defmodule srfi/n)
++ "Original specification: "
++ (let* ([label (format "SRFI ~a" num)]
++ [sub (if subdir? (format "srfi-~a/" num) "")]
++ [url ( (b) (format "~a/srfi-std/~asrfi-~a.html" b sub num))])
++ (cond-element
++ [(or latex text) @link[(url "http://docs.racket-lang.org ") label]]
++ [else @link[(url ".") label]]))))]
++ [(_ num . title) #'(srfi num #:subdir #f . title)]))
++
++@;{ The `lst' argument is a list of
++ (list sym syntactic-form? html-anchor) }
++@(define (redirect n lst #:subdir [subdir? #f])
++ (let ([file (if subdir?
++ (format "srfi-~a/srfi-~a.html" n n)
++ (format "srfi-~a.html" n))]
++ [mod-path (string->symbol (format "srfi/~a" n))])
++ (make-binding-redirect-elements mod-path
++ (map (lambda (b)
++ (list (car b) (cadr b)
++ (build-path "srfi-std" file)
++ (caddr b)))
++ lst))))
++
++@(define in-core
++ (case-lambda
++ [() (in-core ".")]
++ [(k) @elem{This SRFI's bindings are also available in
++ @racketmodname[racket/base]@|k|}]))
++
++@(begin
++ (define-syntax-rule (def-mz mz-if)
++ (begin
++ (require (for-label mzscheme))
++ (define mz-if (racket if))))
++ (def-mz mz-if))
++
++@(define srfi-std (style #f (list (install-resource "srfi-std"))))
++
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc-nonfree/info.rkt racket-6.12/share/pkgs/srfi-doc-nonfree/info.rkt
+--- racket-6.12-orig/share/pkgs/srfi-doc-nonfree/info.rkt 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/info.rkt 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,19 @@
++#lang info
++
++(define collection 'multi)
++
++(define build-deps '("mzscheme-doc"
++ "scheme-lib"
++ "base"
++ "scribble-lib"
++ "srfi-doc"
++ "srfi-lib-nonfree"
++ "racket-doc"
++ "r5rs-doc"
++ "r6rs-doc"
++ "compatibility-lib"))
++(define update-implies '("srfi-lib-nonfree"))
++
++(define pkg-desc "documentation part of \"srfi nonfree\"")
++
++(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt
+--- racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/info.rkt 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,3 @@
++#lang info
++
++(define scribblings '(("srfi-nf.scrbl" (multi-page) (library 100))))
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl
+--- racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-nf.scrbl 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,66 @@
++#lang scribble/doc
++@(require srfi/scribblings/util
++ scribble/manual
++ scribble/eval
++ scriblib/render-cond
++ scribble/core
++ scribble/html-properties
++ (for-syntax scheme/base)
++ (for-label scheme/base
++ racket/stream))
++
++@; ----------------------------------------------------------------------
++
++@title{SRFI Nonfree Libraries and Documentation}
++
++The @link[#:style srfi-std "http://srfi.schemers.org/ "]{Scheme Requests for
++Implementation} (a.k.a. @deftech{SRFI}) process allows individual
++members of the Scheme community to propose libraries and extensions to
++be supported by multiple Scheme implementations.
++
++Racket is distributed with implementations of many SRFIs, most of
++which can be implemented as libraries. To import the bindings of SRFI
++@math{n}, use
++
++@racketblock[
++(require @#,elem{@racketidfont{srfi/}@math{n}})
++]
++
++This document lists the SRFIs that are supported by Racket and
++provides a link to the original SRFI specification (which is also
++distributed as part of Racket's documentation).
++
++The following SRFI specification documents are licensed restrictively.
++
++@table-of-contents[]
++
++
++@; ----------------------------------------
++
++@srfi[5]{A compatible let form with signatures and rest arguments}
++
++@redirect[5 '(
++ (let #t "unnamed")
++)]
++
++Racket provides this SRFI in the @racket[srfi-lib-nonfree] package.
++
++@; ----------------------------------------
++
++@srfi[29]{Localization}
++
++@redirect[29 '(
++ (current-language #f "current-language")
++ (current-country #f "current-country")
++ (current-locale-details #f "current-locale-details")
++ (declare-bundle! #f "declare-bundle!")
++ (store-bundle #f "store-bundle")
++ (load-bundle! #f "load-bundle!")
++ (localized-template #f "localized-template")
++)]
++
++Racket provides a free implementation of this SRFI in the @racket[srfi-lib] package. Only the SRFI specification document is nonfree.
++
++@; ----------------------------------------
++
++@index-section[]
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html
+--- racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-29.html 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,507 @@
++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN">
++<html>
++ <head>
++ <meta name="generator" content="HTML Tidy, see www.w3.org ">
++ <title>SRFI 29: Localization</title>
++ <meta name="author" content="Scott G. Miller">
++ <meta name="description" content="Localization">
++ </head>
++ <body>
++ <H1>Title</H1>
++
++ SRFI 29: Localization
++
++ <H1>Author</H1>
++
++ Scott G. Miller
++
++ <H1>Abstract</H1>
++
++ This document specifies an interface to retrieving and
++ displaying locale sensitive messages. A Scheme program can
++ register one or more translations of templated messages, and
++ then write Scheme code that can transparently retrieve the
++ appropriate message for the locale under which the Scheme
++ system is running. <br>
++
++
++ <H1>Rationale</H1>
++
++ <p>As any programmer that has ever had to deal with making his
++ or her code readable in more than one locale, the process of
++ sufficiently abstracting program messages from their
++ presentation to the user is non-trivial without help from the
++ programming language. Most modern programming language
++ libraries do provide some mechanism for performing this
++ separation.</p>
++
++ <p>A portable API that allows a piece of code to run without
++ modification in different countries and under different
++ languages is a must for any non-trivial software project.
++ The interface should separate the logic of a program from
++ the myriad of translations that may be necessary.</p>
++
++ <p>The interface described in this document provides such
++ functionality. The underlying implementation is also allowed to
++ use whatever datastructures it likes to provide access to the
++ translations in the most efficient manner possible. In
++ addition, the implementation is provided with standardized
++ functions that programs will use for accessing an external,
++ unspecified repository of translations.</p>
++
++ <p>This interface <i>does not</i> cover all aspects of
++ localization, including support for non-latin characters,
++ number and date formatting, etc. Such functionality is the
++ scope of a future SRFI that may extend this one.</p>
++
++ <H1>Dependencies</H1>
++
++ An SRFI-29 conformant implementation must also implement
++ SRFI-28, Basic Format Strings. Message templates are strings
++ that must be processed by the <tt>format</tt> function
++ specified in that SRFI.
++
++ <H1>Specification</H1>
++
++ <h3>Message Bundles</h3>
++
++ <p>A Message Bundle is a set of message templates and their
++ identifying keys. Each bundle contains one or more such
++ key/value pairs. The bundle itself is associated with a
++ <i>bundle specifier</i> which uniquely identifies the
++ bundle.</p>
++
++ <h3>Bundle Specifiers</h3>
++
++ <p>A Bundle Specifier is a Scheme list that describes, in order
++ of importance, the package and locale of a message bundle.
++ In most cases, a locale specifier will have between one
++ and three elements. The first element is a symbol denoting the
++ package for which this bundle applies. The second and third
++ elements denote a <i>locale</i>. The second element (first
++ element of the locale) if present, is the two letter, ISO 639-1
++ language code for the bundle. The third element, if present, is
++ a two letter ISO 3166-1 country code. In some cases, a
++ fourth element may be present, specifying the encoding used for
++ the bundle. All bundle specifier elements are Scheme
++ symbols.</p>
++
++ <p>If only one translation is provided, it should be designated
++ only by a package name, for example <tt>(mathlib)</tt>. This
++ translation is called the <i>default</i> translation.</p>
++
++ <h3>Bundle Searching</h3>
++
++ <p>When a message template is retrieved from a bundle, the
++ Scheme implementation will provide the locale under which the
++ system is currently running. When the template is retrieved,
++ the package name will be specified. The Scheme system should
++ construct a Bundle Specifier from the provided package name and
++ the active locale. For example, when retrieving a message
++ template for French Canadian, in the <tt>mathlib</tt> package,
++ the bundle specifier '<tt>(mathlib fr ca)</tt>' is used. A
++ program may also retrieve the elements of the current locale
++ using the no-argument procedures:</p>
++
++ <p><b><a name="current-language"></a><tt>current-language</tt></b> <tt>->
++ <i>symbol</i></tt><br>
++ <tt><b>current-language</b> <i>symbol</i> ->
++ undefined</tt><br>
++ </p>
++
++ <blockquote>
++ When given no arguments, returns the current ISO 639-1
++ language code as a symbol. If provided with an
++ argument, the current language is set to that named by the
++ symbol for the currently executing Scheme thread (or for the
++ entire Scheme system if such a distinction is not possible).
++
++ </blockquote>
++
++ <p><b><a name="current-country"></a><tt>current-country</tt></b> <tt>->
++ <i>symbol</i></tt><br>
++ <tt><b>current-country</b> <i>symbol</i> ->
++ undefined</tt><br>
++ </p>
++
++ <blockquote>
++ returns the current ISO 3166-1 country code as a symbol.
++ If provided with an argument, the current country is
++ set to that named by the symbol for the currently executing
++ Scheme thread (or for the entire Scheme system if such a
++ distinction is not possible).
++ </blockquote>
++
++ <p><b><a name="current-locale-details"></a><tt>current-locale-details</tt></b> <tt>-> <i>list of
++ symbol</i></tt>s<br>
++ <tt><b>current-locale-details</b> <i>list-of-symbols</i> ->
++ undefined</tt><br>
++ </p>
++
++ <blockquote>
++ Returns a list of additional locale details as a list of
++ symbols. This list may contain information about
++ encodings or other more specific information. If
++ provided with an argument, the current locale details are set
++ to those given in the currently executing Scheme thread (or
++ for the entire Scheme system if such a distinction is not
++ possible).
++ </blockquote>
++
++ <p>The Scheme System should first check for a bundle with the
++ exact name provided. If no such bundle is found, the last
++ element from the list is removed and a search is tried for a
++ bundle with that name. If no bundle is then found, the list is
++ shortened by removing the last element again. If no message is
++ found and the bundle specifier is now the empty list, an error
++ should be raised.</p>
++
++ <p>The reason for this search order is to provide the most
++ locale sensitive template possible, but to fall back on more
++ general templates if a translation has not yet been provided
++ for the given locale.</p>
++
++ <h3>Message Templates</h3>
++
++ <p>A message template is a localized message that may or may
++ not contain one of a number of formatting codes. A message
++ template is a Scheme string. The string is of a form that can
++ be processed by the <tt>format</tt> procedure found in many
++ Scheme systems and formally specified in SRFI-28 (Basic Format
++ Strings).</p>
++
++ <p>This SRFI also extends SRFI-28 to provide an additional
++ <tt>format</tt> escape code:</p>
++
++ <blockquote>
++ <tt>~[n]@*</tt> - Causes a value-requiring escape code that
++ follows this code immediately to reference the [N]'th
++ optional value absolutely, rather than the next unconsumed
++ value. The referenced value is <i>not</i> consumed.
++ </blockquote>
++ This extension allows optional values to be positionally
++ referenced, so that message templates can be constructed that
++ can produce the proper word ordering for a language.
++
++ <h3>Preparing Bundles</h3>
++ Before a bundle may be used by the Scheme system to retrieve
++ localized template messages, they must be made available to the
++ Scheme system. This SRFI specifies a way to portably
++ define the bundles, as well as store them in and retrieve them
++ from an unspecified system which may be provided by resources
++ outside the Scheme system.<br>
++
++
++ <p><b><a name="declare-bundle!"></a><tt>declare-bundle!</tt></b> <tt><i>bundle-specifier
++ association-list</i> -> undefined<br>
++ </tt></p>
++
++ <blockquote>
++ Declares a new bundle named by the given bundle-specifier.
++ The contents of the bundle are defined by the provided
++ association list. The list contains associations
++ between Scheme symbols and the message templates (Scheme
++ strings) they name. If a bundle already exists with the
++ given name, it is overwritten with the newly declared
++ bundle.<br>
++ </blockquote>
++ <tt><a name="store-bundle"></a><b>store-bundle</b> <i>bundle-specifier</i> ->
++ boolean</tt><br>
++
++
++ <blockquote>
++ Attempts to store a bundle named by the given bundle
++ specifier, and previously made available using
++ <tt>declare-bundle!</tt> or <tt>load-bundle!</tt>, in an
++ unspecified mechanism that may be persistent across Scheme
++ system restarts. If successful, a non-false value is
++ returned. If unsuccessful, <tt>#f</tt> is returned.<br>
++ </blockquote>
++ <tt><a name="load-bundle!"></a><b>load-bundle!</b> <i>bundle-specifier</i> ->
++ boolean</tt><br>
++
++
++ <blockquote>
++ Attempts to retrieve a bundle from an unspecified mechanism
++ which stores bundles outside the Scheme system. If the
++ bundle was retrieved successfully, the function returns a
++ non-false value, and the bundle is immediately available to
++ the Scheme system. If the bundle could not be found or loaded
++ successfully, the function returns <tt>#f</tt>, and the
++ Scheme system's bundle registry remains unaffected.<br>
++ </blockquote>
++ A compliant Scheme system may choose not to provide any
++ external mechanism to store localized bundles. If it does
++ not, it must still provide implementations for
++ <tt>store-bundle</tt> and <tt>load-bundle!</tt>. In such a
++ case, both functions must return <tt>#f</tt> regardless of the
++ arguments given. Users of this SRFI should recognize that the
++ inability to load or store a localized bundle in an external
++ repository is <i>not</i> a fatal error.<br>
++
++
++ <h3>Retrieving Localized Message Templates</h3>
++
++ <p><a name="localized-template"></a><b><tt>localized-template</tt></b> <i><tt>package-name
++ message-template-name</tt></i> <tt>-> <i>string or #f<br>
++ </i></tt></p>
++
++ <blockquote>
++ Retrieves a localized message template for the given package
++ name and the given message template name (both symbols).
++ If no such message could be found, false (#f) is
++ returned.<br>
++ <br>
++ </blockquote>
++ After retrieving a template, the calling program can use
++ <tt>format</tt> to produce a string that can be displayed to
++ the user.<br>
++
++
++ <h2>Examples</h2>
++ The below example makes use of SRFI-29 to display simple,
++ localized messages. It also defines its bundles in such a
++ way that the Scheme system may store and retrieve the bundles
++ from a more efficient system catalog, if available.<br>
++
++<pre>
++(let ((translations
++ '(((en) . ((time . "Its ~a, ~a.")
++ (goodbye . "Goodbye, ~a.")))
++ ((fr) . ((time . "~1@*~a, c'est ~a.")
++ (goodbye . "Au revoir, ~a."))))))
++ (for-each (lambda (translation)
++ (let ((bundle-name (cons 'hello-program (car translation))))
++ (if (not (load-bundle! bundle-name))
++ (begin
++ (declare-bundle! bundle-name (cdr translation))
++ (store-bundle! bundle-name)))))
++ translations))
++
++(define localized-message
++ (lambda (message-name . args)
++ (apply format (cons (localized-template 'hello-program
++ message-name)
++ args))))
++
++(let ((myname "Fred"))
++ (display (localized-message 'time "12:00" myname))
++ (display #\newline)
++
++ (display (localized-message 'goodbye myname))
++ (display #\newline))
++
++;; Displays (English):
++;; Its 12:00, Fred.
++;; Goodbye, Fred.
++;;
++;; French:
++;; Fred, c'est 12:00.
++;; Au revoir, Fred.
++</pre>
++
++ <H1>Implementation</H1>
++
++ <p>The implementation requires that the Scheme system provide a
++ definition for <tt>current-language</tt> and
++ <tt>current-country</tt> capable of distinguishing the correct
++ locale present during a Scheme session. The definitions of
++ those functions in the reference implementation are not capable
++ of that distinction. Their implementation is provided only so
++ that the following code can run in any R4RS scheme system.
++ <br>
++ </p>
++
++ <p>In addition, the below implementation of a compliant
++ <tt>format</tt> requires SRFI-6 (Basic String Ports) and
++ SRFI-23 (Error reporting)</p>
++<pre>
++;; The association list in which bundles will be stored
++(define *localization-bundles* '())
++
++;; The current-language and current-country functions provided
++;; here must be rewritten for each Scheme system to default to the
++;; actual locale of the session
++(define current-language
++ (let ((current-language-value 'en))
++ (lambda args
++ (if (null? args)
++ current-language-value
++ (set! current-language-value (car args))))))
++
++(define current-country
++ (let ((current-country-value 'us))
++ (lambda args
++ (if (null? args)
++ current-country-value
++ (set! current-country-value (car args))))))
++
++;; The load-bundle! and store-bundle! both return #f in this
++;; reference implementation. A compliant implementation need
++;; not rewrite these procedures.
++(define load-bundle!
++ (lambda (bundle-specifier)
++ #f))
++
++(define store-bundle!
++ (lambda (bundle-specifier)
++ #f))
++
++;; Declare a bundle of templates with a given bundle specifier
++(define declare-bundle!
++ (letrec ((remove-old-bundle
++ (lambda (specifier bundle)
++ (cond ((null? bundle) '())
++ ((equal? (caar bundle) specifier)
++ (cdr bundle))
++ (else (cons (car bundle)
++ (remove-old-bundle specifier
++ (cdr bundle))))))))
++ (lambda (bundle-specifier bundle-assoc-list)
++ (set! *localization-bundles*
++ (cons (cons bundle-specifier bundle-assoc-list)
++ (remove-old-bundle bundle-specifier
++ *localization-bundles*))))))
++
++;;Retrieve a localized template given its package name and a template name
++(define localized-template
++ (letrec ((rdc
++ (lambda (ls)
++ (if (null? (cdr ls))
++ '()
++ (cons (car ls) (rdc (cdr ls))))))
++ (find-bundle
++ (lambda (specifier template-name)
++ (cond ((assoc specifier *localization-bundles*) =>
++ (lambda (bundle) bundle))
++ ((null? specifier) #f)
++ (else (find-bundle (rdc specifier)
++ template-name))))))
++ (lambda (package-name template-name)
++ (let loop ((specifier (cons package-name
++ (list (current-language)
++ (current-country)))))
++ (and (not (null? specifier))
++ (let ((bundle (find-bundle specifier template-name)))
++ (and bundle
++ (cond ((assq template-name bundle) => cdr)
++ ((null? (cdr specifier)) #f)
++ (else (loop (rdc specifier)))))))))))
++
++;;An SRFI-28 and SRFI-29 compliant version of format. It requires
++;;SRFI-23 for error reporting.
++(define format
++ (lambda (format-string . objects)
++ (let ((buffer (open-output-string)))
++ (let loop ((format-list (string->list format-string))
++ (objects objects)
++ (object-override #f))
++ (cond ((null? format-list) (get-output-string buffer))
++ ((char=? (car format-list) #\~)
++ (cond ((null? (cdr format-list))
++ (error 'format "Incomplete escape sequence"))
++ ((char-numeric? (cadr format-list))
++ (let posloop ((fl (cddr format-list))
++ (pos (string->number
++ (string (cadr format-list)))))
++ (cond ((null? fl)
++ (error 'format "Incomplete escape sequence"))
++ ((and (eq? (car fl) '#\@)
++ (null? (cdr fl)))
++ (error 'format "Incomplete escape sequence"))
++ ((and (eq? (car fl) '#\@)
++ (eq? (cadr fl) '#\*))
++ (loop (cddr fl) objects (list-ref objects pos)))
++ (else
++ (posloop (cdr fl)
++ (+ (* 10 pos)
++ (string->number
++ (string (car fl)))))))))
++ (else
++ (case (cadr format-list)
++ ((#\a)
++ (cond (object-override
++ (begin
++ (display object-override buffer)
++ (loop (cddr format-list) objects #f)))
++ ((null? objects)
++ (error 'format "No value for escape sequence"))
++ (else
++ (begin
++ (display (car objects) buffer)
++ (loop (cddr format-list)
++ (cdr objects) #f)))))
++ ((#\s)
++ (cond (object-override
++ (begin
++ (display object-override buffer)
++ (loop (cddr format-list) objects #f)))
++ ((null? objects)
++ (error 'format "No value for escape sequence"))
++ (else
++ (begin
++ (write (car objects) buffer)
++ (loop (cddr format-list)
++ (cdr objects) #f)))))
++ ((#\%)
++ (if object-override
++ (error 'format "Escape sequence following positional override does not require a value"))
++ (display #\newline buffer)
++ (loop (cddr format-list) objects #f))
++ ((#\~)
++ (if object-override
++ (error 'format "Escape sequence following positional override does not require a value"))
++ (display #\~ buffer)
++ (loop (cddr format-list) objects #f))
++ (else
++ (error 'format "Unrecognized escape sequence"))))))
++ (else (display (car format-list) buffer)
++ (loop (cdr format-list) objects #f)))))))
++
++</pre>
++
++ <H1>Copyright</H1>
++
++ Copyright (C) Scott G. Miller (2002). All Rights Reserved.
++
++ <p>This document and translations of it may be copied and
++ furnished to others, and derivative works that comment on or
++ otherwise explain it or assist in its implementation may be
++ prepared, copied, published and distributed, in whole or in
++ part, without restriction of any kind, provided that the above
++ copyright notice and this paragraph are included on all such
++ copies and derivative works. However, this document itself may
++ not be modified in any way, such as by removing the copyright
++ notice or references to the Scheme Request For Implementation
++ process or editors, except as needed for the purpose of
++ developing SRFIs in which case the procedures for copyrights
++ defined in the SRFI process must be followed, or as required to
++ translate it into languages other than English.</p>
++
++ <p>The limited permissions granted above are perpetual and will
++ not be revoked by the authors or their successors or
++ assigns.</p>
++
++ <p>This document and the information contained herein is
++ provided on an "AS IS" basis and THE AUTHOR AND THE SRFI
++ EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
++ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
++ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES
++ OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>
++ <hr>
++
++ <address>
++ Editor: <a href="mailto:srfi-editors@srfi.schemers.org">David
++ Rush</a>
++ </address>
++
++ <address>
++ Author: <a href="mailto:scgmille@freenetproject.org">Scott G.
++ Miller</a>
++ </address>
++ <!-- Created: Tue Sep 29 19:20:08 EDT 1998 -->
++ <!-- hhmts start -->Last modified: Mon Jun 17 12:00:08 Pacific
++ Daylight Time 2002 <!-- hhmts end --> <br>
++ </body>
++</html>
++
+diff -urN racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html
+--- racket-6.12-orig/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-doc-nonfree/srfi/scribblings/srfi-std/srfi-5.html 2018-01-31 12:22:58.144502000 -0500
+@@ -0,0 +1,345 @@
++<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
++<html>
++<head>
++ <title>SRFI 5: A compatible let form with signatures and rest arguments</title>
++</head>
++<body>
++
++<H1>Title</H1>
++
++SRFI-5: A compatible <code>let</code> form with signatures and rest arguments
++
++<H1>Author</H1>
++
++Andy Gaynor
++
++<H1>Status</H1>
++
++This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html ">here</A>.
++You can access the discussion on this SRFI via <A HREF="http://srfi.schemers.org/srfi-5/mail-archive/maillist.html ">the archive of the mailing list</A>.
++<P><UL>
++<LI>Received: 1999/2/2
++<LI>Draft: 1999/2/10-1999/04/12
++<LI>Final: 1999/4/26
++<LI>Revised reference implementation: 2003/01/27
++</UL>
++
++<H1>Abstract</H1>
++
++The <i>named-let</i> incarnation of the <code>let</code> form has two slight
++inconsistencies with the <code>define</code> form. As defined, the <code>let</code>
++form makes no accommodation for rest arguments, an issue of functionality
++and consistency. As defined, the <code>let</code> form does not accommodate
++signature-style syntax, an issue of aesthetics and consistency. Both
++issues are addressed here in a manner which is compatible with the traditional
++<code>let</code> form but for minor extensions.
++
++<H1>Rationale</H1>
++
++<H2>Signature-style Syntax</H2>
++
++Consider the following two equivalent definitions:
++
++<p><pre>
++(define fibonacci
++ (lambda (n i f0 f1)
++ (if (= i n)
++ f0
++ (fibonacci n (+ i 1) f1 (+ f0 f1)))))
++
++(define (fibonacci n i f0 f1)
++ (if (= i n)
++ f0
++ (fibonacci n (+ i 1) f1 (+ f0 f1))))
++</pre>
++
++Although there is a named-let analog for the former form, there is none
++for the latter. To wit, suppose one wished to compute the 10th element
++of the Fibonacci sequence using a named let:
++
++<p>
++<pre>
++(let fibonacci ((n 10) (i 0) (f0 0) (f1 1))
++ (if (= i n)
++ f0
++ (fibonacci n (+ i 1) f1 (+ f0 f1))))
++Values: 55
++</pre>
++
++As it stands, one cannot equivalently write
++
++<p>
++<pre>
++(let (fibonacci (n 10) (i 0) (f0 0) (f1 1))
++ (if (= i n)
++ f0
++ (fibonacci n (+ i 1) f1 (+ f0 f1))))
++</pre>
++
++which is consistent with <code>define</code>'s signature-style form.
++<p>Those that favor the signature style may prefer this extension.
++In any case, it may be more appropriate to include all bound names within
++the binding section. As presented, this straightforward extension
++introduces no ambiguity or incompatibility with the existing definition
++of let.
++
++<H2>Rest Arguments</H2>
++
++As it stands, one cannot write a named let with rest arguments, as in
++
++<p>
++<pre>
++(let (blast (port (current-output-port)) . (x (+ 1 2) 4 5))
++ (if (null? x)
++ 'just-a-silly-contrived-example
++ (begin
++ (write (car x) port)
++ (apply blast port (cdr x)))))
++</pre>
++
++otherwise equivalent to
++
++<p>
++<pre>
++(letrec ((blast (lambda (port . x)
++ (if (null? x)
++ 'just-a-silly-contrived-example
++ (begin
++ (write (car x) port)
++ (apply blast port (cdr x)))))))
++ (blast (current-output-port) (+ 1 2) 4 5))
++</pre>
++
++While this example is rather contrived, the functionality is not.
++There are several times when the author has used this construct in practice.
++Regardless, there is little reason to deny the <code>let</code> form access to
++all the features of lambda functionality.
++
++<H2>Symbols in Binding Sections</H2>
++
++Both the features above rely upon the placement of symbols in <code>let</code>
++binding lists (this statement is intentially simplistic). The only
++other apparent use of such symbol placement is to tersely bind variables
++to unspecified values. For example, one might desire to use
++<code>(let (foo bar baz) ...)</code>
++to bind <code>foo</code>, <code>bar</code>, and <code>baz</code> to
++unspecified values.
++
++<p>This usage is considered less important in light of the rationales
++presented above, and an alternate syntax is immediately apparent, as
++in <code>(let ((foo) (bar) (baz)) ...)</code> This may even
++be preferable, consistently parenthesizing normal binding clauses.
++
++<H1>Specification</H1>
++
++<H2>Syntax</H2>
++
++<p>
++A formal specification of the syntax follows. Below, body, expression,
++and identifier are free. Each instantiation of binding-name must be
++unique.
++</p>
++
++<p>
++<pre>
++ let = "(" "let" let-bindings body ")"
++ expressions = nothing | expression expressions
++ let-bindings = let-name bindings
++ |"(" let-name "." bindings ")"
++ let-name = identifier
++ bindings = "(" ")"
++ | rest-binding
++ | "(" normal-bindings ["." rest-binding] ")"
++normal-bindings = nothing
++ | normal-binding normal-bindings
++normal-binding = "(" binding-name expression ")"
++ binding-name = identifier
++ rest-binding = "(" binding-name expressions ")"
++</pre>
++
++<p>
++For clarity and convenience, an informal specification follows.
++</p>
++
++<ol>
++<li><a name="unnamed">Unnamed</a>
++
++<p><pre>
++(let ((<parameter> <argument>)...)
++ <body>...)
++</pre>
++</li>
++
++<li><a name="named-non-sig">
++Named, non-signature-style, no rest argument</a>
++
++<p><pre>
++(let <name> ((<parameter> <argument>)...)
++ <body>...)
++</pre>
++</li>
++
++<li><a name="named-sig">Named, signature-style, no rest argument</a>
++
++<p><pre>
++(let (<name> (<parameter> <argument>)...)
++ <body>...)
++</pre>
++</li>
++
++<li><a name="named-non-sig-rest">Named, non-signature-style, rest argument</a>
++
++<p><pre>
++(let <name> ((<parameter> <argument>)...
++
++. (<rest-parameter> <rest-argument>...))
++ <body>...)
++</pre>
++
++<li><a name="named-sig-rest">Named, signature-style, rest argument</a>
++
++<p><pre>
++(let (<name> (<parameter> <argument>)...
++
++. (<rest-parameter> <rest-argument>...))
++ <body>...)
++</pre>
++</li>
++</ol>
++
++<H2>Semantics</H2>
++
++Let <code>$lambda</code> and <code>$letrec</code> be hygienic bindings for the <code>lambda</code>
++and <code>letrec</code> forms, respectively.
++
++<ul>
++<li>For informal syntax 1:
++
++<p><pre>
++(($lambda (<parameter>...) <body>...) <argument>...)
++</pre>
++</li>
++
++<li>For informal syntaxes 2 and 3:
++
++<p>
++<pre>
++($letrec ((<name> ($lambda (<parameter>...) <body>...)))
++ (<name> <argument>...))
++</pre>
++</li>
++
++<li>For informal syntaxes 4 and 5:
++
++<p>
++<pre>
++($letrec ((<name> ($lambda (<parameter>...
++
++. <rest-parameter>) <body>...)))
++ (<name> <argument>... <rest-argument>...))
++</pre>
++</li>
++</ul>
++
++<H1>Implementation</H1>
++
++Here is an implementation using <code>SYNTAX-RULES</code>.
++
++<p>
++<pre>
++;; Use your own standard let.
++;; Or call a lambda.
++;; (define-syntax standard-let
++;;
++;; (syntax-rules ()
++;;
++;; ((let ((var val) ...) body ...)
++;; ((lambda (var ...) body ...) val ...))))
++
++(define-syntax let
++
++ (syntax-rules ()
++
++ ;; No bindings: use standard-let.
++ ((let () body ...)
++ (standard-let () body ...))
++ ;; Or call a lambda.
++ ;; ((lambda () body ...))
++
++ ;; All standard bindings: use standard-let.
++ ((let ((var val) ...) body ...)
++ (standard-let ((var val) ...) body ...))
++ ;; Or call a lambda.
++ ;; ((lambda (var ...) body ...) val ...)
++
++ ;; One standard binding: loop.
++ ;; The all-standard-bindings clause didn't match,
++ ;; so there must be a rest binding.
++ ((let ((var val) . bindings) body ...)
++ (let-loop #f bindings (var) (val) (body ...)))
++
++ ;; Signature-style name: loop.
++ ((let (name binding ...) body ...)
++ (let-loop name (binding ...) () () (body ...)))
++
++ ;; defun-style name: loop.
++ ((let name bindings body ...)
++ (let-loop name bindings () () (body ...)))))
++
++(define-syntax let-loop
++
++ (syntax-rules ()
++
++ ;; Standard binding: destructure and loop.
++ ((let-loop name ((var0 val0) binding ...) (var ... ) (val ... ) body)
++ (let-loop name ( binding ...) (var ... var0) (val ... val0) body))
++
++ ;; Rest binding, no name: use standard-let, listing the rest values.
++ ;; Because of let's first clause, there is no "no bindings, no name" clause.
++ ((let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
++ (standard-let ((var val) ... (rest-var (list rest-val ...))) . body))
++ ;; Or call a lambda with a rest parameter on all values.
++ ;; ((lambda (var ... . rest-var) . body) val ... rest-val ...))
++ ;; Or use one of several other reasonable alternatives.
++
++ ;; No bindings, name: call a letrec'ed lambda.
++ ((let-loop name () (var ...) (val ...) body)
++ ((letrec ((name (lambda (var ...) . body)))
++ name)
++ val ...))
++
++ ;; Rest binding, name: call a letrec'ed lambda.
++ ((let-loop name (rest-var rest-val ...) (var ...) (val ...) body)
++ ((letrec ((name (lambda (var ... . rest-var) . body)))
++ name)
++ val ... rest-val ...))))
++</pre>
++
++
++<H1>Copyright</H1>
++
++Copyright (C) Andy Gaynor (1999). All Rights Reserved.
++<p>This document and translations of it may be copied and furnished to
++others, and derivative works that comment on or otherwise explain it or
++assist in its implementation may be prepared, copied, published and distributed,
++in whole or in part, without restriction of any kind, provided that the
++above copyright notice and this paragraph are included on all such copies
++and derivative works. However, this document itself may not be modified
++in any way, such as by removing the copyright notice or references to the
++Scheme Request For Implementation process or editors, except as needed
++for the purpose of developing SRFIs in which case the procedures for copyrights
++defined in the SRFI process must be followed, or as required to translate
++it into languages other than English.
++<p>The limited permissions granted above are perpetual and will not be
++revoked by the authors or their successors or assigns.
++<p>This document and the information contained herein is provided on an
++"AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE
++USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
++
++ <hr>
++ <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address>
++
++</body>
++</html>
+diff -urN racket-6.12-orig/share/pkgs/srfi-lib/info.rkt racket-6.12/share/pkgs/srfi-lib/info.rkt
+--- racket-6.12-orig/share/pkgs/srfi-lib/info.rkt 2018-01-26 16:10:02.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-lib/info.rkt 2018-01-31 12:22:58.144502000 -0500
+@@ -1 +1,15 @@
+-(module info setup/infotab (#%module-begin (define package-content-state (quote (built "6.12"))) (define collection (quote multi)) (define deps (quote ("scheme-lib" "base" "srfi-lite-lib" "r6rs-lib" "compatibility-lib"))) (define implies (quote ("srfi-lite-lib"))) (define pkg-desc "implementation (no documentation) part of \"srfi\"") (define pkg-authors (quote (mflatt noel chongkai jay)))))
++#lang info
++
++(define collection 'multi)
++
++(define deps '("scheme-lib"
++ "base"
++ "srfi-lite-lib"
++ "r6rs-lib"
++ "compatibility-lib"))
++
++(define implies '("srfi-lite-lib"))
++
++(define pkg-desc "implementation (no documentation) part of \"srfi\"")
++
++(define pkg-authors '(mflatt noel chongkai jay))
+diff -urN racket-6.12-orig/share/pkgs/srfi-lib/srfi/32/sort.txt racket-6.12/share/pkgs/srfi-lib/srfi/32/sort.txt
+--- racket-6.12-orig/share/pkgs/srfi-lib/srfi/32/sort.txt 2018-01-26 15:34:52.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-lib/srfi/32/sort.txt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,1069 +0,0 @@
+-The SRFI-32 sort libraries -*- outline -*-
+-Olin Shivers
+-First draft: 1998/10/19
+-Last update: 2002/7/21
+-
+-[Todo: del-list-neighbor-dups!
+- vector-copy -> subvector
+- use srfi-23 for reporting errors
+- use srfi-16 for n-aries?
+-
+-Emacs should display this document in outline mode. Say c-h m for
+-instructions on how to move through it by sections (e.g., c-c c-n, c-c c-p).
+-
+-* Table of contents
+--------------------
+-Abstract
+-Procedure index
+-Introduction
+-What's wrong with the current state of affairs?
+-Design rules
+- What vs. how
+- Consistency across function signatures
+- Data parameter first, less-than parameter after
+- Ordering, comparison functions & stability
+- All vector operations accept optional subrange parameters
+- Required vs. allowed side-effects
+-Procedure specification
+- Procedure naming and functionality
+- Types of parameters and return values
+- sort-lib - general sorting package
+- Algorithm-specific sorting packages
+-Algorithmic properties
+-Topics to be resolved during discussion phase
+-Porting and optimisation
+-References & Links
+-Acknowledgements
+-Copyright
+-
+-
+-* Abstract
+-----------
+-Current Scheme sorting packages are, every one of them, surprisingly bad. I've
+-designed the API for a full-featured sort toolkit, which I propose as a SRFI.
+-
+-The spec comes with 1200 lines of high-quality reference code: tightly
+-written, highly commented, portable code, available for free. Implementors
+-want this code. It's better than what you have.
+-
+--------------------------------------------------------------------------------
+-* Procedure index
+------------------
+-list-sorted? vector-sorted?
+-
+-list-merge vector-merge
+-list-sort vector-sort
+-list-stable-sort vector-stable-sort
+-list-delete-neighbor-dups vector-delete-neighbor-dups
+-
+-list-merge! vector-merge!
+-list-sort! vector-sort!
+-list-stable-sort! vector-stable-sort!
+-list-delete-neighbor-dups! vector-delete-neighbor-dups!
+-
+-quick-sort heap-sort insert-sort list-merge-sort vector-merge-sort
+-quick-sort! heap-sort! insert-sort! list-merge-sort! vector-merge-sort!
+-quick-sort3!
+-
+-vector-binary-search
+-vector-binary-search3
+-
+--------------------------------------------------------------------------------
+-* Introduction
+---------------
+-As I'll detail below, I wasn't very happy with the state of the Scheme
+-world for sorting and merging lists and vectors. So I have designed and
+-written a fairly comprehensive sorting & merging toolkit. It is
+-
+- - very portable,
+-
+- - much better code than what is currently in Elk, Gambit, Bigloo,
+- Scheme->C, MzScheme, RScheme, Scheme48, MIT Scheme, or slib, and
+-
+- - priced to move: free code.
+-
+-The package includes
+- - Vector insert sort (stable)
+- - Vector heap sort
+- - Vector quick sort (with median-of-3 pivot picking)
+- - Vector merge sort (stable)
+- - Pure and destructive list merge sort (stable)
+- - Stable vector and list merge
+- - Miscellaneous sort-related procedures: Vector and list merging,
+- sorted? predicates, vector binary search, vector and list
+- delete-equal-neighbor procedures.
+- - A general, non-algorithmic set of procedure names for general sorting
+- and merging.
+-
+-Scheme programmers may want to adopt this package. I'd like Scheme
+-implementors to adopt this code and its API -- in fact, the code is a bribe to
+-make it easy for implementors to converge on the suggested API. I mean, you'd
+-really have to be a boor to take this free code I wrote and mutate its
+-interface over to your incompatible, unportable API, wouldn't you? But you
+-could, of course -- it's freely available. More in the spirit of the offering,
+-you could make this API available, and then also write a little module
+-providing your old interface that is defined in terms of this API. "Scheme
+-implementors," in this context, includes slib, which is not a standalone
+-implementation of Scheme, but rather an influential collection of API's and
+-code.
+-
+-The code is tightly bummed. It is clearly written, and commented in my usual
+-voluminous style. This includes notes on porting and implementation-specific
+-optimisations.
+-
+-
+--------------------------------------------------------------------------------
+-* What's wrong with the current state of affairs?
+--------------------------------------------------
+-
+-It's just amazing to me that in 2002, sorting and merging hasn't been
+-completely put to bed. These are well-understood algorithms, each of them well
+-under a page of code. The straightforward algorithms are basic, core stuff --
+-sophomore-level. But if you tour the major Scheme implementations out there on
+-the Net, you find badly written code that provides extremely spotty coverage
+-of the algorithm space. One implementation even has a buggy implementation
+-that has been in use for about 20 years. Another has an O(n^2) algorithm...
+-implemented in C for speed.
+-
+-Open source-code is a wonderful thing. In a couple of hours, I was able to
+-download and check the sources of 9 Scheme systems. Here are my notes from the
+-systems I checked. You can skip to the next section if you aren't morbidly
+-curious.
+-
+-slib
+- sorted? vector-or-list <
+- merge list1 list2 <
+- merge! list1 list2 <
+- sort vector-or-list <
+- sort! vector-or-list <
+-
+- Richard O'Keefe's stable list merge sort is right idea, but implemented
+- using gratuitous variable side effects. It also does redundant SET-CDR!s.
+- The vector sort converts to list, merge sorts, then reconverts
+- to vector. This is a bad idea -- non-local pointer chasing bad; vector
+- shuffling good. If you must allocate temp storage, might as well allocate
+- a temp vector and use vector merge sort.
+-
+-MIT Scheme
+- sort! vector <
+- merge-sort! vector <
+- quick-sort! vector <
+-
+- sort vector-or-list <
+- merge-sort vector-or-list <
+- quick-sort vector-or-list <
+-
+- Naive vector quicksort: loser, for worst-case performance reasons.
+- List sort by "list->vector; quicksort; vector->list," hence also loser.
+- A clever stable vector merge sort, albeit not very bummed.
+-
+-Scheme 48 & T
+- sort-list list <
+- sort-list! list <
+- list-merge! list1 list2 <
+-
+- Bob Nix's implementation of online merge-sort, written in the early 80's.
+- Conses unnecessary bookkeeping structure, which isn't necessary with a
+- proper recursive formulation. Also, does redundant SET-CDR!s. No vector
+- sort. Also, has a bug -- is claimed to be a stable sort, but isn't! To see
+- this, get the S48 code, and try
+- (define (my< x y) (< (abs x) (abs y)))
+- (list-merge! (list 0 2) (list -2) my<) ; -> (0 2 -2)
+- (list-merge! (list 2) (list 0 -2) my<) ; -> (0 -2 2)
+- This could be fixed very easily, but it isn't worth it given the
+- other problems with the algorithm.
+-
+-RScheme
+- vector-sort! vector <
+- sort collection <
+-
+- Good basic implementation of vector heapsort, which has O(n lg n)
+- worst-case time. Code ugly, needs tuning. List sort by "list->vector;
+- sort; vector->list." Nothing for stable sorting.
+-
+-MzScheme
+- quicksort lis <
+- mergesort alox <
+-
+- Sorts lists with (list->vector; quicksort; vector->list) -- but the core
+- quicksort is not available for vector sorting. Nothing for stable sorting.
+- Quicksort picks pivot naively, inducing O(n^2) worse-case behaviour on a
+- fairly common case: an already-sorted list.
+-
+-Bigloo, STK
+- sort vector-or-list <
+- Uses an O(n^2) algorithm... implemented in C for speed. Hmm.
+- (See runtime/Ieee/vector.scm and runtime/Clib/cvector.c)
+-
+-Gambit
+- sort-list list <
+- Nothing for vectors. Simple, slow, unstable merge sort for lists.
+-
+-Elk
+- Another naive quicksort. Lists handled by converting to vector.
+- sort vector-or-list <
+- sort! vector-or-list <
+-
+-Chez Scheme
+- merge < list1 list2
+- merge! < list1 list2
+- sort < list
+- sort! < list
+-
+- These are stable. I have not seen the source code.
+-
+-Common Lisp
+- sort sequence < [key]
+- stable-sort sequence < [key]
+- merge result-type sequence1 sequence2 < [key]
+-
+- The sort procedures are allowed, but not required, to be destructive.
+-
+-SML/NJ
+- sort: ('a*'a -> bool) -> 'a list -> 'a list
+- "Smooth applicative merge sort," which is stable.
+- There is also a highly bummed quicksort for vectors.
+-
+-The right solution: Implement a full toolbox of carefully written standard sort
+-routines.
+-
+-Having the source of all these above-cited Schemes available for study made
+-life a lot easier writing this code. I appreciate the authors making their
+-source available under such open terms.
+-
+-
+--------------------------------------------------------------------------------
+-* Design rules
+---------------
+-
+-** What vs. how
+-===============
+-There are two different interfaces: "what" (simple) & "how" (detailed).
+-
+- - Simple: you specify semantics: datatype (list or vector),
+- mutability, and stability.
+-
+- - Detailed: you specify the actual algorithm (quick, heap,
+- insert, merge). Different algorithms have different properties,
+- both semantic & pragmatic, so these exports are necessary.
+-
+- It is necessarily the case that the specifications of these procedures
+- make statements about execution "pragmatics." For example, the sole
+- distinction between heap sort and quick sort -- both of which are
+- provided by this library -- is one of execution time, which is not a
+- "semantic" distinction. Similar resource-use statements are made about
+- "iterative" procedures, meaning that they can execute on input of
+- arbitrary size in a constant number of stack frames.
+-
+-** Consistency across function signatures
+-=========================================
+-The two interfaces share common function signatures wherever
+-possible, to facilitate switching a given call from one procedure
+-to another.
+-
+-** Less-than parameter first, data parameter after
+-==================================================
+-These procedures uniformly observe the following parameter order:
+-the data to be sorted comes after the comparison function.
+-That is, we write
+- (sort < lis)
+-not
+- (sort lis <).
+-
+-With the sole exception of Chez Scheme, this is the exact opposite of
+-every sort function out there in current use in the Scheme world. (See
+-the summary of related APIs above.) However, it is consistent with common
+-practice across Scheme libraries in general to put the ordering function
+-first -- the "operation currying" convention. (E.g., consider FOR-EACH or
+-MAP or FIND.)
+-
+-The original draft of this SRFI used the data-first/comparison-last convention
+-for backwards compatibility -- a decision I made with internal misgivings.
+-Happily, however, the overwhelming response from the discussion phase
+-supported "cleaning up" this issue and re-converging the parameter order with
+-the general Scheme "op currying" convention. So the original decision was
+-inverted in favor of the comparison-first/data-last convention.
+-
+-** Ordering, comparison functions & stability
+-=============================================
+-These routines take a < comparison function, not a <= comparison
+-function, and they sort into increasing order. The difference between
+-a < spec and a <= spec comes up in three places:
+- - the definition of an ordered or sorted data set,
+- - the definition of a stable sorting algorithm, and
+- - correctness of quicksort.
+-
+-+ We say that a data set (a list or vector) is *sorted* or *ordered*
+- if it contains no adjacent pair of values ... X Y ... such that Y < X.
+-
+- In other words, scanning across the data never takes a "downwards" step.
+-
+- If you use a <= procedure where these algorithms expect a <
+- procedure, you may not get the answers you expect. For example,
+- the LIST-SORTED? function will return false if you pass it a <= comparison
+- function and an ordered list containing adjacent equal elements.
+-
+-+ A "stable" sort is one that preserves the pre-existing order of equal
+- elements. Suppose, for example, that we sort a list of numbers by
+- comparing their absolute values, i.e., using comparison function
+- (lambda (x y) (< (abs x) (abs y)))
+- If we sort a list that contains both 3 and -3:
+- ... 3 ... -3 ...
+- then a stable sort is an algorithm that will not swap the order
+- of these two elements, that is, the answer is guaranteed to to look like
+- ... 3 -3 ...
+- not
+- ... -3 3 ...
+-
+- Choosing < for the comparison function instead of <= affects how stability
+- is coded. Given an adjacent pair X Y, (< y x) means "Y should be moved in
+- front of X" -- otherwise, leave things as they are. So using a <= function
+- where a < function is expected will *invert* stability.
+-
+- This is due to the definition of equality, given a < comparator:
+- (and (not (< x y))
+- (not (< y x)))
+- The definition is rather different, given a <= comparator:
+- (and (<= x y)
+- (<= y x))
+-
+-+ A "stable" merge is one that reliably favors one of its data sets
+- when equal items appear in both data sets. *All merge operations in
+- this library are stable*, breaking ties between data sets in favor
+- of the first data set -- elements of the first list come before equal
+- elements in the second list.
+-
+- So, if we are merging two lists of numbers ordered by absolute value,
+- the stable merge operation LIST-MERGE
+- (list-merge (lambda (x y) (< (abs x) (abs y)))
+- '(0 -2 4 8 -10) '(-1 3 -4 7))
+- reliably places the 4 of the first list before the equal-comparing -4
+- of the second list:
+- (0 -1 -2 4 -4 7 8 -10)
+-
+-+ Some sort algorithms will *not work correctly* if given a <= when they
+- expect a < comparison (or vice-versa). For example, violating quicksort's
+- spec may cause it to produce wrong answers, diverge, raise an error, or do
+- some fourth thing. To see why, consider the left-scan part of the standard
+- quicksort partition step:
+- (let ((i (let scan ((i i)) (if (elt< (vector-ref v i) pivot)
+- (scan (+ i 1))
+- i))))
+- ...)
+- Consider applying this loop to a vector of all zeroes (hence, PIVOT, as
+- well, is zero), but erroneously using <= for the ELT< function. The loop
+- will scan right off the end of the vector, producing a vector-index error.
+- The guarantee that the scan loop will terminate before running off the end
+- of the vector depends critically upon ELT< performing as a true, irreflexive
+- < relation. Running off the end of the vector is only one of a variety of
+- possibly ways to lose -- other, variant implementations of quicksort can,
+- instead, loop forever on some data sets if ELT< is a <= predicate.
+-
+-In short, if your comparison function F answers true to (F x x), then
+- - using a stable sorting or merging algorithm will not give you a
+- stable sort or merge,
+- - LIST-SORTED? may surprise you, and
+- - quicksort may fail in a variety of possible ways.
+-Note that you can synthesize a < function from a <= function with
+- (lambda (x y) (not (<= y x)))
+-if need be.
+-
+-Precise definitions give sharp edges to tools, but require care in use.
+-"Measure twice, cut once."
+-
+-I have adopted the choice of < from Common Lisp. One would assume the definers
+-of Common Lisp had a good reason for adopting < instead of <=, but canvassing
+-several of the principal actors in the definition process has turned up no
+-better reason than "an arbitrary but consistent choice." At minimum, then,
+-this SRFI extends the coverage of that consistent choice.
+-
+-** All vector operations accept optional subrange parameters
+-============================================================
+-The vector operations specified below all take optional START/END arguments
+-indicating a selected subrange of a vector's elements. If a START parameter or
+-START/END parameter pair is given to such a procedure, they must be exact,
+-non-negative integers, such that
+- 0 <= START <= END <= (VECTOR-LENGTH V)
+-where V is the related vector parameter. If not specified, they default to 0
+-and the length of the vector, respectively. They are interpreted to select the
+-range [START,END), that is, all elements from index START (inclusive) up to,
+-but not including, index END.
+-
+-** Required vs. allowed side-effects
+-====================================
+-LIST-SORT! and LIST-STABLE-SORT! are allowed, but not required,
+-to alter their arguments' cons cells to construct the result list. This is
+-consistent with the what-not-how character of the group of procedures
+-to which they belong (the "sort-lib" package).
+-
+-The LIST-DELETE-NEIGHBOR-DUPS!, LIST-MERGE! and LIST-MERGE-SORT! procedures,
+-on the other hand, provide specific algorithms, and, as such, explicitly
+-commit to the use of side-effects on their input lists in order to guarantee
+-their key algorithmic properties (e.g., linear-time operation, constant-space
+-stack use).
+-
+--------------------------------------------------------------------------------
+-* Procedure specification
+--------------------------
+-The procedures are split into several packages. In a Scheme system that has a
+-module or package system, these procedures should be contained in modules
+-named as follows:
+- Package name Functionality
+- ------------ -------------
+- sort-lib General sorting for lists & vectors
+- sorted?-lib Sorted predicates for lists & vectors
+- list-merge-sort-lib List merge sort
+- vector-merge-sort-lib Vector merge sort
+- vector-heap-sort-lib Vector heap sort
+- vector-quick-sort-lib Vector quick sort
+- vector-insert-sort-lib Vector insertion sort
+- delndup-lib List and vector delete neighbor duplicates
+- binsearch-lib Vector binary search
+-
+-A Scheme system without a module system should provide all of the bindings
+-defined in all of these modules as components of the "SRFI-32" package.
+-
+-Note that there is no "list insert sort" package, as you might as well always
+-use list merge sort. The reference implementation's destructive list merge
+-sort will do fewer SET-CDR!s than a destructive insert sort.
+-
+-** Procedure naming and functionality
+-=====================================
+-Almost all of the procedures described below are variants of two basic
+-operations: sorting and merging. These procedures are consistently named
+-by composing a set of basic lexemes to indicate what they do.
+-
+-Lexeme Meaning
+------- -------
+-"sort" The procedure sorts its input data set by some < comparison function.
+-
+-"merge" The procedure merges two ordered data sets into a single ordered
+- result.
+-
+-"stable" This lexeme indicates that the sort is a stable one.
+-
+-"vector" The procedure operates upon vectors.
+-
+-"list" The procedure operates upon lists.
+-
+-"!" Procedures that end in "!" are allowed, and sometimes required,
+- to reuse their input storage to construct their answer.
+-
+-** Types of parameters and return values
+-========================================
+-In the procedures specified below,
+- - A LIS parameter is a list;
+-
+- - A V parameter is a vector;
+-
+- - A < or = parameter is a procedure accepting two arguments taken from the
+- specified procedure's data set(s), and returning a boolean;
+-
+- - START and END parameters are exact, non-negative integers that
+- serve as vector indices selecting a subrange of some associated vector.
+- When specified, they must satisfy the relation
+- 0 <= start <= end <= (vector-length v)
+- where V is the associated vector.
+-
+-Passing values to procedures with these parameters that do not satisfy these
+-types is an error.
+-
+-If a procedure is said to return "unspecified," this means that nothing at all
+-is said about what the procedure returns, not even the number of return
+-values. Such a procedure is not even required to be consistent from call to
+-call in the nature or number of its return values. It is simply required to
+-return a value (or values) that may be passed to a command continuation, e.g.
+-as the value of an expression appearing as a non-terminal subform of a BEGIN
+-expression. Note that in R5RS, this restricts such a procedure to returning a
+-single value; non-R5RS systems may not even provide this restriction.
+-
+-** sort-lib - general sorting package
+-=====================================
+-This library provides basic sorting and merging functionality suitable for
+-general programming. The procedures are named by their semantic properties,
+-i.e., what they do to the data (sort, stable sort, merge, and so forth).
+-
+- Procedure Suggested algorithm
+- -------------------------------------------------------------------------
+- list-sorted? < lis -> boolean
+- list-merge < lis1 lis2 -> list
+- list-merge! < lis1 lis2 -> list
+- list-sort < lis -> list (vector heap or quick)
+- list-sort! < lis -> list (list merge sort)
+- list-stable-sort < lis -> list (vector merge sort)
+- list-stable-sort! < lis -> list (list merge sort)
+- list-delete-neighbor-dups = lis -> list
+- list-delete-neighbor-dups! = lis -> list
+-
+- vector-sorted? < v [start end] -> boolean
+- vector-merge < v1 v2 [start1 end1 start2 end2] -> vector
+- vector-merge! < v v1 v2 [start start1 end1 start2 end2] -> unspecified
+- vector-sort < v [start end] -> vector (heap or quick sort)
+- vector-sort! < v [start end] -> unspecified (heap or quick sort)
+- vector-stable-sort < v [start end] -> vector (vector merge sort)
+- vector-stable-sort! < v [start end] -> unspecified (vector merge sort)
+- vector-delete-neighbor-dups = v [start end] -> vector
+- vector-delete-neighbor-dups! = target source [t-start s-start s-end] -> t-end
+-
+- LIST-SORTED? and VECTOR-SORTED? return true if their input list or vector
+- is in sorted order, as determined by their < comparison parameter.
+-
+- All four merge operations are stable: an element of the initial list LIS1
+- or vector V1 will come before an equal-comparing element in the second
+- list LIS2 or vector V2 in the result.
+-
+- The procedures
+- LIST-MERGE
+- LIST-SORT
+- LIST-STABLE-SORT
+- LIST-DELETE-NEIGHBOR-DUPS
+- do not alter their inputs and are allowed to return a value that shares
+- a common tail with a list argument.
+-
+- The procedures
+- LIST-SORT!
+- LIST-STABLE-SORT!
+- are "linear update" operators -- they are allowed, but not required, to
+- alter the cons cells of their arguments to produce their results.
+-
+- On the other hand, the procedures
+- LIST-DELETE-NEIGHBOR-DUPS!
+- LIST-MERGE!
+- make only a single, iterative, linear-time pass over their argument lists,
+- using SET-CDR!s to rearrange the cells of the lists into the final result
+- -- they work "in place." Hence, any cons cell appearing in the result must
+- have originally appeared in an input. The intent of this
+- iterative-algorithm commitment is to allow the programmer to be sure that
+- if, for example, LIST-MERGE! is asked to merge two ten-million-element
+- lists, the operation will complete without performing some extremely
+- (possibly twenty-million) deep recursion.
+-
+- The vector procedures
+- VECTOR-SORT
+- VECTOR-STABLE-SORT
+- VECTOR-DELETE-NEIGHBOR-DUPS
+- do not alter their inputs, but allocate a fresh vector for their result,
+- of length END - START.
+-
+- The vector procedures
+- VECTOR-SORT!
+- VECTOR-STABLE-SORT!
+- sort their data in-place. (But note that VECTOR-STABLE-SORT! may
+- allocate temporary storage proportional to the size of the input --
+- I am not aware of O(n lg n) stable vector-sorting algorithms that
+- run in constant space.)
+-
+- VECTOR-MERGE returns a vector of length (END1-START1)+(END2-START2).
+-
+- VECTOR-MERGE! writes its result into vector V, beginning at index START,
+- for indices less than END = START + (END1-START1) + (END2-START2). The
+- target subvector
+- V[start,end)
+- may not overlap either source subvector
+- V1[start1,end1)
+- V2[start2,end2).
+-
+- The ...-DELETE-NEIGHBOR-DUPS-... procedures:
+- These procedures delete adjacent duplicate elements from a list or a
+- vector, using a given element-equality procedure. The first/leftmost
+- element of a run of equal elements is the one that survives. The list or
+- vector is not otherwise disordered.
+-
+- These procedures are linear time -- much faster than the O(n^2) general
+- duplicate-element deletors that do not assume any "bunching" of elements
+- (such as the ones provided by SRFI-1). If you want to delete duplicate
+- elements from a large list or vector, you can sort the elements to bring
+- equal items together, then use one of these procedures, for a total time
+- of O(n lg n).
+-
+- The comparison function = passed to these procedures is always applied
+- (= x y)
+- where X comes before Y in the containing list or vector.
+-
+- - LIST-DELETE-NEIGHBOR-DUPS does not alter its input list; its answer
+- may share storage with the input list.
+-
+- - VECTOR-DELETE-NEIGHBOR-DUPS does not alter its input vector, but
+- rather allocates a fresh vector to hold the result.
+-
+- - LIST-DELETE-NEIGHBOR-DUPS! is permitted, but not required, to
+- mutate its input list in order to construct its answer.
+-
+- - VECTOR-DELETE-NEIGHBOR-DUPS! reuses its input vector to hold the
+- answer, packing its answer into the index range [start,end'), where
+- END' is the non-negative exact integer returned as its value. It
+- returns END' as its result. The vector is not altered outside the range
+- [start,end').
+-
+- - VECTOR-DELETE-NEIGHBOR-DUPS! scans vector SOURCE in range
+- [S-START,S-END), writing its result to vector TARGET beginning at index
+- T-START. It returns exact, non-negative integer T-END, which indicates
+- that the results of the operation are found in index range
+- [T-START,T-END) of TARGET; elements of TARGET outside this range
+- are unaltered.
+-
+- It is an error for memory cell TARGET[T-START] to be a memory cell in
+- the region SOURCE[1 + S-START, S-END). In a Scheme implementation
+- that does not allow distinct vectors to share storage, this means
+- that one of the following must be true:
+- 1. (not (eq? source target))
+- 2. t-start not-in [s-start + 1, s-end)
+-
+- - Examples:
+- (list-delete-neighbor-dups = '(1 1 2 7 7 7 0 -2 -2))
+- => (1 2 7 0 -2)
+-
+- (vector-delete-neighbor-dups = '#(1 1 2 7 7 7 0 -2 -2))
+- => #(1 2 7 0 -2)
+-
+- (vector-delete-neighbor-dups = '#(1 1 2 7 7 7 0 -2 -2) 3 7)
+- => #(7 0 -2)
+-
+- ;; Result left in v[3,9):
+- (let ((v (vector 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6)))
+- (cons (vector-delete-neighbor-dups! = v 3)
+- v))
+- => (9 . #(0 0 0 1 2 3 4 5 6 4 4 5 5 6 6))
+-
+-
+-** Algorithm-specific sorting packages
+-======================================
+-These packages provide more specific sorting functionality, that is,
+-specific commitment to particular algorithms that have particular
+-pragmatic consequences (such as memory locality, asymptotic running time)
+-beyond their semantic behaviour (sorting, stable sorting, merging, etc.).
+-Programmers that need a particular algorithm can use one of these packages.
+-
+-sorted?-lib - sorted predicates
+- list-sorted? < lis -> boolean
+- vector-sorted? < v [start end] -> boolean
+-
+- Return #f iff there is an adjacent pair ... X Y ... in the input
+- list or vector such that Y < X. The optional START/END range
+- arguments restrict VECTOR-SORTED? to the indicated subvector.
+-
+-list-merge-sort-lib - list merge sort
+- list-merge-sort < lis -> list
+- list-merge-sort! < lis -> list
+- list-merge lis1 < lis2 -> list
+- list-merge! lis1 < lis2 -> list
+-
+- The sort procedures sort their data using a list merge sort, which is
+- stable. (The reference implementation is, additionally, a "natural" sort.
+- See below for the properties of this algorithm.)
+-
+- The ! procedures are destructive -- they use SET-CDR!s to rearrange the
+- cells of the lists into the proper order. As such, they do not allocate
+- any extra cons cells -- they are "in place" sorts. Additionally,
+- LIST-MERGE! is iterative -- it can operate on arguments of arbitrary size
+- with a constant number of stack frames.
+-
+- The merge operations are stable: an element of LIS1 will come before an
+- equal-comparing element in LIS2 in the result list.
+-
+-vector-merge-sort-lib - vector merge sort
+- vector-merge-sort < v [start end temp] -> vector
+- vector-merge-sort! < v [start end temp] -> unspecified
+- vector-merge < v1 v2 [start1 end1 start2 end2] -> vector
+- vector-merge! < v v1 v2 [start start1 end1 start2 end2] -> unspecified
+-
+- The sort procedures sort their data using vector merge sort, which is
+- stable. (The reference implementation is, additionally, a "natural" sort.
+- See below for the properties of this algorithm.)
+-
+- The optional START/END arguments provide for sorting of subranges, and
+- default to 0 and the length of the corresponding vector.
+-
+- Merge-sorting a vector requires the allocation of a temporary "scratch"
+- work vector for the duration of the sort. This scratch vector can be
+- passed in by the client as the optional TEMP argument; if so, the supplied
+- vector must be of size >= END, and will not be altered outside the range
+- [start,end). If not supplied, the sort routines allocate one themselves.
+-
+- The merge operations are stable: an element of V1 will come before an
+- equal-comparing element in V2 in the result vector.
+-
+- VECTOR-MERGE-SORT! leaves its result in V[start,end).
+-
+- VECTOR-MERGE-SORT returns a vector of length END-START.
+-
+- VECTOR-MERGE returns a vector of length (END1-START1)+(END2-START2).
+-
+- VECTOR-MERGE! writes its result into vector V, beginning at index START,
+- for indices less than END = START + (END1-START1) + (END2-START2). The
+- target subvector
+- V[start,end)
+- may not overlap either source subvector
+- V1[start1,end1)
+- V2[start2,end2).
+-
+-vector-heap-sort-lib - vector heap sort
+- heap-sort < v [start end] -> vector
+- heap-sort! < v [start end] -> unspecified
+-
+- These procedures sort their data using heap sort,
+- which is not a stable sorting algorithm.
+-
+- HEAP-SORT returns a vector of length END-START.
+- HEAP-SORT! is in-place, leaving its result in V[start,end).
+-
+-vector-quick-sort-lib - vector quick sort
+- quick-sort < v [start end] -> vector
+- quick-sort! < v [start end] -> unspecified
+- quick-sort3! c v [start end] -> unspecified
+-
+- These procedures sort their data using quick sort,
+- which is not a stable sorting algorithm.
+-
+- QUICK-SORT returns a vector of length END-START.
+- QUICK-SORT! is in-place, leaving its result in V[start,end).
+-
+- QUICK-SORT3! is a variant of quick-sort that takes a three-way
+- comparison function C. C compares a pair of elements and returns
+- an exact integer whose sign indicates their relationship:
+- (c x y) < 0 => x<y
+- (c x y) = 0 => x=y
+- (c x y) > 0 => x>y
+- To help remember the relationship between the sign of the result and
+- the relation, use the function - as the model for C: (- x y) < 0
+- means that x < y; (- x y) > 0 means that x > y.
+-
+- The extra discrimination provided by the three-way comparison can
+- provide significant speedups when sorting data sets with many duplicates,
+- especially when the comparison function is relatively expensive (e.g.,
+- comparing long strings).
+-
+- WARNING: Some sort algorithms, such as insertion sort or heap sort,
+- can tolerate being passed a <= comparison function when they expect a <
+- function -- insertion and merge sort may simply invert stability; and
+- heap sort will run a bit slower, but otherwise produce a correct answer.
+-
+- Quicksort, however, is much more critically sensitive to the distinction
+- between a < and a <= comparison. If QUICK-SORT or QUICK-SORT! expect a <
+- comparison function, and are erroneously given a <= function, they may,
+- depending on implementation, produce an unsorted result, go into an
+- infinite loop, cause a run-time error, occasionally produce a correct
+- result, or do some fifth thing.
+-
+- Implementors may wish to write QUICKSORT3! so that it (a) tests the
+- comparison function (by checking that (c v[start] v[start]) produces
+- false), or (b) is tolerant of an erroneous <= function, or (c) both.
+- Clients of this function, however, should not count on this.
+-
+-vector-insert-sort-lib - vector insertion sort
+- insert-sort < v [start end] -> vector
+- insert-sort! < v [start end] -> unspecified
+-
+- These procedures stably sort their data using insertion sort.
+-
+- INSERT-SORT returns a vector of length END-START.
+- INSERT-SORT! is in-place, leaving its result in V[start,end).
+-
+-delndup-lib - list and vector delete neighbor duplicates
+- list-delete-neighbor-dups = lis -> list
+- list-delete-neighbor-dups! = lis -> list
+-
+- vector-delete-neighbor-dups = v [start end] -> vector
+- vector-delete-neighbor-dups! = v [start end] -> end'
+-
+- These procedures delete adjacent duplicate elements from a list or
+- a vector, using a given element-equality procedure =. The first/leftmost
+- element of a run of equal elements is the one that survives. The list
+- or vector is not otherwise disordered.
+-
+- These procedures are linear time -- much faster than the O(n^2) general
+- duplicate-element deletors that do not assume any "bunching" of elements
+- (such as the ones provided by SRFI-1). If you want to delete duplicate
+- elements from a large list or vector, you can sort the elements to bring
+- equal items together, then use one of these procedures, for a total time
+- of O(n lg n).
+-
+- The comparison function = passed to these procedures is always applied
+- (= x y)
+- where X comes before Y in the containing list or vector.
+-
+- LIST-DELETE-NEIGHBOR-DUPS does not alter its input list; its answer
+- may share storage with the input list.
+-
+- VECTOR-DELETE-NEIGHBOR-DUPS does not alter its input vector, but
+- rather allocates a fresh vector to hold the result.
+-
+- LIST-DELETE-NEIGHBOR-DUPS! is permitted, but not required, to
+- mutate its input list in order to construct its answer.
+-
+- VECTOR-DELETE-NEIGHBOR-DUPS! reuses its input vector to hold the
+- answer, packing its answer into the index range [start,end'), where
+- END' is the non-negative exact integer returned as its value. It
+- returns END' as its result. The vector is not altered outside the range
+- [start,end').
+-
+- Examples:
+- (list-delete-neighbor-dups = '(1 1 2 7 7 7 0 -2 -2))
+- => (1 2 7 0 -2)
+-
+- (vector-delete-neighbor-dups = '#(1 1 2 7 7 7 0 -2 -2))
+- => #(1 2 7 0 -2)
+-
+- (vector-delete-neighbor-dups = '#(1 1 2 7 7 7 0 -2 -2) 3 7)
+- => #(7 0 -2)
+-
+- ;; Result left in v[3,9):
+- (let ((v (vector 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6)))
+- (cons (vector-delete-neighbor-dups! = v 3)
+- v))
+- => (9 . #(0 0 0 1 2 3 4 5 6 4 4 5 5 6 6))
+-
+-binsearch-lib - vector binary search lib
+- vector-binary-search elt< elt->key key v [start end] -> integer-or-false
+- vector-binary-search3 c v [start end] -> integer-or-false
+-
+- VECTOR-BINARY-SEARCH searches vector V in range [START,END) (which
+- default to 0 and the length of V, respectively) for an element whose
+- associated key is equal to KEY. The procedure ELT->KEY is used to map
+- an element to its associated key. The elements of the vector are assumed
+- to be ordered by the ELT< relation on these keys. That is,
+- (vector-sorted? (lambda (x y) (elt< (elt->key x) (elt->key y)))
+- v start end) => true
+- An element E of V is a match for KEY if it's neither less nor greater
+- than the key:
+- (and (not (elt< (elt->key e) key))
+- (not (elt< key (elt->key e))))
+- If there is such an element, the procedure returns its index in the
+- vector as an exact integer. If there is no such element in the searched
+- range, the procedure returns false.
+-
+- (vector-binary-search < car 4 '#((1 . one) (3 . three)
+- (4 . four) (25 . twenty-five)))
+- => 2
+-
+- (vector-binary-search < car 7 '#((1 . one) (3 . three)
+- (4 . four) (25 . twenty-five)))
+- => #f
+-
+- VECTOR-BINARY-SEARCH3 is a variant that uses a three-way comparison
+- function C. C compares its parameter to the search key, and returns an
+- exact integer whose sign indicates its relationship to the search key.
+- (c x) < 0 => x < search-key
+- (c x) = 0 => x = search-key
+- (c x) > 0 => x > search-key
+-
+- (vector-binary-search3 (lambda (elt) (- (car elt) 4))
+- '#((1 . one) (3 . three)
+- (4 . four) (25 . twenty-five)))
+- => 2
+-
+- Rationale:
+- - Why isn't VECTOR-BINARY-SEARCH's ELT->KEY computation simply absorbed
+- into the < function? It is separated out because the < function is
+- applied twice inside the binary-search inner loop, once with the search
+- key for the first argument and the element key for the second argument,
+- and once, with the reverse argument order. This is not necessary for
+- VECTOR-BINARY-SEARCH3.
+-
+- - When a comparison operation is able to produce a three-way
+- discrimination, the inner loop of the binary search can trim the number
+- of per-iteration comparisons from an average of 1.5 to a guaranteed
+- single comparison per iteration. This can be a significant savings when
+- searching with an expensive comparison operation (e.g., one that
+- uses string compare, sends email, references a database, or queries
+- a network service such as a web server).
+-
+- - Failure is signaled by false (rather than, say, -1) so that searches
+- can be used in conditional forms such as
+- (or (vector-binary-search ...) ...)
+- or
+- (cond ((vector-binary-search ...) => index-consumer)
+- ...)
+-
+--------------------------------------------------------------------------------
+-* Algorithmic properties
+-------------------------
+-Different sort and merge algorithms have different properties.
+-Choose the algorithm that matches your needs:
+-
+-Vector insert sort
+- Stable, but only suitable for small vectors -- O(n^2).
+-
+-Vector quick sort
+- Not stable. Is fast on average -- O(n lg n) -- but has bad worst-case
+- behaviour. Has good memory locality for big vectors (unlike heap sort).
+- A clever pivot-picking trick (median of three samples) helps avoid
+- worst-case behaviour, but pathological cases can still blow up.
+-
+-Vector heap sort
+- Not stable. Guaranteed fast -- O(n lg n) *worst* case. Poor locality
+- on large vectors. A very reliable workhorse.
+-
+-Vector merge sort
+- Stable. Not in-place -- requires a temporary buffer of equal size.
+- Fast -- O(n lg n) -- and has good memory locality for large vectors.
+-
+- The implementation of vector merge sort provided by this SRFI's reference
+- implementation is, additionally, a "natural" sort, meaning that it
+- exploits existing order in the input data, providing O(n) best case.
+-
+-Destructive list merge sort
+- Stable, fast and in-place (i.e., allocates no new cons cells). "Fast"
+- means O(n lg n) worse-case, and substantially better if the data
+- is already mostly ordered, all the way down to linear time for
+- a completely-ordered input list (i.e., it is a "natural" sort).
+-
+- Note that sorting lists involves chasing pointers through memory, which
+- can be a loser on modern machine architectures because of poor cache &
+- page locality. Pointer *writing*, which is what the SET-CDR!s of a
+- destructive list-sort algorithm do, is even worse, especially if your
+- Scheme has a generational GC -- the writes will thrash the write-barrier.
+- Sorting vectors has inherently better locality.
+-
+- This SRFI's destructive list merge and merge sort implementations are
+- opportunistic -- they avoid redundant SET-CDR!s, and try to take long
+- already-ordered runs of list structure as-is when doing the merges.
+-
+-Pure list merge sort
+- Stable and fast -- O(n lg n) worst-case, and possibly O(n), depending
+- upon the input list (see discussion above).
+-
+-
+-Algorithm Stable? Worst case Average case In-place
+-------------------------------------------------------
+-Vector insert Yes O(n^2) O(n^2) Yes
+-Vector quick No O(n^2) O(n lg n) Yes
+-Vector heap No O(n lg n) O(n lg n) Yes
+-Vector merge Yes O(n lg n) O(n lg n) No
+-List merge Yes O(n lg n) O(n lg n) Either
+-
+-
+--------------------------------------------------------------------------------
+-* Porting and optimisation
+---------------------------
+-This package should be trivial to port. There are only four non-R4RS bits
+-in the code:
+-- Use of multiple-value return, with the R5RS VALUES procedure, and the
+- simple (RECEIVE (var ...) mv-exp body ...) multiple-value binding macro
+- of SRFI-8.
+-
+-- A VECTOR-COPY procedure. This is a tiny little procedure:
+- (vector-copy v [start end])
+-
+-- Use of the LET-OPTIONALS macro from scsh to parse and default optional
+- arguments to three routines. Again, easy to port the macro or rewrite
+- the code to parse, default, and error check the args by hand.
+-
+-- Calls to an ERROR function for complaining about bad arguments.
+-
+-This code is tightly bummed, as far as I can go in portable Scheme.
+-
+-You could speed up the vector code a lot by error-checking the procedure
+-parameters and then shifting over to fixnum-specific arithmetic and dangerous
+-vector-indexing and vector-setting primitives. The comments in the code
+-indicate where the initial error checks would have to be added. There are
+-several (QUOTIENT N 2)'s that could be changed to a fixnum right-shift, as
+-well, in both the list and vector code (SRFI 33 provides such an operator).
+-The code is designed to enable this -- each file usually exports one or two
+-"safe" procedures that end up calling an internal "dangerous" primitive. The
+-little exported cover procedures are where you move the error checks.
+-
+-This should provide *big* speedups. In fact, all the code bumming I've done
+-pretty much disappears in the noise unless you have a good compiler and also
+-can dump the vector-index checks and generic arithmetic -- so I've really just
+-set things up for you to exploit.
+-
+-The optional-arg parsing, defaulting, and error checking is done with a
+-portable R4RS macro. But if your Scheme has a faster mechanism (e.g., Chez),
+-you should definitely port over to it. Note that argument defaulting and
+-error-checking are interleaved -- you don't have to error-check defaulted
+-START/END args to see if they are fixnums that are legal vector indices for
+-the corresponding vector, etc.
+-
+-
+--------------------------------------------------------------------------------
+-* References & Links
+---------------------
+-
+-This document, in HTML:
+- http://srfi.schemers.org/srfi-32/srfi-32.html
+- [This link may not be valid while the SRFI is in draft form.]
+-
+-This document, in simple text format:
+- http://srfi.schemers.org/srfi-32/srfi-32.txt
+-
+-Archive of SRFI-32 discussion-list email:
+- http://srfi.schemers.org/srfi-32/mail-archive/maillist.html
+-
+-SRFI web site:
+- http://srfi.schemers.org/
+-
+-[CommonLisp]
+- Common Lisp: the Language
+- Guy L. Steele Jr. (editor).
+- Digital Press, Maynard, Mass., second edition 1990.
+- Available at http://www.elwood.com/alu/table/references.htm#cltl2
+-
+- The Common Lisp "HyperSpec," produced by Kent Pitman, is essentially
+- the ANSI spec for Common Lisp:
+- http://www.xanalys.com/software_tools/reference/HyperSpec/
+-
+-[R5RS]
+- Revised^5 Report on the Algorithmic Language Scheme,
+- R. Kelsey, W. Clinger, J. Rees (editors).
+- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998.
+- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
+-
+- Available at http://www.schemers.org/Documents/Standards/
+-
+-
+--------------------------------------------------------------------------------
+-* Acknowledgements
+-------------------
+-
+-I thank the authors of the open source I consulted when designing this
+-library, particularly Richard O'Keefe, Donovan Kolby and the MIT Scheme Team.
+-
+-
+--------------------------------------------------------------------------------
+-* Copyright
+------------
+-
+-** SRFI text
+-============
+-This document is copyright (C) Olin Shivers (1998, 1999).
+-All Rights Reserved.
+-
+-This document and translations of it may be copied and furnished to others,
+-and derivative works that comment on or otherwise explain it or assist in its
+-implementation may be prepared, copied, published and distributed, in whole or
+-in part, without restriction of any kind, provided that the above copyright
+-notice and this paragraph are included on all such copies and derivative
+-works. However, this document itself may not be modified in any way, such as
+-by removing the copyright notice or references to the Scheme Request For
+-Implementation process or editors, except as needed for the purpose of
+-developing SRFIs in which case the procedures for copyrights defined in the
+-SRFI process must be followed, or as required to translate it into languages
+-other than English.
+-
+-The limited permissions granted above are perpetual and will not be revoked by
+-the authors or their successors or assigns.
+-
+-This document and the information contained herein is provided on an "AS IS"
+-basis and THE AUTHORS AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR
+-IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+-INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+-MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+-
+-** Reference implementation
+-===========================
+-Short summary: no restrictions.
+-
+-While I wrote all of this code myself, I read a lot of code before I began
+-writing. However, all such code is, itself, either open source or public
+-domain, rendering irrelevant any issue of "copyright taint."
+-
+-The natural merge sorts (pure list, destructive list, and vector) are not only
+-my own code, but are implementations of an algorithm of my own devising. They
+-run in O(n lg n) worst case, O(n) best case, and require only a logarithmic
+-number of stack frames. And they are stable. And the destructive-list variant
+-allocates zero cons cells; it simply rearranges the cells of the input list.
+-
+-Hence the reference implementation is
+- Copyright (c) 1998 by Olin Shivers.
+-and made available under the same copyright as the SRFI text (see above).
+diff -urN racket-6.12-orig/share/pkgs/srfi-lib/srfi/32/srfi-32.txt racket-6.12/share/pkgs/srfi-lib/srfi/32/srfi-32.txt
+--- racket-6.12-orig/share/pkgs/srfi-lib/srfi/32/srfi-32.txt 1969-12-31 19:00:00.000000000 -0500
++++ racket-6.12/share/pkgs/srfi-lib/srfi/32/srfi-32.txt 2018-01-31 12:22:58.152501970 -0500
+@@ -0,0 +1,938 @@
++The SRFI-32 sort libraries -*- outline -*-
++Olin Shivers
++First draft: 1998/10/19
++Last update: 2002/7/21
++
++Emacs should display this document in outline mode. Say c-h m for
++instructions on how to move through it by sections (e.g., c-c c-n, c-c c-p).
++
++* Table of contents
++-------------------
++Abstract
++Procedure index
++Introduction
++What's wrong with the current state of affairs?
++Design rules
++ What vs. how
++ Consistency across function signatures
++ Data parameter first, less-than parameter after
++ Ordering, comparison functions & stability
++ All vector operations accept optional subrange parameters
++ Required vs. allowed side-effects
++Procedure specification
++ Procedure naming and functionality
++ Types of parameters and return values
++ sort-lib - general sorting package
++ Algorithm-specific sorting packages
++Algorithmic properties
++Topics to be resolved during discussion phase
++Porting and optimisation
++References & Links
++Acknowledgements
++Copyright
++
++
++* Abstract
++----------
++Current Scheme sorting packages are, every one of them, surprisingly bad. I've
++designed the API for a full-featured sort toolkit, which I propose as an SRFI.
++The spec comes with 1200 lines of high-quality reference code: tightly
++written, highly commented, portable code, available for free. Implementors
++want this code. It's better than what you have.
++
++-------------------------------------------------------------------------------
++* Procedure index
++-----------------
++list-sorted? vector-sorted?
++
++list-merge vector-merge
++list-sort vector-sort
++list-stable-sort vector-stable-sort
++list-delete-neighbor-dups vector-delete-neighbor-dups
++
++list-merge! vector-merge!
++list-sort! vector-sort!
++list-stable-sort! vector-stable-sort!
++list-delete-neighbor-dups! vector-delete-neighbor-dups!
++
++heap-sort quick-sort insert-sort list-merge-sort vector-merge-sort
++heap-sort! quick-sort! insert-sort! list-merge-sort! vector-merge-sort!
++
++-------------------------------------------------------------------------------
++* Introduction
++--------------
++As I'll detail bewlow, I wasn't very happy with the state of the Scheme
++world for sorting and merging lists and vectors. So I have designed and
++written a fairly comprehensive sorting & merging toolkit. It is
++
++ - very portable,
++
++ - much better code than what is currently in Elk, Gambit, Bigloo,
++ Scheme->C, MzScheme, RScheme, Scheme48, MIT Scheme, or slib, and
++
++ - priced to move: free code.
++
++The package includes
++ - Vector insert sort (stable)
++ - Vector heap sort
++ - Vector quick sort (with median-of-3 pivot picking)
++ - Vector merge sort (stable)
++ - Pure and destructive list merge sort (stable)
++ - Stable vector and list merge
++ - Miscellaneous sort-related procedures: Vector and list merging,
++ sorted? predicates, vector binary search, vector and list
++ delete-equal-neighbor procedures.
++ - A general, non-algorithmic set of procedure names for general sorting
++ and merging.
++
++Scheme programmers may want to adopt this package. I'd like Scheme
++implementors to adopt this code and its API -- in fact, the code is a bribe to
++make it easy for implementors to converge on the suggested API. I mean, you'd
++really have to be a boor to take this free code I wrote and mutate its
++interface over to your incompatible, unportable API, wouldn't you? But you
++could, of course -- it's freely available. More in the spirit of the offering,
++you could make this API available, and then also write a little module
++providing your old interface that is defined in terms of this API. "Scheme
++implementors," in this context, includes slib, which isn't really a standalone
++implementation of Scheme, but is an influential collection of API's and code.
++
++The code is tightly bummed. It is clearly written, and commented in my usual
++voluminous style. This includes notes on porting and implementation-specific
++optimisations.
++
++
++-------------------------------------------------------------------------------
++* What's wrong with the current state of affairs?
++-------------------------------------------------
++
++It's just amazing to me that in 2002, sorting and merging hasn't been
++completely put to bed. These are well-understood algorithms, each of them well
++under a page of code. The straightforward algorithms are basic, core stuff --
++sophomore-level. But if you tour the major Scheme implementations out there on
++the Net, you find badly written code that provides extremely spotty coverage
++of the algorithm space. One implementation even has a buggy implementation
++that has been in use for about 20 years!
++
++Open source-code is a wonderful thing. In a couple of hours, I was able to
++download and check the sources of 9 Scheme systems. Here are my notes from the
++systems I checked. You can skip to the next section if you aren't morbidly
++curious.
++
++slib
++ sorted? vector-or-list <
++ merge list1 list2 <
++ merge! list1 list2 <
++ sort vector-or-list <
++ sort! vector-or-list <
++
++ Richard O'Keefe's stable list merge sort is right idea, but implemented
++ using gratuitous variable side effects. It also does redundant SET-CDR!s.
++ The vector sort converts to list, merge sorts, then reconverts
++ to vector. This is a bad idea -- non-local pointer chasing bad; vector
++ shuffling good.
++
++MIT Scheme
++ sort! vector <
++ merge-sort! vector <
++ quick-sort! vector <
++
++ sort vector-or-list <
++ merge-sort vector-or-list <
++ quick-sort vector-or-list <
++
++ Naive vector quicksort: loser, for worst-case performance reasons.
++ List sort by "list->vector; quicksort; vector->list," hence also loser.
++ A clever stable vector merge sort, albeit not very bummed.
++
++Scheme 48 & T
++ sort-list list <
++ sort-list! list <
++ list-merge! list1 list2 <
++
++ Bob Nix's implementation of online merge-sort, written in the early 80's.
++ Conses unnecessary bookkeeping structure, which isn't necessary with a
++ proper recursive formulation. Also, does redundant SET-CDR!s. No vector
++ sort. Also, has a bug -- is claimed to be a stable sort, but isn't! To see
++ this, get the S48 code, and try
++ (define (my< x y) (< (quotient x 2) (quotient y 2)))
++ (list-merge! (list 0 2) (list 3) my<) ; -> (0 2 3)
++ (list-merge! (list 2) (list 0 3) my<) ; -> (0 3 2)
++ This could be fixed very easily, but it isn't worth it given the
++ other problems with the algorithm.
++
++RScheme
++ vector-sort! vector <
++ sort collection <
++
++ Good basic implementation of vector heapsort, which has O(n lg n)
++ worst-case time. Code ugly, needs tuning. List sort by "list->vector;
++ sort; vector->list", which allocates unneeded temp storage. Nothing
++ for stable sorting.
++
++MzScheme
++ Naive quicksort -- but not available for vector sorting, even
++ though it internally uses a vector. Nothing for stable sorting,
++ and naive quicksort has bad worst-case behaviour.
++
++Bigloo, Scheme->C
++ Couldn't find anything -- but maybe I didn't search for the right
++ thing, since the Bigloo names are French. (I invite correction from
++ the Bigloo implementors.)
++
++Gambit
++ sort-list list <
++ Nothing for vectors. Simple, slow, unstable merge sort for lists.
++
++Elk
++ Another naive quicksort. Lists handled by converting to vector.
++ sort vector-or-list <
++ sort! vector-or-list <
++
++Chez Scheme
++ merge < list1 list2
++ merge! < list1 list2
++ sort < list
++ sort! < list
++
++ These are stable. I have not seen the source code.
++
++Common Lisp
++ sort sequence < [key]
++ stable-sort sequence < [key]
++ merge result-type sequence1 sequence2 < [key]
++
++ The sort procedures are allowed, but not required, to be destructive.
++
++SML/NJ
++ sort: ('a*'a -> bool) -> 'a list -> 'a list
++ "Smooth applicative merge sort," which is stable.
++ There is also a highly bummed quicksort for vectors.
++
++The right solution: Implement a full toolbox of carefully written standard sort
++routines.
++
++Having the source available for all of these above-cited Schemes made
++life a lot easier writing this code. I appreciate the authors making their
++source available under such open terms.
++
++
++-------------------------------------------------------------------------------
++* Design rules
++--------------
++
++** What vs. how
++===============
++There are two different interfaces: "what" (simple) & "how" (detailed).
++
++ - Simple: you specify semantics: datatype (list or vector),
++ mutability, and stability.
++
++ - Detailed: you specify the actual algorithm (quick, heap,
++ insert, merge). Different algorithms have different properties,
++ both semantic & pragmatic, so these exports are necessary.
++
++ It is necessarily the case that the specifications of these procedures
++ make statements about execution "pragmatics." For example, the sole
++ distinction between heap sort and quick sort -- both of which are
++ provided by this library -- is one of execution time, which is not a
++ "semantic" distinction. Similar resource-use statements are made about
++ "iterative" procedures, meaning that they can execute on input of
++ arbitrary size without needing to allocate an unbounded number of stack
++ frames.
++
++** Consistency across function signatures
++=========================================
++The two interfaces share common function signatures wherever
++possible, to facilitate switching a given call from one procedure
++to another.
++
++** Data parameter first, less-than parameter after
++==================================================
++These procedures uniformly observe the following parameter order:
++the data to be sorted come before the the comparison function.
++That is, we write
++ (sort lis <)
++not
++ (sort < lis).
++This is consistent with every single implementation out there, with
++the sole exception of Chez Scheme.
++
++In my opinion, it would be more consistent with other Scheme libraries
++to put the ordering function first -- the "operation currying" convention.
++(E.g., consider FOR-EACH or MAP or FIND.) I decided to leave things as they
++are in favor of near-total backwards compatibility with existing practice.
++
++[Perhaps this should be discussed.]
++
++** Ordering, comparison functions & stability
++=============================================
++These routines take a < comparison function, not a <= comparison
++function, and they sort into increasing order. The difference between
++a < spec and a <= spec comes up in two places:
++ - the definition of an ordered or sorted data set, and
++ - the definition of a stable sorting algorithm.
++
+++ We say that a data set (a list or vector) is *sorted* or *ordered*
++ if it contains no adjacent pair of values ... X Y ... such that Y < X.
++
++ In other words, scanning across the data never takes a "downwards" step.
++
++ If you use a <= procedure where these algorithms expect a <
++ procedure, you may not get the answers you expect. For example,
++ the LIST-SORTED? function will return false if you pass it a <= comparison
++ function and an ordered list containing adjacent equal elements.
++
+++ A "stable" sort is one that preserves the pre-existing order of equal
++ elements. Suppose, for example, that we sort a list of numbers by
++ comparing their absolute values, i.e., using comparison function
++ (lambda (x y) (< (abs x) (abs y)))
++ If we sort a list that contains both 3 and -3:
++ ... 3 ... -3 ...
++ then a stable sort is an algorithm that will not swap the order
++ of these two elements, that is, the answer will look like
++ ... 3 -3 ...
++ not
++ ... -3 3 ...
++
++ Choosing < for the comparison function instead of <= affects how stability
++ is coded. Given an adjacent pair X Y, (< y x) means "Y should be moved in
++ front of X" -- otherwise, leave things as they are. So using a <= function
++ where a < function is expected will *invert* stability.
++
++ This is due to the definition of equality, given a < comparator:
++ (and (not (< x y))
++ (not (< y x)))
++ The definition is rather different, given a <= comparator:
++ (and (<= x y)
++ (<= x y))
++
+++ A "stable" merge is one that reliably favors one of its data sets
++ when equal items appear in both data sets. *All merge operations in
++ this library are stable*, breaking ties between data sets in favor
++ of the first data set -- elements of the first list come before equal
++ elements in the second list.
++
++ So, if we are merging two lists of numbers ordered by absolute value
++ using the stable merge operation LIST-MERGE
++ (list-merge '(0 -2 4 8 -10) '(-1 3 -4 7)
++ (lambda (x y) (< (abs x) (abs y))))
++ reliably places the 4 of the first list before the equal-comparing -4
++ of the second list:
++ (0 -1 -2 4 -4 7 8 -10)
++
++In short, if your comparison function F answers true to (F x x), then
++using a stable sorting or merging algorithm will not give you a stable sort
++or merge, and LIST-SORTED? may surprise you. Note that you can synthesize a <
++function from a <= function with
++ (lambda (x y) (not (<= y x)))
++if need be.
++
++Precise definitions give sharp edges to tools, but require care
++in use. "Measure twice, cut once."
++
++I have adopted the choice of < from Common Lisp. I assume they
++had a good reason for adopting < instead of <=. I'd love to know
++what this reason is; send me email if you can explain it, please.
++
++** All vector operations accept optional subrange parameters
++============================================================
++The vector operations specified below all take optional START/END arguments
++indicating a selected subrange of a vector's elements. If a START parameter or
++START/END parameter pair is given to such a procedure, they must be exact,
++non-negative integers, such that
++ 0 <= START <= END <= (VECTOR-LENGTH V)
++where V is the related vector parameter. If not specified, they default to 0
++and the length of the vector, respectively. They are interpreted to select the
++range [START,END), that is, all elements from index START (inclusive) up to,
++but not including, index END.
++
++** Required vs. allowed side-effects
++====================================
++LIST-SORT! and LIST-STABLE-SORT! are allowed, but not required,
++to alter their arguments' cons cells to construct the result list. This is
++consistent with the what-not-how character of the group of procedures
++to which they belong (the "sort-lib" package).
++
++The LIST-DELETE-NEIGHBOR-DUPS!, LIST-MERGE! and LIST-MERGE-SORT! procedures,
++on the other hand, provide specific algorithms, and, as such, explicitly
++commit to the use of side-effects on their input lists in order to guarantee
++their key algorithmic properties (e.g., linear-time operation, constant-space
++stack use).
++
++-------------------------------------------------------------------------------
++* Procedure specification
++-------------------------
++The procedures are split into several packages. In a Scheme system that has a
++module or package system, these procedures should be contained in modules
++named as follows:
++ Package name Functionality
++ ------------ -------------
++ sort-lib General sorting for lists & vectors
++ sorted?-lib Sorted predicates for lists & vectors
++ list-merge-sort-lib List merge sort
++ vector-merge-sort-lib Vector merge sort
++ vector-heap-sort-lib Vector heap sort
++ vector-quick-sort-lib Vector quick sort
++ vector-insert-sort-lib Vector insertion sort
++ delndup-lib List and vector delete neighbor duplicates
++
++A Scheme system without a module system should provide all of the bindings
++defined in all of these modules as components of the "SRFI-32" package.
++
++Note that there is no list insert sort package, as you might as well always
++use list merge sort. The reference implementation's destructive list merge
++sort will do fewer SET-CDR!s than a destructive insert sort.
++
++** Procedure naming and functionality
++=====================================
++Almost all of the procedures described below are variants of two basic
++operations: sorting and merging. These procedures are consistently named
++by composing a set of basic lexemes to indicate what they do.
++
++Lexeme Meaning
++------ -------
++"sort" The procedure sorts its input data set by some < comparison function.
++
++"merge" The procedure merges two ordered data sets into a single ordered
++ result.
++
++"stable" This lexeme indicates that the sort is a stable one.
++
++"vector" The procedure operates upon vectors.
++
++"list" The procedure operates upon lists.
++
++"!" Procedures that end in "!" are allowed, and sometimes required,
++ to reuse their input storage to construct their answer.
++
++** Types of parameters and return values
++========================================
++In the procedures specified below,
++ - A LIS parameter is a list;
++
++ - A V parameter is a vector;
++
++ - A < or = parameter is a procedure accepting two arguments taken from the
++ specified procedure's data set(s), and returning a boolean;
++
++ - START and END parameters are exact, non-negative integers that
++ serve as vector indices selecting a subrange of some associated vector.
++ When specified, they must satisfy the relation
++ 0 <= start <= end <= (vector-length v)
++ where V is the associated vector.
++
++Passing values to procedures with these parameters that do not satisfy these
++types is an error.
++
++If a procedure is said to return "unspecified," this means that nothing at all
++is said about what the procedure returns, not even the number of return
++values. Such a procedure is not even required to be consistent from call to
++call in the nature or number of its return values. It is simply required to
++return a value (or values) that may be passed to a command continuation, e.g.
++as the value of an expression appearing as a non-terminal subform of a BEGIN
++expression. Note that in R5RS, this restricts such a procedure to returning a
++single value; non-R5RS systems may not even provide this restriction.
++
++** sort-lib - general sorting package
++=====================================
++This library provides basic sorting and merging functionality suitable for
++general programming. The procedures are named by their semantic properties,
++i.e., what they do to the data (sort, stable