--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
+ Copyright (c) 2017, Linaro. All rights reserved.\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/AndroidBootImgLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BdsLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/DevicePathFromText.h>\r
+\r
+/* Validate the node is media hard drive type */\r
+EFI_STATUS\r
+ValidateAndroidMediaDevicePath (\r
+ IN EFI_DEVICE_PATH *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node, *NextNode;\r
+\r
+ NextNode = DevicePath;\r
+ while (NextNode != NULL) {\r
+ Node = NextNode;\r
+ if (IS_DEVICE_PATH_NODE (Node, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ NextNode = NextDevicePathNode (Node);\r
+ }\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+AndroidBootAppEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *BootPathStr;\r
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
+ EFI_DEVICE_PATH *DevicePath;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ UINT32 MediaId, BlockSize;\r
+ VOID *Buffer;\r
+ EFI_HANDLE Handle;\r
+ UINTN BootImgSize;\r
+\r
+ BootPathStr = (CHAR16 *)PcdGetPtr (PcdAndroidBootDevicePath);\r
+ ASSERT (BootPathStr != NULL);\r
+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL,\r
+ (VOID **)&EfiDevicePathFromTextProtocol);\r
+ ASSERT_EFI_ERROR(Status);\r
+ DevicePath = (EFI_DEVICE_PATH *)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (BootPathStr);\r
+ ASSERT (DevicePath != NULL);\r
+\r
+ Status = ValidateAndroidMediaDevicePath (DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid,\r
+ &DevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlockIo,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ MediaId = BlockIo->Media->MediaId;\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+ Buffer = AllocatePages (EFI_SIZE_TO_PAGES (sizeof(ANDROID_BOOTIMG_HEADER)));\r
+ if (Buffer == NULL) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ /* Load header of boot.img */\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ MediaId,\r
+ 0,\r
+ BlockSize,\r
+ Buffer\r
+ );\r
+ Status = AndroidBootImgGetImgSize (Buffer, &BootImgSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to get AndroidBootImg Size: %r\n", Status));\r
+ return Status;\r
+ }\r
+ BootImgSize = ALIGN_VALUE (BootImgSize, BlockSize);\r
+ FreePages (Buffer, EFI_SIZE_TO_PAGES (sizeof(ANDROID_BOOTIMG_HEADER)));\r
+\r
+ /* Both PartitionStart and PartitionSize are counted as block size. */\r
+ Buffer = AllocatePages (EFI_SIZE_TO_PAGES (BootImgSize));\r
+ if (Buffer == NULL) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ /* Load header of boot.img */\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ MediaId,\r
+ 0,\r
+ BootImgSize,\r
+ Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to read blocks: %r\n", Status));\r
+ goto EXIT;\r
+ }\r
+\r
+ Status = AndroidBootImgBoot (Buffer, BootImgSize);\r
+\r
+EXIT:\r
+ return Status;\r
+}\r