TianoCore EDK2 master
Loading...
Searching...
No Matches
BootAndroidBootImg.c
Go to the documentation of this file.
1
10
11#include <Protocol/DevicePath.h>
13
16#include <Library/UefiLib.h>
17
18// Device Path representing an image in memory
19#pragma pack(1)
20typedef struct {
24#pragma pack()
25
26STATIC CONST MEMORY_DEVICE_PATH MemoryDevicePathTemplate =
27{
28 {
29 {
32 {
33 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
34 (UINT8)((sizeof (MEMMAP_DEVICE_PATH)) >> 8),
35 },
36 }, // Header
37 0, // StartingAddress (set at runtime)
38 0 // EndingAddress (set at runtime)
39 }, // Node1
40 {
41 END_DEVICE_PATH_TYPE,
42 END_ENTIRE_DEVICE_PATH_SUBTYPE,
43 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
44 } // End
45};
46
61 IN EFI_HANDLE ParentImageHandle,
62 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
63 IN UINTN LoadOptionsSize,
64 IN VOID *LoadOptions
65 )
66{
67 EFI_STATUS Status;
68 EFI_HANDLE ImageHandle;
69 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
70
71 // Load the image from the device path with Boot Services function
72 Status = gBS->LoadImage (
73 TRUE,
74 ParentImageHandle,
75 DevicePath,
76 NULL,
77 0,
78 &ImageHandle
79 );
80 if (EFI_ERROR (Status)) {
81 //
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.
86 //
87 if (Status == EFI_SECURITY_VIOLATION) {
88 gBS->UnloadImage (ImageHandle);
89 }
90
91 return Status;
92 }
93
94 // Passed LoadOptions to the EFI Application
95 if (LoadOptionsSize != 0) {
96 Status = gBS->HandleProtocol (
97 ImageHandle,
98 &gEfiLoadedImageProtocolGuid,
99 (VOID **)&LoadedImage
100 );
101 if (EFI_ERROR (Status)) {
102 return Status;
103 }
104
105 LoadedImage->LoadOptionsSize = LoadOptionsSize;
106 LoadedImage->LoadOptions = LoadOptions;
107 }
108
109 // Before calling the image, enable the Watchdog Timer for the 5 Minute period
110 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
111 // Start the image
112 Status = gBS->StartImage (ImageHandle, NULL, NULL);
113 // Clear the Watchdog Timer after the image returns
114 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
115
116 return Status;
117}
118
120BootAndroidBootImg (
121 IN UINTN BufferSize,
122 IN VOID *Buffer
123 )
124{
125 EFI_STATUS Status;
126 CHAR8 KernelArgs[ANDROID_BOOTIMG_KERNEL_ARGS_SIZE];
127 VOID *Kernel;
128 UINTN KernelSize;
129 VOID *Ramdisk;
130 UINTN RamdiskSize;
131 MEMORY_DEVICE_PATH KernelDevicePath;
132 CHAR16 *LoadOptions, *NewLoadOptions;
133
134 Status = ParseAndroidBootImg (
135 Buffer,
136 &Kernel,
137 &KernelSize,
138 &Ramdisk,
139 &RamdiskSize,
140 KernelArgs
141 );
142 if (EFI_ERROR (Status)) {
143 return Status;
144 }
145
146 KernelDevicePath = MemoryDevicePathTemplate;
147
148 // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to
149 // appease GCC.
150 KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel;
151 KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Kernel + KernelSize;
152
153 // Initialize Linux command line
154 LoadOptions = CatSPrint (NULL, L"%a", KernelArgs);
155 if (LoadOptions == NULL) {
156 return EFI_OUT_OF_RESOURCES;
157 }
158
159 if (RamdiskSize != 0) {
160 NewLoadOptions = CatSPrint (
161 LoadOptions,
162 L" initrd=0x%x,0x%x",
163 (UINTN)Ramdisk,
164 RamdiskSize
165 );
166 FreePool (LoadOptions);
167 if (NewLoadOptions == NULL) {
168 return EFI_OUT_OF_RESOURCES;
169 }
170
171 LoadOptions = NewLoadOptions;
172 }
173
174 Status = StartEfiApplication (
176 (EFI_DEVICE_PATH_PROTOCOL *)&KernelDevicePath,
177 StrSize (LoadOptions),
178 LoadOptions
179 );
180 if (EFI_ERROR (Status)) {
181 DEBUG ((DEBUG_ERROR, "Couldn't Boot Linux: %d\n", Status));
182 Status = EFI_DEVICE_ERROR;
183 goto FreeLoadOptions;
184 }
185
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"));
189 return EFI_SUCCESS;
190
191FreeLoadOptions:
192 FreePool (LoadOptions);
193 return Status;
194}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
STATIC EFI_STATUS StartEfiApplication(IN EFI_HANDLE ParentImageHandle, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN LoadOptionsSize, IN VOID *LoadOptions)
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_MEMMAP_DP
Definition: DevicePath.h:109
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
CHAR16 *EFIAPI CatSPrint(IN CHAR16 *String OPTIONAL, IN CONST CHAR16 *FormatString,...)
Definition: UefiLibPrint.c:827
EFI_PHYSICAL_ADDRESS StartingAddress
Definition: DevicePath.h:123
EFI_PHYSICAL_ADDRESS EndingAddress
Definition: DevicePath.h:127