new file mode 100644
@@ -0,0 +1,26 @@
+/*
+# 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>
+
+EFI_STATUS
+EFIAPI
+DriEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RdkHttpBoot ();
+ return Status;
+}
new file mode 100644
@@ -0,0 +1,56 @@
+#
+# 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 = RdkDriLoader
+ FILE_GUID = 081ba18a-d71e-40a7-99a9-cdb86463966d
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DriEntryPoint
+
+[Sources]
+ Dri.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
+
+[LibraryClasses]
+ RdkBootManagerLib
+ UefiApplicationEntryPoint
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
new file mode 100644
@@ -0,0 +1,32 @@
+/*
+# 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>
+
+EFI_STATUS
+EFIAPI
+DriSecureBootEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RdkHttpBoot ();
+
+ Status = RdkSecureBoot(
+ ImageHandle,
+ SystemTable->BootServices
+ );
+
+ return Status;
+}
new file mode 100644
@@ -0,0 +1,57 @@
+#
+# 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 = RdkDriSecureLoader
+ FILE_GUID = dd52d1d7-0de2-4552-98e0-8dbee458a502
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DriSecureBootEntryPoint
+
+[Sources]
+ DriSecureBoot.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
+
+[LibraryClasses]
+ RdkBootManagerLib
+ UefiApplicationEntryPoint
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
new file mode 100644
@@ -0,0 +1,30 @@
+/*
+# 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>
+
+EFI_STATUS
+EFIAPI
+SecureBootEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RdkSecureBoot (
+ ImageHandle,
+ SystemTable->BootServices
+ );
+
+ return Status;
+}
new file mode 100644
@@ -0,0 +1,57 @@
+#
+# 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 = RdkSecureLoader
+ FILE_GUID = b2c7930f-07ef-4305-ac4e-1ce2085a7031
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SecureBootEntryPoint
+
+[Sources]
+ SecureBoot.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
+
+[LibraryClasses]
+ RdkBootManagerLib
+ UefiApplicationEntryPoint
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
new file mode 100644
@@ -0,0 +1,97 @@
+/*
+# 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 "RdkDxe.h"
+
+STATIC
+VOID
+PlatformRegisterFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+ INTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ ASSERT (DevicePath != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ Attributes,
+ Description,
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount, LoadOptionTypeBoot
+ );
+
+ OptionIndex = EfiBootManagerFindLoadOption (
+ &NewOption, BootOptions, BootOptionCount
+ );
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+ ASSERT_EFI_ERROR (Status);
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+EFI_STATUS
+EFIAPI
+RdkDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ PlatformRegisterFvBootOption (
+ PcdGetPtr (PcdRdkSecureBootFile), L"Rdk Secure Boot", LOAD_OPTION_ACTIVE
+ );
+
+ PlatformRegisterFvBootOption (
+ PcdGetPtr (PcdRdkDriFile), L"Rdk Dri", LOAD_OPTION_ACTIVE
+ );
+
+ PlatformRegisterFvBootOption (
+ PcdGetPtr (PcdRdkDriSecureBootFile), L"Rdk Secure Dri Boot", LOAD_OPTION_ACTIVE
+ );
+
+ return EFI_SUCCESS;
+}
new file mode 100644
@@ -0,0 +1,14 @@
+#ifndef __RDK_DRIVER_H__
+#define __RDK_DRIVER_H__
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#endif /* __RDK_DRIVER_H__ */
new file mode 100644
@@ -0,0 +1,45 @@
+#
+# 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 = RDKDriver
+ FILE_GUID = 305da1a1-cd7d-4d61-bf83-8e79a7839a33
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 0.1
+ ENTRY_POINT = RdkDriverEntryPoint
+
+[Sources]
+ RdkDxe.c
+ RdkDxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec
+
+[LibraryClasses]
+ UefiBootManagerLib
+ UefiDriverEntryPoint
+
+[FixedPcd]
+ gRdkTokenSpaceGuid.PcdRdkDriFile
+ gRdkTokenSpaceGuid.PcdRdkSecureBootFile
+ gRdkTokenSpaceGuid.PcdRdkDriSecureBootFile
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -0,0 +1,7 @@
+#ifndef _RDK_HTTP_BOOT_H_
+#define _RDK_HTTP_BOOT_H_
+
+extern EFI_STATUS
+RdkHttpBoot ( VOID );
+
+#endif /* _RDK_HTTP_BOOT_H_ */
new file mode 100644
@@ -0,0 +1,136 @@
+#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) );})
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+typedef struct ListHead {
+ struct ListHead *Next, *Prev;
+} LIST_HEAD;
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+static inline void INIT_LIST_HEAD(LIST_HEAD *List)
+{
+ List->Next = List;
+ List->Prev = List;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __ListAdd(LIST_HEAD *New,
+ LIST_HEAD *Prev,
+ LIST_HEAD *Next)
+{
+ Next->Prev = New;
+ New->Next = Next;
+ New->Prev = Prev;
+ Prev->Next = New;
+}
+
+/**
+ * ListAdd - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void ListAdd(LIST_HEAD *New, LIST_HEAD *Head)
+{
+ __ListAdd(New, Head, Head->Next);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __ListDel(LIST_HEAD *Prev, LIST_HEAD *Next)
+{
+ Next->Prev = Prev;
+ Prev->Next = Next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void ListDel(LIST_HEAD *Entry)
+{
+ __ListDel(Entry->Prev, Entry->Next);
+ Entry->Next = NULL;
+ Entry->Prev = NULL;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int ListEmpty(const LIST_HEAD *Head)
+{
+ return Head->Next == Head;
+}
+
+/**
+ * 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)->Next, typeof(*Pos), Member); \
+ &Pos->Member != (Head); \
+ Pos = LIST_ENTRY(Pos->Member.Next, 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)->Next, typeof(*Pos), Member), \
+ N = LIST_ENTRY(Pos->Member.Next, typeof(*Pos), Member); \
+ &Pos->Member != (Head); \
+ Pos = N, N = LIST_ENTRY(N->Member.Next, typeof(*N), Member))
+
+#endif /* __LIST_H__ */
new file mode 100644
@@ -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__ */
new file mode 100644
@@ -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_HEAD List;
+} DIR_NODE;
+
+extern EFI_STATUS
+GetRdkVariable (
+ IN CONST CHAR16 *Name,
+ OUT CONST CHAR16 **Value
+ );
+
+#endif /* __RDK_FILE_H__ */
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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_HEAD *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);
+ ListAdd(&Node->List, Head);
+ }
+ 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_HEAD *Head
+ )
+{
+ DIR_NODE *Node;
+ DIR_NODE *Temp;
+
+ LIST_FOR_EACH_ENTRY_SAFE (Node, Temp, Head, List) {
+ ListDel(&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_HEAD DirList[2];
+
+ *Result = NULL;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+
+ INIT_LIST_HEAD(&DirList[0]);
+ INIT_LIST_HEAD(&DirList[1]);
+
+ for (Current = 0, LsFiles(DevPath, TargetFile, Result, &DirList[Current]);
+ !ListEmpty(&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;
+}
new file mode 100644
@@ -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;
+}
Linaro and RDK are working on standardizing the boot process for RDK STB boxes using Uefi. Added applications are reference implementation of RDK STB boot process on Arm platforms Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: kalyan-nagabhirava <kalyankumar.nagabhirava@linaro.org> --- EmbeddedPkg/Application/Dri/Dri.c | 26 + EmbeddedPkg/Application/Dri/Dri.inf | 56 ++ .../Application/DriSecureBoot/DriSecureBoot.c | 32 ++ .../Application/DriSecureBoot/DriSecureBoot.inf | 57 ++ EmbeddedPkg/Application/SecureBoot/SecureBoot.c | 30 ++ EmbeddedPkg/Application/SecureBoot/SecureBoot.inf | 57 ++ EmbeddedPkg/Drivers/RdkDxe/RdkDxe.c | 97 ++++ EmbeddedPkg/Drivers/RdkDxe/RdkDxe.h | 14 + EmbeddedPkg/Drivers/RdkDxe/RdkDxe.inf | 45 ++ EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c | 536 +++++++++++++++++++ EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c | 315 +++++++++++ .../Library/RdkBootManagerLib/Include/DiskIo.h | 20 + .../Library/RdkBootManagerLib/Include/HttpBoot.h | 7 + .../Library/RdkBootManagerLib/Include/List.h | 136 +++++ .../RdkBootManagerLib/Include/RdkBootManagerLib.h | 31 ++ .../Library/RdkBootManagerLib/Include/RdkFile.h | 20 + .../Library/RdkBootManagerLib/Include/SecureBoot.h | 40 ++ .../RdkBootManagerLib/RdkBootManagerLib.dec | 52 ++ .../RdkBootManagerLib/RdkBootManagerLib.inf | 81 +++ EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c | 259 +++++++++ EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c | 577 +++++++++++++++++++++ 21 files changed, 2488 insertions(+) create mode 100644 EmbeddedPkg/Application/Dri/Dri.c create mode 100644 EmbeddedPkg/Application/Dri/Dri.inf create mode 100644 EmbeddedPkg/Application/DriSecureBoot/DriSecureBoot.c create mode 100644 EmbeddedPkg/Application/DriSecureBoot/DriSecureBoot.inf create mode 100644 EmbeddedPkg/Application/SecureBoot/SecureBoot.c create mode 100644 EmbeddedPkg/Application/SecureBoot/SecureBoot.inf create mode 100644 EmbeddedPkg/Drivers/RdkDxe/RdkDxe.c create mode 100644 EmbeddedPkg/Drivers/RdkDxe/RdkDxe.h create mode 100644 EmbeddedPkg/Drivers/RdkDxe/RdkDxe.inf create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/DiskIo.c create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/HttpBoot.c create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/DiskIo.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/HttpBoot.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/List.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/RdkFile.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/Include/SecureBoot.h create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.dec create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/RdkBootManagerLib.inf create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/RdkFile.c create mode 100644 EmbeddedPkg/Library/RdkBootManagerLib/SecureBoot.c -- 2.15.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel