Split android boot header definition to share code among different applications and libraries.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jun Nie jun.nie@linaro.org --- .../Application/AndroidFastboot/AndroidBootImg.c | 35 ++----------- .../AndroidFastboot/AndroidFastbootApp.h | 1 + .../AndroidFastboot/Arm/BootAndroidBootImg.c | 2 +- EmbeddedPkg/Include/Library/AndroidBootImgLib.h | 58 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 EmbeddedPkg/Include/Library/AndroidBootImgLib.h
diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c index f3e770b..2f7f093 100644 --- a/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c +++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c @@ -14,32 +14,6 @@
#include "AndroidFastbootApp.h"
-#define BOOT_MAGIC "ANDROID!" -#define BOOT_MAGIC_LENGTH sizeof (BOOT_MAGIC) - 1 - -// 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)) - -// No documentation for this really - sizes of fields has been determined -// empirically. -#pragma pack(1) -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; -#pragma pack() - // Find the kernel and ramdisk in an Android boot.img. // return EFI_INVALID_PARAMTER if the boot.img is invalid (i.e. doesn't have the // right magic value), @@ -64,7 +38,8 @@ ParseAndroidBootImg (
Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
- if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) { + if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC, + ANDROID_BOOT_MAGIC_LENGTH) != 0) { return EFI_INVALID_PARAMETER; }
@@ -72,7 +47,7 @@ ParseAndroidBootImg ( return EFI_NOT_FOUND; }
- ASSERT (IS_POWER_OF_2 (Header->PageSize)); + ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));
*KernelSize = Header->KernelSize; *Kernel = BootImgBytePtr + Header->PageSize; @@ -84,8 +59,8 @@ ParseAndroidBootImg ( + ALIGN_VALUE (Header->KernelSize, Header->PageSize)); }
- AsciiStrnCpyS (KernelArgs, BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs, - BOOTIMG_KERNEL_ARGS_SIZE); + AsciiStrnCpyS (KernelArgs, ANDROID_BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs, + ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);
return EFI_SUCCESS; } diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h index f62660f..e4c5aa3 100644 --- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h +++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h @@ -15,6 +15,7 @@ #ifndef __ANDROID_FASTBOOT_APP_H__ #define __ANDROID_FASTBOOT_APP_H__
+#include <Library/AndroidBootImgLib.h> #include <Library/BaseLib.h> #include <Library/DebugLib.h> #include <Library/MemoryAllocationLib.h> diff --git a/EmbeddedPkg/Application/AndroidFastboot/Arm/BootAndroidBootImg.c b/EmbeddedPkg/Application/AndroidFastboot/Arm/BootAndroidBootImg.c index f446cce..1d9024b 100644 --- a/EmbeddedPkg/Application/AndroidFastboot/Arm/BootAndroidBootImg.c +++ b/EmbeddedPkg/Application/AndroidFastboot/Arm/BootAndroidBootImg.c @@ -112,7 +112,7 @@ BootAndroidBootImg ( ) { EFI_STATUS Status; - CHAR8 KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE]; + CHAR8 KernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE]; VOID *Kernel; UINTN KernelSize; VOID *Ramdisk; diff --git a/EmbeddedPkg/Include/Library/AndroidBootImgLib.h b/EmbeddedPkg/Include/Library/AndroidBootImgLib.h new file mode 100644 index 0000000..06da751 --- /dev/null +++ b/EmbeddedPkg/Include/Library/AndroidBootImgLib.h @@ -0,0 +1,58 @@ +/** @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 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE 512 + +#define ANDROID_BOOT_MAGIC "ANDROID!" +#define ANDROID_BOOT_MAGIC_LENGTH (sizeof (ANDROID_BOOT_MAGIC) - 1) + +// No documentation for this really - sizes of fields has been determined +// empirically. +#pragma pack(1) +/* https://android.googlesource.com/platform/system/core/+/master/mkbootimg/boo... */ +typedef struct { + UINT8 BootMagic[ANDROID_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[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE]; + UINT32 Id[32]; +} ANDROID_BOOTIMG_HEADER; +#pragma pack () + +/* 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)) +/* Android boot image page size is not specified, but it should be power of 2 + * and larger than boot header */ +#define IS_VALID_ANDROID_PAGE_SIZE(Val) \ + (IS_POWER_OF_2(Val) && (Val > sizeof(ANDROID_BOOTIMG_HEADER))) +#endif /* __ABOOTIMG_H__ */
Add an android kernel loader that could load kernel from storage device. This android boot image BDS add addtitional cmdline/dtb/ramfs support besides kernel that is introduced by Android boot header.
This patch is derived from Haojian's code as below link. https://patches.linaro.org/patch/94683/
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jun Nie jun.nie@linaro.org --- .../Application/AndroidBoot/AndroidBootApp.c | 140 ++++++ .../Application/AndroidBoot/AndroidBootApp.inf | 64 +++ EmbeddedPkg/EmbeddedPkg.dec | 2 + EmbeddedPkg/EmbeddedPkg.dsc | 2 + EmbeddedPkg/Include/Library/AndroidBootImgLib.h | 13 + EmbeddedPkg/Include/Protocol/AndroidBootImg.h | 47 ++ .../Library/AndroidBootImgLib/AndroidBootImgLib.c | 471 +++++++++++++++++++++ .../AndroidBootImgLib/AndroidBootImgLib.inf | 48 +++ 8 files changed, 787 insertions(+) create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf create mode 100644 EmbeddedPkg/Include/Protocol/AndroidBootImg.h create mode 100644 EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c create mode 100644 EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf
diff --git a/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c new file mode 100644 index 0000000..977167d --- /dev/null +++ b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c @@ -0,0 +1,140 @@ +/** @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/AndroidBootImgLib.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> + +/* Validate the node is media hard drive type */ +EFI_STATUS +ValidateAndroidMediaDevicePath ( + IN EFI_DEVICE_PATH *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node, *NextNode; + + NextNode = DevicePath; + while (NextNode != NULL) { + Node = NextNode; + if (IS_DEVICE_PATH_NODE (Node, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP)) { + return EFI_SUCCESS; + } + NextNode = NextDevicePathNode (Node); + } + return EFI_INVALID_PARAMETER; +} + +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_BLOCK_IO_PROTOCOL *BlockIo; + UINT32 MediaId, BlockSize; + VOID *Buffer; + EFI_HANDLE Handle; + UINTN BootImgSize; + + 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); + + Status = ValidateAndroidMediaDevicePath (DevicePath); + if (EFI_ERROR (Status)) { + return Status; + } + + 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 ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status)); + return Status; + } + + MediaId = BlockIo->Media->MediaId; + BlockSize = BlockIo->Media->BlockSize; + Buffer = AllocatePages (EFI_SIZE_TO_PAGES (sizeof(ANDROID_BOOTIMG_HEADER))); + if (Buffer == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + /* Load header of boot.img */ + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + 0, + BlockSize, + Buffer + ); + Status = AndroidBootImgGetImgSize (Buffer, &BootImgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get AndroidBootImg Size: %r\n", Status)); + return Status; + } + BootImgSize = ALIGN_VALUE (BootImgSize, BlockSize); + FreePages (Buffer, EFI_SIZE_TO_PAGES (sizeof(ANDROID_BOOTIMG_HEADER))); + + /* Both PartitionStart and PartitionSize are counted as block size. */ + Buffer = AllocatePages (EFI_SIZE_TO_PAGES (BootImgSize)); + if (Buffer == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + /* Load header of boot.img */ + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + 0, + BootImgSize, + Buffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to read blocks: %r\n", Status)); + goto EXIT; + } + + Status = AndroidBootImgBoot (Buffer, BootImgSize); + +EXIT: + return Status; +} diff --git a/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf b/EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf new file mode 100644 index 0000000..f1ee0bd --- /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] + AndroidBootImgLib + 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/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec index 4cd528a..8ad2a84 100644 --- a/EmbeddedPkg/EmbeddedPkg.dec +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -80,6 +80,7 @@ gAndroidFastbootPlatformProtocolGuid = { 0x524685a0, 0x89a0, 0x11e3, {0x9d, 0x4d, 0xbf, 0xa9, 0xf6, 0xa4, 0x03, 0x08}} gUsbDeviceProtocolGuid = { 0x021bd2ca, 0x51d2, 0x11e3, {0x8e, 0x56, 0xb7, 0x54, 0x17, 0xc7, 0x0b, 0x44 }} gPlatformGpioProtocolGuid = { 0x52ce9845, 0x5af4, 0x43e2, {0xba, 0xfd, 0x23, 0x08, 0x12, 0x54, 0x7a, 0xc2 }} + gAndroidBootImgProtocolGuid = { 0x9859bb19, 0x407c, 0x4f8b, {0xbc, 0xe1, 0xf8, 0xda, 0x65, 0x65, 0xf4, 0xa5 }}
[PcdsFeatureFlag.common] gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|FALSE|BOOLEAN|0x00000001 @@ -181,6 +182,7 @@ gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbProductId|0xbeef|UINT32|0x00000023 gEmbeddedTokenSpaceGuid.PcdAndroidFastbootTcpPort|1234|UINT32|0x00000024
+ gEmbeddedTokenSpaceGuid.PcdAndroidBootDevicePath|L""|VOID*|0x00000057
[PcdsFixedAtBuild.ARM] gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010 diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc index 16b368e..4a34e34 100644 --- a/EmbeddedPkg/EmbeddedPkg.dsc +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -52,6 +52,7 @@ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ AndroidBootImgLib|EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf BaseLib|MdePkg/Library/BaseLib/BaseLib.inf BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf @@ -272,6 +273,7 @@ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf }
+ EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf { <LibraryClasses> # It depends on BdsLib that depends on TimerLib diff --git a/EmbeddedPkg/Include/Library/AndroidBootImgLib.h b/EmbeddedPkg/Include/Library/AndroidBootImgLib.h index 06da751..331caa5 100644 --- a/EmbeddedPkg/Include/Library/AndroidBootImgLib.h +++ b/EmbeddedPkg/Include/Library/AndroidBootImgLib.h @@ -55,4 +55,17 @@ typedef struct { * and larger than boot header */ #define IS_VALID_ANDROID_PAGE_SIZE(Val) \ (IS_POWER_OF_2(Val) && (Val > sizeof(ANDROID_BOOTIMG_HEADER))) + +EFI_STATUS +AndroidBootImgGetImgSize ( + IN VOID *BootImg, + OUT UINTN *ImgSize + ); + +EFI_STATUS +AndroidBootImgBoot ( + IN VOID *Buffer, + IN UINTN BufferSize + ); + #endif /* __ABOOTIMG_H__ */ diff --git a/EmbeddedPkg/Include/Protocol/AndroidBootImg.h b/EmbeddedPkg/Include/Protocol/AndroidBootImg.h new file mode 100644 index 0000000..1c458d0 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/AndroidBootImg.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 __ANDROID_BOOTIMG_PROTOCOL_H__ +#define __ANDROID_BOOTIMG_PROTOCOL_H__ + +// +// Protocol interface structure +// +typedef struct _ANDROID_BOOTIMG_PROTOCOL ANDROID_BOOTIMG_PROTOCOL; + +// +// Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *ANDROID_BOOTIMG_APPEND_KERNEL_ARGS) ( + IN CHAR16 *Args, + IN UINTN Size + ); + +typedef +EFI_STATUS +(EFIAPI *ANDROID_BOOTIMG_UPDATE_DTB) ( + IN EFI_PHYSICAL_ADDRESS OrigDtbBase; + OUT EFI_PHYSICAL_ADDRESS *NewDtbBase; + ); + +struct _ANDROID_BOOTIMG_PROTOCOL { + ANDROID_BOOTIMG_APPEND_KERNEL_ARGS AppendArgs; + ANDROID_BOOTIMG_UPDATE_DTB UpdateDtb; +}; + +extern EFI_GUID gAndroidBootImgProtocolGuid; + +#endif /* __ANDROID_BOOTIMG_PROTOCOL_H__ */ diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c new file mode 100644 index 0000000..cb4fb67 --- /dev/null +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c @@ -0,0 +1,471 @@ +/** @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 <libfdt.h> +#include <Library/AndroidBootImgLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/AndroidBootImg.h> +#include <Protocol/LoadedImage.h> + +#include <libfdt.h> + +#define FDT_ADDITIONAL_ENTRIES_SIZE 0x400 + +typedef struct { + MEMMAP_DEVICE_PATH Node1; + EFI_DEVICE_PATH_PROTOCOL End; +} MEMORY_DEVICE_PATH; + +STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg; + +STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate = +{ + { + { + 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 +AndroidBootImgGetImgSize ( + IN VOID *BootImg, + OUT UINTN *ImgSize + ) +{ + ANDROID_BOOTIMG_HEADER *Header; + + Header = (ANDROID_BOOTIMG_HEADER *) BootImg; + + if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC, + ANDROID_BOOT_MAGIC_LENGTH) != 0) { + return EFI_INVALID_PARAMETER; + } + + /* The page size is not specified, but it should be power of 2 at least */ + ASSERT (IS_VALID_ANDROID_PAGE_SIZE (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 +AndroidBootImgGetKernelInfo ( + IN VOID *BootImg, + OUT VOID **Kernel, + OUT UINTN *KernelSize + ) +{ + ANDROID_BOOTIMG_HEADER *Header; + + Header = (ANDROID_BOOTIMG_HEADER *) BootImg; + + if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC, + ANDROID_BOOT_MAGIC_LENGTH) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (Header->KernelSize == 0) { + return EFI_NOT_FOUND; + } + + ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize)); + + *KernelSize = Header->KernelSize; + *Kernel = BootImg + Header->PageSize; + return EFI_SUCCESS; +} + +EFI_STATUS +AndroidBootImgGetRamdiskInfo ( + 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 ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC, + ANDROID_BOOT_MAGIC_LENGTH) != 0) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (IS_VALID_ANDROID_PAGE_SIZE (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 +AndroidBootImgGetSecondBootLoaderInfo ( + IN VOID *BootImg, + OUT VOID **Second, + OUT UINTN *SecondSize + ) +{ + ANDROID_BOOTIMG_HEADER *Header; + UINTN BootImgBytePtr; + + // Cast to UINT8 so we can do pointer arithmetic + BootImgBytePtr = (UINTN) BootImg; + + Header = (ANDROID_BOOTIMG_HEADER *) BootImg; + + if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC, + ANDROID_BOOT_MAGIC_LENGTH) != 0) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (IS_VALID_ANDROID_PAGE_SIZE (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 +AndroidBootImgGetKernelArgs ( + IN VOID *BootImg, + OUT CHAR8 *KernelArgs + ) +{ + ANDROID_BOOTIMG_HEADER *Header; + + Header = (ANDROID_BOOTIMG_HEADER *) BootImg; + AsciiStrnCpyS (KernelArgs, ANDROID_BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs, + ANDROID_BOOTIMG_KERNEL_ARGS_SIZE); + + return EFI_SUCCESS; +} + +EFI_STATUS +AndroidBootImgGetFdt ( + IN VOID *BootImg, + IN VOID **FdtBase + ) +{ + UINTN SecondLoaderSize; + EFI_STATUS Status; + + /* Check whether FDT is located in second boot region as some vendor do so, + * because second loader is never used as far as I know. */ + Status = AndroidBootImgGetSecondBootLoaderInfo ( + BootImg, + FdtBase, + &SecondLoaderSize + ); + return Status; +} + +EFI_STATUS +AndroidBootImgUpdateArgs ( + IN VOID *BootImg, + OUT VOID *KernelArgs + ) +{ + CHAR8 ImageKernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE]; + EFI_STATUS Status; + + // Get kernel arguments from Android boot image + Status = AndroidBootImgGetKernelArgs (BootImg, ImageKernelArgs); + if (EFI_ERROR (Status)) { + return Status; + } + AsciiStrToUnicodeStrS (ImageKernelArgs, KernelArgs, + ANDROID_BOOTIMG_KERNEL_ARGS_SIZE >> 1); + // Append platform kernel arguments + if(mAndroidBootImg->AppendArgs) { + Status = mAndroidBootImg->AppendArgs (KernelArgs, + ANDROID_BOOTIMG_KERNEL_ARGS_SIZE); + } + return Status; +} + +EFI_STATUS +AndroidBootImgLocateFdt ( + IN VOID *BootImg, + IN VOID **FdtBase + ) +{ + INTN Err; + EFI_STATUS Status; + + Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, FdtBase); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + Status = AndroidBootImgGetFdt (BootImg, FdtBase); + if (EFI_ERROR (Status)) { + return Status; + } + Err = fdt_check_header (*FdtBase); + if (Err != 0) { + DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (Err:%d)\n", + Err)); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +INTN +AndroidBootImgGetChosenNode ( + IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase + ) +{ + IN INTN ChosenNode; + + ChosenNode = fdt_subnode_offset ((CONST VOID *)UpdatedFdtBase, 0, "chosen"); + if (ChosenNode < 0) { + ChosenNode = fdt_add_subnode((VOID *)UpdatedFdtBase, 0, "chosen"); + if (ChosenNode < 0) { + DEBUG ((DEBUG_ERROR, "Fail to find fdt node chosen!\n")); + return 0; + } + } + return ChosenNode; +} + +EFI_STATUS +AndroidBootImgSetProperty64 ( + IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase, + IN INTN ChosenNode, + IN CHAR8 *PropertyName, + IN UINT64 Val + ) +{ + INTN Err; + struct fdt_property *Property; + int Len; + + Property = fdt_get_property_w((VOID *)UpdatedFdtBase, ChosenNode, + PropertyName, &Len); + if (NULL == Property && Len == -FDT_ERR_NOTFOUND) { + Val = cpu_to_fdt64(Val); + Err = fdt_appendprop ((VOID *)UpdatedFdtBase, ChosenNode, + PropertyName, &Val, sizeof (UINT64)); + if (Err) { + DEBUG ((DEBUG_ERROR, "fdt_appendprop() fail: %a\n", fdt_strerror (Err))); + return EFI_INVALID_PARAMETER; + } + } else if (Property != NULL) { + Err = fdt_setprop_u64((VOID *)UpdatedFdtBase, ChosenNode, + PropertyName, Val); + if (Err) { + DEBUG ((DEBUG_ERROR, "fdt_setprop_u64() fail: %a\n", fdt_strerror (Err))); + return EFI_INVALID_PARAMETER; + } + } else { + DEBUG ((DEBUG_ERROR, "Failed to set fdt Property %a\n", PropertyName)); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +EFI_STATUS +AndroidBootImgUpdateFdt ( + IN VOID *BootImg, + IN VOID *FdtBase, + IN VOID *RamdiskData, + IN UINTN RamdiskSize + ) +{ + INTN ChosenNode, Err, NewFdtSize; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS UpdatedFdtBase, NewFdtBase; + + NewFdtSize = (UINTN)fdt_totalsize (FdtBase) + + FDT_ADDITIONAL_ENTRIES_SIZE; + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, + EFI_SIZE_TO_PAGES (NewFdtSize), &UpdatedFdtBase); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Warning: Failed to reallocate FDT, err %d.\n", + Status)); + return Status; + } + + // Load the Original FDT tree into the new region + Err = fdt_open_into(FdtBase, (VOID*)UpdatedFdtBase, NewFdtSize); + if (Err) { + DEBUG ((DEBUG_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Err))); + Status = EFI_INVALID_PARAMETER; + goto Fdt_Exit; + } + + ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase); + if (!ChosenNode) { + goto Fdt_Exit; + } + + Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, + "linux,initrd-start", + (UINT64)RamdiskData); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } + + Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, + "linux,initrd-end", + (UINT64)(RamdiskData + RamdiskSize)); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } + + if (mAndroidBootImg->UpdateDtb) { + Status = mAndroidBootImg->UpdateDtb (UpdatedFdtBase, &NewFdtBase); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } + } + + Status = gBS->InstallConfigurationTable ( + &gFdtTableGuid, + (VOID *)(UINTN)NewFdtBase + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + +Fdt_Exit: + gBS->FreePages (UpdatedFdtBase, EFI_SIZE_TO_PAGES (NewFdtSize)); + return Status; +} + +EFI_STATUS +AndroidBootImgBoot ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + EFI_STATUS Status; + VOID *Kernel; + UINTN KernelSize; + MEMORY_DEVICE_PATH KernelDevicePath; + EFI_HANDLE ImageHandle; + VOID *NewKernelArg; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + VOID *RamdiskData; + UINTN RamdiskSize; + IN VOID *FdtBase; + + Status = gBS->LocateProtocol (&gAndroidBootImgProtocolGuid, NULL, + (VOID **) &mAndroidBootImg); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AndroidBootImgGetKernelInfo ( + Buffer, + &Kernel, + &KernelSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + NewKernelArg = AllocateZeroPool (ANDROID_BOOTIMG_KERNEL_ARGS_SIZE); + if (NewKernelArg == NULL) { + DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n")); + return EFI_OUT_OF_RESOURCES; + } + + Status = AndroidBootImgUpdateArgs (Buffer, NewKernelArg); + if (EFI_ERROR (Status)) { + FreePool (NewKernelArg); + return Status; + } + + Status = AndroidBootImgGetRamdiskInfo ( + Buffer, + &RamdiskData, + &RamdiskSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AndroidBootImgLocateFdt (Buffer, &FdtBase); + if (EFI_ERROR (Status)) { + FreePool (NewKernelArg); + return Status; + } + + Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize); + if (EFI_ERROR (Status)) { + FreePool (NewKernelArg); + return Status; + } + + KernelDevicePath = mMemoryDevicePathTemplate; + + 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, 0x10000, 0, NULL); + // Start the image + Status = gBS->StartImage (ImageHandle, NULL, NULL); + // Clear the Watchdog Timer if the image returns + gBS->SetWatchdogTimer (0, 0x10000, 0, NULL); + return EFI_SUCCESS; +} diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf new file mode 100644 index 0000000..c92bac0 --- /dev/null +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.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 = AndroidBootImgLib + FILE_GUID = ed3b8739-6fa7-4cb1-8aeb-2496f8fcaefa + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = AndroidBootImgLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + AndroidBootImgLib.c + +[LibraryClasses] + DebugLib + FdtLib + PrintLib + UefiBootServicesTableLib + UefiLib + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[Protocols] + gAndroidBootImgProtocolGuid + +[Guids] + gFdtTableGuid
On Wed, Aug 09, 2017 at 06:39:23PM +0800, Jun Nie wrote:
Add an android kernel loader that could load kernel from storage device. This android boot image BDS add addtitional cmdline/dtb/ramfs support besides kernel that is introduced by Android boot header.
This patch is derived from Haojian's code as below link. https://patches.linaro.org/patch/94683/
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jun Nie jun.nie@linaro.org
.../Application/AndroidBoot/AndroidBootApp.c | 140 ++++++ .../Application/AndroidBoot/AndroidBootApp.inf | 64 +++ EmbeddedPkg/EmbeddedPkg.dec | 2 + EmbeddedPkg/EmbeddedPkg.dsc | 2 + EmbeddedPkg/Include/Library/AndroidBootImgLib.h | 13 + EmbeddedPkg/Include/Protocol/AndroidBootImg.h | 47 ++ .../Library/AndroidBootImgLib/AndroidBootImgLib.c | 471 +++++++++++++++++++++ .../AndroidBootImgLib/AndroidBootImgLib.inf | 48 +++ 8 files changed, 787 insertions(+) create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.c create mode 100644 EmbeddedPkg/Application/AndroidBoot/AndroidBootApp.inf create mode 100644 EmbeddedPkg/Include/Protocol/AndroidBootImg.h create mode 100644 EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c create mode 100644 EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf
diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c new file mode 100644 index 0000000..cb4fb67 --- /dev/null +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c @@ -0,0 +1,471 @@ +/** @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 <libfdt.h> +#include <Library/AndroidBootImgLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h>
+#include <Protocol/AndroidBootImg.h> +#include <Protocol/LoadedImage.h>
+#include <libfdt.h>
+#define FDT_ADDITIONAL_ENTRIES_SIZE 0x400
+typedef struct {
- MEMMAP_DEVICE_PATH Node1;
- EFI_DEVICE_PATH_PROTOCOL End;
+} MEMORY_DEVICE_PATH;
+STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg;
+STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate = +{
- {
- {
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 +AndroidBootImgGetImgSize (
- IN VOID *BootImg,
- OUT UINTN *ImgSize
- )
+{
- ANDROID_BOOTIMG_HEADER *Header;
- Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
- if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,
ANDROID_BOOT_MAGIC_LENGTH) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- /* The page size is not specified, but it should be power of 2 at least */
- ASSERT (IS_VALID_ANDROID_PAGE_SIZE (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 +AndroidBootImgGetKernelInfo (
- IN VOID *BootImg,
- OUT VOID **Kernel,
- OUT UINTN *KernelSize
- )
+{
- ANDROID_BOOTIMG_HEADER *Header;
- Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
- if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,
ANDROID_BOOT_MAGIC_LENGTH) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- if (Header->KernelSize == 0) {
- return EFI_NOT_FOUND;
- }
- ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));
- *KernelSize = Header->KernelSize;
- *Kernel = BootImg + Header->PageSize;
- return EFI_SUCCESS;
+}
+EFI_STATUS +AndroidBootImgGetRamdiskInfo (
- 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 ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,
ANDROID_BOOT_MAGIC_LENGTH) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- ASSERT (IS_VALID_ANDROID_PAGE_SIZE (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 +AndroidBootImgGetSecondBootLoaderInfo (
- IN VOID *BootImg,
- OUT VOID **Second,
- OUT UINTN *SecondSize
- )
+{
- ANDROID_BOOTIMG_HEADER *Header;
- UINTN BootImgBytePtr;
- // Cast to UINT8 so we can do pointer arithmetic
- BootImgBytePtr = (UINTN) BootImg;
Why is this BootImgBytePtr kept around? It is completely redundant.
Using special pointers to avoid dealing with pointer arithmetic is an antipattern, and although the actual pointer was removed here, the same antipattern is followed.
Please change as I asked last time around - DELETE BootImgBytePtr completely...
- Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
- if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,
ANDROID_BOOT_MAGIC_LENGTH) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));
- *SecondSize = Header->SecondStageBootloaderSize;
- if (Header->SecondStageBootloaderSize != 0) {
- *Second = (VOID *) (BootImgBytePtr
... and use (UINTN)BootImg here.
+ Header->PageSize
+ ALIGN_VALUE (Header->KernelSize, Header->PageSize)
+ ALIGN_VALUE (Header->RamdiskSize, Header->PageSize));
- }
- return EFI_SUCCESS;
+}
Now, before I noticed this I was just running some final sanity checks and noticed this code is not 32-bit safe.
If you can also fold in the following:
<<<
diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c index cb4fb6740a..bf33c64d25 100644 --- a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c @@ -259,7 +259,7 @@ AndroidBootImgLocateFdt (
INTN AndroidBootImgGetChosenNode ( - IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase + IN UINTN UpdatedFdtBase ) { IN INTN ChosenNode; @@ -277,10 +277,10 @@ AndroidBootImgGetChosenNode (
EFI_STATUS AndroidBootImgSetProperty64 ( - IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase, - IN INTN ChosenNode, - IN CHAR8 *PropertyName, - IN UINT64 Val + IN UINTN UpdatedFdtBase, + IN INTN ChosenNode, + IN CHAR8 *PropertyName, + IN UINT64 Val ) { INTN Err; @@ -334,7 +334,7 @@ AndroidBootImgUpdateFdt ( }
// Load the Original FDT tree into the new region - Err = fdt_open_into(FdtBase, (VOID*)UpdatedFdtBase, NewFdtSize); + Err = fdt_open_into(FdtBase, (VOID*)(UINTN)UpdatedFdtBase, NewFdtSize); if (Err) { DEBUG ((DEBUG_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Err))); Status = EFI_INVALID_PARAMETER; @@ -348,14 +348,14 @@ AndroidBootImgUpdateFdt (
Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, "linux,initrd-start", - (UINT64)RamdiskData); + (UINTN)RamdiskData); if (EFI_ERROR (Status)) { goto Fdt_Exit; }
Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, "linux,initrd-end", - (UINT64)(RamdiskData + RamdiskSize)); + (UINTN)(RamdiskData + RamdiskSize)); if (EFI_ERROR (Status)) { goto Fdt_Exit; }
we can go ahead and commit this patch. Note that 1/2 has already been pushed, so no need to resend.
Regards,
Leif
+EFI_STATUS +AndroidBootImgGetKernelArgs (
- IN VOID *BootImg,
- OUT CHAR8 *KernelArgs
- )
+{
- ANDROID_BOOTIMG_HEADER *Header;
- Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
- AsciiStrnCpyS (KernelArgs, ANDROID_BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs,
- ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);
- return EFI_SUCCESS;
+}
+EFI_STATUS +AndroidBootImgGetFdt (
- IN VOID *BootImg,
- IN VOID **FdtBase
- )
+{
- UINTN SecondLoaderSize;
- EFI_STATUS Status;
- /* Check whether FDT is located in second boot region as some vendor do so,
- because second loader is never used as far as I know. */
- Status = AndroidBootImgGetSecondBootLoaderInfo (
BootImg,
FdtBase,
&SecondLoaderSize
);
- return Status;
+}
+EFI_STATUS +AndroidBootImgUpdateArgs (
- IN VOID *BootImg,
- OUT VOID *KernelArgs
- )
+{
- CHAR8 ImageKernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE];
- EFI_STATUS Status;
- // Get kernel arguments from Android boot image
- Status = AndroidBootImgGetKernelArgs (BootImg, ImageKernelArgs);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- AsciiStrToUnicodeStrS (ImageKernelArgs, KernelArgs,
ANDROID_BOOTIMG_KERNEL_ARGS_SIZE >> 1);
- // Append platform kernel arguments
- if(mAndroidBootImg->AppendArgs) {
- Status = mAndroidBootImg->AppendArgs (KernelArgs,
ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);
- }
- return Status;
+}
+EFI_STATUS +AndroidBootImgLocateFdt (
- IN VOID *BootImg,
- IN VOID **FdtBase
- )
+{
- INTN Err;
- EFI_STATUS Status;
- Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, FdtBase);
- if (!EFI_ERROR (Status)) {
- return EFI_SUCCESS;
- }
- Status = AndroidBootImgGetFdt (BootImg, FdtBase);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Err = fdt_check_header (*FdtBase);
- if (Err != 0) {
- DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (Err:%d)\n",
Err));
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
+}
+INTN +AndroidBootImgGetChosenNode (
- IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase
- )
+{
- IN INTN ChosenNode;
- ChosenNode = fdt_subnode_offset ((CONST VOID *)UpdatedFdtBase, 0, "chosen");
- if (ChosenNode < 0) {
- ChosenNode = fdt_add_subnode((VOID *)UpdatedFdtBase, 0, "chosen");
if (ChosenNode < 0) {
DEBUG ((DEBUG_ERROR, "Fail to find fdt node chosen!\n"));
return 0;
- }
- }
- return ChosenNode;
+}
+EFI_STATUS +AndroidBootImgSetProperty64 (
- IN EFI_PHYSICAL_ADDRESS UpdatedFdtBase,
- IN INTN ChosenNode,
- IN CHAR8 *PropertyName,
- IN UINT64 Val
- )
+{
- INTN Err;
- struct fdt_property *Property;
- int Len;
- Property = fdt_get_property_w((VOID *)UpdatedFdtBase, ChosenNode,
PropertyName, &Len);
- if (NULL == Property && Len == -FDT_ERR_NOTFOUND) {
- Val = cpu_to_fdt64(Val);
- Err = fdt_appendprop ((VOID *)UpdatedFdtBase, ChosenNode,
PropertyName, &Val, sizeof (UINT64));
- if (Err) {
DEBUG ((DEBUG_ERROR, "fdt_appendprop() fail: %a\n", fdt_strerror (Err)));
return EFI_INVALID_PARAMETER;
- }
- } else if (Property != NULL) {
- Err = fdt_setprop_u64((VOID *)UpdatedFdtBase, ChosenNode,
PropertyName, Val);
- if (Err) {
DEBUG ((DEBUG_ERROR, "fdt_setprop_u64() fail: %a\n", fdt_strerror (Err)));
return EFI_INVALID_PARAMETER;
- }
- } else {
- DEBUG ((DEBUG_ERROR, "Failed to set fdt Property %a\n", PropertyName));
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
+}
+EFI_STATUS +AndroidBootImgUpdateFdt (
- IN VOID *BootImg,
- IN VOID *FdtBase,
- IN VOID *RamdiskData,
- IN UINTN RamdiskSize
- )
+{
- INTN ChosenNode, Err, NewFdtSize;
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS UpdatedFdtBase, NewFdtBase;
- NewFdtSize = (UINTN)fdt_totalsize (FdtBase)
+ FDT_ADDITIONAL_ENTRIES_SIZE;
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,
EFI_SIZE_TO_PAGES (NewFdtSize), &UpdatedFdtBase);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "Warning: Failed to reallocate FDT, err %d.\n",
Status));
- return Status;
- }
- // Load the Original FDT tree into the new region
- Err = fdt_open_into(FdtBase, (VOID*)UpdatedFdtBase, NewFdtSize);
- if (Err) {
- DEBUG ((DEBUG_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Err)));
- Status = EFI_INVALID_PARAMETER;
- goto Fdt_Exit;
- }
- ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase);
- if (!ChosenNode) {
- goto Fdt_Exit;
- }
- Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,
"linux,initrd-start",
(UINT64)RamdiskData);
- if (EFI_ERROR (Status)) {
- goto Fdt_Exit;
- }
- Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,
"linux,initrd-end",
(UINT64)(RamdiskData + RamdiskSize));
- if (EFI_ERROR (Status)) {
- goto Fdt_Exit;
- }
- if (mAndroidBootImg->UpdateDtb) {
- Status = mAndroidBootImg->UpdateDtb (UpdatedFdtBase, &NewFdtBase);
- if (EFI_ERROR (Status)) {
goto Fdt_Exit;
- }
- }
- Status = gBS->InstallConfigurationTable (
&gFdtTableGuid,
(VOID *)(UINTN)NewFdtBase
);
- if (!EFI_ERROR (Status)) {
- return EFI_SUCCESS;
- }
+Fdt_Exit:
- gBS->FreePages (UpdatedFdtBase, EFI_SIZE_TO_PAGES (NewFdtSize));
- return Status;
+}
+EFI_STATUS +AndroidBootImgBoot (
- IN VOID *Buffer,
- IN UINTN BufferSize
- )
+{
- EFI_STATUS Status;
- VOID *Kernel;
- UINTN KernelSize;
- MEMORY_DEVICE_PATH KernelDevicePath;
- EFI_HANDLE ImageHandle;
- VOID *NewKernelArg;
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
- VOID *RamdiskData;
- UINTN RamdiskSize;
- IN VOID *FdtBase;
- Status = gBS->LocateProtocol (&gAndroidBootImgProtocolGuid, NULL,
(VOID **) &mAndroidBootImg);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = AndroidBootImgGetKernelInfo (
Buffer,
&Kernel,
&KernelSize
);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- NewKernelArg = AllocateZeroPool (ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);
- if (NewKernelArg == NULL) {
- DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n"));
- return EFI_OUT_OF_RESOURCES;
- }
- Status = AndroidBootImgUpdateArgs (Buffer, NewKernelArg);
- if (EFI_ERROR (Status)) {
- FreePool (NewKernelArg);
- return Status;
- }
- Status = AndroidBootImgGetRamdiskInfo (
Buffer,
&RamdiskData,
&RamdiskSize
);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = AndroidBootImgLocateFdt (Buffer, &FdtBase);
- if (EFI_ERROR (Status)) {
- FreePool (NewKernelArg);
- return Status;
- }
- Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize);
- if (EFI_ERROR (Status)) {
- FreePool (NewKernelArg);
- return Status;
- }
- KernelDevicePath = mMemoryDevicePathTemplate;
- 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, 0x10000, 0, NULL);
- // Start the image
- Status = gBS->StartImage (ImageHandle, NULL, NULL);
- // Clear the Watchdog Timer if the image returns
- gBS->SetWatchdogTimer (0, 0x10000, 0, NULL);
- return EFI_SUCCESS;
+} diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf new file mode 100644 index 0000000..c92bac0 --- /dev/null +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.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 = AndroidBootImgLib
- FILE_GUID = ed3b8739-6fa7-4cb1-8aeb-2496f8fcaefa
- MODULE_TYPE = BASE
- VERSION_STRING = 1.0
- LIBRARY_CLASS = AndroidBootImgLib
+# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +#
+[Sources]
- AndroidBootImgLib.c
+[LibraryClasses]
- DebugLib
- FdtLib
- PrintLib
- UefiBootServicesTableLib
- UefiLib
+[Packages]
- EmbeddedPkg/EmbeddedPkg.dec
- MdePkg/MdePkg.dec
+[Protocols]
- gAndroidBootImgProtocolGuid
+[Guids]
- gFdtTableGuid
-- 1.9.1