3 Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "AndroidFastbootApp.h"
11 #include <Protocol/DevicePath.h>
12 #include <Protocol/LoadedImage.h>
14 #include <Library/DevicePathLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
18 // Device Path representing an image in memory
21 MEMMAP_DEVICE_PATH Node1
;
22 EFI_DEVICE_PATH_PROTOCOL End
;
26 STATIC CONST MEMORY_DEVICE_PATH MemoryDevicePathTemplate
=
33 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
34 (UINT8
)((sizeof (MEMMAP_DEVICE_PATH
)) >> 8),
37 0, // StartingAddress (set at runtime)
38 0 // EndingAddress (set at runtime)
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 }
48 Start an EFI Application from a Device Path
50 @param ParentImageHandle Handle of the calling image
51 @param DevicePath Location of the EFI Application
53 @retval EFI_SUCCESS All drivers have been connected
54 @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
55 @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
61 IN EFI_HANDLE ParentImageHandle
,
62 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
63 IN UINTN LoadOptionsSize
,
68 EFI_HANDLE ImageHandle
;
69 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
71 // Load the image from the device path with Boot Services function
72 Status
= gBS
->LoadImage (
80 if (EFI_ERROR (Status
)) {
82 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
83 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
84 // If the caller doesn't have the option to defer the execution of an image, we should
85 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
87 if (Status
== EFI_SECURITY_VIOLATION
) {
88 gBS
->UnloadImage (ImageHandle
);
94 // Passed LoadOptions to the EFI Application
95 if (LoadOptionsSize
!= 0) {
96 Status
= gBS
->HandleProtocol (
98 &gEfiLoadedImageProtocolGuid
,
101 if (EFI_ERROR (Status
)) {
105 LoadedImage
->LoadOptionsSize
= LoadOptionsSize
;
106 LoadedImage
->LoadOptions
= LoadOptions
;
109 // Before calling the image, enable the Watchdog Timer for the 5 Minute period
110 gBS
->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL
);
112 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
113 // Clear the Watchdog Timer after the image returns
114 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
126 CHAR8 KernelArgs
[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE
];
131 MEMORY_DEVICE_PATH KernelDevicePath
;
132 CHAR16
*LoadOptions
, *NewLoadOptions
;
134 Status
= ParseAndroidBootImg (
142 if (EFI_ERROR (Status
)) {
146 KernelDevicePath
= MemoryDevicePathTemplate
;
148 // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to
150 KernelDevicePath
.Node1
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Kernel
;
151 KernelDevicePath
.Node1
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Kernel
+ KernelSize
;
153 // Initialize Linux command line
154 LoadOptions
= CatSPrint (NULL
, L
"%a", KernelArgs
);
155 if (LoadOptions
== NULL
) {
156 return EFI_OUT_OF_RESOURCES
;
159 if (RamdiskSize
!= 0) {
160 NewLoadOptions
= CatSPrint (
162 L
" initrd=0x%x,0x%x",
166 FreePool (LoadOptions
);
167 if (NewLoadOptions
== NULL
) {
168 return EFI_OUT_OF_RESOURCES
;
171 LoadOptions
= NewLoadOptions
;
174 Status
= StartEfiApplication (
176 (EFI_DEVICE_PATH_PROTOCOL
*)&KernelDevicePath
,
177 StrSize (LoadOptions
),
180 if (EFI_ERROR (Status
)) {
181 DEBUG ((DEBUG_ERROR
, "Couldn't Boot Linux: %d\n", Status
));
182 Status
= EFI_DEVICE_ERROR
;
183 goto FreeLoadOptions
;
186 // If we got here we do a confused face because BootLinuxFdt returned,
187 // reporting success.
188 DEBUG ((DEBUG_ERROR
, "WARNING: BdsBootLinuxFdt returned EFI_SUCCESS.\n"));
192 FreePool (LoadOptions
);