]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Application/AndroidFastboot/Arm/BootAndroidBootImg.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmbeddedPkg / Application / AndroidFastboot / Arm / BootAndroidBootImg.c
1 /** @file
2
3 Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "AndroidFastbootApp.h"
10
11 #include <Protocol/DevicePath.h>
12 #include <Protocol/LoadedImage.h>
13
14 #include <Library/DevicePathLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
17
18 // Device Path representing an image in memory
19 #pragma pack(1)
20 typedef struct {
21 MEMMAP_DEVICE_PATH Node1;
22 EFI_DEVICE_PATH_PROTOCOL End;
23 } MEMORY_DEVICE_PATH;
24 #pragma pack()
25
26 STATIC CONST MEMORY_DEVICE_PATH MemoryDevicePathTemplate =
27 {
28 {
29 {
30 HARDWARE_DEVICE_PATH,
31 HW_MEMMAP_DP,
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
47 /**
48 Start an EFI Application from a Device Path
49
50 @param ParentImageHandle Handle of the calling image
51 @param DevicePath Location of the EFI Application
52
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.
56
57 **/
58 STATIC
59 EFI_STATUS
60 StartEfiApplication (
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
119 EFI_STATUS
120 BootAndroidBootImg (
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 (
175 gImageHandle,
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
191 FreeLoadOptions:
192 FreePool (LoadOptions);
193 return Status;
194 }