1 /** @file 2 * 3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved. 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 <Library/UefiApplicationEntryPoint.h> 16 #include <Library/BaseMemoryLib.h> 17 18 #include <Protocol/DevicePathFromText.h> 19 20 #include "LinuxLoader.h" 21 22 /** 23 The user Entry Point for Application. The user code starts with this function 24 as the real entry point for the application. 25 26 @param[in] ImageHandle The firmware allocated handle for the EFI image. 27 @param[in] SystemTable A pointer to the EFI System Table. 28 29 @retval EFI_SUCCESS The entry point was executed successfully. 30 @retval EFI_NOT_FOUND Protocol not found. 31 @retval EFI_NOT_FOUND Path to the Linux kernel not found. 32 @retval EFI_ABORTED The initialisation of the Shell Library failed. 33 @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a 34 conflict between two parameters. 35 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 36 37 **/ 38 EFI_STATUS 39 EFIAPI 40 LinuxLoaderEntryPoint ( 41 IN EFI_HANDLE ImageHandle, 42 IN EFI_SYSTEM_TABLE *SystemTable 43 ) 44 { 45 EFI_STATUS Status; 46 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; 47 EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; 48 CHAR16 *KernelPath; 49 CHAR16 *FdtPath; 50 CHAR16 *InitrdPath; 51 CHAR16 *KernelTextDevicePath; 52 CHAR16 *FdtTextDevicePath; 53 CHAR16 *InitrdTextDevicePath; 54 CHAR16 *LinuxCommandLine; 55 UINTN AtagMachineType; 56 EFI_DEVICE_PATH *KernelDevicePath; 57 EFI_DEVICE_PATH *FdtDevicePath; 58 EFI_DEVICE_PATH *InitrdDevicePath; 59 CHAR8 *AsciiLinuxCommandLine; 60 LIST_ENTRY ResourceList; 61 LIST_ENTRY *ResourceLink; 62 SYSTEM_MEMORY_RESOURCE *Resource; 63 EFI_PHYSICAL_ADDRESS SystemMemoryBase; 64 65 Status = gBS->LocateProtocol ( 66 &gEfiDevicePathFromTextProtocolGuid, 67 NULL, 68 (VOID **)&EfiDevicePathFromTextProtocol 69 ); 70 if (EFI_ERROR (Status)) { 71 return EFI_NOT_FOUND; 72 } 73 74 // 75 // Register the strings for the user interface in the HII Database. 76 // This shows the way to the multi-language support, even if 77 // only the English language is actually supported. The strings to register 78 // are stored in the "LinuxLoaderStrings[]" array. This array is 79 // built by the building process from the "*.uni" file associated to 80 // the present application (cf. LinuxLoader.inf). Examine the Build 81 // folder of the application and you will find the array defined in the 82 // LinuxLoaderStrDefs.h file. 83 // 84 mLinuxLoaderHiiHandle = HiiAddPackages ( 85 &mLinuxLoaderHiiGuid, 86 ImageHandle, 87 LinuxLoaderStrings, 88 NULL 89 ); 90 if (mLinuxLoaderHiiHandle == NULL) { 91 return EFI_NOT_FOUND; 92 } 93 94 Status = gBS->HandleProtocol ( 95 ImageHandle, 96 &gEfiShellParametersProtocolGuid, 97 (VOID**)&ShellParameters 98 ); 99 100 KernelDevicePath = NULL; 101 FdtDevicePath = NULL; 102 InitrdDevicePath = NULL; 103 AsciiLinuxCommandLine = NULL; 104 105 // 106 // Call the proper function to handle the command line 107 // depending on whether the application has been called 108 // from the Shell or not. 109 // 110 111 if (!EFI_ERROR (Status)) { 112 KernelTextDevicePath = NULL; 113 FdtTextDevicePath = NULL; 114 InitrdTextDevicePath = NULL; 115 116 Status = ProcessShellParameters ( 117 &KernelPath, &FdtPath, &InitrdPath, &LinuxCommandLine, &AtagMachineType 118 ); 119 if (EFI_ERROR (Status)) { 120 goto Error; 121 } 122 123 KernelDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (KernelPath); 124 if (KernelDevicePath != NULL) { 125 FreePool (KernelPath); 126 } else { 127 KernelTextDevicePath = KernelPath; 128 } 129 130 if (FdtPath != NULL) { 131 FdtDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (FdtPath); 132 if (FdtDevicePath != NULL) { 133 FreePool (FdtPath); 134 } else { 135 FdtTextDevicePath = FdtPath; 136 } 137 } 138 139 if (InitrdPath != NULL) { 140 InitrdDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (InitrdPath); 141 if (InitrdDevicePath != NULL) { 142 FreePool (InitrdPath); 143 } else { 144 InitrdTextDevicePath = InitrdPath; 145 } 146 } 147 148 } else { 149 Status = ProcessAppCommandLine ( 150 &KernelTextDevicePath, &FdtTextDevicePath, 151 &InitrdTextDevicePath, &LinuxCommandLine, &AtagMachineType 152 ); 153 if (EFI_ERROR (Status)) { 154 goto Error; 155 } 156 } 157 158 Status = EFI_INVALID_PARAMETER; 159 if (KernelTextDevicePath != NULL) { 160 KernelDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ( 161 KernelTextDevicePath 162 ); 163 if (KernelDevicePath == NULL) { 164 goto Error; 165 } 166 } 167 if (FdtTextDevicePath != NULL) { 168 FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ( 169 FdtTextDevicePath 170 ); 171 if (FdtDevicePath == NULL) { 172 goto Error; 173 } 174 } 175 if (InitrdTextDevicePath != NULL) { 176 InitrdDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ( 177 InitrdTextDevicePath 178 ); 179 if (InitrdDevicePath == NULL) { 180 goto Error; 181 } 182 } 183 184 if (LinuxCommandLine != NULL) { 185 AsciiLinuxCommandLine = AllocatePool ((StrLen (LinuxCommandLine) + 1) * sizeof (CHAR8)); 186 if (AsciiLinuxCommandLine == NULL) { 187 Status = EFI_OUT_OF_RESOURCES; 188 goto Error; 189 } 190 UnicodeStrToAsciiStr (LinuxCommandLine, AsciiLinuxCommandLine); 191 } 192 193 // 194 // Find Base of System Memory - we keep the lowest physical address 195 // 196 SystemMemoryBase = ~0; 197 GetSystemMemoryResources (&ResourceList); 198 ResourceLink = ResourceList.ForwardLink; 199 while (ResourceLink != NULL && ResourceLink != &ResourceList) { 200 Resource = (SYSTEM_MEMORY_RESOURCE*)ResourceLink; 201 if (Resource->PhysicalStart < SystemMemoryBase) { 202 SystemMemoryBase = Resource->PhysicalStart; 203 } 204 ResourceLink = ResourceLink->ForwardLink; 205 } 206 207 if (AtagMachineType != ARM_FDT_MACHINE_TYPE) { 208 Status = BootLinuxAtag (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, AsciiLinuxCommandLine, AtagMachineType); 209 } else { 210 Status = BootLinuxFdt (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, FdtDevicePath, AsciiLinuxCommandLine); 211 } 212 213 Error: 214 if (KernelTextDevicePath != NULL) { 215 FreePool (KernelTextDevicePath); 216 } 217 if (FdtTextDevicePath != NULL) { 218 FreePool (FdtTextDevicePath); 219 } 220 if (InitrdTextDevicePath != NULL) { 221 FreePool (InitrdTextDevicePath); 222 } 223 if (LinuxCommandLine != NULL) { 224 FreePool (LinuxCommandLine); 225 } 226 if (KernelDevicePath != NULL) { 227 FreePool (KernelDevicePath); 228 } 229 if (FdtDevicePath != NULL) { 230 FreePool (FdtDevicePath); 231 } 232 if (InitrdDevicePath != NULL) { 233 FreePool (InitrdDevicePath); 234 } 235 if (AsciiLinuxCommandLine != NULL) { 236 FreePool (AsciiLinuxCommandLine); 237 } 238 239 if (EFI_ERROR (Status)) { 240 PrintHii (NULL, STRING_TOKEN (STR_ERROR), Status); 241 } 242 243 HiiRemovePackages (mLinuxLoaderHiiHandle); 244 245 return Status; 246 } 247