Merge "QcomModulePkg: Enable the sdllvm analyze under a flag"
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index c9b3fca..2b7416f 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -34,6 +34,12 @@
 	VERIFIED_BOOT_2 := VERIFIED_BOOT_2=0
 endif
 
+ifeq ($(BOARD_LEVB_ENABLE),true)
+	VERIFIED_BOOT_LE := VERIFIED_BOOT_LE=1
+else
+	VERIFIED_BOOT_LE := VERIFIED_BOOT_LE=0
+endif
+
 ifeq ($(TARGET_BUILD_VARIANT),user)
 	USER_BUILD_VARIANT := USER_BUILD_VARIANT=1
 else
@@ -76,6 +82,7 @@
 		all \
 		$(VERIFIED_BOOT) \
 		$(VERIFIED_BOOT_2) \
+		$(VERIFIED_BOOT_LE) \
 		$(USER_BUILD_VARIANT) \
 		CLANG_BIN=$(CLANG_BIN) \
 		CLANG_PREFIX=$(CLANG35_PREFIX)\
diff --git a/QcomModulePkg/Include/Library/BootLinux.h b/QcomModulePkg/Include/Library/BootLinux.h
index ef6c532..55904d9 100644
--- a/QcomModulePkg/Include/Library/BootLinux.h
+++ b/QcomModulePkg/Include/Library/BootLinux.h
@@ -57,6 +57,10 @@
 #include <Protocol/LoadedImage.h>
 #include <Protocol/SerialIo.h>
 #include <Protocol/SimpleFileSystem.h>
+#include <Protocol/EFISecRSA.h>
+#include <Protocol/Hash.h>
+#include <Protocol/Hash2.h>
+#include <Protocol/EFIASN1X509.h>
 
 #include "Board.h"
 #include "BootImage.h"
