VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c@ 109019

Last change on this file since 109019 was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette