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 }
49 Start an EFI Application from a Device Path
51 @param ParentImageHandle Handle of the calling image
52 @param DevicePath Location of the EFI Application
54 @retval EFI_SUCCESS All drivers have been connected
55 @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
56 @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
62 IN EFI_HANDLE ParentImageHandle
,
63 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
64 IN UINTN LoadOptionsSize
,
69 EFI_HANDLE ImageHandle
;
70 EFI_LOADED_IMAGE_PROTOCOL
* LoadedImage
;
72 // Load the image from the device path with Boot Services function
73 Status
= gBS
->LoadImage (TRUE
, ParentImageHandle
, DevicePath
, NULL
, 0,
75 if (EFI_ERROR (Status
)) {
77 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
78 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
79 // If the caller doesn't have the option to defer the execution of an image, we should
80 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
82 if (Status
== EFI_SECURITY_VIOLATION
) {
83 gBS
->UnloadImage (ImageHandle
);
88 // Passed LoadOptions to the EFI Application
89 if (LoadOptionsSize
!= 0) {
90 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiLoadedImageProtocolGuid
,
91 (VOID
**) &LoadedImage
);
92 if (EFI_ERROR (Status
)) {
96 LoadedImage
->LoadOptionsSize
= LoadOptionsSize
;
97 LoadedImage
->LoadOptions
= LoadOptions
;
100 // Before calling the image, enable the Watchdog Timer for the 5 Minute period
101 gBS
->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL
);
103 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
104 // Clear the Watchdog Timer after the image returns
105 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
117 CHAR8 KernelArgs
[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE
];
122 MEMORY_DEVICE_PATH KernelDevicePath
;
123 CHAR16
*LoadOptions
, *NewLoadOptions
;
125 Status
= ParseAndroidBootImg (
133 if (EFI_ERROR (Status
)) {
137 KernelDevicePath
= MemoryDevicePathTemplate
;
139 // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to
141 KernelDevicePath
.Node1
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Kernel
;
142 KernelDevicePath
.Node1
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Kernel
+ KernelSize
;
144 // Initialize Linux command line
145 LoadOptions
= CatSPrint (NULL
, L
"%a", KernelArgs
);
146 if (LoadOptions
== NULL
) {
147 return EFI_OUT_OF_RESOURCES
;
150 if (RamdiskSize
!= 0) {
151 NewLoadOptions
= CatSPrint (LoadOptions
, L
" initrd=0x%x,0x%x",
152 (UINTN
)Ramdisk
, RamdiskSize
);
153 FreePool (LoadOptions
);
154 if (NewLoadOptions
== NULL
) {
155 return EFI_OUT_OF_RESOURCES
;
157 LoadOptions
= NewLoadOptions
;
160 Status
= StartEfiApplication (gImageHandle
,
161 (EFI_DEVICE_PATH_PROTOCOL
*) &KernelDevicePath
,
162 StrSize (LoadOptions
),
164 if (EFI_ERROR (Status
)) {
165 DEBUG ((DEBUG_ERROR
, "Couldn't Boot Linux: %d\n", Status
));
166 Status
= EFI_DEVICE_ERROR
;
167 goto FreeLoadOptions
;
170 // If we got here we do a confused face because BootLinuxFdt returned,
171 // reporting success.
172 DEBUG ((DEBUG_ERROR
, "WARNING: BdsBootLinuxFdt returned EFI_SUCCESS.\n"));
176 FreePool (LoadOptions
);