1 /** @file 2 3 Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR> 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "AndroidFastbootApp.h" 16 17 #include <Protocol/DevicePath.h> 18 19 #include <Library/BaseMemoryLib.h> 20 #include <Library/BdsLib.h> 21 #include <Library/DevicePathLib.h> 22 #include <Library/PrintLib.h> 23 #include <Library/UefiBootServicesTableLib.h> 24 #include <Library/UefiRuntimeServicesTableLib.h> 25 #include <Library/UefiLib.h> 26 27 #define LINUX_LOADER_COMMAND_LINE L"%s -f %s -c %s" 28 29 // This GUID is defined in the INGF file of ArmPkg/Application/LinuxLoader 30 CONST EFI_GUID mLinuxLoaderAppGuid = { 0x701f54f2, 0x0d70, 0x4b89, { 0xbc, 0x0a, 0xd9, 0xca, 0x25, 0x37, 0x90, 0x59 }}; 31 32 // Device Path representing an image in memory 33 #pragma pack(1) 34 typedef struct { 35 MEMMAP_DEVICE_PATH Node1; 36 EFI_DEVICE_PATH_PROTOCOL End; 37 } MEMORY_DEVICE_PATH; 38 #pragma pack() 39 40 STATIC CONST MEMORY_DEVICE_PATH MemoryDevicePathTemplate = 41 { 42 { 43 { 44 HARDWARE_DEVICE_PATH, 45 HW_MEMMAP_DP, 46 { 47 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), 48 (UINT8)((sizeof (MEMMAP_DEVICE_PATH)) >> 8), 49 }, 50 }, // Header 51 0, // StartingAddress (set at runtime) 52 0 // EndingAddress (set at runtime) 53 }, // Node1 54 { 55 END_DEVICE_PATH_TYPE, 56 END_ENTIRE_DEVICE_PATH_SUBTYPE, 57 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } 58 } // End 59 }; 60 61 #define KERNEL_IMAGE_STEXT_OFFSET 0x12C 62 #define KERNEL_IMAGE_RAW_SIZE_OFFSET 0x130 63 64 EFI_STATUS 65 BootAndroidBootImg ( 66 IN UINTN BufferSize, 67 IN VOID *Buffer 68 ) 69 { 70 EFI_STATUS Status; 71 CHAR8 KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE]; 72 VOID *Kernel; 73 UINTN KernelSize; 74 VOID *Ramdisk; 75 UINTN RamdiskSize; 76 MEMORY_DEVICE_PATH KernelDevicePath; 77 MEMORY_DEVICE_PATH* RamdiskDevicePath; 78 EFI_PHYSICAL_ADDRESS FdtBase; 79 CHAR16 UnicodeArgs[BOOTIMG_KERNEL_ARGS_SIZE]; 80 CHAR16 InitrdArgs[64]; 81 BDS_LOAD_OPTION *BdsLoadOptions; 82 UINTN VariableSize; 83 CHAR16 SerialNoArgs[40], DataUnicode[17]; 84 85 Status = ParseAndroidBootImg ( 86 Buffer, 87 &Kernel, 88 &KernelSize, 89 &Ramdisk, 90 &RamdiskSize, 91 KernelArgs 92 ); 93 if (EFI_ERROR (Status)) { 94 return Status; 95 } 96 97 KernelDevicePath = MemoryDevicePathTemplate; 98 99 KernelSize = *(UINT32 *)(Kernel + KERNEL_IMAGE_STEXT_OFFSET) + 100 *(UINT32 *)(Kernel + KERNEL_IMAGE_RAW_SIZE_OFFSET); 101 FdtBase = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel + KernelSize; 102 Status = gBS->InstallConfigurationTable (&gFdtTableGuid, (VOID *)FdtBase); 103 ASSERT_EFI_ERROR (Status); 104 105 // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to 106 // appease GCC. 107 KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel; 108 KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel + KernelSize; 109 110 RamdiskDevicePath = NULL; 111 if (RamdiskSize != 0) { 112 RamdiskDevicePath = (MEMORY_DEVICE_PATH*)DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*) &MemoryDevicePathTemplate); 113 114 RamdiskDevicePath->Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Ramdisk; 115 RamdiskDevicePath->Node1.EndingAddress = ((EFI_PHYSICAL_ADDRESS)(UINTN) Ramdisk) + RamdiskSize; 116 } 117 118 BdsLoadOptions = (BDS_LOAD_OPTION *)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); 119 ASSERT (BdsLoadOptions != NULL); 120 BdsLoadOptions->FilePathList = &KernelDevicePath.Node1.Header; 121 ASSERT (BdsLoadOptions->FilePathList != NULL); 122 BdsLoadOptions->FilePathListLength = GetDevicePathSize (BdsLoadOptions->FilePathList); 123 BdsLoadOptions->Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT; 124 125 AsciiStrToUnicodeStr (KernelArgs, UnicodeArgs); 126 UnicodeSPrint (InitrdArgs, 64 * sizeof(CHAR16), L" initrd=0x%x,0x%x", 127 (EFI_PHYSICAL_ADDRESS)(UINTN) Ramdisk, RamdiskSize); 128 StrCat (UnicodeArgs, InitrdArgs); 129 130 VariableSize = 17 * sizeof(CHAR16); 131 Status = gRT->GetVariable ((CHAR16 *)L"SerialNo", &gHiKeyVariableGuid, NULL, 132 &VariableSize, &DataUnicode); 133 if (!EFI_ERROR (Status)) { 134 DataUnicode[(VariableSize / sizeof(CHAR16)) - 1] = '\0'; 135 ZeroMem (SerialNoArgs, 40 * sizeof (CHAR16)); 136 UnicodeSPrint (SerialNoArgs, 40 * sizeof(CHAR16), L" androidboot.serialno=%s", DataUnicode); 137 StrCat (UnicodeArgs, SerialNoArgs); 138 } 139 140 BdsLoadOptions->OptionalDataSize = StrSize (UnicodeArgs); 141 BdsLoadOptions->OptionalData = UnicodeArgs; 142 BdsLoadOptions->Description = NULL; 143 144 145 Status = BdsStartEfiApplication (gImageHandle, BdsLoadOptions->FilePathList, BdsLoadOptions->OptionalDataSize, BdsLoadOptions->OptionalData); 146 if (EFI_ERROR (Status)) { 147 DEBUG ((EFI_D_ERROR, "Couldn't Boot Linux: %d\n", Status)); 148 return EFI_DEVICE_ERROR; 149 } 150 151 if (RamdiskDevicePath) { 152 FreePool (RamdiskDevicePath); 153 } 154 155 // If we got here we do a confused face because BootLinuxFdt returned, 156 // reporting success. 157 DEBUG ((EFI_D_ERROR, "WARNING: BdsBootLinuxFdt returned EFI_SUCCESS.\n")); 158 return EFI_SUCCESS; 159 } 160