]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c
EmbeddedPkg: 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
e7108d0e 23#define FDT_ADDITIONAL_ENTRIES_SIZE 0x400\r
fa74dd22
JN
24\r
25typedef struct {\r
e7108d0e
MK
26 MEMMAP_DEVICE_PATH Node1;\r
27 EFI_DEVICE_PATH_PROTOCOL End;\r
fa74dd22
JN
28} MEMORY_DEVICE_PATH;\r
29\r
7ea7f9c0 30typedef struct {\r
e7108d0e
MK
31 VENDOR_DEVICE_PATH VendorMediaNode;\r
32 EFI_DEVICE_PATH_PROTOCOL EndNode;\r
7ea7f9c0
JB
33} RAMDISK_DEVICE_PATH;\r
34\r
e7108d0e
MK
35STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg;\r
36STATIC VOID *mRamdiskData = NULL;\r
37STATIC UINTN mRamdiskSize = 0;\r
38STATIC EFI_HANDLE mRamDiskLoadFileHandle = NULL;\r
fa74dd22 39\r
e7108d0e 40STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate =\r
fa74dd22
JN
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
e7108d0e 61STATIC CONST RAMDISK_DEVICE_PATH mRamdiskDevicePath =\r
7ea7f9c0
JB
62{\r
63 {\r
64 {\r
65 MEDIA_DEVICE_PATH,\r
66 MEDIA_VENDOR_DP,\r
e7108d0e 67 { sizeof (VENDOR_DEVICE_PATH), 0 }\r
7ea7f9c0
JB
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
e7108d0e
MK
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
7ea7f9c0
JB
115 )\r
116\r
117{\r
118 // Verify if the valid parameters\r
e7108d0e
MK
119 if ((This == NULL) ||\r
120 (BufferSize == NULL) ||\r
121 (FilePath == NULL) ||\r
122 !IsDevicePathValid (FilePath, 0))\r
123 {\r
7ea7f9c0
JB
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126\r
127 if (BootPolicy) {\r
128 return EFI_UNSUPPORTED;\r
129 }\r
130\r
131 // Check if the given buffer size is big enough\r
132 // EFI_BUFFER_TOO_SMALL to allow caller to allocate a bigger buffer\r
133 if (mRamdiskSize == 0) {\r
134 return EFI_NOT_FOUND;\r
135 }\r
e7108d0e
MK
136\r
137 if ((Buffer == NULL) || (*BufferSize < mRamdiskSize)) {\r
7ea7f9c0
JB
138 *BufferSize = mRamdiskSize;\r
139 return EFI_BUFFER_TOO_SMALL;\r
140 }\r
141\r
142 // Copy InitRd\r
143 CopyMem (Buffer, mRamdiskData, mRamdiskSize);\r
144 *BufferSize = mRamdiskSize;\r
145\r
146 return EFI_SUCCESS;\r
147}\r
148\r
149///\r
150/// Load File Protocol instance\r
151///\r
152STATIC EFI_LOAD_FILE2_PROTOCOL mAndroidBootImgLoadFile2 = {\r
153 AndroidBootImgLoadFile2\r
154};\r
155\r
fa74dd22
JN
156EFI_STATUS\r
157AndroidBootImgGetImgSize (\r
e7108d0e
MK
158 IN VOID *BootImg,\r
159 OUT UINTN *ImgSize\r
fa74dd22
JN
160 )\r
161{\r
e7108d0e 162 ANDROID_BOOTIMG_HEADER *Header;\r
fa74dd22 163\r
e7108d0e 164 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
fa74dd22 165\r
e7108d0e
MK
166 if (AsciiStrnCmp (\r
167 (CONST CHAR8 *)Header->BootMagic,\r
168 ANDROID_BOOT_MAGIC,\r
169 ANDROID_BOOT_MAGIC_LENGTH\r
170 ) != 0)\r
171 {\r
fa74dd22
JN
172 return EFI_INVALID_PARAMETER;\r
173 }\r
174\r
175 /* The page size is not specified, but it should be power of 2 at least */\r
176 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
177\r
178 /* Get real size of abootimg */\r
179 *ImgSize = ALIGN_VALUE (Header->KernelSize, Header->PageSize) +\r
180 ALIGN_VALUE (Header->RamdiskSize, Header->PageSize) +\r
181 ALIGN_VALUE (Header->SecondStageBootloaderSize, Header->PageSize) +\r
182 Header->PageSize;\r
183 return EFI_SUCCESS;\r
184}\r
185\r
186EFI_STATUS\r
187AndroidBootImgGetKernelInfo (\r
e7108d0e 188 IN VOID *BootImg,\r
fa74dd22 189 OUT VOID **Kernel,\r
e7108d0e 190 OUT UINTN *KernelSize\r
fa74dd22
JN
191 )\r
192{\r
e7108d0e 193 ANDROID_BOOTIMG_HEADER *Header;\r
fa74dd22 194\r
e7108d0e 195 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
fa74dd22 196\r
e7108d0e
MK
197 if (AsciiStrnCmp (\r
198 (CONST CHAR8 *)Header->BootMagic,\r
199 ANDROID_BOOT_MAGIC,\r
200 ANDROID_BOOT_MAGIC_LENGTH\r
201 ) != 0)\r
202 {\r
fa74dd22
JN
203 return EFI_INVALID_PARAMETER;\r
204 }\r
205\r
206 if (Header->KernelSize == 0) {\r
207 return EFI_NOT_FOUND;\r
208 }\r
209\r
210 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
211\r
212 *KernelSize = Header->KernelSize;\r
e7108d0e 213 *Kernel = (VOID *)((UINTN)BootImg + Header->PageSize);\r
fa74dd22
JN
214 return EFI_SUCCESS;\r
215}\r
216\r
217EFI_STATUS\r
218AndroidBootImgGetRamdiskInfo (\r
e7108d0e 219 IN VOID *BootImg,\r
fa74dd22 220 OUT VOID **Ramdisk,\r
e7108d0e 221 OUT UINTN *RamdiskSize\r
fa74dd22
JN
222 )\r
223{\r
e7108d0e 224 ANDROID_BOOTIMG_HEADER *Header;\r
fa74dd22
JN
225\r
226 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
227\r
e7108d0e
MK
228 if (AsciiStrnCmp (\r
229 (CONST CHAR8 *)Header->BootMagic,\r
230 ANDROID_BOOT_MAGIC,\r
231 ANDROID_BOOT_MAGIC_LENGTH\r
232 ) != 0)\r
233 {\r
fa74dd22
JN
234 return EFI_INVALID_PARAMETER;\r
235 }\r
236\r
237 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
238\r
239 *RamdiskSize = Header->RamdiskSize;\r
240\r
241 if (Header->RamdiskSize != 0) {\r
242 *Ramdisk = (VOID *)((INTN)BootImg\r
243 + Header->PageSize\r
244 + ALIGN_VALUE (Header->KernelSize, Header->PageSize));\r
245 }\r
e7108d0e 246\r
fa74dd22
JN
247 return EFI_SUCCESS;\r
248}\r
249\r
250EFI_STATUS\r
251AndroidBootImgGetSecondBootLoaderInfo (\r
e7108d0e 252 IN VOID *BootImg,\r
fa74dd22 253 OUT VOID **Second,\r
e7108d0e 254 OUT UINTN *SecondSize\r
fa74dd22
JN
255 )\r
256{\r
e7108d0e 257 ANDROID_BOOTIMG_HEADER *Header;\r
fa74dd22
JN
258\r
259 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
260\r
e7108d0e
MK
261 if (AsciiStrnCmp (\r
262 (CONST CHAR8 *)Header->BootMagic,\r
263 ANDROID_BOOT_MAGIC,\r
264 ANDROID_BOOT_MAGIC_LENGTH\r
265 ) != 0)\r
266 {\r
fa74dd22
JN
267 return EFI_INVALID_PARAMETER;\r
268 }\r
269\r
270 ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));\r
271\r
272 *SecondSize = Header->SecondStageBootloaderSize;\r
273\r
274 if (Header->SecondStageBootloaderSize != 0) {\r
275 *Second = (VOID *)((UINTN)BootImg\r
276 + Header->PageSize\r
277 + ALIGN_VALUE (Header->KernelSize, Header->PageSize)\r
278 + ALIGN_VALUE (Header->RamdiskSize, Header->PageSize));\r
279 }\r
e7108d0e 280\r
fa74dd22
JN
281 return EFI_SUCCESS;\r
282}\r
283\r
284EFI_STATUS\r
285AndroidBootImgGetKernelArgs (\r
e7108d0e
MK
286 IN VOID *BootImg,\r
287 OUT CHAR8 *KernelArgs\r
fa74dd22
JN
288 )\r
289{\r
e7108d0e 290 ANDROID_BOOTIMG_HEADER *Header;\r
fa74dd22 291\r
e7108d0e
MK
292 Header = (ANDROID_BOOTIMG_HEADER *)BootImg;\r
293 AsciiStrnCpyS (\r
294 KernelArgs,\r
295 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE,\r
296 Header->KernelArgs,\r
297 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE\r
298 );\r
fa74dd22
JN
299\r
300 return EFI_SUCCESS;\r
301}\r
302\r
303EFI_STATUS\r
304AndroidBootImgGetFdt (\r
e7108d0e
MK
305 IN VOID *BootImg,\r
306 IN VOID **FdtBase\r
fa74dd22
JN
307 )\r
308{\r
e7108d0e
MK
309 UINTN SecondLoaderSize;\r
310 EFI_STATUS Status;\r
fa74dd22
JN
311\r
312 /* Check whether FDT is located in second boot region as some vendor do so,\r
313 * because second loader is never used as far as I know. */\r
314 Status = AndroidBootImgGetSecondBootLoaderInfo (\r
315 BootImg,\r
316 FdtBase,\r
317 &SecondLoaderSize\r
e7108d0e 318 );\r
fa74dd22
JN
319 return Status;\r
320}\r
321\r
322EFI_STATUS\r
323AndroidBootImgUpdateArgs (\r
e7108d0e
MK
324 IN VOID *BootImg,\r
325 OUT VOID *KernelArgs\r
fa74dd22
JN
326 )\r
327{\r
e7108d0e
MK
328 CHAR8 ImageKernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE];\r
329 EFI_STATUS Status;\r
fa74dd22
JN
330\r
331 // Get kernel arguments from Android boot image\r
332 Status = AndroidBootImgGetKernelArgs (BootImg, ImageKernelArgs);\r
333 if (EFI_ERROR (Status)) {\r
334 return Status;\r
335 }\r
e7108d0e
MK
336\r
337 AsciiStrToUnicodeStrS (\r
338 ImageKernelArgs,\r
339 KernelArgs,\r
340 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE >> 1\r
341 );\r
fa74dd22 342 // Append platform kernel arguments\r
e7108d0e
MK
343 if (mAndroidBootImg->AppendArgs) {\r
344 Status = mAndroidBootImg->AppendArgs (\r
345 KernelArgs,\r
346 ANDROID_BOOTIMG_KERNEL_ARGS_SIZE\r
347 );\r
fa74dd22 348 }\r
e7108d0e 349\r
fa74dd22
JN
350 return Status;\r
351}\r
352\r
7ea7f9c0
JB
353EFI_STATUS\r
354AndroidBootImgInstallLoadFile2 (\r
e7108d0e
MK
355 IN VOID *RamdiskData,\r
356 IN UINTN RamdiskSize\r
7ea7f9c0
JB
357 )\r
358{\r
359 mRamDiskLoadFileHandle = NULL;\r
e7108d0e
MK
360 mRamdiskData = RamdiskData;\r
361 mRamdiskSize = RamdiskSize;\r
7ea7f9c0
JB
362 return gBS->InstallMultipleProtocolInterfaces (\r
363 &mRamDiskLoadFileHandle,\r
364 &gEfiLoadFile2ProtocolGuid,\r
365 &mAndroidBootImgLoadFile2,\r
366 &gEfiDevicePathProtocolGuid,\r
367 &mRamdiskDevicePath,\r
368 NULL\r
369 );\r
370}\r
371\r
372EFI_STATUS\r
373AndroidBootImgUninstallLoadFile2 (\r
374 VOID\r
375 )\r
376{\r
e7108d0e 377 EFI_STATUS Status;\r
7ea7f9c0 378\r
e7108d0e 379 Status = EFI_SUCCESS;\r
7ea7f9c0
JB
380 mRamdiskData = NULL;\r
381 mRamdiskSize = 0;\r
382 if (mRamDiskLoadFileHandle != NULL) {\r
383 Status = gBS->UninstallMultipleProtocolInterfaces (\r
384 mRamDiskLoadFileHandle,\r
385 &gEfiLoadFile2ProtocolGuid,\r
386 &mAndroidBootImgLoadFile2,\r
387 &gEfiDevicePathProtocolGuid,\r
388 &mRamdiskDevicePath,\r
389 NULL\r
390 );\r
391 mRamDiskLoadFileHandle = NULL;\r
392 }\r
e7108d0e 393\r
7ea7f9c0
JB
394 return Status;\r
395}\r
396\r
e7108d0e
MK
397BOOLEAN\r
398AndroidBootImgAcpiSupported (\r
7ea7f9c0
JB
399 VOID\r
400 )\r
401{\r
402 EFI_STATUS Status;\r
e7108d0e 403 VOID *AcpiTable;\r
7ea7f9c0
JB
404\r
405 Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiTable);\r
406 return !EFI_ERROR (Status);\r
407}\r
408\r
fa74dd22
JN
409EFI_STATUS\r
410AndroidBootImgLocateFdt (\r
e7108d0e
MK
411 IN VOID *BootImg,\r
412 IN VOID **FdtBase\r
fa74dd22
JN
413 )\r
414{\r
e7108d0e
MK
415 INTN Err;\r
416 EFI_STATUS Status;\r
fa74dd22
JN
417\r
418 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, FdtBase);\r
419 if (!EFI_ERROR (Status)) {\r
420 return EFI_SUCCESS;\r
421 }\r
422\r
423 Status = AndroidBootImgGetFdt (BootImg, FdtBase);\r
424 if (EFI_ERROR (Status)) {\r
425 return Status;\r
426 }\r
e7108d0e 427\r
fa74dd22
JN
428 Err = fdt_check_header (*FdtBase);\r
429 if (Err != 0) {\r
e7108d0e
MK
430 DEBUG ((\r
431 DEBUG_ERROR,\r
432 "ERROR: Device Tree header not valid (Err:%d)\n",\r
433 Err\r
434 ));\r
fa74dd22
JN
435 return EFI_INVALID_PARAMETER;\r
436 }\r
e7108d0e 437\r
fa74dd22
JN
438 return EFI_SUCCESS;\r
439}\r
440\r
441INTN\r
442AndroidBootImgGetChosenNode (\r
e7108d0e 443 IN INTN UpdatedFdtBase\r
fa74dd22
JN
444 )\r
445{\r
e7108d0e 446 INTN ChosenNode;\r
fa74dd22
JN
447\r
448 ChosenNode = fdt_subnode_offset ((CONST VOID *)UpdatedFdtBase, 0, "chosen");\r
449 if (ChosenNode < 0) {\r
e7108d0e
MK
450 ChosenNode = fdt_add_subnode ((VOID *)UpdatedFdtBase, 0, "chosen");\r
451 if (ChosenNode < 0) {\r
452 DEBUG ((DEBUG_ERROR, "Fail to find fdt node chosen!\n"));\r
453 return 0;\r
fa74dd22
JN
454 }\r
455 }\r
e7108d0e 456\r
fa74dd22
JN
457 return ChosenNode;\r
458}\r
459\r
460EFI_STATUS\r
461AndroidBootImgSetProperty64 (\r
e7108d0e
MK
462 IN INTN UpdatedFdtBase,\r
463 IN INTN ChosenNode,\r
464 IN CHAR8 *PropertyName,\r
465 IN UINT64 Val\r
fa74dd22
JN
466 )\r
467{\r
e7108d0e
MK
468 INTN Err;\r
469 struct fdt_property *Property;\r
470 int Len;\r
471\r
472 Property = fdt_get_property_w (\r
473 (VOID *)UpdatedFdtBase,\r
474 ChosenNode,\r
475 PropertyName,\r
476 &Len\r
477 );\r
478 if ((NULL == Property) && (Len == -FDT_ERR_NOTFOUND)) {\r
479 Val = cpu_to_fdt64 (Val);\r
480 Err = fdt_appendprop (\r
481 (VOID *)UpdatedFdtBase,\r
482 ChosenNode,\r
483 PropertyName,\r
484 &Val,\r
485 sizeof (UINT64)\r
486 );\r
fa74dd22
JN
487 if (Err) {\r
488 DEBUG ((DEBUG_ERROR, "fdt_appendprop() fail: %a\n", fdt_strerror (Err)));\r
489 return EFI_INVALID_PARAMETER;\r
490 }\r
491 } else if (Property != NULL) {\r
e7108d0e
MK
492 Err = fdt_setprop_u64 (\r
493 (VOID *)UpdatedFdtBase,\r
494 ChosenNode,\r
495 PropertyName,\r
496 Val\r
497 );\r
fa74dd22
JN
498 if (Err) {\r
499 DEBUG ((DEBUG_ERROR, "fdt_setprop_u64() fail: %a\n", fdt_strerror (Err)));\r
500 return EFI_INVALID_PARAMETER;\r
501 }\r
502 } else {\r
503 DEBUG ((DEBUG_ERROR, "Failed to set fdt Property %a\n", PropertyName));\r
504 return EFI_INVALID_PARAMETER;\r
505 }\r
e7108d0e 506\r
fa74dd22
JN
507 return EFI_SUCCESS;\r
508}\r
509\r
510EFI_STATUS\r
511AndroidBootImgUpdateFdt (\r
e7108d0e
MK
512 IN VOID *BootImg,\r
513 IN VOID *FdtBase,\r
514 IN VOID *RamdiskData,\r
515 IN UINTN RamdiskSize\r
fa74dd22
JN
516 )\r
517{\r
e7108d0e
MK
518 INTN ChosenNode, Err, NewFdtSize;\r
519 EFI_STATUS Status;\r
520 EFI_PHYSICAL_ADDRESS UpdatedFdtBase, NewFdtBase;\r
fa74dd22
JN
521\r
522 NewFdtSize = (UINTN)fdt_totalsize (FdtBase)\r
523 + FDT_ADDITIONAL_ENTRIES_SIZE;\r
e7108d0e
MK
524 Status = gBS->AllocatePages (\r
525 AllocateAnyPages,\r
526 EfiBootServicesData,\r
527 EFI_SIZE_TO_PAGES (NewFdtSize),\r
528 &UpdatedFdtBase\r
529 );\r
fa74dd22 530 if (EFI_ERROR (Status)) {\r
e7108d0e
MK
531 DEBUG ((\r
532 DEBUG_WARN,\r
533 "Warning: Failed to reallocate FDT, err %d.\n",\r
534 Status\r
535 ));\r
fa74dd22
JN
536 return Status;\r
537 }\r
538\r
539 // Load the Original FDT tree into the new region\r
e7108d0e 540 Err = fdt_open_into (FdtBase, (VOID *)(INTN)UpdatedFdtBase, NewFdtSize);\r
fa74dd22
JN
541 if (Err) {\r
542 DEBUG ((DEBUG_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Err)));\r
543 Status = EFI_INVALID_PARAMETER;\r
544 goto Fdt_Exit;\r
545 }\r
546\r
7ea7f9c0
JB
547 if (FeaturePcdGet (PcdAndroidBootLoadFile2)) {\r
548 Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
549 if (EFI_ERROR (Status)) {\r
550 goto Fdt_Exit;\r
551 }\r
552 } else {\r
e7108d0e 553 ChosenNode = AndroidBootImgGetChosenNode (UpdatedFdtBase);\r
7ea7f9c0
JB
554 if (!ChosenNode) {\r
555 goto Fdt_Exit;\r
556 }\r
fa74dd22 557\r
e7108d0e
MK
558 Status = AndroidBootImgSetProperty64 (\r
559 UpdatedFdtBase,\r
560 ChosenNode,\r
561 "linux,initrd-start",\r
562 (UINTN)RamdiskData\r
563 );\r
7ea7f9c0
JB
564 if (EFI_ERROR (Status)) {\r
565 goto Fdt_Exit;\r
566 }\r
fa74dd22 567\r
e7108d0e
MK
568 Status = AndroidBootImgSetProperty64 (\r
569 UpdatedFdtBase,\r
570 ChosenNode,\r
571 "linux,initrd-end",\r
572 (UINTN)RamdiskData + RamdiskSize\r
573 );\r
7ea7f9c0
JB
574 if (EFI_ERROR (Status)) {\r
575 goto Fdt_Exit;\r
576 }\r
fa74dd22
JN
577 }\r
578\r
579 if (mAndroidBootImg->UpdateDtb) {\r
580 Status = mAndroidBootImg->UpdateDtb (UpdatedFdtBase, &NewFdtBase);\r
581 if (EFI_ERROR (Status)) {\r
582 goto Fdt_Exit;\r
583 }\r
c0cd26f4
JB
584 } else {\r
585 NewFdtBase = UpdatedFdtBase;\r
fa74dd22 586 }\r
e7108d0e 587\r
c0cd26f4
JB
588 Status = gBS->InstallConfigurationTable (\r
589 &gFdtTableGuid,\r
590 (VOID *)(UINTN)NewFdtBase\r
591 );\r
fa74dd22 592\r
fa74dd22
JN
593 if (!EFI_ERROR (Status)) {\r
594 return EFI_SUCCESS;\r
595 }\r
596\r
597Fdt_Exit:\r
598 gBS->FreePages (UpdatedFdtBase, EFI_SIZE_TO_PAGES (NewFdtSize));\r
599 return Status;\r
600}\r
601\r
602EFI_STATUS\r
603AndroidBootImgBoot (\r
e7108d0e
MK
604 IN VOID *Buffer,\r
605 IN UINTN BufferSize\r
fa74dd22
JN
606 )\r
607{\r
e7108d0e
MK
608 EFI_STATUS Status;\r
609 VOID *Kernel;\r
610 UINTN KernelSize;\r
611 MEMORY_DEVICE_PATH KernelDevicePath;\r
612 EFI_HANDLE ImageHandle;\r
613 VOID *NewKernelArg;\r
614 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
615 VOID *RamdiskData;\r
616 UINTN RamdiskSize;\r
617 IN VOID *FdtBase;\r
fa74dd22 618\r
f2a7e24e 619 NewKernelArg = NULL;\r
e7108d0e 620 ImageHandle = NULL;\r
f2a7e24e 621\r
e7108d0e
MK
622 Status = gBS->LocateProtocol (\r
623 &gAndroidBootImgProtocolGuid,\r
624 NULL,\r
625 (VOID **)&mAndroidBootImg\r
626 );\r
fa74dd22 627 if (EFI_ERROR (Status)) {\r
f2a7e24e 628 goto Exit;\r
fa74dd22
JN
629 }\r
630\r
631 Status = AndroidBootImgGetKernelInfo (\r
e7108d0e
MK
632 Buffer,\r
633 &Kernel,\r
634 &KernelSize\r
635 );\r
fa74dd22 636 if (EFI_ERROR (Status)) {\r
f2a7e24e 637 goto Exit;\r
fa74dd22
JN
638 }\r
639\r
640 NewKernelArg = AllocateZeroPool (ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);\r
641 if (NewKernelArg == NULL) {\r
642 DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n"));\r
f2a7e24e
JB
643 Status = EFI_OUT_OF_RESOURCES;\r
644 goto Exit;\r
fa74dd22
JN
645 }\r
646\r
647 Status = AndroidBootImgUpdateArgs (Buffer, NewKernelArg);\r
648 if (EFI_ERROR (Status)) {\r
f2a7e24e 649 goto Exit;\r
fa74dd22
JN
650 }\r
651\r
652 Status = AndroidBootImgGetRamdiskInfo (\r
e7108d0e
MK
653 Buffer,\r
654 &RamdiskData,\r
655 &RamdiskSize\r
656 );\r
fa74dd22 657 if (EFI_ERROR (Status)) {\r
f2a7e24e 658 goto Exit;\r
fa74dd22
JN
659 }\r
660\r
7ea7f9c0
JB
661 if (AndroidBootImgAcpiSupported ()) {\r
662 Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
663 if (EFI_ERROR (Status)) {\r
664 goto Exit;\r
665 }\r
666 } else {\r
667 Status = AndroidBootImgLocateFdt (Buffer, &FdtBase);\r
668 if (EFI_ERROR (Status)) {\r
669 goto Exit;\r
670 }\r
fa74dd22 671\r
7ea7f9c0
JB
672 Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize);\r
673 if (EFI_ERROR (Status)) {\r
674 goto Exit;\r
675 }\r
fa74dd22
JN
676 }\r
677\r
678 KernelDevicePath = mMemoryDevicePathTemplate;\r
679\r
e7108d0e
MK
680 KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel;\r
681 KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel\r
fa74dd22
JN
682 + KernelSize;\r
683\r
e7108d0e
MK
684 Status = gBS->LoadImage (\r
685 TRUE,\r
686 gImageHandle,\r
687 (EFI_DEVICE_PATH *)&KernelDevicePath,\r
688 (VOID *)(UINTN)Kernel,\r
689 KernelSize,\r
690 &ImageHandle\r
691 );\r
82e0c422 692 if (EFI_ERROR (Status)) {\r
f2a7e24e 693 goto Exit;\r
82e0c422 694 }\r
fa74dd22
JN
695\r
696 // Set kernel arguments\r
e7108d0e
MK
697 Status = gBS->HandleProtocol (\r
698 ImageHandle,\r
699 &gEfiLoadedImageProtocolGuid,\r
700 (VOID **)&ImageInfo\r
701 );\r
f2a7e24e
JB
702 if (EFI_ERROR (Status)) {\r
703 goto Exit;\r
704 }\r
e7108d0e
MK
705\r
706 ImageInfo->LoadOptions = NewKernelArg;\r
fa74dd22
JN
707 ImageInfo->LoadOptionsSize = StrLen (NewKernelArg) * sizeof (CHAR16);\r
708\r
709 // Before calling the image, enable the Watchdog Timer for the 5 Minute period\r
710 gBS->SetWatchdogTimer (5 * 60, 0x10000, 0, NULL);\r
711 // Start the image\r
712 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
713 // Clear the Watchdog Timer if the image returns\r
714 gBS->SetWatchdogTimer (0, 0x10000, 0, NULL);\r
f2a7e24e
JB
715\r
716Exit:\r
e7108d0e 717 // Unload image as it will not be used anymore\r
f2a7e24e
JB
718 if (ImageHandle != NULL) {\r
719 gBS->UnloadImage (ImageHandle);\r
720 ImageHandle = NULL;\r
721 }\r
e7108d0e 722\r
f2a7e24e
JB
723 if (EFI_ERROR (Status)) {\r
724 if (NewKernelArg != NULL) {\r
725 FreePool (NewKernelArg);\r
726 NewKernelArg = NULL;\r
727 }\r
728 }\r
e7108d0e 729\r
7ea7f9c0 730 AndroidBootImgUninstallLoadFile2 ();\r
f2a7e24e 731 return Status;\r
fa74dd22 732}\r