diff --git a/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.dec b/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.dec
new file mode 100644
index 000000000000..3f3635592325
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.dec
@@ -0,0 +1,50 @@
+#
+#  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.PcdRdkSystemPartitionName|""|VOID*|0x02000003
+  gRdkTokenSpaceGuid.PcdRdkConfFileName|""|VOID*|0x02000004
+  gRdkTokenSpaceGuid.PcdRdkCmdLineArgs|""|VOID*|0x02000013
+  gRdkTokenSpaceGuid.PcdRdkConfFileDevicePath|L""|VOID*|0x02000014
+  gRdkTokenSpaceGuid.PcdDtbAvailable|FALSE|BOOLEAN|0x00300014
+
+  # 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/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.inf b/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.inf
new file mode 100644
index 000000000000..ecd9f578a580
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.inf
@@ -0,0 +1,79 @@
+#
+#  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
+  Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.dec
+
+[Guids]
+  gEfiCertX509Guid
+  gEfiCertPkcs7Guid
+  gEfiCustomModeEnableGuid
+  gEfiImageSecurityDatabaseGuid
+  gFdtTableGuid
+  gRdkGlobalVariableGuid
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathToTextProtocolGuid
+  gEfiDevicePathFromTextProtocolGuid
+  gEfiLoadedImageProtocolGuid
+  gEfiShellProtocolGuid
+  gEfiDiskIoProtocolGuid
+  gEfiLoadFileProtocolGuid
+
+[Pcd]
+  gRdkTokenSpaceGuid.PcdRdkCmdLineArgs
+  gRdkTokenSpaceGuid.PcdRdkSystemPartitionName
+  gRdkTokenSpaceGuid.PcdRdkConfFileName
+  gRdkTokenSpaceGuid.PcdRdkConfFileDevicePath
+  gRdkTokenSpaceGuid.PcdDtbAvailable
+
+[LibraryClasses]
+  FileHandleLib
+  ArmLib
+  BaseLib
+  DebugLib
+  DevicePathLib
+  HobLib
+  PcdLib
+  NetLib
+
diff --git a/Platform/Comcast/Library/RdkBootManagerLib/Include/DiskIo.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/DiskIo.h
new file mode 100644
index 000000000000..003df0c0715c
--- /dev/null
+++ b/Platform/Comcast/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/Platform/Comcast/Library/RdkBootManagerLib/Include/HttpBoot.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/HttpBoot.h
new file mode 100644
index 000000000000..80f448ee4140
--- /dev/null
+++ b/Platform/Comcast/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/Platform/Comcast/Library/RdkBootManagerLib/Include/List.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/List.h
new file mode 100644
index 000000000000..02a44f6699ac
--- /dev/null
+++ b/Platform/Comcast/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/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h
new file mode 100644
index 000000000000..5b0b2b1afb79
--- /dev/null
+++ b/Platform/Comcast/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/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkFile.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkFile.h
new file mode 100644
index 000000000000..c5b1d43d5f76
--- /dev/null
+++ b/Platform/Comcast/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                 6
+
+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/Platform/Comcast/Library/RdkBootManagerLib/Include/SecureBoot.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/SecureBoot.h
new file mode 100644
index 000000000000..3cfd687670b5
--- /dev/null
+++ b/Platform/Comcast/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/Platform/Comcast/Library/RdkBootManagerLib/DiskIo.c b/Platform/Comcast/Library/RdkBootManagerLib/DiskIo.c
new file mode 100644
index 000000000000..7d1952dbcca1
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/DiskIo.c
@@ -0,0 +1,358 @@
+#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;
+
+/*
+ * 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;
+  }
+}
+
+/*
+ * lists the available Block Io and adds handle of given dev path
+ */
+STATIC
+EFI_STATUS
+ListBlockIos (
+    IN CHAR16       *PartitionName
+  )
+{
+    EFI_STATUS                        Status;
+    EFI_HANDLE                        *AllHandles;
+    EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *DevPathToText;
+    EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+    UINTN                             LoopIndex;
+    UINTN                             NumHandles;
+    UINT16                            *DeviceFullPath;
+    DISKIO_PARTITION_LIST             *Entry;
+
+    InitializeListHead (&mPartitionListHead);
+
+    Status = gBS->LocateProtocol (
+        &gEfiDevicePathToTextProtocolGuid,
+        NULL,
+        (VOID **) &DevPathToText
+        );
+    ASSERT_EFI_ERROR (Status);
+
+    // Get every Block IO protocol instance installed in the system
+    Status = gBS->LocateHandleBuffer (
+      ByProtocol,
+      &gEfiBlockIoProtocolGuid,
+      NULL,
+      &NumHandles,
+      &AllHandles
+      );
+    ASSERT_EFI_ERROR (Status);
+    DEBUG((DEBUG_INFO, "Block IO: %d handles \n", NumHandles));
+
+    // Get HTTP driver handle from AllHandles
+    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
+          );
+
+      DeviceFullPath = DevPathToText->ConvertDevicePathToText (
+          DevicePath,
+          FALSE,
+          TRUE
+          );
+
+      DEBUG((DEBUG_INFO,"Handle[%d] is %p, fullpath %s\n", LoopIndex, AllHandles[LoopIndex], DeviceFullPath));
+
+      if ( 0 == StrCmp ( PartitionName, DeviceFullPath ) ) {
+          DEBUG((DEBUG_INFO, "rootfs partition path matched\n"));
+          //
+          // Add the partition handle to the list
+          //
+          // Create entry
+          Entry = AllocatePool (sizeof (DISKIO_PARTITION_LIST));
+          if (Entry == NULL) {
+            Status = EFI_OUT_OF_RESOURCES;
+            goto Exit;
+          }
+
+          // Copy handle and partition name
+          Entry->PartitionHandle = AllHandles[LoopIndex];
+          StrnCpy (
+              Entry->PartitionName,
+              PartitionName,
+              PARTITION_NAME_MAX_LENGTH
+          );
+          InsertTailList (&mPartitionListHead, &Entry->Link);
+          break;
+      }
+    }
+    FreePool(AllHandles);
+    ASSERT ( LoopIndex < NumHandles );
+Exit:
+    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;
+  SPARSE_HEADER            *SparseHeader;
+  UINT16                   UnicodePartitionName[100];
+
+  AsciiStrToUnicodeStr ( PartitionName, UnicodePartitionName);
+  DEBUG((DEBUG_INFO, "Unicode partition name %s\n", UnicodePartitionName));
+
+  Status = ListBlockIos (UnicodePartitionName);
+  ASSERT_EFI_ERROR ( Status );
+
+  Entry = (DISKIO_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
+  ASSERT ( NULL != Entry );
+
+  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:
+  FreePartitionList();
+  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/Platform/Comcast/Library/RdkBootManagerLib/HttpBoot.c b/Platform/Comcast/Library/RdkBootManagerLib/HttpBoot.c
new file mode 100644
index 000000000000..f3298c149593
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/HttpBoot.c
@@ -0,0 +1,323 @@
+/*
+#  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;
+
+#if defined (MDE_CPU_AARCH64)
+  INT64 Offset = (INT64)&Ip4Nic->LoadFile;
+#else //if defined (MDE_CPU_ARM)
+  INT32 Offset = (INT32)&Ip4Nic->LoadFile;
+#endif
+  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) {
+      DEBUG((DEBUG_INFO, "IPv4 protocol found\n"));
+      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);
+  FileBuffer=NULL;
+
+  // 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);
+
+  if ( FixedPcdGetBool ( PcdDtbAvailable ) ) {
+  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/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c b/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c
new file mode 100644
index 000000000000..e590468b195d
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c
@@ -0,0 +1,345 @@
+#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));
+  ASSERT( NULL != Dest );
+  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 = Next = 0, Status=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;
+
+  //Initialize to NULL
+  for(OuterLoopIndex=0; OuterLoopIndex < MAX_VAR; OuterLoopIndex++) {
+      VarResult[OuterLoopIndex][0] = VarResult[OuterLoopIndex][1] = NULL;
+  }
+
+  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]);
+      //skip new line
+      Next += 2;
+    }
+  }
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+InitRdkVariables (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  UINTN         RdkSize;
+  UINT8         *RdkData;
+  CHAR16        *Result;
+  CONST CHAR16  *DevPath;
+  CONST CHAR16  *RdkFileName;
+
+  DevPath     = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileDevicePath);
+  RdkFileName = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileName);
+
+  Status = FindFileInDir(DevPath, RdkFileName, &Result);
+  if(EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "Failed to find file %s in %s\n", RdkFileName, DevPath));
+    return Status;
+  }
+
+  Status = RdkReadFile ((CONST CHAR16 *)Result, (VOID**) &RdkData, &RdkSize);
+  if(EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "Failed to read file %s\n", RdkFileName));
+    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;
+  }
+
+  //Initialize to NULL
+  *Value = NULL;
+
+  for(Count=0; Count<MAX_VAR; Count++) {
+    if(NULL != VarResult[Count][0] && 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;
+}
+
+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);
+
+    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;
+    }
+
+    if (FileSize != NULL) *FileSize  = BufferSize;
+
+    Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+    if (EFI_ERROR (Status) || BufferSize != SourceFileSize) {
+        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;
+}
diff --git a/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c b/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
new file mode 100644
index 000000000000..3d593361e6e8
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
@@ -0,0 +1,506 @@
+#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 )) {
+        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 =  DevicePathFromTextProtocol->ConvertTextToDevicePath(Path);
+    if(KeyFileDevicePath != NULL)
+    {
+        Status = OpenFileByDevicePath(&KeyFileDevicePath,FileHandle,OpenMode,0);
+        if(Status != EFI_SUCCESS)
+        {
+            DEBUG ((DEBUG_ERROR, "Getting FileHandle of %s Failed\n",Path));
+        }
+    }
+    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
+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;
+}
+
+STATIC
+VOID
+RdkSetVariable (
+    VOID
+)
+{
+    CONST CHAR16	*KeyPath = NULL;
+    EFI_STATUS  	Status;
+
+    Status = GetRdkVariable(L"ROOTCERT", &KeyPath);
+
+    //set only if the Kek Crt file mentioned in the configuration file
+    if ( NULL != KeyPath ) {
+        UINT8       *KekCrtData = NULL;
+        UINTN       KekCrtSize;
+
+        Status = RdkReadFile (
+                     KeyPath,
+                     (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);
+
+        if ( KekCrtData ) FreePool(KekCrtData);
+    }
+
+    Status = GetRdkVariable(L"KEKCERT", &KeyPath);
+    ASSERT_EFI_ERROR (Status);
+
+    UINT8 *KekKey = NULL;
+    UINTN KekKeySize = 0;
+    Status = RdkReadFile (
+                 KeyPath,
+                 (VOID **)&KekKey,
+                 &KekKeySize
+             );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = GetRdkVariable(L"PKCERT", &KeyPath);
+    ASSERT_EFI_ERROR (Status);
+
+    UINT8 *PkKey = NULL;
+    UINTN PkKeySize = 0;
+    Status = RdkReadFile (
+                 KeyPath,
+                 (VOID **)&PkKey,
+                 &PkKeySize
+             );
+    ASSERT_EFI_ERROR (Status);
+
+    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);
+    }
+
+    if ( PkKey ) FreePool(PkKey);
+    if ( KekKey ) FreePool(KekKey);
+}
+
+EFI_STATUS
+RdkSecureBoot (
+    EFI_HANDLE        ImageHandle,
+    EFI_BOOT_SERVICES *BootServices
+)
+{
+    UINTN                               ExitDataSize;
+    CHAR16                              *ExitData;
+    CHAR16                      	LoadOption[128];
+    CONST CHAR8		                *CmdLine;
+    CHAR16	                        *ImagePath;
+    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;
+    CmdLine	  = (CONST CHAR8 *)FixedPcdGetPtr (PcdRdkCmdLineArgs);
+
+    if ( FixedPcdGetBool ( PcdDtbAvailable ) ) {
+        UINT8        *FdtData = NULL;
+        CONST CHAR16 *DtbPath = NULL;
+
+        Status = GetRdkVariable(L"DTB", &DtbPath); 
+        ASSERT_EFI_ERROR (Status);
+
+        Status = RdkReadFile (DtbPath, (VOID**) &FdtData, NULL);
+        ASSERT_EFI_ERROR (Status);
+
+        Status = gBS->InstallConfigurationTable (&gFdtTableGuid,(VOID*)FdtData);
+        ASSERT_EFI_ERROR (Status);
+    }
+
+    RdkSetVariable();
+
+    Status = GetRdkVariable(L"IMAGE", (CONST CHAR16**)&ImagePath); 
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->LocateProtocol (
+                 &gEfiDevicePathFromTextProtocolGuid,
+                 NULL,
+                 (VOID**)&DevicePathFromTextProtocol
+             );
+    ASSERT_EFI_ERROR(Status);
+
+    FilePath  = DevicePathFromTextProtocol->ConvertTextToDevicePath(ImagePath);
+    ASSERT( NULL != FilePath);
+
+    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;
+}