diff --git a/QcomModulePkg/Include/Library/LEOEMCertificate.h b/QcomModulePkg/Include/Library/LEOEMCertificate.h
new file mode 100644
index 0000000..23d77b9
--- /dev/null
+++ b/QcomModulePkg/Include/Library/LEOEMCertificate.h
@@ -0,0 +1,130 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __LE_OEM_CERTIFICATE_H
+#define __LE_OEM_CERTIFICATE_H
+
+/*
+    Instructions to generate private.key and X509 certificate
+
+A) Generate a sha256 self-signed X509 certificate and a 2048 bits
+   RSA private key
+$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout
+                                                   qtipri.key -out qti.crt.pem
+
+B) convert private key from PKCS#8 to PKCS#1 format, save it as qti.key.
+$ openssl rsa -in qtipri.key -out qti.key
+
+C) This private key "qti.key" need to be saved under folder
+   "poky/recipes-kernel/linux-quic/kernel/" and
+   "poky/recipes-kernel/linux-msm-4.9/kernel/", used to generate bootimage
+   signature.
+
+D) convert certificate from PEM to DER format
+$ openssl x509 -outform der -in qti.crt.pem -out qti.crt.der
+
+E) open qti.crt.der file in a HEX editor, and then put HEX numbers into array
+    LeOemCertificate[] in LEOEMCertificate.h
+
+*/
+
+static CONST UINT8 LeOemCertificate[] = {
+    0x30, 0x82, 0x03, 0x4F, 0x30, 0x82, 0x02, 0x37, 0xA0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x09, 0x00, 0xED, 0x2C, 0x2E, 0x88, 0xA4, 0xC8, 0xF4, 0x60,
+    0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
+    0x0B, 0x05, 0x00, 0x30, 0x3E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
+    0x55, 0x04, 0x08, 0x0C, 0x02, 0x43, 0x41, 0x31, 0x0C, 0x30, 0x0A, 0x06,
+    0x03, 0x55, 0x04, 0x0A, 0x0C, 0x03, 0x51, 0x54, 0x49, 0x31, 0x14, 0x30,
+    0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0B, 0x4C, 0x45, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x4B, 0x65, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x31,
+    0x37, 0x30, 0x36, 0x31, 0x34, 0x32, 0x32, 0x32, 0x34, 0x34, 0x33, 0x5A,
+    0x17, 0x0D, 0x31, 0x38, 0x30, 0x36, 0x31, 0x34, 0x32, 0x32, 0x32, 0x34,
+    0x34, 0x33, 0x5A, 0x30, 0x3E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
+    0x55, 0x04, 0x08, 0x0C, 0x02, 0x43, 0x41, 0x31, 0x0C, 0x30, 0x0A, 0x06,
+    0x03, 0x55, 0x04, 0x0A, 0x0C, 0x03, 0x51, 0x54, 0x49, 0x31, 0x14, 0x30,
+    0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0B, 0x4C, 0x45, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x4B, 0x65, 0x79, 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, 0xCD, 0x4E, 0xC2, 0x72, 0xAE, 0x2F, 0xF8, 0xE2,
+    0xF2, 0xEB, 0x96, 0xC8, 0xDE, 0xDB, 0xBC, 0x5F, 0x03, 0xF1, 0x8B, 0x36,
+    0xBB, 0x5E, 0xAC, 0x4B, 0x75, 0x44, 0xF2, 0x8C, 0xB2, 0x46, 0xF3, 0x73,
+    0xF2, 0xDC, 0xCE, 0x5D, 0x7E, 0xE6, 0x9C, 0x18, 0xF5, 0x04, 0x4D, 0xA3,
+    0x1E, 0x25, 0xDB, 0xD9, 0x81, 0x09, 0x1A, 0xE6, 0xA2, 0x8E, 0xF1, 0xFA,
+    0x72, 0x5C, 0xAA, 0xC4, 0x2C, 0xC3, 0x58, 0x70, 0xC1, 0xE1, 0x94, 0xCC,
+    0x5D, 0x32, 0x92, 0xD0, 0xBA, 0x18, 0x82, 0xF0, 0x2B, 0xA1, 0xA4, 0x94,
+    0x64, 0x03, 0x59, 0xD2, 0x3D, 0x39, 0x0B, 0xE7, 0x1A, 0x7D, 0xF2, 0xC1,
+    0x78, 0x6B, 0x5F, 0x51, 0x74, 0x4B, 0x63, 0x30, 0xCB, 0xF6, 0x04, 0xCB,
+    0xE8, 0x18, 0x3F, 0x5C, 0x31, 0xCC, 0x10, 0x5C, 0xAF, 0xFB, 0xC3, 0x50,
+    0x47, 0x9F, 0x4A, 0xCA, 0x64, 0xA9, 0xB3, 0x80, 0xA7, 0x35, 0x33, 0xC7,
+    0x1C, 0x0D, 0x0B, 0xAA, 0x48, 0x2F, 0x59, 0x66, 0xC8, 0x76, 0xB4, 0x9C,
+    0x01, 0xFB, 0xA2, 0xF3, 0x2B, 0xC4, 0x0F, 0xE8, 0x82, 0x3D, 0x31, 0xBE,
+    0x6C, 0xA2, 0x5B, 0xC3, 0x5F, 0xB0, 0x6F, 0x90, 0xB1, 0xD3, 0xB3, 0x54,
+    0xED, 0x7A, 0x4B, 0x42, 0x03, 0xB5, 0x85, 0x93, 0x9E, 0x6C, 0x64, 0x9D,
+    0xB2, 0x83, 0x4B, 0x0C, 0xCD, 0xD3, 0x27, 0x6F, 0x37, 0xA7, 0x99, 0x44,
+    0xFA, 0x63, 0x2B, 0x2E, 0xAE, 0x48, 0x0A, 0xEF, 0x6C, 0x26, 0x03, 0x2D,
+    0x35, 0xA3, 0xFC, 0x00, 0xCF, 0xE3, 0x45, 0xF1, 0x80, 0x4A, 0xAD, 0x52,
+    0xE0, 0xD9, 0x84, 0x5E, 0xD5, 0x1D, 0xEE, 0xDD, 0xCA, 0x99, 0x7A, 0x8F,
+    0xE5, 0x54, 0x5A, 0x2D, 0xF5, 0xC2, 0x90, 0xD2, 0xED, 0xB1, 0xBC, 0xD8,
+    0x56, 0x22, 0xFE, 0x25, 0x30, 0x77, 0xB2, 0x77, 0xDD, 0xDA, 0xF3, 0x83,
+    0x7C, 0xC2, 0xD9, 0x21, 0x9D, 0x52, 0x32, 0x1B, 0x02, 0x03, 0x01, 0x00,
+    0x01, 0xA3, 0x50, 0x30, 0x4E, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
+    0x04, 0x16, 0x04, 0x14, 0x16, 0x26, 0x6C, 0x02, 0xEC, 0x9E, 0x88, 0x19,
+    0xF4, 0x7A, 0x19, 0xA8, 0x90, 0x08, 0x72, 0xB4, 0x4B, 0x18, 0x21, 0x3D,
+    0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+    0x14, 0x16, 0x26, 0x6C, 0x02, 0xEC, 0x9E, 0x88, 0x19, 0xF4, 0x7A, 0x19,
+    0xA8, 0x90, 0x08, 0x72, 0xB4, 0x4B, 0x18, 0x21, 0x3D, 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, 0x79, 0x03, 0x42, 0x8F, 0x25,
+    0x8C, 0xC7, 0x75, 0xF8, 0x91, 0x20, 0x76, 0x5C, 0x45, 0xD1, 0x88, 0x22,
+    0x6B, 0xDC, 0xFC, 0xAB, 0x65, 0x7D, 0x39, 0x46, 0xAD, 0xC4, 0x18, 0x1D,
+    0xFB, 0x6A, 0x67, 0x50, 0xC6, 0xE4, 0xBC, 0x73, 0xD2, 0xE6, 0xB6, 0x3A,
+    0xC9, 0xB8, 0x41, 0x24, 0x13, 0x3E, 0xF3, 0xBC, 0x0C, 0xC7, 0xE2, 0x2D,
+    0xB4, 0x3C, 0x33, 0xA6, 0x66, 0x0D, 0xD6, 0x3D, 0x8E, 0x3C, 0x2D, 0xFA,
+    0x78, 0xF1, 0x30, 0xB5, 0x11, 0xF9, 0x73, 0x52, 0x56, 0x03, 0x84, 0x75,
+    0x27, 0x16, 0xF3, 0x8E, 0x17, 0xFD, 0xAA, 0xC1, 0x89, 0x4D, 0x6F, 0xA7,
+    0x28, 0xE4, 0x56, 0xC1, 0x2B, 0x8F, 0xC7, 0x4D, 0xF2, 0xC8, 0x65, 0xA7,
+    0xD1, 0x77, 0x11, 0x16, 0x03, 0x62, 0xB4, 0x22, 0xA8, 0x0F, 0x1A, 0x4B,
+    0x1B, 0x22, 0x29, 0x9B, 0x56, 0xEF, 0xAC, 0x64, 0xDB, 0x2A, 0x70, 0x0A,
+    0x7B, 0x1D, 0x31, 0x4E, 0xC6, 0xAF, 0x32, 0x63, 0xEE, 0xD8, 0x20, 0x0F,
+    0x8B, 0x7E, 0xC4, 0x6F, 0x04, 0x71, 0x10, 0x01, 0x3D, 0x17, 0x50, 0xF9,
+    0x70, 0xB2, 0x2B, 0x01, 0x8F, 0xE2, 0xA5, 0x5C, 0xEB, 0xD8, 0x74, 0xBC,
+    0x22, 0x8C, 0xF4, 0xEF, 0x10, 0xD4, 0xD5, 0x49, 0xCD, 0xB3, 0x7C, 0x8F,
+    0xEF, 0x23, 0x88, 0xCE, 0xBC, 0xBA, 0xA8, 0x3B, 0x9C, 0x48, 0xE0, 0x50,
+    0x9A, 0x70, 0x7D, 0xAE, 0xAF, 0x8C, 0xDA, 0x53, 0xBD, 0x40, 0x49, 0x17,
+    0x3F, 0xD5, 0x19, 0x77, 0x9C, 0xD5, 0x52, 0xEF, 0xB7, 0xD6, 0x00, 0x0A,
+    0xED, 0x9D, 0x4C, 0x81, 0x25, 0x3B, 0x6A, 0x66, 0xDC, 0xA6, 0xBB, 0x80,
+    0x60, 0x1E, 0xA6, 0x7E, 0x55, 0xF2, 0xC9, 0x07, 0xAA, 0x04, 0x89, 0x99,
+    0x76, 0xCC, 0x37, 0xB8, 0xAD, 0x78, 0x03, 0x81, 0x8A, 0x7B, 0x7B, 0x44,
+    0x59, 0x20, 0x84, 0x78, 0xD8, 0x77, 0x6D, 0xF9, 0x80, 0x94, 0xCF
+};
+
+#endif
diff --git a/QcomModulePkg/Include/Library/VerifiedBoot.h b/QcomModulePkg/Include/Library/VerifiedBoot.h
index 350bbc3..9972dc8 100644
--- a/QcomModulePkg/Include/Library/VerifiedBoot.h
+++ b/QcomModulePkg/Include/Library/VerifiedBoot.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,7 +31,24 @@
 
 #include <Uefi.h>
 
-enum { NO_AVB = 0, AVB_1, AVB_2 };
+enum
+{
+  NO_AVB = 0,
+  AVB_1,
+  AVB_2,
+  AVB_LE
+};
+
+#define VB_SHA256_SIZE  32
+#define LE_BOOTIMG_SIG_SIZE 256
+
+typedef enum {
+  VB_UNDEFINED_HASH = 0,
+  VB_SHA1,
+  VB_SHA256,
+  VB_UNSUPPORTED_HASH,
+  VB_RESERVED_HASH = 0x7fffffff /* force to 32 bits */
+} VB_HASH;
 
 #define GUARD(code)                                                            \
   do {                                                                         \
diff --git a/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c b/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
index 5f5d67b..866c5e1 100644
--- a/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
+++ b/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
@@ -304,6 +304,10 @@
           (EFI_D_INFO, "ExecImgFromVolume(): multiple partitions found.\r\n"));
       return EFI_LOAD_ERROR;
     }
+  } else {
+    DEBUG ((EFI_D_ERROR,
+            "%s: GetBlkIOHandles failed: %r\n", __func__, Status));
+    return Status;
   }
 
   BlkIo = HandleInfoList[0].BlkIo;
@@ -521,6 +525,10 @@
       DEBUG ((EFI_D_INFO, "%s: multiple partitions found.\r\n", __func__));
       return EFI_LOAD_ERROR;
     }
+  } else {
+    DEBUG ((EFI_D_ERROR,
+            "%s: GetBlkIOHandles failed: %r\n", __func__, Status));
+    return Status;
   }
 
   BlkIo = HandleInfoList[0].BlkIo;
