public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: kalyan-nagabhirava <kalyankumar.nagabhirava@linaro.org>
To: edk2-devel@lists.01.org
Subject: [PATCH v2 1/3] [edk2 EmbeddedPkg]:Implementation of secure boot and HTTP Image download
Date: Thu,  7 Dec 2017 19:04:22 +0530	[thread overview]
Message-ID: <20171207133424.24674-2-kalyankumar.nagabhirava@linaro.org> (raw)
In-Reply-To: <20171207133424.24674-1-kalyankumar.nagabhirava@linaro.org>

Linaro and RDK are working on standardizing the boot process for RDK STB
boxes using Uefi, as part of that implemented secure boot and HTTP image
download functionality.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: kalyan-nagabhirava <kalyankumar.nagabhirava@linaro.org>
---
 EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec       |  52 ++
 EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.inf       |  81 +++
 EmbeddedPkg/Library/RdkBootManagerLib/Include/DiskIo.h            |  20 +
 EmbeddedPkg/Library/RdkBootManagerLib/Include/HttpBoot.h          |   7 +
 EmbeddedPkg/Library/RdkBootManagerLib/Include/List.h              |  52 ++
 EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h |  31 ++
 EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkFile.h           |  20 +
 EmbeddedPkg/Library/RdkBootManagerLib/Include/SecureBoot.h        |  40 ++
 EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c                    | 536 ++++++++++++++++++
 EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c                  | 315 +++++++++++
 EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c                   | 259 +++++++++
 EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c                | 577 ++++++++++++++++++++
 12 files changed, 1990 insertions(+)

diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec b/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec
new file mode 100644
index 000000000000..2f84d1c56db3
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec
@@ -0,0 +1,52 @@
+#
+#  Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
+#
+#  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]
+  DEC_SPECIFICATION              = 0x00010019
+  PACKAGE_NAME                   = RdkPkg
+  PACKAGE_GUID                   = 2f1f2d5e-d9e1-4aa1-8eb9-fed94682e140
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+
+[Guids.common]
+  gRdkTokenSpaceGuid            =  { 0x408c1892, 0xf11a, 0x40c7, { 0xaa, 0x5f, 0x0d, 0x16, 0xc8, 0xb2, 0x52, 0x59 } }
+  gRdkGlobalVariableGuid        =  { 0xc3253c90, 0xa24f, 0x4599, { 0xa6, 0x64, 0x1f, 0x88, 0x13, 0x77, 0x8f, 0xc9 } }
+
+[PcdsFixedAtBuild.common]
+  # Rdk Library
+  gRdkTokenSpaceGuid.PcdRdkRsvdReadSize|0x2000|UINT32|0x02000001
+  gRdkTokenSpaceGuid.PcdRdkRsvdPartitionName|""|VOID*|0x02000002
+  gRdkTokenSpaceGuid.PcdRdkSystemPartitionName|""|VOID*|0x02000003
+  gRdkTokenSpaceGuid.PcdRdkConfFileName|""|VOID*|0x02000004
+  gRdkTokenSpaceGuid.PcdRdkCmdLineArgs|""|VOID*|0x02000013
+  gRdkTokenSpaceGuid.PcdRdkConfFileDevicePath|L""|VOID*|0x02000014
+  gRdkTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00300013
+
+  # GUID of RdkSecureBootLoader
+  gRdkTokenSpaceGuid.PcdRdkSecureBootFile|{ 0x0f, 0x93, 0xc7, 0xb2, 0xef, 0x07, 0x05, 0x43, 0xac, 0x4e, 0x1c, 0xe2, 0x08, 0x5a, 0x70, 0x31 }|VOID*|0x00000100
+
+  # GUID of RdkDri
+  gRdkTokenSpaceGuid.PcdRdkDriFile|{ 0x8a, 0xa1, 0x1b, 0x08, 0x1e, 0xd7, 0xa7, 0x40, 0x99, 0xa9, 0xcd, 0xb8, 0x64, 0x63, 0x96, 0x6d }|VOID*|0x00001000
+
+  # GUID of RdkDriSecureBootLoader
+  gRdkTokenSpaceGuid.PcdRdkDriSecureBootFile|{ 0xd7, 0xd1, 0x52, 0xdd, 0xe2, 0x0d, 0x52, 0x45, 0x98, 0xe0, 0x8d, 0xbe, 0xe4, 0x58, 0xa5, 0x02 }|VOID*|0x00100000
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.inf b/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.inf
new file mode 100644
index 000000000000..aee849db2333
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.inf
@@ -0,0 +1,81 @@
+#
+#  Copyright (c) 2016-2017, Linaro Limited. All rights reserved.
+#  Copyright (c) 2016-2017, comcast . All rights reserved.
+#
+#  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 Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+
+[Defines]
+  INF_VERSION     = 0x00010006
+  BASE_NAME       = RdkBootManagerLib
+  FILE_GUID       = 901f54f2-9d70-9b89-9c0a-d9ca25379059
+  MODULE_TYPE     = DXE_DRIVER
+  VERSION_STRING  = 1.0
+  LIBRARY_CLASS   = RdkBootManagerLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+[Sources]
+  DiskIo.c
+  SecureBoot.c
+  HttpBoot.c
+  RdkFile.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ShellPkg/ShellPkg.dec
+  SecurityPkg/SecurityPkg.dec
+  CryptoPkg/CryptoPkg.dec
+  NetworkPkg/NetworkPkg.dec
+  EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec
+
+[Guids]
+  gEfiCertX509Guid
+  gEfiCertPkcs7Guid
+  gEfiCustomModeEnableGuid
+  gEfiImageSecurityDatabaseGuid
+  gFdtTableGuid
+  gRdkGlobalVariableGuid
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathToTextProtocolGuid
+  gEfiDevicePathFromTextProtocolGuid
+  gEfiLoadedImageProtocolGuid
+  gEfiShellProtocolGuid
+  gEfiDiskIoProtocolGuid
+  gEfiLoadFileProtocolGuid
+
+[Pcd]
+  gRdkTokenSpaceGuid.PcdRdkCmdLineArgs
+  gRdkTokenSpaceGuid.PcdRdkRsvdReadSize
+  gRdkTokenSpaceGuid.PcdRdkRsvdPartitionName
+  gRdkTokenSpaceGuid.PcdRdkSystemPartitionName
+  gRdkTokenSpaceGuid.PcdRdkConfFileName
+  gRdkTokenSpaceGuid.PcdRdkConfFileDevicePath
+  gRdkTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath
+
+[LibraryClasses]
+  FileHandleLib
+  ArmLib
+  BaseLib
+  DebugLib
+  DevicePathLib
+  HobLib
+  PcdLib
+  NetLib
+
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/DiskIo.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/DiskIo.h
new file mode 100644
index 000000000000..003df0c0715c
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/DiskIo.h
@@ -0,0 +1,20 @@
+#ifndef _RDK_DISK_IO_H_
+#define _RDK_DISK_IO_H_
+
+extern
+EFI_STATUS
+PartitionRead (
+	IN CHAR8  *PartitionName,
+	IN VOID   *Image,
+	IN UINTN  Size
+	);
+
+extern
+EFI_STATUS
+PartitionWrite (
+	IN CHAR8  *PartitionName,
+	IN VOID   *Image,
+	IN UINTN  Size
+	);
+
+#endif /* _RDK_DISK_IO_H_ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/HttpBoot.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/HttpBoot.h
new file mode 100644
index 000000000000..80f448ee4140
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/HttpBoot.h
@@ -0,0 +1,7 @@
+#ifndef _RDK_HTTP_BOOT_H_
+#define _RDK_HTTP_BOOT_H_
+
+extern EFI_STATUS
+RdkHttpBoot ( VOID );
+
+#endif /* _RDK_HTTP_BOOT_H_ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/List.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/List.h
new file mode 100644
index 000000000000..02a44f6699ac
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/List.h
@@ -0,0 +1,52 @@
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#define OFFSETOF(TYPE, MEMBER) ((long unsigned int) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:	the pointer to the member.
+ * @type:	the type of the container struct this is embedded in.
+ * @member:	the name of the member within the struct.
+ *
+ */
+#define CONTAINER_OF(Ptr, Type, Member) ({			\
+	const typeof( ((Type *)0)->Member ) *__Mptr = (Ptr);	\
+	(Type *)( (char *)__Mptr - OFFSETOF(Type,Member) );})
+
+
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &LIST_HEAD pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define LIST_ENTRY(Ptr, Type, Member) \
+	CONTAINER_OF(Ptr, Type, Member)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define LIST_FOR_EACH_ENTRY(Pos, Head, Member)				\
+	for (Pos = LIST_ENTRY((Head)->ForwardLink, typeof(*Pos), Member);	\
+	     &Pos->Member != (Head);					\
+	     Pos = LIST_ENTRY(Pos->Member.ForwardLink, typeof(*Pos), Member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define LIST_FOR_EACH_ENTRY_SAFE(Pos, N, Head, Member)			\
+	for (Pos = LIST_ENTRY((Head)->ForwardLink, typeof(*Pos), Member),	\
+		N = LIST_ENTRY(Pos->Member.ForwardLink, typeof(*Pos), Member);	\
+	     &Pos->Member != (Head);					\
+	     Pos = N, N = LIST_ENTRY(N->Member.ForwardLink, typeof(*N), Member))
+
+#endif /* __LIST_H__ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h
new file mode 100644
index 000000000000..5b0b2b1afb79
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h
@@ -0,0 +1,31 @@
+#ifndef __RDK_BOOT_MANAGER_LIB_H__
+#define __RDK_BOOT_MANAGER_LIB_H__
+
+#include <Library/BdsLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/AndroidFastbootPlatform.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/AuthenticatedVariableFormat.h>
+#include <HttpBootDxe/HttpBootDxe.h>
+#include <Include/Guid/AuthenticatedVariableFormat.h>
+#include "SecureBoot.h"
+#include "HttpBoot.h"
+#include "RdkFile.h"
+#include "DiskIo.h"
+
+#endif /* __RDK_BOOT_MANAGER_LIB_H__ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkFile.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkFile.h
new file mode 100644
index 000000000000..e3dd09ab332c
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkFile.h
@@ -0,0 +1,20 @@
+#ifndef __RDK_FILE_H__
+#define __RDK_FILE_H__
+
+#include "List.h"
+
+#define ALLOCATE_STRING_MEM(X)  AllocateZeroPool((X + 1) * sizeof(CHAR16))
+#define MAX_VAR                 4
+
+typedef struct {
+    CHAR16  *Name;
+    LIST_ENTRY List;
+} DIR_NODE;
+
+extern EFI_STATUS
+GetRdkVariable (
+  IN  CONST CHAR16  *Name,
+  OUT CONST CHAR16  **Value
+  );
+
+#endif /* __RDK_FILE_H__ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/Include/SecureBoot.h b/EmbeddedPkg/Library/RdkBootManagerLib/Include/SecureBoot.h
new file mode 100644
index 000000000000..3cfd687670b5
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/Include/SecureBoot.h
@@ -0,0 +1,40 @@
+#ifndef _RDK_SECURE_BOOT_H_
+#define _RDK_SECURE_BOOT_H_
+
+#define FILE_HDR_SIZE 16
+
+extern UINTN Str2Int (
+	VOID * Str
+);
+
+extern EFI_STATUS RdkSecureBoot (
+		EFI_HANDLE		ImageHandle,
+		EFI_BOOT_SERVICES      *BootServices);
+
+extern EFI_STATUS RdkReadFile (
+		IN  	CONST CHAR16 			*Path,
+		IN OUT  VOID                    **BufferPtr,
+		OUT  	UINTN                   *FileSize
+		);
+
+extern EFI_STATUS RdkWriteFile (
+		IN  	CONST CHAR16 			*Path,
+		IN OUT  VOID                    **BufferPtr,
+		OUT  	UINTN                   *FileSize
+		);
+
+extern EFI_STATUS GetFileHandler (
+    		OUT 	EFI_FILE_HANDLE *FileHandle,
+    		IN 	CONST CHAR16    *Path,
+    		IN  	UINT64          OpenMode
+);
+
+typedef enum KEY
+{
+	PK_KEY=1,
+	KEK_KEY,
+	DB_KEY,
+	DBX_KEY
+} eKey;
+
+#endif /* _RDK_SECURE_BOOT_H_ */
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c b/EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c
new file mode 100644
index 000000000000..204a139d9fcb
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c
@@ -0,0 +1,536 @@
+#include <RdkBootManagerLib.h>
+
+/* See sparse_format.h in AOSP  */
+#define SPARSE_HEADER_MAGIC       0xed26ff3a
+#define CHUNK_TYPE_RAW            0xCAC1
+#define CHUNK_TYPE_FILL           0xCAC2
+#define CHUNK_TYPE_DONT_CARE      0xCAC3
+#define CHUNK_TYPE_CRC32          0xCAC4
+
+#define PARTITION_NAME_MAX_LENGTH     72/2
+
+#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \
+    sizeof (EFI_DEVICE_PATH_PROTOCOL))
+
+#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \
+    ((Char) <= L'Z' && (Char) >= L'Z'))
+
+typedef struct _DISKIO_PARTITION_LIST {
+  LIST_ENTRY  Link;
+  CHAR16      PartitionName[PARTITION_NAME_MAX_LENGTH];
+  EFI_HANDLE  PartitionHandle;
+} DISKIO_PARTITION_LIST;
+
+typedef struct _SPARSE_HEADER {
+  UINT32    Magic;
+  UINT16    MajorVersion;
+  UINT16    MinorVersion;
+  UINT16    FileHeaderSize;
+  UINT16    ChunkHeaderSize;
+  UINT32    BlockSize;
+  UINT32    TotalBlocks;
+  UINT32    TotalChunks;
+  UINT32    ImageChecksum;
+} SPARSE_HEADER;
+
+typedef struct _CHUNK_HEADER {
+  UINT16    ChunkType;
+  UINT16    Reserved1;
+  UINT32    ChunkSize;
+  UINT32    TotalSize;
+} CHUNK_HEADER;
+
+STATIC LIST_ENTRY       mPartitionListHead;
+STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *mTextOut;
+STATIC UINT8        PartitionInited = 0;
+
+/*
+ * Helper to free the partition list
+ */
+STATIC
+VOID
+FreePartitionList (
+    VOID
+)
+{
+  DISKIO_PARTITION_LIST *Entry;
+  DISKIO_PARTITION_LIST *NextEntry;
+
+  Entry = (DISKIO_PARTITION_LIST *) GetFirstNode (&mPartitionListHead);
+  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
+    NextEntry = (DISKIO_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link);
+
+    RemoveEntryList (&Entry->Link);
+    FreePool (Entry);
+
+    Entry = NextEntry;
+  }
+}
+
+/*
+ * Read the PartitionName fields from the GPT partition entries, putting them
+ * into an allocated array that should later be freed.
+ */
+STATIC
+EFI_STATUS
+ReadPartitionEntries (
+    IN  EFI_BLOCK_IO_PROTOCOL   *BlockIo,
+    OUT EFI_PARTITION_ENTRY   **PartitionEntries
+  )
+{
+  UINTN                       EntrySize;
+  UINTN                       NumEntries;
+  UINTN                       BufferSize;
+  UINT32                      MediaId;
+  EFI_PARTITION_TABLE_HEADER  *GptHeader;
+  EFI_STATUS                  Status;
+
+  MediaId = BlockIo->Media->MediaId;
+
+  //
+  // Read size of Partition entry and number of entries from GPT header
+  //
+  GptHeader = AllocatePool (BlockIo->Media->BlockSize);
+  if (GptHeader == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, (VOID *) GptHeader);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Check there is a GPT on the media
+  if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID ||
+      GptHeader->MyLBA != 1) {
+    DEBUG ((DEBUG_ERROR,
+        "Fastboot platform: No GPT on flash. "
+        "Fastboot on Versatile Express does not support MBR.\n"
+    ));
+    return EFI_DEVICE_ERROR;
+  }
+
+  EntrySize = GptHeader->SizeOfPartitionEntry;
+  NumEntries = GptHeader->NumberOfPartitionEntries;
+
+  FreePool (GptHeader);
+
+  ASSERT (EntrySize != 0);
+  ASSERT (NumEntries != 0);
+
+  BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize);
+  *PartitionEntries = AllocatePool (BufferSize);
+  if (PartitionEntries == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries);
+  if (EFI_ERROR (Status)) {
+    FreePool (PartitionEntries);
+    return Status;
+  }
+
+  return Status;
+}
+
+/*
+ * Initialise: Open the Android NVM device and find the partitions on it. Save them in
+ * a list along with the "PartitionName" fields for their GPT entries.
+ * We will use these partition names as the key in
+ * FastbootPlatformFlashPartition.
+ */
+EFI_STATUS
+InitDiskIo (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_DEVICE_PATH_PROTOCOL            *FlashDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL            *FlashDevicePathDup;
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL            *NextNode;
+  HARDDRIVE_DEVICE_PATH               *PartitionNode;
+  UINTN                               NumHandles;
+  EFI_HANDLE                          *AllHandles;
+  UINTN                                 LoopIndex;
+  EFI_HANDLE                            FlashHandle;
+  EFI_BLOCK_IO_PROTOCOL               *FlashBlockIo;
+  EFI_PARTITION_ENTRY                 *PartitionEntries;
+  DISKIO_PARTITION_LIST               *Entry;
+
+  InitializeListHead (&mPartitionListHead);
+
+  Status = gBS->LocateProtocol (&gEfiSimpleTextOutProtocolGuid, NULL, (VOID **) &mTextOut);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+        "Fastboot platform: Couldn't open Text Output Protocol: %r\n", Status
+    ));
+    return Status;
+  }
+
+  //
+  // Get EFI_HANDLES for all the partitions on the block devices pointed to by
+  // PcdFastbootFlashDevicePath, also saving their GPT partition labels.
+  // There's no way to find all of a device's children, so we get every handle
+  // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones
+  // that don't represent partitions on the flash device.
+  //
+
+  FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)PcdGetPtr (PcdAndroidFastbootNvmDevicePath));
+
+  //
+  // Open the Disk IO protocol on the flash device - this will be used to read
+  // partition names out of the GPT entries
+  //
+  // Create another device path pointer because LocateDevicePath will modify it.
+  FlashDevicePathDup = FlashDevicePath;
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
+    // Failing to locate partitions should not prevent to do other Android FastBoot actions
+    return EFI_SUCCESS;
+  }
+
+  Status = gBS->OpenProtocol (
+    FlashHandle,
+    &gEfiBlockIoProtocolGuid,
+    (VOID **) &FlashBlockIo,
+    gImageHandle,
+    NULL,
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read the GPT partition entry array into memory so we can get the partition names
+  Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status));
+    // Failing to locate partitions should not prevent to do other Android FastBoot actions
+    return EFI_SUCCESS;
+  }
+
+  // Get every Block IO protocol instance installed in the system
+  Status = gBS->LocateHandleBuffer (
+    ByProtocol,
+    &gEfiBlockIoProtocolGuid,
+    NULL,
+    &NumHandles,
+    &AllHandles
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  // Filter out handles that aren't children of the flash device
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    // Get the device path for the handle
+    Status = gBS->OpenProtocol (
+      AllHandles[LoopIndex],
+      &gEfiDevicePathProtocolGuid,
+      (VOID **) &DevicePath,
+      gImageHandle,
+      NULL,
+      EFI_OPEN_PROTOCOL_GET_PROTOCOL
+      );
+    ASSERT_EFI_ERROR (Status);
+
+    // Check if it is a sub-device of the flash device
+    if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) {
+      // Device path starts with path of flash device. Check it isn't the flash
+      // device itself.
+      NextNode = NextDevicePathNode (DevicePath);
+      if (IsDevicePathEndType (NextNode)) {
+        // Create entry
+        Entry = AllocatePool (sizeof (DISKIO_PARTITION_LIST));
+        if (Entry == NULL) {
+          Status = EFI_OUT_OF_RESOURCES;
+          FreePartitionList ();
+          goto Exit;
+        }
+
+        // Copy handle and partition name
+        Entry->PartitionHandle = AllHandles[LoopIndex];
+        StrCpy (Entry->PartitionName, L"ptable");
+        InsertTailList (&mPartitionListHead, &Entry->Link);
+        continue;
+      }
+
+      // Assert that this device path node represents a partition.
+      ASSERT (NextNode->Type == MEDIA_DEVICE_PATH &&
+          NextNode->SubType == MEDIA_HARDDRIVE_DP);
+
+      PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode;
+
+      // Assert that the partition type is GPT. ReadPartitionEntries checks for
+      // presence of a GPT, so we should never find MBR partitions.
+      // ("MBRType" is a misnomer - this field is actually called "Partition
+      //  Format")
+      ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER);
+
+      // The firmware may install a handle for "partition 0", representing the
+      // whole device. Ignore it.
+      if (PartitionNode->PartitionNumber == 0) {
+        continue;
+      }
+
+      //
+      // Add the partition handle to the list
+      //
+
+      // Create entry
+      Entry = AllocatePool (sizeof (DISKIO_PARTITION_LIST));
+      if (Entry == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        FreePartitionList ();
+        goto Exit;
+      }
+
+      // Copy handle and partition name
+      Entry->PartitionHandle = AllHandles[LoopIndex];
+      StrnCpy (
+          Entry->PartitionName,
+          PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1.
+          PARTITION_NAME_MAX_LENGTH
+      );
+      InsertTailList (&mPartitionListHead, &Entry->Link);
+
+      // Print a debug message if the partition label is empty or looks like
+      // garbage.
+      if (!IS_ALPHA (Entry->PartitionName[0])) {
+        DEBUG ((DEBUG_WARN,
+            "Warning: Partition %d doesn't seem to have a GPT partition label. "
+            "You won't be able to flash it with Fastboot.\n",
+            PartitionNode->PartitionNumber
+        ));
+      }
+    }
+  }
+
+  Exit:
+  FreePool (PartitionEntries);
+  FreePool (FlashDevicePath);
+  FreePool (AllHandles);
+  return Status;
+
+}
+
+STATIC
+EFI_STATUS
+OpenPartition (
+  IN  CHAR8       *PartitionName,
+  IN  VOID        *Image,
+  IN  UINTN       Size,
+  OUT EFI_BLOCK_IO_PROTOCOL     **BlockIo,
+  OUT EFI_DISK_IO_PROTOCOL      **DiskIo
+  )
+{
+  EFI_STATUS               Status;
+  UINTN                    PartitionSize;
+  DISKIO_PARTITION_LIST    *Entry;
+  CHAR16                   PartitionNameUnicode[60];
+  BOOLEAN                  PartitionFound;
+  SPARSE_HEADER            *SparseHeader;
+
+  if(!PartitionInited)
+  {
+    InitDiskIo();
+    PartitionInited = 1;
+  }
+
+  AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
+
+  PartitionFound = FALSE;
+  Entry = (DISKIO_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
+  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
+    // Search the partition list for the partition named by PartitionName
+    if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
+      PartitionFound = TRUE;
+      break;
+    }
+
+    Entry = (DISKIO_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
+  }
+  if (!PartitionFound) {
+    Status = EFI_NOT_FOUND;
+    goto exit;
+  }
+
+  Status = gBS->OpenProtocol (
+    Entry->PartitionHandle,
+    &gEfiBlockIoProtocolGuid,
+    (VOID **) BlockIo,
+    gImageHandle,
+    NULL,
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+    );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to open Block IO protocol: %r\n", Status));
+    Status = EFI_NOT_FOUND;
+    goto exit;
+  }
+
+  SparseHeader=(SPARSE_HEADER *)Image;
+
+  if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) {
+    DEBUG ((DEBUG_INFO, "Sparse Magic: 0x%x Major: %d Minor: %d fhs: %d chs: %d bs: %d tbs: %d tcs: %d checksum: %d \n",
+      SparseHeader->Magic, SparseHeader->MajorVersion, SparseHeader->MinorVersion,  SparseHeader->FileHeaderSize,
+      SparseHeader->ChunkHeaderSize, SparseHeader->BlockSize, SparseHeader->TotalBlocks,
+      SparseHeader->TotalChunks, SparseHeader->ImageChecksum));
+
+    if (SparseHeader->MajorVersion != 1) {
+      DEBUG ((DEBUG_ERROR, "Sparse image version %d.%d not supported.\n",
+            SparseHeader->MajorVersion, SparseHeader->MinorVersion));
+      Status = EFI_INVALID_PARAMETER;
+      goto exit;
+    }
+
+    Size = SparseHeader->BlockSize * SparseHeader->TotalBlocks;
+  }
+
+  // Check image will fit on device
+  PartitionSize = (BlockIo[0]->Media->LastBlock + 1) * BlockIo[0]->Media->BlockSize;
+  if (PartitionSize < Size) {
+    DEBUG ((DEBUG_ERROR, "Partition not big enough.\n"));
+    DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size));
+
+    Status = EFI_VOLUME_FULL;
+    goto exit;
+  }
+
+  Status = gBS->OpenProtocol (
+    Entry->PartitionHandle,
+    &gEfiDiskIoProtocolGuid,
+    (VOID **) DiskIo,
+    gImageHandle,
+    NULL,
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+    );
+
+exit:
+  return Status;
+}
+
+EFI_STATUS
+PartitionRead (
+  IN CHAR8  *PartitionName,
+  IN VOID   *Image,
+  IN UINTN  Size
+  )
+{
+  EFI_STATUS               Status;
+  EFI_BLOCK_IO_PROTOCOL    *BlockIo;
+  EFI_DISK_IO_PROTOCOL     *DiskIo;
+  UINT32                   MediaId;
+
+  Status = OpenPartition (PartitionName, Image, Size, &BlockIo, &DiskIo);
+  if (EFI_ERROR (Status)) {
+    goto exit;
+  }
+
+  MediaId = BlockIo->Media->MediaId;
+
+  Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, Size, Image);
+  if (EFI_ERROR (Status)) {
+    goto exit;
+  }
+
+  BlockIo->FlushBlocks(BlockIo);
+
+exit:
+  return Status;
+}
+
+
+EFI_STATUS
+PartitionWrite (
+  IN CHAR8  *PartitionName,
+  IN VOID   *Image,
+  IN UINTN  Size
+  )
+{
+  EFI_STATUS               Status;
+  EFI_BLOCK_IO_PROTOCOL    *BlockIo;
+  EFI_DISK_IO_PROTOCOL     *DiskIo;
+  UINT32                   MediaId;
+  SPARSE_HEADER            *SparseHeader;
+  CHUNK_HEADER             *ChunkHeader;
+  UINT32                   Chunk;
+  UINTN                    Offset;
+
+  Status = OpenPartition (PartitionName, Image, Size, &BlockIo, &DiskIo);
+  if (EFI_ERROR (Status)) {
+    goto exit;
+  }
+
+  Offset = 0;
+  MediaId = BlockIo->Media->MediaId;
+  SparseHeader = (SPARSE_HEADER *)Image;
+
+  if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) {
+    CHAR16 OutputString[64];
+    UINTN ChunkPrintDensity =
+      SparseHeader->TotalChunks > 1600 ? SparseHeader->TotalChunks / 200 : 32;
+
+    Image += SparseHeader->FileHeaderSize;
+    for (Chunk = 0; Chunk < SparseHeader->TotalChunks; Chunk++) {
+      UINTN WriteSize;
+      ChunkHeader = (CHUNK_HEADER *)Image;
+
+      // Show progress. Don't do it for every packet as outputting text
+      // might be time consuming. ChunkPrintDensity is calculated to
+      // provide an update every half percent change for large
+      // downloads.
+      if (Chunk % ChunkPrintDensity == 0) {
+        UnicodeSPrint(OutputString, sizeof(OutputString),
+            L"\r%5d / %5d chunks written (%d%%)", Chunk,
+            SparseHeader->TotalChunks,
+            (Chunk * 100) / SparseHeader->TotalChunks);
+        mTextOut->OutputString(mTextOut, OutputString);
+      }
+
+      DEBUG ((DEBUG_INFO, "Chunk #%d - Type: 0x%x Size: %d TotalSize: %d Offset %d\n",
+            (Chunk+1), ChunkHeader->ChunkType, ChunkHeader->ChunkSize,
+            ChunkHeader->TotalSize, Offset));
+      Image += sizeof(CHUNK_HEADER);
+      WriteSize=(SparseHeader->BlockSize) * ChunkHeader->ChunkSize;
+      switch (ChunkHeader->ChunkType) {
+        case CHUNK_TYPE_RAW:
+          DEBUG ((DEBUG_INFO, "Writing %d at Offset %d\n", WriteSize, Offset));
+          Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset, WriteSize, Image);
+          if (EFI_ERROR (Status)) {
+            goto exit;
+          }
+          Image+=WriteSize;
+          break;
+        case CHUNK_TYPE_DONT_CARE:
+          break;
+        case CHUNK_TYPE_CRC32:
+          break;
+        default:
+          DEBUG ((DEBUG_ERROR, "Unknown Chunk Type: 0x%x", ChunkHeader->ChunkType));
+          Status = EFI_PROTOCOL_ERROR;
+          goto exit;
+      }
+      Offset += WriteSize;
+    }
+
+    UnicodeSPrint(OutputString, sizeof(OutputString),
+        L"\r%5d / %5d chunks written (100%%)\r\n",
+        SparseHeader->TotalChunks, SparseHeader->TotalChunks);
+    mTextOut->OutputString(mTextOut, OutputString);
+
+  } else {
+
+    Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
+    if (EFI_ERROR (Status)) {
+      goto exit;
+    }
+  }
+
+  BlockIo->FlushBlocks(BlockIo);
+
+exit:
+  return Status;
+}
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c b/EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c
new file mode 100644
index 000000000000..e89241c51b99
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c
@@ -0,0 +1,315 @@
+/*
+#  Copyright (c) 2016-2017, Linaro Limited. All rights reserved.
+#
+#  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 <RdkBootManagerLib.h>
+
+STATIC EFI_LOAD_FILE_PROTOCOL  *LoadFile = NULL;
+STATIC HTTP_BOOT_PRIVATE_DATA  *Private  = NULL;
+
+STATIC
+VOID
+HttpPrivateFromLoadFile (
+  IN   EFI_LOAD_FILE_PROTOCOL   *LoadFile,
+  OUT  HTTP_BOOT_PRIVATE_DATA   **Private
+  )
+{
+  HTTP_BOOT_VIRTUAL_NIC  *Ip4Nic = NULL;
+
+  INT64 Offset = (INT64)&Ip4Nic->LoadFile;
+  Ip4Nic = (VOID *)((char *)LoadFile - Offset);
+  ASSERT (Ip4Nic->Signature == HTTP_BOOT_VIRTUAL_NIC_SIGNATURE);
+  *Private = Ip4Nic->Private;
+}
+
+STATIC
+VOID
+HttpGetLoadFileHandle (
+  OUT EFI_LOAD_FILE_PROTOCOL  **LoadFile
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             LoopIndex;
+  UINTN                             NumHandles;
+  EFI_HANDLE                        *AllHandles;
+  EFI_HANDLE                        Handle;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *DevPathToText;
+  UINT16                            *DeviceFullPath;
+
+  Status = gBS->LocateProtocol (
+      &gEfiDevicePathToTextProtocolGuid,
+      NULL,
+      (VOID **) &DevPathToText
+      );
+  ASSERT_EFI_ERROR (Status);
+
+  // Get every LoadFile protocol instance installed in the system
+  Status = gBS->LocateHandleBuffer (
+      ByProtocol,
+      &gEfiLoadFileProtocolGuid,
+      NULL,
+      &NumHandles,
+      &AllHandles
+      );
+  ASSERT_EFI_ERROR (Status);
+
+  // Get HTTP driver handle from AllHandles
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+
+    Handle = AllHandles[LoopIndex];
+
+    // Get the device path for the handle
+    Status = gBS->OpenProtocol (
+        Handle,
+        &gEfiDevicePathProtocolGuid,
+        (VOID **) &DevicePath,
+        gImageHandle,
+        NULL,
+        EFI_OPEN_PROTOCOL_GET_PROTOCOL
+        );
+    ASSERT_EFI_ERROR (Status);
+
+    DeviceFullPath = DevPathToText->ConvertDevicePathToText (
+        DevicePath,
+        FALSE,
+        TRUE
+        );
+
+    ASSERT(DeviceFullPath != NULL);
+
+    if(StrStr(DeviceFullPath, L"IPv4") != NULL) {
+
+      Status = gBS->OpenProtocol (
+          Handle,
+          &gEfiLoadFileProtocolGuid,
+          (VOID **) LoadFile,
+          gImageHandle,
+          NULL,
+          EFI_OPEN_PROTOCOL_GET_PROTOCOL
+          );
+      ASSERT_EFI_ERROR (Status);
+
+      FreePool (AllHandles);
+      break;
+    }
+  }
+
+  ASSERT ( LoopIndex < NumHandles );
+}
+
+STATIC
+EFI_STATUS
+HttpUpdatePath (
+  IN   CHAR16                   *Uri,
+  OUT  EFI_DEVICE_PATH_PROTOCOL **NewDevicePath
+  )
+{
+  EFI_DEV_PATH              *Node;
+  EFI_DEVICE_PATH_PROTOCOL  *TmpDevicePath;
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  UINTN                     Length;
+  CHAR8                     AsciiUri[URI_STR_MAX_SIZE];
+
+  Node           = NULL;
+  TmpDevicePath  = NULL;
+  Status         = EFI_SUCCESS;
+
+  // Convert the scheme to all lower case.
+  for (Index = 0; Index < StrLen (Uri); Index++) {
+    if (Uri[Index] == L':') {
+      break;
+    }
+    if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {
+      Uri[Index] -= (CHAR16)(L'A' - L'a');
+    }
+  }
+
+  // Only accept empty URI, or http and https URI.
+  if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Create a new device path by appending the IP node and URI node to
+  // the driver's parent device path
+  Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
+  if (Node == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+  Node->Ipv4.Header.Type    = MESSAGING_DEVICE_PATH;
+  Node->Ipv4.Header.SubType = MSG_IPv4_DP;
+  SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
+  TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+  FreePool (Node);
+  if (TmpDevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // Update the URI node with the input boot file URI.
+  UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri));
+  Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);
+  Node = AllocatePool (Length);
+  if (Node == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    FreePool (TmpDevicePath);
+    goto ON_EXIT;
+  }
+  Node->DevPath.Type    = MESSAGING_DEVICE_PATH;
+  Node->DevPath.SubType = MSG_URI_DP;
+  SetDevicePathNodeLength (Node, Length);
+  CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, AsciiStrSize (AsciiUri));
+  *NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+  FreePool (Node);
+  FreePool (TmpDevicePath);
+  if (*NewDevicePath == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+HttpGetImage (
+  IN   CHAR16  *Uri,
+  OUT  UINT8   **FileBuffer,
+  OUT  UINTN   *FileSize
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_STATUS                Status;
+
+  *FileBuffer   = NULL;
+  NewDevicePath = NULL;
+  *FileSize     = 0;
+
+  // Get the LoadFile Handle and
+  // Private structure of HTTP driver
+  if (LoadFile == NULL) {
+    HttpGetLoadFileHandle (&LoadFile);
+    HttpPrivateFromLoadFile (LoadFile, &Private);
+  }
+
+  // Update URI path
+  Status = HttpUpdatePath (Uri, &NewDevicePath);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  // Get the HTTP image from server
+  Status = LoadFile->LoadFile (LoadFile, NewDevicePath, TRUE, FileSize, *FileBuffer);
+  if((Status != EFI_WARN_FILE_SYSTEM) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    goto ON_EXIT;
+  }
+
+  *FileBuffer = AllocatePool (*FileSize);
+  if (*FileBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = LoadFile->LoadFile (LoadFile, NewDevicePath, TRUE, FileSize, *FileBuffer);
+  if (EFI_ERROR (Status)) {
+    FreePool (FileBuffer);
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  if (NewDevicePath != NULL) {
+    FreePool (NewDevicePath);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+RdkHttpBoot (
+  VOID
+  )
+{
+  EFI_STATUS  	Status;
+  VOID        	*FilePtr;
+  UINT8       	*FileBuffer;
+  UINT16      	*Uri;
+  UINTN       	FileSize;
+  UINTN       	LoopIndex;
+  UINTN       	Size;
+  CONST CHAR16  *DtbPath;
+  CONST CHAR16	*ImagePath;
+  CONST CHAR16  *ServerUrlPath;
+
+  Status = GetRdkVariable(L"URL", &ServerUrlPath); 
+  ASSERT_EFI_ERROR (Status);
+
+  // Get the Server name stored in file Server.url
+  Status = RdkReadFile(ServerUrlPath, (VOID **)&FileBuffer, &FileSize);
+  ASSERT_EFI_ERROR (Status);
+
+  Uri = AllocateZeroPool (sizeof(*Uri) * (FileSize+1));
+  if (Uri == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  for(LoopIndex=0; LoopIndex<FileSize; LoopIndex++) {
+    Uri[LoopIndex] = FileBuffer[LoopIndex];
+  }
+
+  if(FileBuffer[FileSize-1] == '\n') {
+    Uri[FileSize-1] = '\0';
+  }
+
+  FreePool (FileBuffer);
+
+  // Disable watchdog
+  Status = gBS->SetWatchdogTimer (0, 0x10000, 0, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "HttpBoot: Couldn't disable watchdog timer: %r\n", Status));
+  }
+
+  // Get the File from server using it's URI
+  Status = HttpGetImage (Uri, &FileBuffer, &FileSize);
+  ASSERT_EFI_ERROR (Status);
+
+  // Write the received image to flash
+  FilePtr   = FileBuffer;
+  Size      = Str2Int(FilePtr);
+  FilePtr  += FILE_HDR_SIZE;
+  Status    = PartitionWrite((CHAR8 *) FixedPcdGetPtr (PcdRdkSystemPartitionName), FilePtr, Size);
+  ASSERT_EFI_ERROR (Status);
+
+  FilePtr  += Size;
+  Size      = Str2Int(FilePtr);
+  FilePtr  += FILE_HDR_SIZE;
+  Status    = GetRdkVariable(L"IMAGE", &ImagePath); 
+  ASSERT_EFI_ERROR (Status);
+  Status    = RdkWriteFile(ImagePath, &FilePtr, &Size);
+  ASSERT_EFI_ERROR (Status);
+
+  FilePtr  += Size;
+  Size      = Str2Int(FilePtr);
+  FilePtr  += FILE_HDR_SIZE;
+  Status    = GetRdkVariable(L"DTB", &DtbPath); 
+  ASSERT_EFI_ERROR (Status);
+  Status    = RdkWriteFile(DtbPath, &FilePtr, &Size);
+  ASSERT_EFI_ERROR (Status);
+
+  FreePool (FileBuffer);
+  FreePool (Uri);
+
+  return Status;
+}
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c b/EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c
new file mode 100644
index 000000000000..3f454e6605b9
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c
@@ -0,0 +1,259 @@
+#include <RdkBootManagerLib.h>
+
+STATIC UINT8    VarablesInitialzed = 0;
+STATIC CHAR16   *VarResult[MAX_VAR][2];
+
+STATIC
+VOID
+SaveString (
+  OUT CHAR16    **Dest,
+  IN  CHAR16    *String1,
+  IN  CHAR16    *String2
+  )
+{
+  *Dest = ALLOCATE_STRING_MEM(StrLen(String1) + StrLen(String2));
+  StrCat(*Dest, String1);
+  StrCat(*Dest, String2);
+}
+
+STATIC
+EFI_STATUS
+LsFiles (
+  IN  CONST CHAR16  *DirPath,
+  IN  CONST CHAR16  *TargetFile,
+  OUT CHAR16        **Result,
+  IN  LIST_ENTRY    *Head
+  )
+{
+  EFI_STATUS          Status;
+  EFI_FILE_INFO       *FileInfo;
+  EFI_FILE_PROTOCOL   *FileHandle;
+  BOOLEAN             NoFile;
+  CHAR16              *TempPath;
+  DIR_NODE            *Node;
+
+  NoFile    = FALSE;
+  TempPath  = ALLOCATE_STRING_MEM(StrLen(DirPath) + 1);
+  StrCat(TempPath, DirPath);
+  StrCat(TempPath, L"/");
+
+  Status = GetFileHandler(&FileHandle, DirPath, EFI_FILE_MODE_READ);
+  ASSERT_EFI_ERROR(Status);
+
+  for ( Status = FileHandleFindFirstFile(FileHandle, &FileInfo)
+      ; !EFI_ERROR(Status) && !NoFile
+      ; Status = FileHandleFindNextFile(FileHandle, FileInfo, &NoFile)
+      ) {
+    if((FileInfo->Attribute & EFI_FILE_DIRECTORY) &&
+        (StrCmp(FileInfo->FileName, L".") != 0) &&
+        (StrCmp(FileInfo->FileName, L"..") != 0)) {
+      Node = AllocateZeroPool(sizeof (DIR_NODE));
+      SaveString(&Node->Name, TempPath, FileInfo->FileName);
+      InsertHeadList(Head,&Node->List);
+    }
+    else if(StrCmp(FileInfo->FileName, TargetFile) == 0) {
+      SaveString(Result, TempPath, FileInfo->FileName);
+      Status = EFI_SUCCESS;
+      goto ON_EXIT;
+    }
+  }
+
+  Status = EFI_NOT_FOUND;
+
+ON_EXIT:
+  FreePool(TempPath);
+  return Status;
+}
+
+STATIC
+VOID
+DelDirList (
+  IN  LIST_ENTRY *Head
+  )
+{
+  DIR_NODE  *Node;
+  DIR_NODE  *Temp;
+
+  LIST_FOR_EACH_ENTRY_SAFE (Node, Temp, Head, List) {
+    RemoveEntryList(&Node->List);
+    FreePool(Node->Name);
+    FreePool(Node);
+  }
+}
+
+STATIC
+EFI_STATUS
+FindFileInDir (
+  IN  CONST CHAR16  *DevPath,
+  IN  CONST CHAR16  *TargetFile,
+  OUT CHAR16    **Result
+  )
+{
+  UINT8       Current;
+  UINT8       Next;
+  DIR_NODE    *Temp;
+  LIST_ENTRY  DirList[2];
+
+  *Result           = NULL;
+  EFI_STATUS Status = EFI_NOT_FOUND;
+
+  InitializeListHead(&DirList[0]);
+  InitializeListHead(&DirList[1]);
+
+  for (Current = 0, LsFiles(DevPath, TargetFile, Result, &DirList[Current]);
+      !IsListEmpty(&DirList[Current]);
+      Current = Next) {
+    Next = Current ^ 1;
+    DelDirList(&DirList[Next]);
+
+    LIST_FOR_EACH_ENTRY(Temp, &DirList[Current], List) {
+      Status = LsFiles(Temp->Name, TargetFile, Result, &DirList[Next]);
+      if(!EFI_ERROR(Status)) {
+        DelDirList(&DirList[Current]);
+        break;
+      }
+    }
+  }
+
+  DelDirList(&DirList[Next]);
+  return Status;
+}
+
+STATIC
+UINTN
+StrSpn (
+  IN CHAR8    *String,
+  IN CHAR8    *CharSet
+  )
+{
+  UINTN Count;
+
+  for(Count=0; String[Count] && !(String[Count] == CharSet[0]); Count++);
+  return Count;
+}
+
+STATIC
+CHAR16 *
+Ascii2Uefi (
+  IN CHAR8  *String
+  )
+{
+  CHAR16  *Result;
+  UINTN   Size;
+
+  Size    = AsciiStrLen(String);
+  Result  = ALLOCATE_STRING_MEM(Size);
+
+  while(Size--) {
+    Result[Size] = String[Size];
+  }
+
+  return Result;
+}
+
+STATIC
+EFI_STATUS
+InitVarList (
+  IN  CHAR8  *FileData,
+  IN  UINTN   FileSize
+  )
+{
+  UINTN       InnerLoopIndex;
+  UINTN       OuterLoopIndex;
+  UINTN       Current;
+  UINTN       Next;
+  CHAR8       *VarDelimiter[2];
+  EFI_STATUS  Status;
+
+  VarDelimiter[0] = "=";
+  VarDelimiter[1] = "\"";
+  Status          = EFI_SUCCESS;
+
+  for(OuterLoopIndex=0, Next=0; OuterLoopIndex<MAX_VAR &&  Next < FileSize; OuterLoopIndex++) {
+    for(InnerLoopIndex=0; InnerLoopIndex<2; InnerLoopIndex++) {
+      Current = Next;
+      Next += StrSpn(&FileData[Next], VarDelimiter[InnerLoopIndex]);
+      FileData[Next] = '\0';
+      VarResult[OuterLoopIndex][InnerLoopIndex] = Ascii2Uefi(&FileData[Current]);
+      Next += 2;
+    }
+  }
+
+  if(OuterLoopIndex < MAX_VAR) {
+    Status = EFI_NOT_FOUND;
+  }
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+InitRdkVariables (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  UINTN         RdkSize;
+  UINT8         *RdkData;
+  CHAR16        **Result;
+  CONST CHAR16  *DevPath;
+  CONST CHAR16  *RdkFileName;
+
+  Result      = NULL;
+  DevPath     = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileDevicePath);
+  RdkFileName = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileName);
+
+  Status = FindFileInDir(DevPath, RdkFileName, Result);
+  if(EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = RdkReadFile ((CONST CHAR16 *)*Result, (VOID**) &RdkData, &RdkSize);
+  if(EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = InitVarList ((CHAR8 *)RdkData, RdkSize);
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+GetVarValue (
+  IN  CONST CHAR16 *Name,
+  OUT CONST CHAR16 **Value
+  )
+{
+  UINTN         Count;
+  EFI_STATUS    Status;
+
+  if(!VarablesInitialzed) {
+    Status = InitRdkVariables();
+    if(EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    VarablesInitialzed = 1;
+  }
+
+  for(Count=0; Count<MAX_VAR; Count++) {
+    if(StrCmp(Name, VarResult[Count][0]) == 0) {
+      *Value = VarResult[Count][1];
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetRdkVariable (
+  IN  CONST CHAR16  *Name,
+  OUT CONST CHAR16  **Value
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = GetVarValue(Name, Value);
+  return Status;
+}
diff --git a/EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c b/EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c
new file mode 100644
index 000000000000..dacf203dc724
--- /dev/null
+++ b/EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c
@@ -0,0 +1,577 @@
+#include <RdkBootManagerLib.h>
+
+STATIC
+EFI_STATUS
+OpenFileByDevicePath(
+    IN OUT  EFI_DEVICE_PATH_PROTOCOL  **FilePath,
+    OUT     EFI_FILE_HANDLE           *FileHandle,
+    IN      UINT64                    OpenMode,
+    IN      UINT64                    Attributes
+)
+{
+    EFI_STATUS                        Status;
+    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *EfiSimpleFileSystemProtocol;
+    EFI_FILE_PROTOCOL                 *Handle1;
+    EFI_FILE_PROTOCOL                 *Handle2;
+    EFI_HANDLE                        DeviceHandle;
+
+    //if ((FilePath == NULL || FileHandle == NULL)) {
+    if ((FilePath == NULL )) {
+        return EFI_INVALID_PARAMETER;
+    }
+
+    Status = gBS->LocateDevicePath (
+                 &gEfiSimpleFileSystemProtocolGuid,
+                 FilePath,
+                 &DeviceHandle
+             );
+    if (EFI_ERROR (Status)) {
+        return Status;
+    }
+
+    Status = gBS->OpenProtocol(
+                 DeviceHandle,
+                 &gEfiSimpleFileSystemProtocolGuid,
+                 (VOID**)&EfiSimpleFileSystemProtocol,
+                 gImageHandle,
+                 NULL,
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+             );
+    if (EFI_ERROR (Status)) {
+        return Status;
+    }
+
+    Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+    if (EFI_ERROR (Status)) {
+        FileHandle = NULL;
+        return Status;
+    }
+
+    //
+    // go down directories one node at a time.
+    //
+    while (!IsDevicePathEnd (*FilePath)) {
+        //
+        // For file system access each node should be a file path component
+        //
+        if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
+                DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+           ) {
+            FileHandle = NULL;
+            return (EFI_INVALID_PARAMETER);
+        }
+        //
+        // Open this file path node
+        //
+        Handle2  = Handle1;
+        Handle1 = NULL;
+
+        //
+        // Try to test opening an existing file
+        //
+        Status = Handle2->Open (
+                     Handle2,
+                     &Handle1,
+                     ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                     OpenMode &~EFI_FILE_MODE_CREATE,
+                     0
+                 );
+
+        //
+        // see if the error was that it needs to be created
+        //
+        if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
+            Status = Handle2->Open (
+                         Handle2,
+                         &Handle1,
+                         ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                         OpenMode,
+                         Attributes
+                     );
+        }
+        //
+        // Close the last node
+        //
+        Handle2->Close (Handle2);
+
+        if (EFI_ERROR(Status)) {
+            return (Status);
+        }
+
+        //
+        // Get the next node
+        //
+        *FilePath = NextDevicePathNode (*FilePath);
+    }
+
+    //
+    // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+    //
+    *FileHandle = (VOID*)Handle1;
+
+    return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFileHandler (
+    OUT EFI_FILE_HANDLE *FileHandle,
+    IN  CONST CHAR16    *Path,
+    IN  UINT64          OpenMode
+)
+{
+    EFI_STATUS                          Status;
+    EFI_DEVICE_PATH_PROTOCOL            *KeyFileDevicePath;
+    EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *DevicePathFromTextProtocol;
+
+    Status        = EFI_SUCCESS;
+    KeyFileDevicePath   = NULL;
+
+    Status = gBS->LocateProtocol (
+                 &gEfiDevicePathFromTextProtocolGuid,
+                 NULL,
+                 (VOID**)&DevicePathFromTextProtocol
+             );
+    ASSERT_EFI_ERROR(Status);
+
+    //  KeyFileDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Path);
+    KeyFileDevicePath =  DevicePathFromTextProtocol->ConvertTextToDevicePath(Path);
+    if(KeyFileDevicePath != NULL)
+    {
+        Status = OpenFileByDevicePath(&KeyFileDevicePath,FileHandle,OpenMode,0);
+        if(Status != EFI_SUCCESS)
+        {
+            DEBUG ((DEBUG_INFO, "Getting FileHandle of %s Failed\n",Path));
+        }
+    }
+    return Status;
+}
+
+STATIC
+EFI_STATUS
+CreateTimeBasedPayload (
+    IN OUT UINTN  *DataSize,
+    IN OUT UINT8  **Data
+)
+{
+    EFI_STATUS                       Status;
+    UINT8                            *NewData;
+    UINT8                            *Payload;
+    UINTN                            PayloadSize;
+    EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;
+    UINTN                            DescriptorSize;
+    EFI_TIME                         Time;
+
+    if (Data == NULL || DataSize == NULL) {
+        return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // In Setup mode or Custom mode, the variable does not need to be signed but the
+    // parameters to the SetVariable() call still need to be prepared as authenticated
+    // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
+    // data in it.
+    //
+
+    Payload     = *Data;
+    PayloadSize = *DataSize;
+
+    DescriptorSize    = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
+    NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
+    if (NewData == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+    }
+
+    if ((Payload != NULL) && (PayloadSize != 0)) {
+        CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
+    }
+
+    DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
+
+    ZeroMem (&Time, sizeof (EFI_TIME));
+    Status = gRT->GetTime (&Time, NULL);
+    if (EFI_ERROR (Status)) {
+        FreePool(NewData);
+        return Status;
+    }
+    Time.Pad1       = 0;
+    Time.Nanosecond = 0;
+    Time.TimeZone   = 0;
+    Time.Daylight   = 0;
+    Time.Pad2       = 0;
+    CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
+
+    DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
+    DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
+    DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+    CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
+
+    if (Payload != NULL) {
+        FreePool(Payload);
+    }
+
+    *DataSize = DescriptorSize + PayloadSize;
+    *Data     = NewData;
+    return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SetBootMode (
+    IN UINT8  SecureBootMode
+)
+{
+    return gRT->SetVariable (
+               EFI_CUSTOM_MODE_NAME,
+               &gEfiCustomModeEnableGuid,
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+               sizeof (UINT8),
+               &SecureBootMode
+           );
+}
+
+STATIC
+EFI_STATUS
+SetVariable (
+    IN EFI_SIGNATURE_LIST *PkCert,
+    IN UINTN              DataSize,
+    IN eKey               KeyType
+)
+{
+    UINT32  Attr;
+    EFI_STATUS   Status=EFI_SUCCESS ;
+    Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
+           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+    if(KeyType == PK_KEY)
+    {
+        DEBUG ((DEBUG_INFO, "Setting PK Key\n"));
+        Status = gRT->SetVariable (
+                     EFI_PLATFORM_KEY_NAME,
+                     &gEfiGlobalVariableGuid,
+                     Attr,
+                     DataSize,
+                     PkCert
+                 );
+    }
+    else if( KeyType == KEK_KEY)
+    {
+        DEBUG ((DEBUG_INFO, "Setting KEK Key\n"));
+        Status = gRT->SetVariable (
+                     EFI_KEY_EXCHANGE_KEY_NAME,
+                     &gEfiGlobalVariableGuid,
+                     Attr,
+                     DataSize,
+                     PkCert
+                 );
+
+        Status = gRT->SetVariable (
+                     EFI_IMAGE_SECURITY_DATABASE,
+                     &gEfiImageSecurityDatabaseGuid,
+                     Attr,
+                     DataSize,
+                     PkCert
+                 );
+    }
+    else
+    {
+        ASSERT(FALSE);
+    }
+    return Status;
+
+}
+
+STATIC
+VOID
+PopulateCert (
+    OUT EFI_SIGNATURE_LIST  **Cert,
+    IN  UINTN               DataSize,
+    IN  UINT8               *Data
+)
+{
+    EFI_SIGNATURE_DATA  *CertData = NULL;
+
+    if( (*Cert) == NULL)
+    {
+        (*Cert) = (EFI_SIGNATURE_LIST*) AllocateZeroPool ( sizeof(EFI_SIGNATURE_LIST)
+                  + sizeof(EFI_SIGNATURE_DATA) - 1
+                  + DataSize );
+
+        ASSERT ((*Cert) != NULL);
+    }
+    (*Cert)->SignatureListSize   = (UINT32) (sizeof(EFI_SIGNATURE_LIST)
+                                   + sizeof(EFI_SIGNATURE_DATA) - 1
+                                   + DataSize);
+    (*Cert)->SignatureSize       = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + DataSize);
+    (*Cert)->SignatureHeaderSize = 0;
+    CopyGuid (&(*Cert)->SignatureType, &gEfiCertX509Guid);
+
+
+    CertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*Cert) + sizeof(EFI_SIGNATURE_LIST) + (*Cert)->SignatureHeaderSize);
+    ASSERT (CertData != NULL);
+
+    CopyGuid (&CertData->SignatureOwner, &gEfiGlobalVariableGuid);
+    CopyMem (&CertData->SignatureData, Data, DataSize);
+}
+
+STATIC
+EFI_STATUS
+RegisterCert (
+    IN  UINT8   *KeyData,
+    IN  UINTN   KeySize,
+    IN  eKey    KeyType
+)
+{
+    EFI_STATUS          Status;
+    EFI_SIGNATURE_LIST  *Cert = NULL;
+
+    Status = SetBootMode(CUSTOM_SECURE_BOOT_MODE);
+    ASSERT_EFI_ERROR (Status);
+
+    PopulateCert(&Cert, KeySize, KeyData);
+
+    KeySize = Cert->SignatureListSize;
+
+    Status = CreateTimeBasedPayload (&KeySize, (UINT8**) &Cert);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = SetVariable(Cert,KeySize,KeyType);
+    return Status;
+}
+
+UINTN
+Str2Int (
+    VOID * Str
+)
+{
+    UINTN i, Size;
+    UINT8 *Ptr = Str;
+
+    for(i=0, Size=0; i<FILE_HDR_SIZE; i++)
+    {
+        Size = (Ptr[i] - '0') + (Size * 10);
+    }
+
+    return Size;
+}
+
+STATIC
+VOID
+RdkSetVariable (
+    VOID
+)
+{
+    UINTN      		KekCrtSize;
+    UINT8       	*KekCrtData;
+    CONST CHAR16	*KekCrtPath;
+    EFI_STATUS  	Status;
+
+    Status = GetRdkVariable(L"KEK", &KekCrtPath);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = RdkReadFile (
+                 KekCrtPath,
+                 (VOID **)&KekCrtData,
+                 &KekCrtSize
+             );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gRT->SetVariable (
+                 L"RdkRootCertificate",
+                 &gRdkGlobalVariableGuid,
+                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                 KekCrtSize,
+                 KekCrtData
+             );
+    ASSERT_EFI_ERROR(Status);
+
+    /* Read PK and KEK keys from reserved partition */
+    STATIC UINT8 *Buffer = NULL;
+    UINT32 RsvdReadSize = PcdGet32 (PcdRdkRsvdReadSize);
+    Buffer = AllocateZeroPool(RsvdReadSize);
+    PartitionRead((CHAR8 *)FixedPcdGetPtr (PcdRdkRsvdPartitionName), Buffer, RsvdReadSize);
+
+    INT32 PkKeySize, KekKeySize;
+
+    UINT8 * PkKey = Buffer;
+    PkKeySize = Str2Int (PkKey);
+    PkKey += FILE_HDR_SIZE;
+
+    UINT8 * KekKey = PkKey + PkKeySize;
+    KekKeySize = Str2Int (KekKey);
+    KekKey += FILE_HDR_SIZE;
+
+    INT8* SetupMode = NULL;
+    eKey KeyType;
+
+    KeyType = PK_KEY;
+    Status = RegisterCert(PkKey,PkKeySize,KeyType);
+    GetEfiGlobalVariable2 (L"SetupMode", (VOID**)&SetupMode, NULL);
+
+    if (*SetupMode == 0)
+    {
+        DEBUG ((DEBUG_INFO, "PK Key Got Registered. Now System in User Mode\n"));
+        KeyType = KEK_KEY;
+        Status = RegisterCert(KekKey,KekKeySize,KeyType);
+    }
+    else if(*SetupMode == 1)
+    {
+        DEBUG ((DEBUG_INFO, "System in Standard System Mode ::: Secure Boot Not enabled\n"));
+        ASSERT_EFI_ERROR(Status);
+    }
+
+    FreePool(Buffer);
+}
+
+EFI_STATUS
+RdkReadFile (
+    IN      CONST CHAR16  *Path,
+    IN OUT  VOID          **BufferPtr,
+    OUT     UINTN         *FileSize
+)
+{
+    UINTN             BufferSize;
+    UINT64            SourceFileSize;
+    VOID              *Buffer;
+    EFI_STATUS        Status;
+    EFI_FILE_HANDLE   FileHandle;
+
+    Status = GetFileHandler(&FileHandle, Path, EFI_FILE_MODE_READ);
+    ASSERT_EFI_ERROR(Status);
+
+    if (FileSize == NULL) {
+        return EFI_INVALID_PARAMETER;
+    }
+
+    Buffer = NULL;
+
+    // Get the file size
+    Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+    if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+    }
+
+    Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+    if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+    }
+
+    Status = FileHandle->SetPosition (FileHandle, 0);
+    if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+    }
+
+    BufferSize = (UINTN) SourceFileSize;
+    Buffer =  AllocateZeroPool(BufferSize);
+    if (Buffer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+    }
+
+    BufferSize = (UINTN) SourceFileSize;
+    *FileSize  = BufferSize;
+
+    Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+    if (EFI_ERROR (Status) || BufferSize != *FileSize) {
+        FreePool (Buffer);
+        Buffer = NULL;
+        Status  = EFI_BAD_BUFFER_SIZE;
+        goto ON_EXIT;
+    }
+
+ON_EXIT:
+
+    *BufferPtr = Buffer;
+    return Status;
+}
+
+EFI_STATUS
+RdkWriteFile (
+    IN      CONST CHAR16    *Path,
+    IN OUT  VOID            **BufferPtr,
+    OUT     UINTN           *FileSize
+)
+{
+    EFI_STATUS        Status;
+    EFI_FILE_HANDLE   FileHandle;
+
+    if (FileSize == NULL) {
+        return EFI_INVALID_PARAMETER;
+    }
+
+    Status = GetFileHandler(&FileHandle, Path, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE);
+    ASSERT_EFI_ERROR(Status);
+
+    Status = FileHandle->Write (FileHandle, FileSize, *BufferPtr);
+    ASSERT_EFI_ERROR (Status);
+
+    return Status;
+}
+
+EFI_STATUS
+RdkSecureBoot (
+    EFI_HANDLE        ImageHandle,
+    EFI_BOOT_SERVICES *BootServices
+)
+{
+    UINT8                               *FdtData;
+    UINTN                               FdtDataSize;
+    UINTN                               *ExitDataSize;
+    CHAR16                              **ExitData;
+    CHAR16                        	    LoadOption[128];
+    CONST CHAR8				                  *CmdLine;
+    CONST CHAR16			                  *ImagePath;
+    CONST CHAR16			                  *DtbPath;
+    EFI_STATUS                          Status;
+    EFI_HANDLE                          Handle;
+    EFI_DEVICE_PATH_PROTOCOL            *FilePath;
+    EFI_LOADED_IMAGE_PROTOCOL           *ImageInfo;
+    EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *DevicePathFromTextProtocol;
+
+    FilePath      = NULL;
+    ExitData      = NULL;
+    ExitDataSize  = NULL;
+    CmdLine	      = (CONST CHAR8 *)FixedPcdGetPtr (PcdRdkCmdLineArgs);
+
+    Status = GetRdkVariable(L"DTB", &DtbPath); 
+    ASSERT_EFI_ERROR (Status);
+
+    Status = RdkReadFile (DtbPath, (VOID**) &FdtData, &FdtDataSize);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->InstallConfigurationTable (&gFdtTableGuid,(VOID*)FdtData);
+    ASSERT_EFI_ERROR (Status);
+
+    RdkSetVariable();
+
+    Status = GetRdkVariable(L"IMAGE", &ImagePath); 
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->LocateProtocol (
+                 &gEfiDevicePathFromTextProtocolGuid,
+                 NULL,
+                 (VOID**)&DevicePathFromTextProtocol
+             );
+    ASSERT_EFI_ERROR(Status);
+
+    FilePath  = DevicePathFromTextProtocol->ConvertTextToDevicePath(ImagePath);
+
+    Status    = BootServices->LoadImage (
+                    TRUE,
+                    ImageHandle,
+                    FilePath,
+                    NULL,
+                    0,
+                    &Handle
+                );
+    ASSERT_EFI_ERROR (Status);
+
+    UnicodeSPrintAsciiFormat (LoadOption, sizeof(LoadOption), CmdLine);
+
+    Status = BootServices->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+    ASSERT_EFI_ERROR (Status);
+    ImageInfo->LoadOptionsSize  = sizeof(LoadOption);
+    ImageInfo->LoadOptions      = LoadOption;
+
+    Status = BootServices->StartImage (Handle, ExitDataSize, ExitData);
+    ASSERT_EFI_ERROR (Status);
+
+    return Status;
+}
-- 
2.15.0



  reply	other threads:[~2017-12-07 13:31 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-07 13:34 [PATCH v2 0/3] Adding secure boot and HTTP image download features for Linux based platform kalyan-nagabhirava
2017-12-07 13:34 ` kalyan-nagabhirava [this message]
2017-12-07 13:34 ` [PATCH v2 2/3] EmbeddedPkg: secureboot application using RdkBootManagerLib kalyan-nagabhirava
2017-12-07 13:34 ` [PATCH v2 3/3] EmbeddedPkg: Httpimage downlaod application kalyan-nagabhirava
2017-12-07 14:06 ` [PATCH v2 0/3] Adding secure boot and HTTP image download features for Linux based platform Ard Biesheuvel
2017-12-07 14:25   ` Kalyan Nagabhirava
2017-12-08 10:07     ` Kalyan Nagabhirava

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171207133424.24674-2-kalyankumar.nagabhirava@linaro.org \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox