]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Application/LinuxLoader/LinuxLoader.c
70b960b66f0e4a0f35744a3f2a74cf0a950929f4
[mirror_edk2.git] / ArmPkg / Application / LinuxLoader / LinuxLoader.c
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 }