diff --git a/QcomModulePkg/Library/BootLib/Recovery.c b/QcomModulePkg/Library/BootLib/Recovery.c
index 7beb5c5..d7569cd 100644
--- a/QcomModulePkg/Library/BootLib/Recovery.c
+++ b/QcomModulePkg/Library/BootLib/Recovery.c
@@ -65,6 +65,10 @@
       DEBUG ((EFI_D_INFO, "%s: multiple partitions found.\r\n", __func__));
       return EFI_LOAD_ERROR;
     }
+  } else {
+    DEBUG ((EFI_D_ERROR,
+           "%s: GetBlkIOHandles failed: %r\n", __func__, Status));
+    return Status;
   }
 
   BlkIo = HandleInfoList[0].BlkIo;
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
index b9d6dbd..d955706 100644
--- a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
+++ b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
@@ -1542,7 +1542,9 @@
   }
   AsciiStrToUnicodeStr (arg, PartitionName);
 
-  if (TargetBuildVariantUser ()) {
+  if ((GetAVBVersion () == AVB_LE) ||
+      ((GetAVBVersion () != AVB_LE) &&
+      (TargetBuildVariantUser ()))) {
     if (!IsUnlocked ()) {
       FastbootFail ("Flashing is not allowed in Lock State");
       return;
@@ -1729,7 +1731,10 @@
   }
   AsciiStrToUnicodeStr (arg, PartitionName);
 
-  if (TargetBuildVariantUser ()) {
+
+  if ((GetAVBVersion () == AVB_LE) ||
+      ((GetAVBVersion () != AVB_LE) &&
+      (TargetBuildVariantUser ()))) {
     if (!IsUnlocked ()) {
       FastbootFail ("Erase is not allowed in Lock State");
       return;
@@ -2353,12 +2358,25 @@
     return;
   }
 
-  Status = DisplayUnlockMenu (Type, State);
-  if (Status != EFI_SUCCESS) {
-    FastbootFail ("Command not support: the display is not enabled");
-    return;
+
+  if (GetAVBVersion () != AVB_LE) {
+    Status = DisplayUnlockMenu (Type, State);
+    if (Status != EFI_SUCCESS) {
+      FastbootFail ("Command not support: the display is not enabled");
+      return;
+    } else {
+      FastbootOkay ("");
+    }
   } else {
+    Status = SetDeviceUnlockValue (Type, State);
+    if (Status != EFI_SUCCESS) {
+         AsciiSPrint (response, MAX_RSP_SIZE, "\tSet device %a failed: %r",
+                  (State ? "unlocked!" : "locked!"), Status);
+         FastbootFail (response);
+         return;
+    }
     FastbootOkay ("");
+    RebootDevice (RECOVERY_MODE);
   }
 }
 #endif
diff --git a/QcomModulePkg/Library/avb/AvbLib.inf b/QcomModulePkg/Library/avb/AvbLib.inf
index 9d6777a..bfb3a75 100644
--- a/QcomModulePkg/Library/avb/AvbLib.inf
+++ b/QcomModulePkg/Library/avb/AvbLib.inf
@@ -95,6 +95,8 @@
 	gEfiPartitionRecordGuid
 	gEfiHash2ProtocolGuid
 	gEfiHashAlgorithmSha256Guid
+	gEfiQcomASN1X509ProtocolGuid
+	gEfiQcomSecRSAProtocolGuid
 
 [FixedPcd]
 	gQcomTokenSpaceGuid.EnableMdtpSupport
diff --git a/QcomModulePkg/Library/avb/VerifiedBoot.c b/QcomModulePkg/Library/avb/VerifiedBoot.c
index 300b922..51aa5bb 100644
--- a/QcomModulePkg/Library/avb/VerifiedBoot.c
+++ b/QcomModulePkg/Library/avb/VerifiedBoot.c
@@ -32,6 +32,7 @@
 #include "libavb/libavb.h"
 #include <Library/MenuKeysDetection.h>
 #include <Library/VerifiedBootMenu.h>
+#include <Library/LEOEMCertificate.h>
 
 STATIC CONST CHAR8 *VerityMode = " androidboot.veritymode=";
 STATIC CONST CHAR8 *VerifiedState = " androidboot.verifiedbootstate=";
@@ -70,12 +71,14 @@
 UINT32
 GetAVBVersion ()
 {
-#if VERIFIED_BOOT_2
-  return 2;
+#if VERIFIED_BOOT_LE
+  return AVB_LE;
+#elif VERIFIED_BOOT_2
+  return AVB_2;
 #elif VERIFIED_BOOT
-  return 1;
+  return AVB_1;
 #else
-  return 0;
+  return NO_AVB;
 #endif
 }
 
@@ -358,6 +361,277 @@
 }
 
 STATIC EFI_STATUS
+LEGetImageHash (QcomAsn1x509Protocol *pEfiQcomASN1X509Protocol,
+        VB_HASH HashAlgorithm,
+        UINT8 *Img, UINTN ImgSize,
+        UINT8 *ImgHash, UINTN HashSize)
+{
+    EFI_STATUS Status = EFI_FAILURE;
+    EFI_GUID *HashAlgorithmGuid;
+    UINTN DigestSize = 0;
+    EFI_HASH2_OUTPUT Hash2Output;
+    EFI_HASH2_PROTOCOL *pEfiHash2Protocol = NULL;
+
+    if (pEfiQcomASN1X509Protocol == NULL ||
+        Img == NULL ||
+        ImgHash == NULL) {
+        DEBUG ((EFI_D_ERROR,
+                "LEGetRSAPublicKeyInfoFromCertificate: Invalid pointer\n"));
+        return EFI_INVALID_PARAMETER;
+    }
+
+    switch (HashAlgorithm) {
+    case VB_SHA256:
+        HashAlgorithmGuid = &gEfiHashAlgorithmSha256Guid;
+        break;
+    default:
+        DEBUG ((EFI_D_ERROR,
+            "VB: LEGetImageHash: not supported algorithm:%d\n", HashAlgorithm));
+        Status = EFI_UNSUPPORTED;
+        goto exit;
+    }
+
+    Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid,
+                 NULL, (VOID **)&pEfiHash2Protocol);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+        "VB:LEGetImageHash: LocateProtocol unsuccessful!Status: %r\n", Status));
+        goto exit;
+    }
+
+    Status = pEfiHash2Protocol->GetHashSize (pEfiHash2Protocol,
+                HashAlgorithmGuid, &DigestSize);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+         "VB: LEGetImageHash: GetHashSize unsuccessful! Status: %r\n", Status));
+        goto exit;
+    }
+    if (HashSize != DigestSize) {
+        DEBUG ((EFI_D_ERROR,
+            "VB: LEGetImageHash: Invalid size! HashSize: %d, DigestSize: %d\n"
+            , HashSize, DigestSize));
+        Status = EFI_FAILURE;
+        goto exit;
+    }
+    Status = pEfiHash2Protocol->HashInit (pEfiHash2Protocol, HashAlgorithmGuid);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+            "VB: LEGetImageHash: HashInit unsuccessful! Status: %r\n", Status));
+        goto exit;
+    }
+    Status = pEfiHash2Protocol->HashUpdate (pEfiHash2Protocol, Img, ImgSize);
+    if (EFI_SUCCESS != Status) {
+
+        DEBUG ((EFI_D_ERROR,
+            "VB: LEGetImageHash: HashUpdate unsuccessful(Img)!Status: %r\n"
+            , Status));
+        goto exit;
+    }
+    Status = pEfiHash2Protocol->HashFinal (pEfiHash2Protocol, &Hash2Output);
+    if (EFI_SUCCESS != Status) {
+
+        DEBUG ((EFI_D_ERROR,
+        "VB: LEGetImageHash: HashFinal unsuccessful! Status: %r\n", Status));
+        goto exit;
+    }
+    gBS->CopyMem ((VOID *)ImgHash, (VOID *)&Hash2Output, DigestSize);
+    Status = EFI_SUCCESS;
+
+exit:
+    return Status;
+}
+
+STATIC EFI_STATUS LEGetRSAPublicKeyInfoFromCertificate (
+                QcomAsn1x509Protocol *pEfiQcomASN1X509Protocol,
+                CERTIFICATE *Certificate,
+                secasn1_data_type *Modulus,
+                secasn1_data_type *PublicExp,
+                UINT32 *PaddingType)
+{
+    EFI_STATUS Status = EFI_FAILURE;
+    RSA RsaKey = {NULL};
+
+    if (pEfiQcomASN1X509Protocol == NULL ||
+        Certificate == NULL ||
+        Modulus == NULL ||
+        PublicExp == NULL ||
+        PaddingType == NULL) {
+        DEBUG ((EFI_D_ERROR,
+                "LEGetRSAPublicKeyInfoFromCertificate: Invalid pointer\n"));
+        return EFI_INVALID_PARAMETER;
+    }
+
+    Status = pEfiQcomASN1X509Protocol->ASN1X509GetRSAFromCert
+                    (pEfiQcomASN1X509Protocol, Certificate, &RsaKey);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+            "VB: ASN1X509GetRSAFromCert unsuccessful! Status : %r\n", Status));
+        goto exit;
+    }
+    Status = pEfiQcomASN1X509Protocol->ASN1X509GetKeymaterial
+            (pEfiQcomASN1X509Protocol, &RsaKey, Modulus, PublicExp);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+            "VB: ASN1X509GetKeymaterial unsuccessful! Status: %r\n", Status));
+        goto exit;
+    }
+    *PaddingType = CE_RSA_PAD_PKCS1_V1_5_SIG;
+exit:
+    return Status;
+}
+STATIC EFI_STATUS LEVerifyHashWithRSASignature (
+                UINT8 *ImgHash,
+                VB_HASH HashAlgorithm,
+                secasn1_data_type *Modulus,
+                secasn1_data_type *PublicExp,
+                UINT32 PaddingType,
+                CONST UINT8 *SignaturePtr,
+                UINT32 SignatureLen)
+{
+    EFI_STATUS Status = EFI_FAILURE;
+    CE_RSA_KEY Key = {0};
+    BigInt ModulusBi;
+    BigInt PublicExpBi;
+    INT32 HashIdx;
+    INT32 HashLen;
+    VOID *PaddingInfo = NULL;
+    QcomSecRsaProtocol *pEfiQcomSecRSAProtocol = NULL;
+    SetMem (&Key, sizeof (CE_RSA_KEY), 0);
+
+    if (ImgHash == NULL ||
+        Modulus == NULL ||
+        PublicExp == NULL ||
+        SignaturePtr == NULL) {
+        DEBUG ((EFI_D_ERROR, "LEVerifyHashWithRSASignature:Invalid pointer\n"));
+        return EFI_INVALID_PARAMETER;
+    }
+
+    switch (HashAlgorithm) {
+    case VB_SHA256:
+        HashIdx = CE_HASH_IDX_SHA256;
+        HashLen = VB_SHA256_SIZE;
+        break;
+    default:
+        DEBUG ((EFI_D_ERROR,
+                "VB: LEVerifySignature: Hash algorithm not supported\n"));
+        Status = EFI_UNSUPPORTED;
+        goto exit;
+    }
+
+    Key.N = AllocatePool (sizeof (S_BIGINT));
+    if (Key.N == NULL) {
+        DEBUG ((EFI_D_ERROR,
+                "VB: LEVerifySignature: mem allocation err for Key.N\n"));
+        goto exit;
+    }
+    Key.e = AllocatePool (sizeof (S_BIGINT));
+    if (Key.e == NULL) {
+        DEBUG ((EFI_D_ERROR,
+                "VB: LEVerifySignature: mem allocation err for Key.e\n"));
+        goto exit;
+    }
+    Status = gBS->LocateProtocol (&gEfiQcomSecRSAProtocolGuid,
+                NULL, (VOID **) &pEfiQcomSecRSAProtocol);
+    if ( Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+        "VB: LEVerifySignature: LocateProtocol failed, Status: %r\n", Status));
+        goto exit;
+    }
+
+    Status = pEfiQcomSecRSAProtocol->SecRSABigIntReadBin (
+            pEfiQcomSecRSAProtocol, Modulus->data, Modulus->Len, &ModulusBi);
+    if ( Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+                "VB: LEVerifySignature: SecRSABigIntReadBin for Modulus failed!"
+                "Status: %r\n", Status));
+        goto exit;
+    }
+    Status = pEfiQcomSecRSAProtocol->SecRSABigIntReadBin (
+        pEfiQcomSecRSAProtocol, PublicExp->data, PublicExp->Len,  &PublicExpBi);
+    if ( Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: LEVerifySignature: SecRSABigIntReadBin for"
+                        " Modulus failed! Status: %r\n", Status));
+        goto exit;
+    }
+
+    Key.N->Bi = ModulusBi;
+    Key.e->Bi = PublicExpBi;
+    Key.e->Sign = S_BIGINT_POS;
+    Key.Type = CE_RSA_KEY_PUBLIC;
+
+    Status = pEfiQcomSecRSAProtocol->SecRSAVerifySig (pEfiQcomSecRSAProtocol,
+                &Key, PaddingType,
+                    PaddingInfo, HashIdx,
+                    ImgHash, HashLen, (UINT8*)SignaturePtr, SignatureLen);
+
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR,
+        "VB: LEVerifySignature: SecRSAVerifySig failed! Status: %r\n", Status));
+        goto exit;
+    }
+
+    DEBUG ((EFI_D_VERBOSE, "VB: LEVerifySignature: SecRSAVerifySig success!"
+                      " Status: %r\n", Status));
+
+    Status = EFI_SUCCESS;
+exit:
+    if (Key.N != NULL) {
+        FreePool (Key.N);
+    }
+    if (Key.e != NULL) {
+        FreePool (Key.e);
+    }
+    return Status;
+}
+
+STATIC EFI_STATUS LEVerifyHashWithSignature (
+                    QcomAsn1x509Protocol *pEfiQcomASN1X509Protocol,
+                    UINT8 *ImgHash, VB_HASH HashAlgorithm,
+                    CERTIFICATE *Certificate,
+                    CONST UINT8 *SignaturePtr,
+                    UINT32 SignatureLen)
+{
+    EFI_STATUS Status = EFI_FAILURE;
+    secasn1_data_type Modulus = {NULL};
+    secasn1_data_type PublicExp = {NULL};
+    UINT32 PaddingType = 0;
+
+    if (pEfiQcomASN1X509Protocol == NULL ||
+        ImgHash == NULL ||
+        Certificate == NULL ||
+        SignaturePtr == NULL) {
+        DEBUG ((EFI_D_ERROR, "LEVerifyHashWithSignature: Invalid pointer\n"));
+        return EFI_INVALID_PARAMETER;
+    }
+
+    /* TODO: get subject publick key info from certificate, implement new
+                                                    algorithm in XBL*/
+    /* XBL implemented by default sha256 and rsaEncryption with
+                                                    PKCS1_V1_5 padding*/
+
+    Status = LEGetRSAPublicKeyInfoFromCertificate (pEfiQcomASN1X509Protocol,
+                Certificate, &Modulus, &PublicExp, &PaddingType);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: LEGetRSAPublicKeyInfoFromCertificate "
+                      "unsuccessful! Status: %r\n", Status));
+        goto exit;
+    }
+
+    Status = LEVerifyHashWithRSASignature (ImgHash, HashAlgorithm,
+                &Modulus, &PublicExp, PaddingType,
+                SignaturePtr, SignatureLen);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: LEVerifyHashWithSignature unsuccessful! "
+                      "Status: %r\n", Status));
+        goto exit;
+    }
+    Status = EFI_SUCCESS;
+exit:
+    return Status;
+}
+
+
+STATIC EFI_STATUS
 LoadImageAndAuthVB2 (BootInfo *Info)
 {
   EFI_STATUS Status = EFI_SUCCESS;
@@ -560,7 +834,7 @@
 
   /* Set Rot & Boot State*/
   Data.Color = Info->BootState;
-  Data.IsUnlocked = AllowVerificationError;
+  Data. IsUnlocked = AllowVerificationError;
   Data.PublicKeyLength = UserData->PublicKeyLen;
   Data.PublicKey = UserData->PublicKey;
 
@@ -665,6 +939,85 @@
   return EFI_SUCCESS;
 }
 
