From: Jun Nie <jun.nie@linaro.org>
To: haojian.zhuang@linaro.org, leif.lindholm@linaro.org,
ard.biesheuvel@linaro.org, edk2-devel@lists.01.org,
linaro-uefi@lists.linaro.org
Cc: shawn.guo@linaro.org, jason.liu@linaro.org, Jun Nie <jun.nie@linaro.org>
Subject: [PATCH v2 1/2] EmbeddedPkg/AndroidBoot: boot android kernel from storage
Date: Thu, 6 Jul 2017 21:29:05 +0800 [thread overview]
Message-ID: <1499347746-16786-1-git-send-email-jun.nie@linaro.org> (raw)
Add an android kernel loader that could load kernel from storage
device. This patch is from Haojian's code. The minor change
is that alternative dtb is searched in second loader binary of
Android bootimage if dtb is not found after Linux kernel.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
.../Application/AndroidBoot/AndroidBootApp.c | 129 ++++++++
.../Application/AndroidBoot/AndroidBootApp.inf | 64 ++++
EmbeddedPkg/Include/Library/AbootimgLib.h | 65 ++++
EmbeddedPkg/Include/Protocol/Abootimg.h | 47 +++
EmbeddedPkg/Library/AbootimgLib/AbootimgLib.c | 350 +++++++++++++++++++++
EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf | 48 +++
6 files changed, 703 insertions(+)
create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c
create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf
create mode 100644 EmbeddedPkg/Include/Library/AbootimgLib.h
create mode 100644 EmbeddedPkg/Include/Protocol/Abootimg.h
create mode 100644 EmbeddedPkg/Library/AbootimgLib/AbootimgLib.c
create mode 100644 EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf
diff --git a/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c
new file mode 100644
index 0000000..9ed931b
--- /dev/null
+++ b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c
@@ -0,0 +1,129 @@
+/** @file
+
+ Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2017, Linaro. 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 <Library/AbootimgLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BdsLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePathFromText.h>
+
+#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
+
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+
+EFI_STATUS
+EFIAPI
+AndroidBootAppEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *BootPathStr;
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
+ EFI_DEVICE_PATH *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Node, *NextNode;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ UINT32 MediaId, BlockSize;
+ VOID *Buffer;
+ EFI_HANDLE Handle;
+ UINTN Size;
+
+ BootPathStr = (CHAR16 *)PcdGetPtr (PcdAndroidBootDevicePath);
+ ASSERT (BootPathStr != NULL);
+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
+ ASSERT_EFI_ERROR(Status);
+ DevicePath = (EFI_DEVICE_PATH *)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (BootPathStr);
+ ASSERT (DevicePath != NULL);
+
+ /* Find DevicePath node of Partition */
+ NextNode = DevicePath;
+ while (1) {
+ Node = NextNode;
+ if (IS_DEVICE_PATH_NODE (Node, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP)) {
+ break;
+ }
+ NextNode = NextDevicePathNode (Node);
+ }
+
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &Handle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Failed to get BlockIo: %r\n", Status));
+ return Status;
+ }
+
+ MediaId = BlockIo->Media->MediaId;
+ BlockSize = BlockIo->Media->BlockSize;
+ Buffer = AllocatePages (1);
+ if (Buffer == NULL) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ /* Load header of boot.img */
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ MediaId,
+ 0,
+ BlockSize,
+ Buffer
+ );
+ Status = AbootimgGetImgSize (Buffer, &Size);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Failed to get Abootimg Size: %r\n", Status));
+ return Status;
+ }
+ Size = ALIGN (Size, BlockSize);
+ FreePages (Buffer, 1);
+
+ /* Both PartitionStart and PartitionSize are counted as block size. */
+ Buffer = AllocatePages (EFI_SIZE_TO_PAGES (Size));
+ if (Buffer == NULL) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ /* Load header of boot.img */
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ MediaId,
+ 0,
+ Size,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Failed to read blocks: %r\n", Status));
+ goto EXIT;
+ }
+
+ Status = AbootimgBoot (Buffer, Size);
+
+EXIT:
+ return Status;
+}
diff --git a/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf
new file mode 100644
index 0000000..8f6c8186
--- /dev/null
+++ b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf
@@ -0,0 +1,64 @@
+#/** @file
+#
+# Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2017, Linaro. 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]
+ INF_VERSION = 0x00010019
+ BASE_NAME = AndroidBootApp
+ FILE_GUID = 3a738b36-b9c5-4763-abbd-6cbd4b25f9ff
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AndroidBootAppEntryPoint
+
+[Sources.common]
+ AndroidBootApp.c
+
+[LibraryClasses]
+ AbootimgLib
+ BaseLib
+ BaseMemoryLib
+ BdsLib
+ DebugLib
+ DevicePathLib
+ DxeServicesTableLib
+ FdtLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gAndroidFastbootPlatformProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiSimpleTextOutProtocolGuid
+ gEfiSimpleTextInProtocolGuid
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[Packages.ARM, Packages.AARCH64]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[Guids]
+ gFdtTableGuid
+
+[Pcd]
+ gEmbeddedTokenSpaceGuid.PcdAndroidBootDevicePath
diff --git a/EmbeddedPkg/Include/Library/AbootimgLib.h b/EmbeddedPkg/Include/Library/AbootimgLib.h
new file mode 100644
index 0000000..c0372d4
--- /dev/null
+++ b/EmbeddedPkg/Include/Library/AbootimgLib.h
@@ -0,0 +1,65 @@
+/** @file
+
+ Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2017, Linaro.
+
+ 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.
+
+**/
+
+#ifndef __ABOOTIMG_H__
+#define __ABOOTIMG_H__
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#define BOOTIMG_KERNEL_ARGS_SIZE 512
+
+#define BOOT_MAGIC "ANDROID!"
+#define BOOT_MAGIC_LENGTH (sizeof (BOOT_MAGIC) - 1)
+
+/* It's the value of arm64 efi stub kernel */
+#define KERNEL_IMAGE_STEXT_OFFSET 0x12C
+#define KERNEL_IMAGE_RAW_SIZE_OFFSET 0x130
+
+#define FDT_SIZE_OFFSET 0x4
+
+typedef struct {
+ CHAR8 BootMagic[BOOT_MAGIC_LENGTH];
+ UINT32 KernelSize;
+ UINT32 KernelAddress;
+ UINT32 RamdiskSize;
+ UINT32 RamdiskAddress;
+ UINT32 SecondStageBootloaderSize;
+ UINT32 SecondStageBootloaderAddress;
+ UINT32 KernelTaggsAddress;
+ UINT32 PageSize;
+ UINT32 Reserved[2];
+ CHAR8 ProductName[16];
+ CHAR8 KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE];
+ UINT32 Id[32];
+} ANDROID_BOOTIMG_HEADER;
+
+EFI_STATUS
+AbootimgGetImgSize (
+ IN VOID *BootImg,
+ OUT UINTN *ImgSize
+ );
+
+EFI_STATUS
+AbootimgBoot (
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+ );
+
+#endif /* __ABOOTIMG_H__ */
diff --git a/EmbeddedPkg/Include/Protocol/Abootimg.h b/EmbeddedPkg/Include/Protocol/Abootimg.h
new file mode 100644
index 0000000..c85dad2
--- /dev/null
+++ b/EmbeddedPkg/Include/Protocol/Abootimg.h
@@ -0,0 +1,47 @@
+/** @file
+
+ Copyright (c) 2017, Linaro. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+#ifndef __ABOOTIMG_PROTOCOL_H__
+#define __ABOOTIMG_PROTOCOL_H__
+
+//
+// Protocol interface structure
+//
+typedef struct _ABOOTIMG_PROTOCOL ABOOTIMG_PROTOCOL;
+
+//
+// Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *ABOOTIMG_APPEND_KERNEL_ARGS) (
+ IN CHAR16 *Args,
+ IN UINTN Size
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *ABOOTIMG_UPDATE_DTB) (
+ IN EFI_PHYSICAL_ADDRESS OrigDtbBase;
+ OUT EFI_PHYSICAL_ADDRESS *NewDtbBase;
+ );
+
+struct _ABOOTIMG_PROTOCOL {
+ ABOOTIMG_APPEND_KERNEL_ARGS AppendArgs;
+ ABOOTIMG_UPDATE_DTB UpdateDtb;
+};
+
+extern EFI_GUID gAbootimgProtocolGuid;
+
+#endif /* __ABOOTIMG_PROTOCOL_H__ */
diff --git a/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.c b/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.c
new file mode 100644
index 0000000..ea30a01
--- /dev/null
+++ b/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.c
@@ -0,0 +1,350 @@
+/** @file
+
+ Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2017, Linaro. 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 <Library/AbootimgLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/Abootimg.h>
+#include <Protocol/LoadedImage.h>
+
+#include <libfdt.h>
+
+// Check Val (unsigned) is a power of 2 (has only one bit set)
+#define IS_POWER_OF_2(Val) (Val != 0 && ((Val & (Val - 1)) == 0))
+
+typedef struct {
+ MEMMAP_DEVICE_PATH Node1;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} MEMORY_DEVICE_PATH;
+
+STATIC ABOOTIMG_PROTOCOL *mAbootimg;
+
+STATIC CONST MEMORY_DEVICE_PATH MemoryDevicePathTemplate =
+{
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ {
+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
+ (UINT8)((sizeof (MEMMAP_DEVICE_PATH)) >> 8),
+ },
+ }, // Header
+ 0, // StartingAddress (set at runtime)
+ 0 // EndingAddress (set at runtime)
+ }, // Node1
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ } // End
+};
+
+EFI_STATUS
+AbootimgGetImgSize (
+ IN VOID *BootImg,
+ OUT UINTN *ImgSize
+ )
+{
+ ANDROID_BOOTIMG_HEADER *Header;
+
+ Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
+
+ if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (IS_POWER_OF_2 (Header->PageSize));
+
+ /* Get real size of abootimg */
+ *ImgSize = ALIGN_VALUE (Header->KernelSize, Header->PageSize) +
+ ALIGN_VALUE (Header->RamdiskSize, Header->PageSize) +
+ ALIGN_VALUE (Header->SecondStageBootloaderSize, Header->PageSize) +
+ Header->PageSize;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AbootimgGetKernelInfo (
+ IN VOID *BootImg,
+ OUT VOID **Kernel,
+ OUT UINTN *KernelSize
+ )
+{
+ ANDROID_BOOTIMG_HEADER *Header;
+
+ Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
+
+ if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Header->KernelSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (IS_POWER_OF_2 (Header->PageSize));
+
+ *KernelSize = Header->KernelSize;
+ *Kernel = BootImg + Header->PageSize;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AbootimgGetRamdiskInfo (
+ IN VOID *BootImg,
+ OUT VOID **Ramdisk,
+ OUT UINTN *RamdiskSize
+ )
+{
+ ANDROID_BOOTIMG_HEADER *Header;
+ UINT8 *BootImgBytePtr;
+
+ // Cast to UINT8 so we can do pointer arithmetic
+ BootImgBytePtr = (UINT8 *) BootImg;
+
+ Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
+
+ if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (IS_POWER_OF_2 (Header->PageSize));
+
+ *RamdiskSize = Header->RamdiskSize;
+
+ if (Header->RamdiskSize != 0) {
+ *Ramdisk = (VOID *) (BootImgBytePtr
+ + Header->PageSize
+ + ALIGN_VALUE (Header->KernelSize, Header->PageSize));
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AbootimgGetSecondBootLoaderInfo (
+ IN VOID *BootImg,
+ OUT VOID **Second,
+ OUT UINTN *SecondSize
+ )
+{
+ ANDROID_BOOTIMG_HEADER *Header;
+ UINT8 *BootImgBytePtr;
+
+ // Cast to UINT8 so we can do pointer arithmetic
+ BootImgBytePtr = (UINT8 *) BootImg;
+
+ Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
+
+ if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (IS_POWER_OF_2 (Header->PageSize));
+
+ *SecondSize = Header->SecondStageBootloaderSize;
+
+ if (Header->SecondStageBootloaderSize != 0) {
+ *Second = (VOID *) (BootImgBytePtr
+ + Header->PageSize
+ + ALIGN_VALUE (Header->KernelSize, Header->PageSize)
+ + ALIGN_VALUE (Header->RamdiskSize, Header->PageSize));
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AbootimgGetKernelArgs (
+ IN VOID *BootImg,
+ OUT CHAR8 *KernelArgs
+ )
+{
+ ANDROID_BOOTIMG_HEADER *Header;
+
+ Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
+ AsciiStrnCpyS (KernelArgs, BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs,
+ BOOTIMG_KERNEL_ARGS_SIZE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AbootimgInstallFdt (
+ IN VOID *BootImg,
+ IN EFI_PHYSICAL_ADDRESS FdtBase,
+ OUT VOID *KernelArgs
+ )
+{
+ VOID *Ramdisk;
+ UINTN RamdiskSize;
+ CHAR8 ImgKernelArgs[BOOTIMG_KERNEL_ARGS_SIZE];
+ INTN err;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS NewFdtBase;
+
+ Status = gBS->LocateProtocol (&gAbootimgProtocolGuid, NULL, (VOID **) &mAbootimg);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AbootimgGetRamdiskInfo (
+ BootImg,
+ &Ramdisk,
+ &RamdiskSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = AbootimgGetKernelArgs (
+ BootImg,
+ ImgKernelArgs
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ // Get kernel arguments from Android boot image
+ AsciiStrToUnicodeStrS (ImgKernelArgs, KernelArgs, BOOTIMG_KERNEL_ARGS_SIZE >> 1);
+ // Set the ramdisk in command line arguments
+ UnicodeSPrint (
+ (CHAR16 *)KernelArgs + StrLen (KernelArgs), BOOTIMG_KERNEL_ARGS_SIZE,
+ L" initrd=0x%x,0x%x",
+ (UINTN)Ramdisk, (UINTN)RamdiskSize
+ );
+
+ // Append platform kernel arguments
+ Status = mAbootimg->AppendArgs (KernelArgs, BOOTIMG_KERNEL_ARGS_SIZE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = mAbootimg->UpdateDtb (FdtBase, &NewFdtBase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Sanity checks on the new FDT blob.
+ //
+ err = fdt_check_header ((VOID*)(UINTN)NewFdtBase);
+ if (err != 0) {
+ Print (L"ERROR: Device Tree header not valid (err:%d)\n", err);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->InstallConfigurationTable (
+ &gFdtTableGuid,
+ (VOID *)(UINTN)NewFdtBase
+ );
+ return Status;
+}
+
+EFI_STATUS
+AbootimgBoot (
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *Kernel;
+ UINTN KernelSize;
+ VOID *SecondLoader;
+ UINTN SecondLoaderSize;
+ MEMORY_DEVICE_PATH KernelDevicePath;
+ EFI_HANDLE ImageHandle;
+ EFI_PHYSICAL_ADDRESS FdtBase;
+ VOID *NewKernelArg;
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+ INTN Err;
+
+ Status = AbootimgGetKernelInfo (
+ Buffer,
+ &Kernel,
+ &KernelSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /* For flatten image, Fdt is attached at the end of kernel.
+ Get real kernel size.
+ */
+ KernelSize = *(UINT32 *)((EFI_PHYSICAL_ADDRESS)(UINTN)Kernel + KERNEL_IMAGE_STEXT_OFFSET) +
+ *(UINT32 *)((EFI_PHYSICAL_ADDRESS)(UINTN)Kernel + KERNEL_IMAGE_RAW_SIZE_OFFSET);
+
+ NewKernelArg = AllocateZeroPool (BOOTIMG_KERNEL_ARGS_SIZE);
+ if (NewKernelArg == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ /* FDT is at the end of kernel image */
+ FdtBase = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel + KernelSize;
+ //
+ // Sanity checks on the original FDT blob.
+ //
+ Err = fdt_check_header ((VOID*)(UINTN)FdtBase);
+ if (Err != 0) {
+ /* Check whether FDT is located in second boot loader */
+ Status = AbootimgGetSecondBootLoaderInfo (
+ Buffer,
+ &SecondLoader,
+ &SecondLoaderSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Err = fdt_check_header ((VOID*)(UINTN)SecondLoader);
+ if (Err != 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (Err:%d)\n", Err));
+ return EFI_INVALID_PARAMETER;
+ }
+ FdtBase = (EFI_PHYSICAL_ADDRESS)SecondLoader;
+ }
+
+ Status = AbootimgInstallFdt (Buffer, FdtBase, NewKernelArg);
+ if (EFI_ERROR (Status)) {
+ FreePool (NewKernelArg);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ KernelDevicePath = MemoryDevicePathTemplate;
+
+ // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to
+ // appease GCC.
+ KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel;
+ KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel + KernelSize;
+
+ Status = gBS->LoadImage (TRUE, gImageHandle, (EFI_DEVICE_PATH *)&KernelDevicePath, (VOID*)(UINTN)Kernel, KernelSize, &ImageHandle);
+
+ // Set kernel arguments
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+ ImageInfo->LoadOptions = NewKernelArg;
+ ImageInfo->LoadOptionsSize = StrLen (NewKernelArg) * sizeof (CHAR16);
+
+ // Before calling the image, enable the Watchdog Timer for the 5 Minute period
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+ // Start the image
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ // Clear the Watchdog Timer after the image returns
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+ return EFI_SUCCESS;
+}
diff --git a/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf b/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf
new file mode 100644
index 0000000..461dcb8
--- /dev/null
+++ b/EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf
@@ -0,0 +1,48 @@
+#/** @file
+#
+# Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2017, Linaro. 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]
+ INF_VERSION = 0x00010019
+ BASE_NAME = AbootimgLib
+ FILE_GUID = ed3b8739-6fa7-4cb1-8aeb-2496f8fcaefa
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = AbootimgLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ AbootimgLib.c
+
+[LibraryClasses]
+ DebugLib
+ FdtLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[Protocols]
+ gAbootimgProtocolGuid
+
+[Guids]
+ gFdtTableGuid
--
1.9.1
next reply other threads:[~2017-07-06 13:27 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-06 13:29 Jun Nie [this message]
2017-07-06 13:29 ` [PATCH v2 2/2] EmbeddedPkg: add Android boot device path and guid Jun Nie
2017-07-07 8:36 ` Jun Nie
2017-07-18 16:06 ` Leif Lindholm
2017-07-18 9:48 ` [PATCH v2 1/2] EmbeddedPkg/AndroidBoot: boot android kernel from storage Jun Nie
2017-07-18 16:04 ` Leif Lindholm
2017-07-19 10:00 ` Jun Nie
2017-07-19 21:57 ` Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1499347746-16786-1-git-send-email-jun.nie@linaro.org \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox