]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBootManagerLib/QemuKernel.c
ddfef925edd321a4822b84f9fc51888c81e03310
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLib / QemuKernel.c
1 /** @file
2
3 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include <Uefi.h>
9
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/LoadLinuxLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/QemuFwCfgLib.h>
15 #include <Library/ReportStatusCodeLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/UefiLib.h>
18
19
20 EFI_STATUS
21 TryRunningQemuKernel (
22 VOID
23 )
24 {
25 EFI_STATUS Status;
26 UINTN KernelSize;
27 UINTN KernelInitialSize;
28 VOID *KernelBuf;
29 UINTN SetupSize;
30 VOID *SetupBuf;
31 UINTN CommandLineSize;
32 CHAR8 *CommandLine;
33 UINTN InitrdSize;
34 VOID* InitrdData;
35
36 SetupBuf = NULL;
37 SetupSize = 0;
38 KernelBuf = NULL;
39 KernelInitialSize = 0;
40 CommandLine = NULL;
41 CommandLineSize = 0;
42 InitrdData = NULL;
43 InitrdSize = 0;
44
45 if (!QemuFwCfgIsAvailable ()) {
46 return EFI_NOT_FOUND;
47 }
48
49 QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);
50 KernelSize = (UINTN) QemuFwCfgRead64 ();
51
52 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);
53 SetupSize = (UINTN) QemuFwCfgRead64 ();
54
55 if (KernelSize == 0 || SetupSize == 0) {
56 DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n"));
57 return EFI_NOT_FOUND;
58 }
59
60 SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize));
61 if (SetupBuf == NULL) {
62 DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n"));
63 return EFI_OUT_OF_RESOURCES;
64 }
65
66 DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize));
67 DEBUG ((EFI_D_INFO, "Reading kernel setup image ..."));
68 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);
69 QemuFwCfgReadBytes (SetupSize, SetupBuf);
70 DEBUG ((EFI_D_INFO, " [done]\n"));
71
72 Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize);
73 if (EFI_ERROR (Status)) {
74 goto FreeAndReturn;
75 }
76
77 Status = LoadLinuxInitializeKernelSetup (SetupBuf);
78 if (EFI_ERROR (Status)) {
79 goto FreeAndReturn;
80 }
81
82 KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize);
83 if (KernelInitialSize == 0) {
84 Status = EFI_UNSUPPORTED;
85 goto FreeAndReturn;
86 }
87
88 KernelBuf = LoadLinuxAllocateKernelPages (
89 SetupBuf,
90 EFI_SIZE_TO_PAGES (KernelInitialSize));
91 if (KernelBuf == NULL) {
92 DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n"));
93 Status = EFI_OUT_OF_RESOURCES;
94 goto FreeAndReturn;
95 }
96
97 DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize));
98 DEBUG ((EFI_D_INFO, "Reading kernel image ..."));
99 QemuFwCfgSelectItem (QemuFwCfgItemKernelData);
100 QemuFwCfgReadBytes (KernelSize, KernelBuf);
101 DEBUG ((EFI_D_INFO, " [done]\n"));
102
103 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);
104 CommandLineSize = (UINTN) QemuFwCfgRead64 ();
105
106 if (CommandLineSize > 0) {
107 CommandLine = LoadLinuxAllocateCommandLinePages (
108 EFI_SIZE_TO_PAGES (CommandLineSize));
109 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);
110 QemuFwCfgReadBytes (CommandLineSize, CommandLine);
111 } else {
112 CommandLine = NULL;
113 }
114
115 Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine);
116 if (EFI_ERROR (Status)) {
117 goto FreeAndReturn;
118 }
119
120 QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);
121 InitrdSize = (UINTN) QemuFwCfgRead64 ();
122
123 if (InitrdSize > 0) {
124 InitrdData = LoadLinuxAllocateInitrdPages (
125 SetupBuf,
126 EFI_SIZE_TO_PAGES (InitrdSize)
127 );
128 DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize));
129 DEBUG ((EFI_D_INFO, "Reading initrd image ..."));
130 QemuFwCfgSelectItem (QemuFwCfgItemInitrdData);
131 QemuFwCfgReadBytes (InitrdSize, InitrdData);
132 DEBUG ((EFI_D_INFO, " [done]\n"));
133 } else {
134 InitrdData = NULL;
135 }
136
137 Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize);
138 if (EFI_ERROR (Status)) {
139 goto FreeAndReturn;
140 }
141
142 //
143 // Signal the EVT_SIGNAL_READY_TO_BOOT event
144 //
145 EfiSignalEventReadyToBoot();
146
147 REPORT_STATUS_CODE (EFI_PROGRESS_CODE,
148 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));
149
150 Status = LoadLinux (KernelBuf, SetupBuf);
151
152 FreeAndReturn:
153 if (SetupBuf != NULL) {
154 FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize));
155 }
156 if (KernelBuf != NULL) {
157 FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize));
158 }
159 if (CommandLine != NULL) {
160 FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize));
161 }
162 if (InitrdData != NULL) {
163 FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize));
164 }
165
166 return Status;
167 }
168