+STATIC EFI_STATUS LoadImageAndAuthForLE (BootInfo *Info)
+{
+    EFI_STATUS Status = EFI_SUCCESS;
+    QcomAsn1x509Protocol *QcomAsn1X509Protocal = NULL;
+    CONST UINT8 *OemCertFile = LeOemCertificate;
+    UINTN OemCertFileLen = sizeof (LeOemCertificate);
+    CERTIFICATE OemCert = {NULL};
+    UINTN HashSize;
+    UINT8 *ImgHash = NULL;
+    UINTN ImgSize;
+    VB_HASH HashAlgorithm;
+    UINT8 *SigAddr = NULL;
+    UINT32 SigSize = 0;
+
+    /*Load image*/
+    GUARD (VBCommonInit (Info));
+    GUARD (LoadImageNoAuth (Info));
+
+    /* Initialize Verified Boot*/
+    device_info_vb_t DevInfo_vb;
+    DevInfo_vb.is_unlocked = IsUnlocked ();
+    DevInfo_vb.is_unlock_critical = IsUnlockCritical ();
+    Status = Info->VbIntf->VBDeviceInit (Info->VbIntf,
+                                        (device_info_vb_t *)&DevInfo_vb);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: Error during VBDeviceInit: %r\n", Status));
+        return Status;
+    }
+
+    /* Locate QcomAsn1x509Protocol*/
+    Status = gBS->LocateProtocol (&gEfiQcomASN1X509ProtocolGuid, NULL,
+                                 (VOID **)&QcomAsn1X509Protocal);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: Error LocateProtocol "
+                      "gEfiQcomASN1X509ProtocolGuid: %r\n", Status));
+        return Status;
+    }
+
+    /* Read OEM certificate from the embedded header file */
+    Status = QcomAsn1X509Protocal->ASN1X509VerifyOEMCertificate
+                (QcomAsn1X509Protocal, OemCertFile, OemCertFileLen, &OemCert);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: Error during "
+                      "ASN1X509VerifyOEMCertificate: %r\n", Status));
+        return Status;
+    }
+
+    /*Calculate kernel image hash, SHA256 is used by default*/
+    HashAlgorithm = VB_SHA256;
+    HashSize = VB_SHA256_SIZE;
+    ImgSize = Info->Images[0].ImageSize;
+    ImgHash = AllocatePool (HashSize);
+    if (ImgHash == NULL) {
+        DEBUG ((EFI_D_ERROR, "kernel image hash buffer allocation failed!\n"));
+        Status = EFI_OUT_OF_RESOURCES;
+        return Status;
+    }
+    Status = LEGetImageHash (QcomAsn1X509Protocal, HashAlgorithm,
+                (UINT8 *)Info->Images[0].ImageBuffer,
+                ImgSize, ImgHash, HashSize);
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: Error during VBGetImageHash: %r\n", Status));
+        return Status;
+    }
+
+    SigAddr = (UINT8 *)Info->Images[0].ImageBuffer + ImgSize;
+    SigSize = LE_BOOTIMG_SIG_SIZE;
+    Status = LEVerifyHashWithSignature (QcomAsn1X509Protocal, ImgHash,
+    HashAlgorithm, &OemCert, SigAddr, SigSize);
+
+    if (Status != EFI_SUCCESS) {
+        DEBUG ((EFI_D_ERROR, "VB: Error during "
+                      "LEVBVerifyHashWithSignature: %r\n", Status));
+        return Status;
+    }
+    DEBUG ((EFI_D_INFO, "VB: LoadImageAndAuthForLE complete!\n"));
+    return Status;
+}
+
 EFI_STATUS
 LoadImageAndAuth (BootInfo *Info)
 {
@@ -733,6 +1086,9 @@
   case AVB_2:
     Status = LoadImageAndAuthVB2 (Info);
     break;
+  case AVB_LE:
+    Status = LoadImageAndAuthForLE (Info);
+    break;
   default:
     DEBUG ((EFI_D_ERROR, "Unsupported AVB version %d\n", AVBVersion));
     Status = EFI_UNSUPPORTED;
@@ -756,14 +1112,15 @@
     return Status;
   }
 
