]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
OvmfPkg/X86QemuLoadImageLib: add dummy assignment to work around GCC
[mirror_edk2.git] / OvmfPkg / Library / X86QemuLoadImageLib / X86QemuLoadImageLib.c
... / ...
CommitLineData
1/** @file\r
2 X86 specific implementation of QemuLoadImageLib library class interface\r
3 with support for loading mixed mode images and non-EFI stub images\r
4\r
5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
6 Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9**/\r
10\r
11#include <Uefi.h>\r
12\r
13#include <Guid/QemuKernelLoaderFsMedia.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/LoadLinuxLib.h>\r
16#include <Library/MemoryAllocationLib.h>\r
17#include <Library/PrintLib.h>\r
18#include <Library/QemuFwCfgLib.h>\r
19#include <Library/QemuLoadImageLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Protocol/DevicePath.h>\r
22#include <Protocol/LoadedImage.h>\r
23#include <Protocol/OvmfLoadedX86LinuxKernel.h>\r
24\r
25#pragma pack (1)\r
26typedef struct {\r
27 EFI_DEVICE_PATH_PROTOCOL FilePathHeader;\r
28 CHAR16 FilePath[ARRAY_SIZE (L"kernel")];\r
29} KERNEL_FILE_DEVPATH;\r
30\r
31typedef struct {\r
32 VENDOR_DEVICE_PATH VenMediaNode;\r
33 KERNEL_FILE_DEVPATH FileNode;\r
34 EFI_DEVICE_PATH_PROTOCOL EndNode;\r
35} KERNEL_VENMEDIA_FILE_DEVPATH;\r
36#pragma pack ()\r
37\r
38STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = {\r
39 {\r
40 {\r
41 MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
42 { sizeof (VENDOR_DEVICE_PATH) }\r
43 },\r
44 QEMU_KERNEL_LOADER_FS_MEDIA_GUID\r
45 }, {\r
46 {\r
47 MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP,\r
48 { sizeof (KERNEL_FILE_DEVPATH) }\r
49 },\r
50 L"kernel",\r
51 }, {\r
52 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
53 { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
54 }\r
55};\r
56\r
57STATIC\r
58VOID\r
59FreeLegacyImage (\r
60 IN OVMF_LOADED_X86_LINUX_KERNEL *LoadedImage\r
61 )\r
62{\r
63 if (LoadedImage->SetupBuf != NULL) {\r
64 FreePages (LoadedImage->SetupBuf,\r
65 EFI_SIZE_TO_PAGES (LoadedImage->SetupSize));\r
66 }\r
67 if (LoadedImage->KernelBuf != NULL) {\r
68 FreePages (LoadedImage->KernelBuf,\r
69 EFI_SIZE_TO_PAGES (LoadedImage->KernelInitialSize));\r
70 }\r
71 if (LoadedImage->CommandLine != NULL) {\r
72 FreePages (LoadedImage->CommandLine,\r
73 EFI_SIZE_TO_PAGES (LoadedImage->CommandLineSize));\r
74 }\r
75 if (LoadedImage->InitrdData != NULL) {\r
76 FreePages (LoadedImage->InitrdData,\r
77 EFI_SIZE_TO_PAGES (LoadedImage->InitrdSize));\r
78 }\r
79}\r
80\r
81STATIC\r
82EFI_STATUS\r
83QemuLoadLegacyImage (\r
84 OUT EFI_HANDLE *ImageHandle\r
85 )\r
86{\r
87 EFI_STATUS Status;\r
88 UINTN KernelSize;\r
89 UINTN SetupSize;\r
90 OVMF_LOADED_X86_LINUX_KERNEL *LoadedImage;\r
91\r
92 QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);\r
93 KernelSize = (UINTN)QemuFwCfgRead32 ();\r
94\r
95 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);\r
96 SetupSize = (UINTN)QemuFwCfgRead32 ();\r
97\r
98 if (KernelSize == 0 || SetupSize == 0) {\r
99 DEBUG ((DEBUG_INFO, "qemu -kernel was not used.\n"));\r
100 return EFI_NOT_FOUND;\r
101 }\r
102\r
103 LoadedImage = AllocateZeroPool (sizeof (*LoadedImage));\r
104 if (LoadedImage == NULL) {\r
105 return EFI_OUT_OF_RESOURCES;\r
106 }\r
107\r
108 LoadedImage->SetupSize = SetupSize;\r
109 LoadedImage->SetupBuf = LoadLinuxAllocateKernelSetupPages (\r
110 EFI_SIZE_TO_PAGES (LoadedImage->SetupSize));\r
111 if (LoadedImage->SetupBuf == NULL) {\r
112 DEBUG ((DEBUG_ERROR, "Unable to allocate memory for kernel setup!\n"));\r
113 Status = EFI_OUT_OF_RESOURCES;\r
114 goto FreeImageDesc;\r
115 }\r
116\r
117 DEBUG ((DEBUG_INFO, "Setup size: 0x%x\n", (UINT32)LoadedImage->SetupSize));\r
118 DEBUG ((DEBUG_INFO, "Reading kernel setup image ..."));\r
119 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);\r
120 QemuFwCfgReadBytes (LoadedImage->SetupSize, LoadedImage->SetupBuf);\r
121 DEBUG ((DEBUG_INFO, " [done]\n"));\r
122\r
123 Status = LoadLinuxCheckKernelSetup (LoadedImage->SetupBuf,\r
124 LoadedImage->SetupSize);\r
125 if (EFI_ERROR (Status)) {\r
126 goto FreeImage;\r
127 }\r
128\r
129 Status = LoadLinuxInitializeKernelSetup (LoadedImage->SetupBuf);\r
130 if (EFI_ERROR (Status)) {\r
131 goto FreeImage;\r
132 }\r
133\r
134 LoadedImage->KernelInitialSize = LoadLinuxGetKernelSize (\r
135 LoadedImage->SetupBuf, KernelSize);\r
136 if (LoadedImage->KernelInitialSize == 0) {\r
137 Status = EFI_UNSUPPORTED;\r
138 goto FreeImage;\r
139 }\r
140\r
141 LoadedImage->KernelBuf = LoadLinuxAllocateKernelPages (\r
142 LoadedImage->SetupBuf,\r
143 EFI_SIZE_TO_PAGES (LoadedImage->KernelInitialSize)\r
144 );\r
145 if (LoadedImage->KernelBuf == NULL) {\r
146 DEBUG ((DEBUG_ERROR, "Unable to allocate memory for kernel!\n"));\r
147 Status = EFI_OUT_OF_RESOURCES;\r
148 goto FreeImage;\r
149 }\r
150\r
151 DEBUG ((DEBUG_INFO, "Kernel size: 0x%x\n", (UINT32)KernelSize));\r
152 DEBUG ((DEBUG_INFO, "Reading kernel image ..."));\r
153 QemuFwCfgSelectItem (QemuFwCfgItemKernelData);\r
154 QemuFwCfgReadBytes (KernelSize, LoadedImage->KernelBuf);\r
155 DEBUG ((DEBUG_INFO, " [done]\n"));\r
156\r
157 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);\r
158 LoadedImage->CommandLineSize = (UINTN)QemuFwCfgRead32 ();\r
159\r
160 if (LoadedImage->CommandLineSize > 0) {\r
161 LoadedImage->CommandLine = LoadLinuxAllocateCommandLinePages (\r
162 EFI_SIZE_TO_PAGES (\r
163 LoadedImage->CommandLineSize));\r
164 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);\r
165 QemuFwCfgReadBytes (LoadedImage->CommandLineSize, LoadedImage->CommandLine);\r
166 }\r
167\r
168 Status = LoadLinuxSetCommandLine (LoadedImage->SetupBuf,\r
169 LoadedImage->CommandLine);\r
170 if (EFI_ERROR (Status)) {\r
171 goto FreeImage;\r
172 }\r
173\r
174 QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);\r
175 LoadedImage->InitrdSize = (UINTN)QemuFwCfgRead32 ();\r
176\r
177 if (LoadedImage->InitrdSize > 0) {\r
178 LoadedImage->InitrdData = LoadLinuxAllocateInitrdPages (\r
179 LoadedImage->SetupBuf,\r
180 EFI_SIZE_TO_PAGES (LoadedImage->InitrdSize));\r
181 DEBUG ((DEBUG_INFO, "Initrd size: 0x%x\n",\r
182 (UINT32)LoadedImage->InitrdSize));\r
183 DEBUG ((DEBUG_INFO, "Reading initrd image ..."));\r
184 QemuFwCfgSelectItem (QemuFwCfgItemInitrdData);\r
185 QemuFwCfgReadBytes (LoadedImage->InitrdSize, LoadedImage->InitrdData);\r
186 DEBUG ((DEBUG_INFO, " [done]\n"));\r
187 }\r
188\r
189 Status = LoadLinuxSetInitrd (LoadedImage->SetupBuf, LoadedImage->InitrdData,\r
190 LoadedImage->InitrdSize);\r
191 if (EFI_ERROR (Status)) {\r
192 goto FreeImage;\r
193 }\r
194\r
195 *ImageHandle = NULL;\r
196 Status = gBS->InstallProtocolInterface (ImageHandle,\r
197 &gOvmfLoadedX86LinuxKernelProtocolGuid, EFI_NATIVE_INTERFACE,\r
198 LoadedImage);\r
199 if (EFI_ERROR (Status)) {\r
200 goto FreeImage;\r
201 }\r
202 return EFI_SUCCESS;\r
203\r
204FreeImage:\r
205 FreeLegacyImage (LoadedImage);\r
206FreeImageDesc:\r
207 FreePool (LoadedImage);\r
208 return Status;\r
209}\r
210\r
211STATIC\r
212EFI_STATUS\r
213QemuStartLegacyImage (\r
214 IN EFI_HANDLE ImageHandle\r
215 )\r
216{\r
217 EFI_STATUS Status;\r
218 OVMF_LOADED_X86_LINUX_KERNEL *LoadedImage;\r
219\r
220 Status = gBS->OpenProtocol (\r
221 ImageHandle,\r
222 &gOvmfLoadedX86LinuxKernelProtocolGuid,\r
223 (VOID **)&LoadedImage,\r
224 gImageHandle, // AgentHandle\r
225 NULL, // ControllerHandle\r
226 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
227 );\r
228 if (EFI_ERROR (Status)) {\r
229 return EFI_INVALID_PARAMETER;\r
230 }\r
231\r
232 return LoadLinux (LoadedImage->KernelBuf, LoadedImage->SetupBuf);\r
233}\r
234\r
235STATIC\r
236EFI_STATUS\r
237QemuUnloadLegacyImage (\r
238 IN EFI_HANDLE ImageHandle\r
239 )\r
240{\r
241 EFI_STATUS Status;\r
242 OVMF_LOADED_X86_LINUX_KERNEL *LoadedImage;\r
243\r
244 Status = gBS->OpenProtocol (\r
245 ImageHandle,\r
246 &gOvmfLoadedX86LinuxKernelProtocolGuid,\r
247 (VOID **)&LoadedImage,\r
248 gImageHandle, // AgentHandle\r
249 NULL, // ControllerHandle\r
250 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
251 );\r
252 if (EFI_ERROR (Status)) {\r
253 return EFI_INVALID_PARAMETER;\r
254 }\r
255\r
256 Status = gBS->UninstallProtocolInterface (ImageHandle,\r
257 &gOvmfLoadedX86LinuxKernelProtocolGuid, LoadedImage);\r
258 ASSERT_EFI_ERROR (Status);\r
259\r
260 FreeLegacyImage (LoadedImage);\r
261 FreePool (LoadedImage);\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265/**\r
266 Download the kernel, the initial ramdisk, and the kernel command line from\r
267 QEMU's fw_cfg. The kernel will be instructed via its command line to load\r
268 the initrd from the same Simple FileSystem where the kernel was loaded from.\r
269\r
270 @param[out] ImageHandle The image handle that was allocated for\r
271 loading the image\r
272\r
273 @retval EFI_SUCCESS The image was loaded successfully.\r
274 @retval EFI_NOT_FOUND Kernel image was not found.\r
275 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
276 @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.\r
277\r
278 @return Error codes from any of the underlying\r
279 functions.\r
280**/\r
281EFI_STATUS\r
282EFIAPI\r
283QemuLoadKernelImage (\r
284 OUT EFI_HANDLE *ImageHandle\r
285 )\r
286{\r
287 EFI_STATUS Status;\r
288 EFI_HANDLE KernelImageHandle;\r
289 EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;\r
290 UINTN CommandLineSize;\r
291 CHAR8 *CommandLine;\r
292 UINTN InitrdSize;\r
293\r
294 //\r
295 // Redundant assignment to work around GCC48/GCC49 limitations.\r
296 //\r
297 CommandLine = NULL;\r
298\r
299 //\r
300 // Load the image. This should call back into the QEMU EFI loader file system.\r
301 //\r
302 Status = gBS->LoadImage (\r
303 FALSE, // BootPolicy: exact match required\r
304 gImageHandle, // ParentImageHandle\r
305 (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,\r
306 NULL, // SourceBuffer\r
307 0, // SourceSize\r
308 &KernelImageHandle\r
309 );\r
310 switch (Status) {\r
311 case EFI_SUCCESS:\r
312 break;\r
313\r
314 case EFI_NOT_FOUND:\r
315 //\r
316 // The image does not exist - no -kernel image was supplied via the\r
317 // command line so no point in invoking the legacy fallback\r
318 //\r
319 return EFI_NOT_FOUND;\r
320\r
321 case EFI_SECURITY_VIOLATION:\r
322 //\r
323 // We are running with UEFI secure boot enabled, and the image failed to\r
324 // authenticate. For compatibility reasons, we fall back to the legacy\r
325 // loader in this case. Since the image has been loaded, we need to unload\r
326 // it before proceeding\r
327 //\r
328 gBS->UnloadImage (KernelImageHandle);\r
329 //\r
330 // Fall through\r
331 //\r
332 case EFI_UNSUPPORTED:\r
333 //\r
334 // The image is not natively supported or cross-type supported. Let's try\r
335 // loading it using the loader that parses the bzImage metadata directly.\r
336 //\r
337 Status = QemuLoadLegacyImage (&KernelImageHandle);\r
338 if (EFI_ERROR (Status)) {\r
339 DEBUG ((DEBUG_ERROR, "%a: QemuLoadLegacyImage(): %r\n", __FUNCTION__,\r
340 Status));\r
341 return Status;\r
342 }\r
343 *ImageHandle = KernelImageHandle;\r
344 return EFI_SUCCESS;\r
345\r
346 default:\r
347 DEBUG ((DEBUG_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status));\r
348 return Status;\r
349 }\r
350\r
351 //\r
352 // Construct the kernel command line.\r
353 //\r
354 Status = gBS->OpenProtocol (\r
355 KernelImageHandle,\r
356 &gEfiLoadedImageProtocolGuid,\r
357 (VOID **)&KernelLoadedImage,\r
358 gImageHandle, // AgentHandle\r
359 NULL, // ControllerHandle\r
360 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
361 );\r
362 ASSERT_EFI_ERROR (Status);\r
363\r
364 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);\r
365 CommandLineSize = (UINTN)QemuFwCfgRead32 ();\r
366\r
367 if (CommandLineSize == 0) {\r
368 KernelLoadedImage->LoadOptionsSize = 0;\r
369 } else {\r
370 CommandLine = AllocatePool (CommandLineSize);\r
371 if (CommandLine == NULL) {\r
372 Status = EFI_OUT_OF_RESOURCES;\r
373 goto UnloadImage;\r
374 }\r
375\r
376 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);\r
377 QemuFwCfgReadBytes (CommandLineSize, CommandLine);\r
378\r
379 //\r
380 // Verify NUL-termination of the command line.\r
381 //\r
382 if (CommandLine[CommandLineSize - 1] != '\0') {\r
383 DEBUG ((DEBUG_ERROR, "%a: kernel command line is not NUL-terminated\n",\r
384 __FUNCTION__));\r
385 Status = EFI_PROTOCOL_ERROR;\r
386 goto FreeCommandLine;\r
387 }\r
388\r
389 //\r
390 // Drop the terminating NUL, convert to UTF-16.\r
391 //\r
392 KernelLoadedImage->LoadOptionsSize = (UINT32) ((CommandLineSize - 1) * 2);\r
393 }\r
394\r
395 QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);\r
396 InitrdSize = (UINTN)QemuFwCfgRead32 ();\r
397\r
398 if (InitrdSize > 0) {\r
399 //\r
400 // Append ' initrd=initrd' in UTF-16.\r
401 //\r
402 KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2;\r
403 }\r
404\r
405 if (KernelLoadedImage->LoadOptionsSize == 0) {\r
406 KernelLoadedImage->LoadOptions = NULL;\r
407 } else {\r
408 //\r
409 // NUL-terminate in UTF-16.\r
410 //\r
411 KernelLoadedImage->LoadOptionsSize += 2;\r
412\r
413 KernelLoadedImage->LoadOptions = AllocatePool (\r
414 KernelLoadedImage->LoadOptionsSize);\r
415 if (KernelLoadedImage->LoadOptions == NULL) {\r
416 KernelLoadedImage->LoadOptionsSize = 0;\r
417 Status = EFI_OUT_OF_RESOURCES;\r
418 goto FreeCommandLine;\r
419 }\r
420\r
421 UnicodeSPrintAsciiFormat (\r
422 KernelLoadedImage->LoadOptions,\r
423 KernelLoadedImage->LoadOptionsSize,\r
424 "%a%a",\r
425 (CommandLineSize == 0) ? "" : CommandLine,\r
426 (InitrdSize == 0) ? "" : " initrd=initrd"\r
427 );\r
428 DEBUG ((DEBUG_INFO, "%a: command line: \"%s\"\n", __FUNCTION__,\r
429 (CHAR16 *)KernelLoadedImage->LoadOptions));\r
430 }\r
431\r
432 *ImageHandle = KernelImageHandle;\r
433 return EFI_SUCCESS;\r
434\r
435FreeCommandLine:\r
436 if (CommandLineSize > 0) {\r
437 FreePool (CommandLine);\r
438 }\r
439UnloadImage:\r
440 gBS->UnloadImage (KernelImageHandle);\r
441\r
442 return Status;\r
443}\r
444\r
445/**\r
446 Transfer control to a kernel image loaded with QemuLoadKernelImage ()\r
447\r
448 @param[in,out] ImageHandle Handle of image to be started. May assume a\r
449 different value on return if the image was\r
450 reloaded.\r
451\r
452 @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle\r
453 or the image has already been initialized with\r
454 StartImage\r
455 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the\r
456 image should not be started.\r
457\r
458 @return Error codes returned by the started image\r
459**/\r
460EFI_STATUS\r
461EFIAPI\r
462QemuStartKernelImage (\r
463 IN OUT EFI_HANDLE *ImageHandle\r
464 )\r
465{\r
466 EFI_STATUS Status;\r
467 OVMF_LOADED_X86_LINUX_KERNEL *LoadedImage;\r
468\r
469 Status = gBS->OpenProtocol (\r
470 *ImageHandle,\r
471 &gOvmfLoadedX86LinuxKernelProtocolGuid,\r
472 (VOID **)&LoadedImage,\r
473 gImageHandle, // AgentHandle\r
474 NULL, // ControllerHandle\r
475 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
476 );\r
477 if (!EFI_ERROR (Status)) {\r
478 return QemuStartLegacyImage (*ImageHandle);\r
479 }\r
480\r
481 Status = gBS->StartImage (\r
482 *ImageHandle,\r
483 NULL, // ExitDataSize\r
484 NULL // ExitData\r
485 );\r
486#ifdef MDE_CPU_IA32\r
487 if (Status == EFI_UNSUPPORTED) {\r
488 EFI_HANDLE KernelImageHandle;\r
489\r
490 //\r
491 // On IA32, EFI_UNSUPPORTED means that the image's machine type is X64 while\r
492 // we are expecting a IA32 one, and the StartImage () boot service is unable\r
493 // to handle it, either because the image does not have the special .compat\r
494 // PE/COFF section that Linux specifies for mixed mode capable images, or\r
495 // because we are running without the support code for that. So load the\r
496 // image again, using the legacy loader, and unload the normally loaded\r
497 // image before starting the legacy one.\r
498 //\r
499 Status = QemuLoadLegacyImage (&KernelImageHandle);\r
500 if (EFI_ERROR (Status)) {\r
501 //\r
502 // Note: no change to (*ImageHandle), the caller will release it.\r
503 //\r
504 return Status;\r
505 }\r
506 //\r
507 // Swap in the legacy-loaded image.\r
508 //\r
509 QemuUnloadKernelImage (*ImageHandle);\r
510 *ImageHandle = KernelImageHandle;\r
511 return QemuStartLegacyImage (KernelImageHandle);\r
512 }\r
513#endif\r
514 return Status;\r
515}\r
516\r
517/**\r
518 Unloads an image loaded with QemuLoadKernelImage ().\r
519\r
520 @param ImageHandle Handle that identifies the image to be\r
521 unloaded.\r
522\r
523 @retval EFI_SUCCESS The image has been unloaded.\r
524 @retval EFI_UNSUPPORTED The image has been started, and does not\r
525 support unload.\r
526 @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.\r
527\r
528 @return Exit code from the image's unload function.\r
529**/\r
530EFI_STATUS\r
531EFIAPI\r
532QemuUnloadKernelImage (\r
533 IN EFI_HANDLE ImageHandle\r
534 )\r
535{\r
536 EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;\r
537 EFI_STATUS Status;\r
538\r
539 Status = gBS->OpenProtocol (\r
540 ImageHandle,\r
541 &gEfiLoadedImageProtocolGuid,\r
542 (VOID **)&KernelLoadedImage,\r
543 gImageHandle, // AgentHandle\r
544 NULL, // ControllerHandle\r
545 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
546 );\r
547 if (Status == EFI_UNSUPPORTED) {\r
548 //\r
549 // The handle exists but does not have an instance of the standard loaded\r
550 // image protocol installed on it. Attempt to unload it as a legacy image\r
551 // instead.\r
552 //\r
553 return QemuUnloadLegacyImage (ImageHandle);\r
554 }\r
555\r
556 if (EFI_ERROR (Status)) {\r
557 return EFI_INVALID_PARAMETER;\r
558 }\r
559\r
560 //\r
561 // We are unloading a normal, non-legacy loaded image, either on behalf of\r
562 // an external caller, or called from QemuStartKernelImage() on IA32, while\r
563 // switching from the normal to the legacy method to load and start a X64\r
564 // image.\r
565 //\r
566 if (KernelLoadedImage->LoadOptions != NULL) {\r
567 FreePool (KernelLoadedImage->LoadOptions);\r
568 KernelLoadedImage->LoadOptions = NULL;\r
569 }\r
570 KernelLoadedImage->LoadOptionsSize = 0;\r
571\r
572 return gBS->UnloadImage (ImageHandle);\r
573}\r