AndroidBootImgLib.c 19 KB

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