From nobody Mon Dec 23 18:02:44 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1515390356810318.3594464255152; Sun, 7 Jan 2018 21:45:56 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 15166222D155C; Sun, 7 Jan 2018 21:40:46 -0800 (PST) Received: from mail-pg0-x236.google.com (mail-pg0-x236.google.com [IPv6:2607:f8b0:400e:c05::236]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A3C4F21CB87BF for ; Sun, 7 Jan 2018 21:40:44 -0800 (PST) Received: by mail-pg0-x236.google.com with SMTP id c194so3912207pga.12 for ; Sun, 07 Jan 2018 21:45:54 -0800 (PST) Received: from localhost.localdomain ([220.225.120.129]) by smtp.gmail.com with ESMTPSA id f188sm4348648pfc.22.2018.01.07.21.45.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 07 Jan 2018 21:45:51 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c05::236; helo=mail-pg0-x236.google.com; envelope-from=kalyankumar.nagabhirava@linaro.org; receiver=edk2-devel@lists.01.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YmiCIjYiQs20/0EvfDk4sIM6Ks4tmngS0vH0kpCUe9Q=; b=Fx1uJOAvK6E2uqnpof12Xc42IuDgqTdCfHIIRfDDuEPE4W5HuhO1aUOy5bn9HIelZa 9Pp70OjX2qwE80STxQkisdfXV8AUyFg9B/y2yNJ/u4djHOvtLcFNpa7ldSXgAB3TVl13 nF4/UJHlDsvYaCb0UNcjgEis5peKREOp1Ob6Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YmiCIjYiQs20/0EvfDk4sIM6Ks4tmngS0vH0kpCUe9Q=; b=Vv2LWk96LXIr4h9eEYSEy6OlaLePV7edLi3TtL6RlqgVuxYdFtGtgPZ7H1BCH52o5/ jMvG6l/f98VEExK0P4gq8pKr8gnJzKyB3ju92Kplul066HNqrTjIGhAle43X+/bjbaCS GSn97ebxe12BU3xoy1/7c+bBHsn5sMnv2UXhAd30KfBhVMCgOOrNl1XMJHe0mua8U9qq Mtd18eI36a1M0Ojf98/1aTYv+xH/C0EEdGgYZLwfofahRjiQnx3SkdFic8sL3vZlYZUf cTpuRlDNOfh1eHjOBQuZD7gIaCVGJgrn/Jj61I4Jq2Tu3sHw81hMIPeqvtmx1f5aYYY6 85KA== X-Gm-Message-State: AKGB3mLN0yNdaJRoNztPf5E1xdf3Gv3CkfaXXwqpJ1gAxgbWa458xskK Y1YMIahkAInMmMgCbhAJba7EC0P0QUQ= X-Google-Smtp-Source: ACJfBosyZ3RWudRuIUvtQJb3ImKwUFA/pJjyU3pd8jFtnrnKq9flS+5hFXW12QHZe1Hp9DT4X2X4Qg== X-Received: by 10.84.224.78 with SMTP id a14mr2513548plt.362.1515390352775; Sun, 07 Jan 2018 21:45:52 -0800 (PST) From: kalyan-nagabhirava To: edk2-devel@lists.01.org Date: Mon, 8 Jan 2018 11:15:11 +0530 Message-Id: <20180108054513.2279-3-kalyankumar.nagabhirava@linaro.org> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20180108054513.2279-1-kalyankumar.nagabhirava@linaro.org> References: <20180108054513.2279-1-kalyankumar.nagabhirava@linaro.org> Subject: [edk2] [PATCH v1 2/4] edk2-platforms:comcast: RDK boot manger Library implementation X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Implemented features related to secure boot and DRI (downloading the image = and storing on flash), library has utility of file read and write operations for fat and raw fla= sh partition, it reads file path and load the file content using configuration file. Cc: Ard Biesheuvel Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: kalyan-nagabhirava --- Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.dec | = 50 ++ Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.inf | = 79 +++ Platform/Comcast/Library/RdkBootManagerLib/Include/DiskIo.h | = 20 + Platform/Comcast/Library/RdkBootManagerLib/Include/HttpBoot.h | = 7 + Platform/Comcast/Library/RdkBootManagerLib/Include/List.h | = 52 ++ Platform/Comcast/Library/RdkBootManagerLib/Include/RdkBootManagerLib.h | = 31 ++ Platform/Comcast/Library/RdkBootManagerLib/Include/RdkFile.h | = 20 + Platform/Comcast/Library/RdkBootManagerLib/Include/SecureBoot.h | = 40 ++ Platform/Comcast/Library/RdkBootManagerLib/DiskIo.c | 3= 58 ++++++++++++++ Platform/Comcast/Library/RdkBootManagerLib/HttpBoot.c | 3= 23 +++++++++++++ Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c | 3= 45 +++++++++++++ Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c | 5= 06 ++++++++++++++++++++ 12 files changed, 1831 insertions(+) diff --git a/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.d= ec 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 B= SD 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 IM= PLIED. +# + +[Defines] + DEC_SPECIFICATION =3D 0x00010019 + PACKAGE_NAME =3D RdkPkg + PACKAGE_GUID =3D 2f1f2d5e-d9e1-4aa1-8eb9-fed94682e140 + PACKAGE_VERSION =3D 0.1 + +##########################################################################= ###### +# +# Include Section - list of Include Paths that are provided by this packag= e. +# 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_D= RIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +##########################################################################= ###### +[Includes.common] + Include # Root include for the package + +[Guids.common] + gRdkTokenSpaceGuid =3D { 0x408c1892, 0xf11a, 0x40c7, { 0xaa,= 0x5f, 0x0d, 0x16, 0xc8, 0xb2, 0x52, 0x59 } } + gRdkGlobalVariableGuid =3D { 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*|0x= 00000100 + + # GUID of RdkDri + gRdkTokenSpaceGuid.PcdRdkDriFile|{ 0x8a, 0xa1, 0x1b, 0x08, 0x1e, 0xd7, 0= xa7, 0x40, 0x99, 0xa9, 0xcd, 0xb8, 0x64, 0x63, 0x96, 0x6d }|VOID*|0x00001000 + + # GUID of RdkDriSecureBootLoader + gRdkTokenSpaceGuid.PcdRdkDriSecureBootFile|{ 0xd7, 0xd1, 0x52, 0xdd, 0xe= 2, 0x0d, 0x52, 0x45, 0x98, 0xe0, 0x8d, 0xbe, 0xe4, 0x58, 0xa5, 0x02 }|VOID*= |0x00100000 diff --git a/Platform/Comcast/Library/RdkBootManagerLib/RdkBootManagerLib.i= nf 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 B= SD 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 IM= PLIED. +# + +##########################################################################= ###### +# +# Defines Section - statements that will be processed to create a Makefile. +# +##########################################################################= ###### + +[Defines] + INF_VERSION =3D 0x00010006 + BASE_NAME =3D RdkBootManagerLib + FILE_GUID =3D 901f54f2-9d70-9b89-9c0a-d9ca25379059 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D 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/Pl= atform/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 struc= ture + * @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 =3D (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 =3D LIST_ENTRY((Head)->ForwardLink, typeof(*Pos), Member); \ + &Pos->Member !=3D (Head); \ + Pos =3D 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 =3D LIST_ENTRY((Head)->ForwardLink, typeof(*Pos), Member), \ + N =3D LIST_ENTRY(Pos->Member.ForwardLink, typeof(*Pos), Member); \ + &Pos->Member !=3D (Head); \ + Pos =3D N, N =3D LIST_ENTRY(N->Member.ForwardLink, typeof(*N), Membe= r)) + +#endif /* __LIST_H__ */ diff --git a/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkBootMana= gerLib.h b/Platform/Comcast/Library/RdkBootManagerLib/Include/RdkBootManage= rLib.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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=3D1, + 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 + +/* 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) <=3D L'z' && (Char) >=3D L'a') || \ + ((Char) <=3D L'Z' && (Char) >=3D 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 =3D (DISKIO_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + NextEntry =3D (DISKIO_PARTITION_LIST *) GetNextNode (&mPartitionListHe= ad, &Entry->Link); + + RemoveEntryList (&Entry->Link); + FreePool (Entry); + + Entry =3D 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 =3D gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText + ); + ASSERT_EFI_ERROR (Status); + + // Get every Block IO protocol instance installed in the system + Status =3D 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 =3D 0; LoopIndex < NumHandles; LoopIndex++) { + // Get the device path for the handle + Status =3D gBS->OpenProtocol ( + AllHandles[LoopIndex], + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + DeviceFullPath =3D DevPathToText->ConvertDevicePathToText ( + DevicePath, + FALSE, + TRUE + ); + + DEBUG((DEBUG_INFO,"Handle[%d] is %p, fullpath %s\n", LoopIndex, AllH= andles[LoopIndex], DeviceFullPath)); + + if ( 0 =3D=3D StrCmp ( PartitionName, DeviceFullPath ) ) { + DEBUG((DEBUG_INFO, "rootfs partition path matched\n")); + // + // Add the partition handle to the list + // + // Create entry + Entry =3D AllocatePool (sizeof (DISKIO_PARTITION_LIST)); + if (Entry =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Exit; + } + + // Copy handle and partition name + Entry->PartitionHandle =3D 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 =3D ListBlockIos (UnicodePartitionName); + ASSERT_EFI_ERROR ( Status ); + + Entry =3D (DISKIO_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + ASSERT ( NULL !=3D Entry ); + + Status =3D 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 =3D EFI_NOT_FOUND; + goto exit; + } + + SparseHeader=3D(SPARSE_HEADER *)Image; + + if (SparseHeader->Magic =3D=3D SPARSE_HEADER_MAGIC) { + DEBUG ((DEBUG_INFO, "Sparse Magic: 0x%x Major: %d Minor: %d fhs: %d ch= s: %d bs: %d tbs: %d tcs: %d checksum: %d \n", + SparseHeader->Magic, SparseHeader->MajorVersion, SparseHeader->Minor= Version, SparseHeader->FileHeaderSize, + SparseHeader->ChunkHeaderSize, SparseHeader->BlockSize, SparseHeader= ->TotalBlocks, + SparseHeader->TotalChunks, SparseHeader->ImageChecksum)); + + if (SparseHeader->MajorVersion !=3D 1) { + DEBUG ((DEBUG_ERROR, "Sparse image version %d.%d not supported.\n", + SparseHeader->MajorVersion, SparseHeader->MinorVersion)); + Status =3D EFI_INVALID_PARAMETER; + goto exit; + } + + Size =3D SparseHeader->BlockSize * SparseHeader->TotalBlocks; + } + + // Check image will fit on device + PartitionSize =3D (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", Parti= tionSize, Size)); + + Status =3D EFI_VOLUME_FULL; + goto exit; + } + + Status =3D 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 =3D OpenPartition (PartitionName, Image, Size, &BlockIo, &DiskIo); + if (EFI_ERROR (Status)) { + goto exit; + } + + MediaId =3D BlockIo->Media->MediaId; + + Status =3D 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 =3D OpenPartition (PartitionName, Image, Size, &BlockIo, &DiskIo); + if (EFI_ERROR (Status)) { + goto exit; + } + + Offset =3D 0; + MediaId =3D BlockIo->Media->MediaId; + SparseHeader =3D (SPARSE_HEADER *)Image; + + if (SparseHeader->Magic =3D=3D SPARSE_HEADER_MAGIC) { + CHAR16 OutputString[64]; + UINTN ChunkPrintDensity =3D + SparseHeader->TotalChunks > 1600 ? SparseHeader->TotalChunks / 200 := 32; + + Image +=3D SparseHeader->FileHeaderSize; + for (Chunk =3D 0; Chunk < SparseHeader->TotalChunks; Chunk++) { + UINTN WriteSize; + ChunkHeader =3D (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 =3D=3D 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 O= ffset %d\n", + (Chunk+1), ChunkHeader->ChunkType, ChunkHeader->ChunkSize, + ChunkHeader->TotalSize, Offset)); + Image +=3D sizeof(CHUNK_HEADER); + WriteSize=3D(SparseHeader->BlockSize) * ChunkHeader->ChunkSize; + switch (ChunkHeader->ChunkType) { + case CHUNK_TYPE_RAW: + DEBUG ((DEBUG_INFO, "Writing %d at Offset %d\n", WriteSize, Offs= et)); + Status =3D DiskIo->WriteDisk (DiskIo, MediaId, Offset, WriteSize= , Image); + if (EFI_ERROR (Status)) { + goto exit; + } + Image+=3DWriteSize; + break; + case CHUNK_TYPE_DONT_CARE: + break; + case CHUNK_TYPE_CRC32: + break; + default: + DEBUG ((DEBUG_ERROR, "Unknown Chunk Type: 0x%x", ChunkHeader->Ch= unkType)); + Status =3D EFI_PROTOCOL_ERROR; + goto exit; + } + Offset +=3D WriteSize; + } + + UnicodeSPrint(OutputString, sizeof(OutputString), + L"\r%5d / %5d chunks written (100%%)\r\n", + SparseHeader->TotalChunks, SparseHeader->TotalChunks); + mTextOut->OutputString(mTextOut, OutputString); + + } else { + + Status =3D 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/Platfo= rm/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 B= SD 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 IM= PLIED. +# +*/ +#include + +STATIC EFI_LOAD_FILE_PROTOCOL *LoadFile =3D NULL; +STATIC HTTP_BOOT_PRIVATE_DATA *Private =3D NULL; + +STATIC +VOID +HttpPrivateFromLoadFile ( + IN EFI_LOAD_FILE_PROTOCOL *LoadFile, + OUT HTTP_BOOT_PRIVATE_DATA **Private + ) +{ + HTTP_BOOT_VIRTUAL_NIC *Ip4Nic =3D NULL; + +#if defined (MDE_CPU_AARCH64) + INT64 Offset =3D (INT64)&Ip4Nic->LoadFile; +#else //if defined (MDE_CPU_ARM) + INT32 Offset =3D (INT32)&Ip4Nic->LoadFile; +#endif + Ip4Nic =3D (VOID *)((char *)LoadFile - Offset); + ASSERT (Ip4Nic->Signature =3D=3D HTTP_BOOT_VIRTUAL_NIC_SIGNATURE); + *Private =3D 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 =3D gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText + ); + ASSERT_EFI_ERROR (Status); + + // Get every LoadFile protocol instance installed in the system + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NumHandles, + &AllHandles + ); + ASSERT_EFI_ERROR (Status); + + // Get HTTP driver handle from AllHandles + for (LoopIndex =3D 0; LoopIndex < NumHandles; LoopIndex++) { + + Handle =3D AllHandles[LoopIndex]; + + // Get the device path for the handle + Status =3D gBS->OpenProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + + DeviceFullPath =3D DevPathToText->ConvertDevicePathToText ( + DevicePath, + FALSE, + TRUE + ); + + ASSERT(DeviceFullPath !=3D NULL); + + if(StrStr(DeviceFullPath, L"IPv4") !=3D NULL) { + DEBUG((DEBUG_INFO, "IPv4 protocol found\n")); + Status =3D 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 =3D NULL; + TmpDevicePath =3D NULL; + Status =3D EFI_SUCCESS; + + // Convert the scheme to all lower case. + for (Index =3D 0; Index < StrLen (Uri); Index++) { + if (Uri[Index] =3D=3D L':') { + break; + } + if (Uri[Index] >=3D L'A' && Uri[Index] <=3D L'Z') { + Uri[Index] -=3D (CHAR16)(L'A' - L'a'); + } + } + + // Only accept empty URI, or http and https URI. + if ((StrLen (Uri) !=3D 0) && (StrnCmp (Uri, L"http://", 7) !=3D 0) && (S= trnCmp (Uri, L"https://", 8) !=3D 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 =3D AllocateZeroPool (sizeof (IPv4_DEVICE_PATH)); + if (Node =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Node->Ipv4.Header.Type =3D MESSAGING_DEVICE_PATH; + Node->Ipv4.Header.SubType =3D MSG_IPv4_DP; + SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); + TmpDevicePath =3D AppendDevicePathNode (Private->ParentDevicePath, (EFI_= DEVICE_PATH_PROTOCOL*) Node); + FreePool (Node); + if (TmpDevicePath =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Update the URI node with the input boot file URI. + UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri)); + Length =3D sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri); + Node =3D AllocatePool (Length); + if (Node =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + FreePool (TmpDevicePath); + goto ON_EXIT; + } + Node->DevPath.Type =3D MESSAGING_DEVICE_PATH; + Node->DevPath.SubType =3D MSG_URI_DP; + SetDevicePathNodeLength (Node, Length); + CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, As= ciiStrSize (AsciiUri)); + *NewDevicePath =3D AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH= _PROTOCOL*) Node); + FreePool (Node); + FreePool (TmpDevicePath); + if (*NewDevicePath =3D=3D NULL) { + Status =3D 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 =3D NULL; + NewDevicePath =3D NULL; + *FileSize =3D 0; + + // Get the LoadFile Handle and + // Private structure of HTTP driver + if (LoadFile =3D=3D NULL) { + HttpGetLoadFileHandle (&LoadFile); + HttpPrivateFromLoadFile (LoadFile, &Private); + } + + // Update URI path + Status =3D HttpUpdatePath (Uri, &NewDevicePath); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // Get the HTTP image from server + Status =3D LoadFile->LoadFile (LoadFile, NewDevicePath, TRUE, FileSize, = *FileBuffer); + if((Status !=3D EFI_WARN_FILE_SYSTEM) && (Status !=3D EFI_BUFFER_TOO_SMA= LL)) { + goto ON_EXIT; + } + + *FileBuffer =3D AllocatePool (*FileSize); + if (*FileBuffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status =3D LoadFile->LoadFile (LoadFile, NewDevicePath, TRUE, FileSize, = *FileBuffer); + if (EFI_ERROR (Status)) { + FreePool (FileBuffer); + goto ON_EXIT; + } + +ON_EXIT: + + if (NewDevicePath !=3D 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 =3D GetRdkVariable(L"URL", &ServerUrlPath);=20 + ASSERT_EFI_ERROR (Status); + + // Get the Server name stored in file Server.url + Status =3D RdkReadFile(ServerUrlPath, (VOID **)&FileBuffer, &FileSize); + ASSERT_EFI_ERROR (Status); + + Uri =3D AllocateZeroPool (sizeof(*Uri) * (FileSize+1)); + if (Uri =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR (Status); + } + + for(LoopIndex=3D0; LoopIndexSetWatchdogTimer (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 =3D HttpGetImage (Uri, &FileBuffer, &FileSize); + ASSERT_EFI_ERROR (Status); + + // Write the received image to flash + FilePtr =3D FileBuffer; + Size =3D Str2Int(FilePtr); + FilePtr +=3D FILE_HDR_SIZE; + Status =3D PartitionWrite((CHAR8 *) FixedPcdGetPtr (PcdRdkSystemParti= tionName), FilePtr, Size); + ASSERT_EFI_ERROR (Status); + + FilePtr +=3D Size; + Size =3D Str2Int(FilePtr); + FilePtr +=3D FILE_HDR_SIZE; + Status =3D GetRdkVariable(L"IMAGE", &ImagePath);=20 + ASSERT_EFI_ERROR (Status); + Status =3D RdkWriteFile(ImagePath, &FilePtr, &Size); + ASSERT_EFI_ERROR (Status); + + if ( FixedPcdGetBool ( PcdDtbAvailable ) ) { + FilePtr +=3D Size; + Size =3D Str2Int(FilePtr); + FilePtr +=3D FILE_HDR_SIZE; + Status =3D GetRdkVariable(L"DTB", &DtbPath);=20 + ASSERT_EFI_ERROR (Status); + Status =3D RdkWriteFile(DtbPath, &FilePtr, &Size); + ASSERT_EFI_ERROR (Status); + } + + FreePool (FileBuffer); + FreePool (Uri); + + return Status; +} diff --git a/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c b/Platfor= m/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 + +STATIC UINT8 VarablesInitialzed =3D 0; +STATIC CHAR16 *VarResult[MAX_VAR][2]; + +STATIC +VOID +SaveString ( + OUT CHAR16 **Dest, + IN CHAR16 *String1, + IN CHAR16 *String2 + ) +{ + *Dest =3D ALLOCATE_STRING_MEM(StrLen(String1) + StrLen(String2)); + ASSERT( NULL !=3D 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 =3D FALSE; + TempPath =3D ALLOCATE_STRING_MEM(StrLen(DirPath) + 1); + StrCat(TempPath, DirPath); + StrCat(TempPath, L"/"); + + Status =3D GetFileHandler(&FileHandle, DirPath, EFI_FILE_MODE_READ); + ASSERT_EFI_ERROR(Status); + + for ( Status =3D FileHandleFindFirstFile(FileHandle, &FileInfo) + ; !EFI_ERROR(Status) && !NoFile + ; Status =3D FileHandleFindNextFile(FileHandle, FileInfo, &NoFile) + ) { + if((FileInfo->Attribute & EFI_FILE_DIRECTORY) && + (StrCmp(FileInfo->FileName, L".") !=3D 0) && + (StrCmp(FileInfo->FileName, L"..") !=3D 0)) { + Node =3D AllocateZeroPool(sizeof (DIR_NODE)); + SaveString(&Node->Name, TempPath, FileInfo->FileName); + InsertHeadList(Head,&Node->List); + } + else if(StrCmp(FileInfo->FileName, TargetFile) =3D=3D 0) { + SaveString(Result, TempPath, FileInfo->FileName); + Status =3D EFI_SUCCESS; + goto ON_EXIT; + } + } + + Status =3D 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 =3D NULL; + EFI_STATUS Status =3D EFI_NOT_FOUND; + + InitializeListHead(&DirList[0]); + InitializeListHead(&DirList[1]); + + for (Current =3D Next =3D 0, Status=3DLsFiles(DevPath, TargetFile, Resul= t, &DirList[Current]); + !IsListEmpty(&DirList[Current]); + Current =3D Next) { + Next =3D Current ^ 1; + DelDirList(&DirList[Next]); + + LIST_FOR_EACH_ENTRY(Temp, &DirList[Current], List) { + Status =3D 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=3D0; String[Count] && !(String[Count] =3D=3D CharSet[0]); Coun= t++); + return Count; +} + +STATIC +CHAR16 * +Ascii2Uefi ( + IN CHAR8 *String + ) +{ + CHAR16 *Result; + UINTN Size; + + Size =3D AsciiStrLen(String); + Result =3D ALLOCATE_STRING_MEM(Size); + + while(Size--) { + Result[Size] =3D 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] =3D "=3D"; + VarDelimiter[1] =3D "\""; + Status =3D EFI_SUCCESS; + + //Initialize to NULL + for(OuterLoopIndex=3D0; OuterLoopIndex < MAX_VAR; OuterLoopIndex++) { + VarResult[OuterLoopIndex][0] =3D VarResult[OuterLoopIndex][1] =3D NU= LL; + } + + for(OuterLoopIndex=3D0, Next=3D0; OuterLoopIndex < MAX_VAR && Next < Fil= eSize; OuterLoopIndex++) { + for(InnerLoopIndex=3D0; InnerLoopIndex < 2; InnerLoopIndex++) { + Current =3D Next; + Next +=3D StrSpn(&FileData[Next], VarDelimiter[InnerLoopIndex]); + FileData[Next] =3D '\0'; + VarResult[OuterLoopIndex][InnerLoopIndex] =3D Ascii2Uefi(&FileData[C= urrent]); + //skip new line + Next +=3D 2; + } + } + + return Status; +} + +STATIC +EFI_STATUS +InitRdkVariables ( + VOID + ) +{ + EFI_STATUS Status; + UINTN RdkSize; + UINT8 *RdkData; + CHAR16 *Result; + CONST CHAR16 *DevPath; + CONST CHAR16 *RdkFileName; + + DevPath =3D (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileDevicePath= ); + RdkFileName =3D (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileName); + + Status =3D FindFileInDir(DevPath, RdkFileName, &Result); + if(EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Failed to find file %s in %s\n", RdkFileName, Dev= Path)); + return Status; + } + + Status =3D RdkReadFile ((CONST CHAR16 *)Result, (VOID**) &RdkData, &RdkS= ize); + if(EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Failed to read file %s\n", RdkFileName)); + return Status; + } + + Status =3D 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 =3D InitRdkVariables(); + if(EFI_ERROR(Status)) { + return Status; + } + + VarablesInitialzed =3D 1; + } + + //Initialize to NULL + *Value =3D NULL; + + for(Count=3D0; CountSetPosition (FileHandle, (UINT64) -1); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status =3D FileHandle->GetPosition (FileHandle, &SourceFileSize); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status =3D FileHandle->SetPosition (FileHandle, 0); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + BufferSize =3D (UINTN) SourceFileSize; + Buffer =3D AllocateZeroPool(BufferSize); + if (Buffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (FileSize !=3D NULL) *FileSize =3D BufferSize; + + Status =3D FileHandle->Read (FileHandle, &BufferSize, Buffer); + if (EFI_ERROR (Status) || BufferSize !=3D SourceFileSize) { + FreePool (Buffer); + Buffer =3D NULL; + Status =3D EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; + } + +ON_EXIT: + + *BufferPtr =3D 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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D GetFileHandler(&FileHandle, Path, EFI_FILE_MODE_READ|EFI_FI= LE_MODE_WRITE|EFI_FILE_MODE_CREATE); + ASSERT_EFI_ERROR(Status); + + Status =3D FileHandle->Write (FileHandle, FileSize, *BufferPtr); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c b/Plat= form/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 + +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 =3D=3D NULL )) { + return EFI_INVALID_PARAMETER; + } + + Status =3D gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + FilePath, + &DeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->OpenProtocol( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&EfiSimpleFileSystemProtocol, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystem= Protocol, &Handle1); + if (EFI_ERROR (Status)) { + FileHandle =3D 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) !=3D MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) !=3D MEDIA_FILEPATH_DP + ) { + FileHandle =3D NULL; + return (EFI_INVALID_PARAMETER); + } + // + // Open this file path node + // + Handle2 =3D Handle1; + Handle1 =3D NULL; + + // + // Try to test opening an existing file + // + Status =3D 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 !=3D (OpenMode &~EFI_FILE_MO= DE_CREATE))) { + Status =3D 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 =3D NextDevicePathNode (*FilePath); + } + + // + // This is a weak spot since if the undefined SHELL_FILE_HANDLE format= changes this must change also! + // + *FileHandle =3D (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 =3D EFI_SUCCESS; + KeyFileDevicePath =3D NULL; + + Status =3D gBS->LocateProtocol ( + &gEfiDevicePathFromTextProtocolGuid, + NULL, + (VOID**)&DevicePathFromTextProtocol + ); + ASSERT_EFI_ERROR(Status); + + KeyFileDevicePath =3D DevicePathFromTextProtocol->ConvertTextToDevice= Path(Path); + if(KeyFileDevicePath !=3D NULL) + { + Status =3D OpenFileByDevicePath(&KeyFileDevicePath,FileHandle,Open= Mode,0); + if(Status !=3D EFI_SUCCESS) + { + DEBUG ((DEBUG_ERROR, "Getting FileHandle of %s Failed\n",Path)= ); + } + } + return Status; +} + +UINTN +Str2Int ( + VOID * Str +) +{ + UINTN i, Size; + UINT8 *Ptr =3D Str; + + for(i=3D0, Size=3D0; iGetTime (&Time, NULL); + if (EFI_ERROR (Status)) { + FreePool(NewData); + return Status; + } + Time.Pad1 =3D 0; + Time.Nanosecond =3D 0; + Time.TimeZone =3D 0; + Time.Daylight =3D 0; + Time.Pad2 =3D 0; + CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); + + DescriptorData->AuthInfo.Hdr.dwLength =3D OFFSET_OF (WIN_CERTI= FICATE_UEFI_GUID, CertData); + DescriptorData->AuthInfo.Hdr.wRevision =3D 0x0200; + DescriptorData->AuthInfo.Hdr.wCertificateType =3D WIN_CERT_TYPE_EFI_GU= ID; + CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); + + if (Payload !=3D NULL) { + FreePool(Payload); + } + + *DataSize =3D DescriptorSize + PayloadSize; + *Data =3D 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=3DEFI_SUCCESS ; + Attr =3D EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUT= HENTICATED_WRITE_ACCESS; + if(KeyType =3D=3D PK_KEY) + { + DEBUG ((DEBUG_INFO, "Setting PK Key\n")); + Status =3D gRT->SetVariable ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, + PkCert + ); + } + else if( KeyType =3D=3D KEK_KEY) + { + DEBUG ((DEBUG_INFO, "Setting KEK Key\n")); + Status =3D gRT->SetVariable ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, + PkCert + ); + + Status =3D 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 =3D NULL; + + if( (*Cert) =3D=3D NULL) + { + (*Cert) =3D (EFI_SIGNATURE_LIST*) AllocateZeroPool ( sizeof(EFI_SI= GNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + DataSize ); + + ASSERT ((*Cert) !=3D NULL); + } + (*Cert)->SignatureListSize =3D (UINT32) (sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + DataSize); + (*Cert)->SignatureSize =3D (UINT32) (sizeof(EFI_SIGNATURE_DATA) = - 1 + DataSize); + (*Cert)->SignatureHeaderSize =3D 0; + CopyGuid (&(*Cert)->SignatureType, &gEfiCertX509Guid); + + + CertData =3D (EFI_SIGNATURE_DATA*) ((UINTN)(*Cert) + sizeof(EFI_SIGNAT= URE_LIST) + (*Cert)->SignatureHeaderSize); + ASSERT (CertData !=3D 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 =3D NULL; + + Status =3D SetBootMode(CUSTOM_SECURE_BOOT_MODE); + ASSERT_EFI_ERROR (Status); + + PopulateCert(&Cert, KeySize, KeyData); + + KeySize =3D Cert->SignatureListSize; + + Status =3D CreateTimeBasedPayload (&KeySize, (UINT8**) &Cert); + ASSERT_EFI_ERROR (Status); + + Status =3D SetVariable(Cert,KeySize,KeyType); + return Status; +} + +STATIC +VOID +RdkSetVariable ( + VOID +) +{ + CONST CHAR16 *KeyPath =3D NULL; + EFI_STATUS Status; + + Status =3D GetRdkVariable(L"ROOTCERT", &KeyPath); + + //set only if the Kek Crt file mentioned in the configuration file + if ( NULL !=3D KeyPath ) { + UINT8 *KekCrtData =3D NULL; + UINTN KekCrtSize; + + Status =3D RdkReadFile ( + KeyPath, + (VOID **)&KekCrtData, + &KekCrtSize + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gRT->SetVariable ( + L"RdkRootCertificate", + &gRdkGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIM= E_ACCESS, + KekCrtSize, + KekCrtData + ); + ASSERT_EFI_ERROR(Status); + + if ( KekCrtData ) FreePool(KekCrtData); + } + + Status =3D GetRdkVariable(L"KEKCERT", &KeyPath); + ASSERT_EFI_ERROR (Status); + + UINT8 *KekKey =3D NULL; + UINTN KekKeySize =3D 0; + Status =3D RdkReadFile ( + KeyPath, + (VOID **)&KekKey, + &KekKeySize + ); + ASSERT_EFI_ERROR (Status); + + Status =3D GetRdkVariable(L"PKCERT", &KeyPath); + ASSERT_EFI_ERROR (Status); + + UINT8 *PkKey =3D NULL; + UINTN PkKeySize =3D 0; + Status =3D RdkReadFile ( + KeyPath, + (VOID **)&PkKey, + &PkKeySize + ); + ASSERT_EFI_ERROR (Status); + + INT8* SetupMode =3D NULL; + eKey KeyType; + KeyType =3D PK_KEY; + Status =3D RegisterCert(PkKey,PkKeySize,KeyType); + GetEfiGlobalVariable2 (L"SetupMode", (VOID**)&SetupMode, NULL); + + if (*SetupMode =3D=3D 0) + { + DEBUG ((DEBUG_INFO, "PK Key Got Registered. Now System in User Mod= e\n")); + KeyType =3D KEK_KEY; + Status =3D RegisterCert(KekKey,KekKeySize,KeyType); + } + else if(*SetupMode =3D=3D 1) + { + DEBUG ((DEBUG_INFO, "System in Standard System Mode ::: Secure Boo= t 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 =3D NULL; + ExitData =3D NULL; + CmdLine =3D (CONST CHAR8 *)FixedPcdGetPtr (PcdRdkCmdLineArgs); + + if ( FixedPcdGetBool ( PcdDtbAvailable ) ) { + UINT8 *FdtData =3D NULL; + CONST CHAR16 *DtbPath =3D NULL; + + Status =3D GetRdkVariable(L"DTB", &DtbPath);=20 + ASSERT_EFI_ERROR (Status); + + Status =3D RdkReadFile (DtbPath, (VOID**) &FdtData, NULL); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->InstallConfigurationTable (&gFdtTableGuid,(VOID*)F= dtData); + ASSERT_EFI_ERROR (Status); + } + + RdkSetVariable(); + + Status =3D GetRdkVariable(L"IMAGE", (CONST CHAR16**)&ImagePath);=20 + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol ( + &gEfiDevicePathFromTextProtocolGuid, + NULL, + (VOID**)&DevicePathFromTextProtocol + ); + ASSERT_EFI_ERROR(Status); + + FilePath =3D DevicePathFromTextProtocol->ConvertTextToDevicePath(Imag= ePath); + ASSERT( NULL !=3D FilePath); + + Status =3D BootServices->LoadImage ( + TRUE, + ImageHandle, + FilePath, + NULL, + 0, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + UnicodeSPrintAsciiFormat (LoadOption, sizeof(LoadOption), CmdLine); + + Status =3D BootServices->HandleProtocol (Handle, &gEfiLoadedImageProto= colGuid, (VOID **) &ImageInfo); + ASSERT_EFI_ERROR (Status); + ImageInfo->LoadOptionsSize =3D sizeof(LoadOption); + ImageInfo->LoadOptions =3D LoadOption; + + Status =3D BootServices->StartImage (Handle, &ExitDataSize, &ExitData); + ASSERT_EFI_ERROR (Status); + + return Status; +} --=20 2.15.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel