]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / EmbeddedPkg / Library / AndroidBootImgLib / AndroidBootImgLib.c
CommitLineData
fa74dd22
JN
1/** @file\r
2\r
3 Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
4 Copyright (c) 2017, Linaro. All rights reserved.\r
5\r
878b807a 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
fa74dd22
JN
7\r
8**/\r
9\r
10#include <libfdt.h>\r
11#include <Library/AndroidBootImgLib.h>\r
12#include <Library/PrintLib.h>\r
7ea7f9c0 13#include <Library/DevicePathLib.h>\r
fa74dd22
JN
14#include <Library/UefiBootServicesTableLib.h>\r
15#include <Library/UefiLib.h>\r
16\r
17#include <Protocol/AndroidBootImg.h>\r
7ea7f9c0 18#include <Protocol/LoadFile2.h>\r
fa74dd22
JN
19#include <Protocol/LoadedImage.h>\r
20\r
7ea7f9c0
JB
21#include <Guid/LinuxEfiInitrdMedia.h>\r
22\r
fa74dd22
JN
23#define FDT_ADDITIONAL_ENTRIES_SIZE 0x400\r
24\r
25typedef struct {\r
26 MEMMAP_DEVICE_PATH Node1;\r
27 EFI_DEVICE_PATH_PROTOCOL End;\r
28} MEMORY_DEVICE_PATH;\r
29\r
7ea7f9c0
JB
30typedef struct {\r
31 VENDOR_DEVICE_PATH VendorMediaNode;\r
32 EFI_DEVICE_PATH_PROTOCOL EndNode;\r
33} RAMDISK_DEVICE_PATH;\r
34\r
fa74dd22 35STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg;\r
7ea7f9c0
JB
36STATIC VOID *mRamdiskData = NULL;\r
37STATIC UINTN mRamdiskSize = 0;\r
38STATIC EFI_HANDLE mRamDiskLoadFileHandle = NULL;\r
fa74dd22
JN
39\r
40STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate =\r
41{\r
42 {\r
43 {\r
44 HARDWARE_DEVICE_PATH,\r
45 HW_MEMMAP_DP,\r
46 {\r
47 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),\r
48 (UINT8)((sizeof (MEMMAP_DEVICE_PATH)) >> 8),\r
49 },\r
50 }, // Header\r
51 0, // StartingAddress (set at runtime)\r
52 0 // EndingAddress (set at runtime)\r
53 }, // Node1\r
54 {\r
55 END_DEVICE_PATH_TYPE,\r
56 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
57 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }\r
58 } // End\r
59};\r
60\r
7ea7f9c0
JB
61STATIC CONST RAMDISK_DEVICE_PATH mRamdiskDevicePath =\r
62{\r
63 {\r
64 {\r
65 MEDIA_DEVICE_PATH,\r
66 MEDIA_VENDOR_DP,\r
67 { sizeof (VENDOR_DEVICE_PATH), 0 }\r
68 },\r
69 LINUX_EFI_INITRD_MEDIA_GUID\r
70 },\r
71 {\r
72 END_DEVICE_PATH_TYPE,\r
73 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
74 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }\r
75 }\r
76};\r
77\r
78/**\r
79 Causes the driver to load a specified file.\r
80\r
81 @param This Protocol instance pointer.\r
82 @param FilePath The device specific path of the file to load.\r
83 @param BootPolicy Should always be FALSE.\r
84 @param BufferSize On input the size of Buffer in bytes. On output with a return\r
85 code of EFI_SUCCESS, the amount of data transferred to\r
86 Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,\r
87 the size of Buffer required to retrieve the requested file.\r
88 @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL,\r
89 then no the size of the requested file is returned in\r
90 BufferSize.\r
91\r
92 @retval EFI_SUCCESS The file was loaded.\r
93 @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
94 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
95 BufferSize is NULL.\r
96 @retval EFI_NO_MEDIA No medium was present to load the file.\r
97 @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.\r
98 @retval EFI_NO_RESPONSE The remote system did not respond.\r
99 @retval EFI_NOT_FOUND The file was not found\r
100 @retval EFI_ABORTED The file load process was manually canceled.\r
101 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current\r
102 directory entry. BufferSize has been updated with\r
103 the size needed to complete the request.\r
104\r
105\r
106**/\r
107EFI_STATUS\r
108EFIAPI\r
109AndroidBootImgLoadFile2 (\r
110 IN EFI_LOAD_FILE2_PROTOCOL *This,\r
111 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
112 IN BOOLEAN BootPolicy,\r
113 IN OUT UINTN *BufferSize,\r
114 IN VOID *Buffer OPTIONAL\r
115 )\r
116\r
117{\r
118 // Verify if the valid parameters\r
119 if (This == NULL ||\r
120 BufferSize == NULL ||\r
121 FilePath == NULL ||\r
122 !IsDevicePathValid (FilePath, 0)) {\r
123 return EFI_INVALID_PARAMETER;\r
124 }\r
125\r
126 if (BootPolicy) {\r
127 return EFI_UNSUPPORTED;\r
128 }\r
129\r
130 // Check if the given buffer size is big enough\r
131 // EFI_BUFFER_TOO_SMALL to allow caller to allocate a bigger buffer\r
132 if (mRamdiskSize == 0) {\r
133 return EFI_NOT_FOUND;\r
134 }\r
135 if (Buffer == NULL || *BufferSize < mRamdiskSize) {\r
136 *BufferSize = mRamdiskSize;\r
137 return EFI_BUFFER_TOO_SMALL;\r
138 }\r
139\r
140 // Copy InitRd\r
141 CopyMem (Buffer, mRamdiskData, mRamdiskSize);\r
142 *BufferSize = mRamdiskSize;\r
143\r
144 return EFI_SUCCESS;\r
145}\r
146\r
147///\r
148/// Load File Protocol instance\r
149///\r
150STATIC EFI_LOAD_FILE2_PROTOCOL mAndroidBootImgLoadFile2 = {\r
151 AndroidBootImgLoadFile2\r
152};\r
153\r
fa74dd22
JN
154EFI_STATUS\r
155AndroidBootImgGetImgSize (\r
156 IN VOID *BootImg,\r
157 OUT UINTN *ImgSize\r
158 )\r
159{\r
160 ANDROID_BOOTIMG_HEADER *Header;\r
161\r
162 Header = (ANDROID_BOOTIMG_HEADER *) BootImg;\r
163\r
164 if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,\r
165 ANDROID_BOOT_MAGIC_LENGTH) != 0) {\r
166 return EFI_INVALID_PARAMETER;\r
167 }\r
168\r
169 /* The page size is not specified, but it should be power of 2 at least */\r
170 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
171\r
172 /* Get real size of abootimg */\r
173 *ImgSize = ALIGN_VALUE (Header->KernelSize, Header->PageSize) +\r
174 ALIGN_VALUE (Header->RamdiskSize, Header->PageSize) +\r
175 ALIGN_VALUE (Header->SecondStageBootloaderSize, Header->PageSize) +\r
176 Header->PageSize;\r
177 return EFI_SUCCESS;\r
178}\r
179\r
180EFI_STATUS\r
181AndroidBootImgGetKernelInfo (\r
182 IN VOID *BootImg,\r
183 OUT VOID **Kernel,\r
184 OUT UINTN *KernelSize\r
185 )\r
186{\r
187 ANDROID_BOOTIMG_HEADER *Header;\r
188\r
189 Header = (ANDROID_BOOTIMG_HEADER *) BootImg;\r
190\r
191 if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,\r
192 ANDROID_BOOT_MAGIC_LENGTH) != 0) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195\r
196 if (Header->KernelSize == 0) {\r
197 return EFI_NOT_FOUND;\r
198 }\r
199\r
200 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
201\r
202 *KernelSize = Header->KernelSize;\r
e43d0884 203 *Kernel = (VOID *)((UINTN)BootImg + Header->PageSize);\r
fa74dd22
JN
204 return EFI_SUCCESS;\r
205}\r
206\r
207EFI_STATUS\r
208AndroidBootImgGetRamdiskInfo (\r
209 IN VOID *BootImg,\r
210 OUT VOID **Ramdisk,\r
211 OUT UINTN *RamdiskSize\r
212 )\r
213{\r
214 ANDROID_BOOTIMG_HEADER *Header;\r
215\r
216 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
217\r
218 if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,\r
219 ANDROID_BOOT_MAGIC_LENGTH) != 0) {\r
220 return EFI_INVALID_PARAMETER;\r
221 }\r
222\r
223 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
224\r
225 *RamdiskSize = Header->RamdiskSize;\r
226\r
227 if (Header->RamdiskSize != 0) {\r
228 *Ramdisk = (VOID *)((INTN)BootImg\r
229 + Header->PageSize\r
230 + ALIGN_VALUE (Header->KernelSize, Header->PageSize));\r
231 }\r
232 return EFI_SUCCESS;\r
233}\r
234\r
235EFI_STATUS\r
236AndroidBootImgGetSecondBootLoaderInfo (\r
237 IN VOID *BootImg,\r
238 OUT VOID **Second,\r
239 OUT UINTN *SecondSize\r
240 )\r
241{\r
242 ANDROID_BOOTIMG_HEADER *Header;\r
243\r
244 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
245\r
246 if (AsciiStrnCmp ((CONST CHAR8 *)Header->BootMagic, ANDROID_BOOT_MAGIC,\r
247 ANDROID_BOOT_MAGIC_LENGTH) != 0) {\r
248 return EFI_INVALID_PARAMETER;\r
249 }\r
250\r
251 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
252\r
253 *SecondSize = Header->SecondStageBootloaderSize;\r
254\r
255 if (Header->SecondStageBootloaderSize != 0) {\r
256 *Second = (VOID *)((UINTN)BootImg\r
257 + Header->PageSize\r
258 + ALIGN_VALUE (Header->KernelSize, Header->PageSize)\r
259 + ALIGN_VALUE (Header->RamdiskSize, Header->PageSize));\r
260 }\r
261 return EFI_SUCCESS;\r
262}\r
263\r
264EFI_STATUS\r
265AndroidBootImgGetKernelArgs (\r
266 IN VOID *BootImg,\r
267 OUT CHAR8 *KernelArgs\r
268 )\r
269{\r
270 ANDROID_BOOTIMG_HEADER *Header;\r
271\r
272 Header = (ANDROID_BOOTIMG_HEADER *) BootImg;\r
273 AsciiStrnCpyS (KernelArgs, ANDROID_BOOTIMG_KERNEL_ARGS_SIZE, Header->KernelArgs,\r
274 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);\r
275\r
276 return EFI_SUCCESS;\r
277}\r
278\r
279EFI_STATUS\r
280AndroidBootImgGetFdt (\r
281 IN VOID *BootImg,\r
282 IN VOID **FdtBase\r
283 )\r
284{\r
285 UINTN SecondLoaderSize;\r
286 EFI_STATUS Status;\r
287\r
288 /* Check whether FDT is located in second boot region as some vendor do so,\r
289 * because second loader is never used as far as I know. */\r
290 Status = AndroidBootImgGetSecondBootLoaderInfo (\r
291 BootImg,\r
292 FdtBase,\r
293 &SecondLoaderSize\r
294 );\r
295 return Status;\r
296}\r
297\r
298EFI_STATUS\r
299AndroidBootImgUpdateArgs (\r
300 IN VOID *BootImg,\r
301 OUT VOID *KernelArgs\r
302 )\r
303{\r
304 CHAR8 ImageKernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE];\r
305 EFI_STATUS Status;\r
306\r
307 // Get kernel arguments from Android boot image\r
308 Status = AndroidBootImgGetKernelArgs (BootImg, ImageKernelArgs);\r
309 if (EFI_ERROR (Status)) {\r
310 return Status;\r
311 }\r
312 AsciiStrToUnicodeStrS (ImageKernelArgs, KernelArgs,\r
313 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE >> 1);\r
314 // Append platform kernel arguments\r
315 if(mAndroidBootImg->AppendArgs) {\r
316 Status = mAndroidBootImg->AppendArgs (KernelArgs,\r
317 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);\r
318 }\r
319 return Status;\r
320}\r
321\r
7ea7f9c0
JB
322EFI_STATUS\r
323AndroidBootImgInstallLoadFile2 (\r
324 IN VOID *RamdiskData,\r
325 IN UINTN RamdiskSize\r
326 )\r
327{\r
328 mRamDiskLoadFileHandle = NULL;\r
329 mRamdiskData = RamdiskData;\r
330 mRamdiskSize = RamdiskSize;\r
331 return gBS->InstallMultipleProtocolInterfaces (\r
332 &mRamDiskLoadFileHandle,\r
333 &gEfiLoadFile2ProtocolGuid,\r
334 &mAndroidBootImgLoadFile2,\r
335 &gEfiDevicePathProtocolGuid,\r
336 &mRamdiskDevicePath,\r
337 NULL\r
338 );\r
339}\r
340\r
341EFI_STATUS\r
342AndroidBootImgUninstallLoadFile2 (\r
343 VOID\r
344 )\r
345{\r
346 EFI_STATUS Status;\r
347\r
348 Status = EFI_SUCCESS;\r
349 mRamdiskData = NULL;\r
350 mRamdiskSize = 0;\r
351 if (mRamDiskLoadFileHandle != NULL) {\r
352 Status = gBS->UninstallMultipleProtocolInterfaces (\r
353 mRamDiskLoadFileHandle,\r
354 &gEfiLoadFile2ProtocolGuid,\r
355 &mAndroidBootImgLoadFile2,\r
356 &gEfiDevicePathProtocolGuid,\r
357 &mRamdiskDevicePath,\r
358 NULL\r
359 );\r
360 mRamDiskLoadFileHandle = NULL;\r
361 }\r
362 return Status;\r
363}\r
364\r
365BOOLEAN AndroidBootImgAcpiSupported (\r
366 VOID\r
367 )\r
368{\r
369 EFI_STATUS Status;\r
370 VOID *AcpiTable;\r
371\r
372 Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiTable);\r
373 return !EFI_ERROR (Status);\r
374}\r
375\r
fa74dd22
JN
376EFI_STATUS\r
377AndroidBootImgLocateFdt (\r
378 IN VOID *BootImg,\r
379 IN VOID **FdtBase\r
380 )\r
381{\r
382 INTN Err;\r
383 EFI_STATUS Status;\r
384\r
385 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, FdtBase);\r
386 if (!EFI_ERROR (Status)) {\r
387 return EFI_SUCCESS;\r
388 }\r
389\r
390 Status = AndroidBootImgGetFdt (BootImg, FdtBase);\r
391 if (EFI_ERROR (Status)) {\r
392 return Status;\r
393 }\r
394 Err = fdt_check_header (*FdtBase);\r
395 if (Err != 0) {\r
396 DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (Err:%d)\n",\r
397 Err));\r
398 return EFI_INVALID_PARAMETER;\r
399 }\r
400 return EFI_SUCCESS;\r
401}\r
402\r
403INTN\r
404AndroidBootImgGetChosenNode (\r
405 IN INTN UpdatedFdtBase\r
406 )\r
407{\r
408 INTN ChosenNode;\r
409\r
410 ChosenNode = fdt_subnode_offset ((CONST VOID *)UpdatedFdtBase, 0, "chosen");\r
411 if (ChosenNode < 0) {\r
412 ChosenNode = fdt_add_subnode((VOID *)UpdatedFdtBase, 0, "chosen");\r
413 if (ChosenNode < 0) {\r
414 DEBUG ((DEBUG_ERROR, "Fail to find fdt node chosen!\n"));\r
415 return 0;\r
416 }\r
417 }\r
418 return ChosenNode;\r
419}\r
420\r
421EFI_STATUS\r
422AndroidBootImgSetProperty64 (\r
423 IN INTN UpdatedFdtBase,\r
424 IN INTN ChosenNode,\r
425 IN CHAR8 *PropertyName,\r
426 IN UINT64 Val\r
427 )\r
428{\r
429 INTN Err;\r
430 struct fdt_property *Property;\r
431 int Len;\r
432\r
433 Property = fdt_get_property_w((VOID *)UpdatedFdtBase, ChosenNode,\r
434 PropertyName, &Len);\r
435 if (NULL == Property && Len == -FDT_ERR_NOTFOUND) {\r
436 Val = cpu_to_fdt64(Val);\r
437 Err = fdt_appendprop ((VOID *)UpdatedFdtBase, ChosenNode,\r
438 PropertyName, &Val, sizeof (UINT64));\r
439 if (Err) {\r
440 DEBUG ((DEBUG_ERROR, "fdt_appendprop() fail: %a\n", fdt_strerror (Err)));\r
441 return EFI_INVALID_PARAMETER;\r
442 }\r
443 } else if (Property != NULL) {\r
444 Err = fdt_setprop_u64((VOID *)UpdatedFdtBase, ChosenNode,\r
445 PropertyName, Val);\r
446 if (Err) {\r
447 DEBUG ((DEBUG_ERROR, "fdt_setprop_u64() fail: %a\n", fdt_strerror (Err)));\r
448 return EFI_INVALID_PARAMETER;\r
449 }\r
450 } else {\r
451 DEBUG ((DEBUG_ERROR, "Failed to set fdt Property %a\n", PropertyName));\r
452 return EFI_INVALID_PARAMETER;\r
453 }\r
454 return EFI_SUCCESS;\r
455}\r
456\r
457EFI_STATUS\r
458AndroidBootImgUpdateFdt (\r
459 IN VOID *BootImg,\r
460 IN VOID *FdtBase,\r
461 IN VOID *RamdiskData,\r
462 IN UINTN RamdiskSize\r
463 )\r
464{\r
465 INTN ChosenNode, Err, NewFdtSize;\r
466 EFI_STATUS Status;\r
467 EFI_PHYSICAL_ADDRESS UpdatedFdtBase, NewFdtBase;\r
468\r
469 NewFdtSize = (UINTN)fdt_totalsize (FdtBase)\r
470 + FDT_ADDITIONAL_ENTRIES_SIZE;\r
471 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,\r
472 EFI_SIZE_TO_PAGES (NewFdtSize), &UpdatedFdtBase);\r
473 if (EFI_ERROR (Status)) {\r
474 DEBUG ((DEBUG_WARN, "Warning: Failed to reallocate FDT, err %d.\n",\r
475 Status));\r
476 return Status;\r
477 }\r
478\r
479 // Load the Original FDT tree into the new region\r
480 Err = fdt_open_into(FdtBase, (VOID*)(INTN)UpdatedFdtBase, NewFdtSize);\r
481 if (Err) {\r
482 DEBUG ((DEBUG_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Err)));\r
483 Status = EFI_INVALID_PARAMETER;\r
484 goto Fdt_Exit;\r
485 }\r
486\r
7ea7f9c0
JB
487 if (FeaturePcdGet (PcdAndroidBootLoadFile2)) {\r
488 Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
489 if (EFI_ERROR (Status)) {\r
490 goto Fdt_Exit;\r
491 }\r
492 } else {\r
493 ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase);\r
494 if (!ChosenNode) {\r
495 goto Fdt_Exit;\r
496 }\r
fa74dd22 497\r
7ea7f9c0
JB
498 Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
499 "linux,initrd-start",\r
500 (UINTN)RamdiskData);\r
501 if (EFI_ERROR (Status)) {\r
502 goto Fdt_Exit;\r
503 }\r
fa74dd22 504\r
7ea7f9c0
JB
505 Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
506 "linux,initrd-end",\r
507 (UINTN)RamdiskData + RamdiskSize);\r
508 if (EFI_ERROR (Status)) {\r
509 goto Fdt_Exit;\r
510 }\r
fa74dd22
JN
511 }\r
512\r
513 if (mAndroidBootImg->UpdateDtb) {\r
514 Status = mAndroidBootImg->UpdateDtb (UpdatedFdtBase, &NewFdtBase);\r
515 if (EFI_ERROR (Status)) {\r
516 goto Fdt_Exit;\r
517 }\r
c0cd26f4
JB
518 } else {\r
519 NewFdtBase = UpdatedFdtBase;\r
fa74dd22 520 }\r
c0cd26f4
JB
521 Status = gBS->InstallConfigurationTable (\r
522 &gFdtTableGuid,\r
523 (VOID *)(UINTN)NewFdtBase\r
524 );\r
fa74dd22 525\r
fa74dd22
JN
526 if (!EFI_ERROR (Status)) {\r
527 return EFI_SUCCESS;\r
528 }\r
529\r
530Fdt_Exit:\r
531 gBS->FreePages (UpdatedFdtBase, EFI_SIZE_TO_PAGES (NewFdtSize));\r
532 return Status;\r
533}\r
534\r
535EFI_STATUS\r
536AndroidBootImgBoot (\r
537 IN VOID *Buffer,\r
538 IN UINTN BufferSize\r
539 )\r
540{\r
541 EFI_STATUS Status;\r
542 VOID *Kernel;\r
543 UINTN KernelSize;\r
544 MEMORY_DEVICE_PATH KernelDevicePath;\r
545 EFI_HANDLE ImageHandle;\r
546 VOID *NewKernelArg;\r
547 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
548 VOID *RamdiskData;\r
549 UINTN RamdiskSize;\r
550 IN VOID *FdtBase;\r
551\r
f2a7e24e
JB
552 NewKernelArg = NULL;\r
553 ImageHandle = NULL;\r
554\r
fa74dd22
JN
555 Status = gBS->LocateProtocol (&gAndroidBootImgProtocolGuid, NULL,\r
556 (VOID **) &mAndroidBootImg);\r
557 if (EFI_ERROR (Status)) {\r
f2a7e24e 558 goto Exit;\r
fa74dd22
JN
559 }\r
560\r
561 Status = AndroidBootImgGetKernelInfo (\r
562 Buffer,\r
563 &Kernel,\r
564 &KernelSize\r
565 );\r
566 if (EFI_ERROR (Status)) {\r
f2a7e24e 567 goto Exit;\r
fa74dd22
JN
568 }\r
569\r
570 NewKernelArg = AllocateZeroPool (ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);\r
571 if (NewKernelArg == NULL) {\r
572 DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n"));\r
f2a7e24e
JB
573 Status = EFI_OUT_OF_RESOURCES;\r
574 goto Exit;\r
fa74dd22
JN
575 }\r
576\r
577 Status = AndroidBootImgUpdateArgs (Buffer, NewKernelArg);\r
578 if (EFI_ERROR (Status)) {\r
f2a7e24e 579 goto Exit;\r
fa74dd22
JN
580 }\r
581\r
582 Status = AndroidBootImgGetRamdiskInfo (\r
583 Buffer,\r
584 &RamdiskData,\r
585 &RamdiskSize\r
586 );\r
587 if (EFI_ERROR (Status)) {\r
f2a7e24e 588 goto Exit;\r
fa74dd22
JN
589 }\r
590\r
7ea7f9c0
JB
591 if (AndroidBootImgAcpiSupported ()) {\r
592 Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
593 if (EFI_ERROR (Status)) {\r
594 goto Exit;\r
595 }\r
596 } else {\r
597 Status = AndroidBootImgLocateFdt (Buffer, &FdtBase);\r
598 if (EFI_ERROR (Status)) {\r
599 goto Exit;\r
600 }\r
fa74dd22 601\r
7ea7f9c0
JB
602 Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize);\r
603 if (EFI_ERROR (Status)) {\r
604 goto Exit;\r
605 }\r
fa74dd22
JN
606 }\r
607\r
608 KernelDevicePath = mMemoryDevicePathTemplate;\r
609\r
610 KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel;\r
611 KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel\r
612 + KernelSize;\r
613\r
614 Status = gBS->LoadImage (TRUE, gImageHandle,\r
615 (EFI_DEVICE_PATH *)&KernelDevicePath,\r
616 (VOID*)(UINTN)Kernel, KernelSize, &ImageHandle);\r
82e0c422 617 if (EFI_ERROR (Status)) {\r
f2a7e24e 618 goto Exit;\r
82e0c422 619 }\r
fa74dd22
JN
620\r
621 // Set kernel arguments\r
622 Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid,\r
623 (VOID **) &ImageInfo);\r
f2a7e24e
JB
624 if (EFI_ERROR (Status)) {\r
625 goto Exit;\r
626 }\r
fa74dd22
JN
627 ImageInfo->LoadOptions = NewKernelArg;\r
628 ImageInfo->LoadOptionsSize = StrLen (NewKernelArg) * sizeof (CHAR16);\r
629\r
630 // Before calling the image, enable the Watchdog Timer for the 5 Minute period\r
631 gBS->SetWatchdogTimer (5 * 60, 0x10000, 0, NULL);\r
632 // Start the image\r
633 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
634 // Clear the Watchdog Timer if the image returns\r
635 gBS->SetWatchdogTimer (0, 0x10000, 0, NULL);\r
f2a7e24e
JB
636\r
637Exit:\r
638 //Unload image as it will not be used anymore\r
639 if (ImageHandle != NULL) {\r
640 gBS->UnloadImage (ImageHandle);\r
641 ImageHandle = NULL;\r
642 }\r
643 if (EFI_ERROR (Status)) {\r
644 if (NewKernelArg != NULL) {\r
645 FreePool (NewKernelArg);\r
646 NewKernelArg = NULL;\r
647 }\r
648 }\r
7ea7f9c0 649 AndroidBootImgUninstallLoadFile2 ();\r
f2a7e24e 650 return Status;\r
fa74dd22 651}\r