-  DisplayVerifiedBootScreen (Info);
-  DEBUG ((EFI_D_VERBOSE, "Sending Milestone Call\n"));
-  Status = Info->VbIntf->VBSendMilestone (Info->VbIntf);
-  if (Status != EFI_SUCCESS) {
-    DEBUG ((EFI_D_ERROR, "Error sending milestone call to TZ\n"));
-    return Status;
+  if (AVBVersion != AVB_LE) {
+    DisplayVerifiedBootScreen (Info);
+    DEBUG ((EFI_D_VERBOSE, "Sending Milestone Call\n"));
+    Status = Info->VbIntf->VBSendMilestone (Info->VbIntf);
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((EFI_D_ERROR, "Error sending milestone call to TZ\n"));
+      return Status;
+    }
   }
-
   return Status;
 }
 
diff --git a/QcomModulePkg/QcomModulePkg.dec b/QcomModulePkg/QcomModulePkg.dec
index 8b59d08..87e1683 100644
--- a/QcomModulePkg/QcomModulePkg.dec
+++ b/QcomModulePkg/QcomModulePkg.dec
@@ -134,6 +134,10 @@
   #UBI flasher protocol Guid
   gEfiUbiFlasherProtocolGuid =          { 0xe3eef434, 0x22c9, 0xe33b, { 0x8f, 0x5d, 0x0e, 0x81, 0x68, 0x6a, 0x68, 0xcb } }
 
