| /** @file | |
| Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR> | |
| Copyright (c) 2017, Linaro. All rights reserved. | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Library/AndroidBootImgLib.h> | |
| #include <Library/BaseMemoryLib.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 (Node->Type == MEDIA_DEVICE_PATH && | |
| Node->SubType == 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; | |
| } |