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