+  gEfiQcomASN1X509ProtocolGuid =        { 0x408ec123, 0x134e, 0x4b80, { 0x91, 0x42, 0xb8, 0x9a, 0xe, 0x08, 0xf8, 0xb3 } }
+
+  gEfiQcomSecRSAProtocolGuid =         { 0xeb7a442a, 0xcef4, 0x40a7, {0xa8, 0xae, 0x5a, 0x2e, 0x7f, 0x48, 0xe1, 0x72 } }
+
 [PcdsFixedAtBuild.common]
   # LinuxLoaderCommon
   gQcomTokenSpaceGuid.KernelLoadAddress|0x00080000|UINT32|0x00015000
diff --git a/QcomModulePkg/QcomModulePkg.dsc b/QcomModulePkg/QcomModulePkg.dsc
index 0922391..5a0797e 100644
--- a/QcomModulePkg/QcomModulePkg.dsc
+++ b/QcomModulePkg/QcomModulePkg.dsc
@@ -102,6 +102,9 @@
   !if $(VERIFIED_BOOT_2)
       GCC:*_*_*_CC_FLAGS = -DVERIFIED_BOOT_2
   !endif
+  !if $(VERIFIED_BOOT_LE)
+      GCC:*_*_*_CC_FLAGS = -DVERIFIED_BOOT_LE
+  !endif
   !if $(USER_BUILD_VARIANT) == 0
       GCC:*_*_*_CC_FLAGS = -DENABLE_UPDATE_PARTITIONS_CMDS -DENABLE_BOOT_CMD -DENABLE_DEVICE_CRITICAL_LOCK_UNLOCK_CMDS
   !else
diff --git a/clang-wrapper.py b/clang-wrapper.py
index 531da48..58ec10f 100755
--- a/clang-wrapper.py
+++ b/clang-wrapper.py
@@ -39,6 +39,7 @@
 
 allowed_warnings = set([
     "list.h:80",
+    "LinuxLoaderLib.c:526",
  ])
 
 # Capture the name of the object file, if can find it.
diff --git a/makefile b/makefile
index 94a36cc..f468805 100644
--- a/makefile
+++ b/makefile
@@ -87,6 +87,7 @@
 	-D ABL_OUT_DIR=$(ANDROID_PRODUCT_OUT) \
 	-D VERIFIED_BOOT=$(VERIFIED_BOOT) \
 	-D VERIFIED_BOOT_2=$(VERIFIED_BOOT_2) \
+	-D VERIFIED_BOOT_LE=$(VERIFIED_BOOT_LE) \
 	-D USER_BUILD_VARIANT=$(USER_BUILD_VARIANT) \
 	-D ENABLE_LE_VARIANT=$(ENABLE_LE_VARIANT) \
 	-D UBSAN_UEFI_GCC_FLAG_UNDEFINED=$(UBSAN_GCC_FLAG_UNDEFINED) \