OvmfPkg/PlatformPei: Detect S3 support for QEMU / KVM
[mirror_edk2.git] / OvmfPkg / PlatformPei / Platform.c
1 /**@file
2 Platform PEI driver
3
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 //
18 // The package level header files this module uses
19 //
20 #include <PiPei.h>
21
22 //
23 // The Library classes this module consumes
24 //
25 #include <Library/DebugLib.h>
26 #include <Library/HobLib.h>
27 #include <Library/IoLib.h>
28 #include <Library/MemoryAllocationLib.h>
29 #include <Library/PcdLib.h>
30 #include <Library/PciLib.h>
31 #include <Library/PeimEntryPoint.h>
32 #include <Library/PeiServicesLib.h>
33 #include <Library/QemuFwCfgLib.h>
34 #include <Library/ResourcePublicationLib.h>
35 #include <Guid/MemoryTypeInformation.h>
36 #include <Ppi/MasterBootMode.h>
37 #include <IndustryStandard/Pci22.h>
38
39 #include "Platform.h"
40 #include "Cmos.h"
41
42 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
43 { EfiACPIMemoryNVS, 0x004 },
44 { EfiACPIReclaimMemory, 0x008 },
45 { EfiReservedMemoryType, 0x004 },
46 { EfiRuntimeServicesData, 0x024 },
47 { EfiRuntimeServicesCode, 0x030 },
48 { EfiBootServicesCode, 0x180 },
49 { EfiBootServicesData, 0xF00 },
50 { EfiMaxMemoryType, 0x000 }
51 };
52
53
54 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
55 {
56 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
57 &gEfiPeiMasterBootModePpiGuid,
58 NULL
59 }
60 };
61
62
63 EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
64
65 BOOLEAN mS3Supported = FALSE;
66
67
68 VOID
69 AddIoMemoryBaseSizeHob (
70 EFI_PHYSICAL_ADDRESS MemoryBase,
71 UINT64 MemorySize
72 )
73 {
74 BuildResourceDescriptorHob (
75 EFI_RESOURCE_MEMORY_MAPPED_IO,
76 EFI_RESOURCE_ATTRIBUTE_PRESENT |
77 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
78 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
79 EFI_RESOURCE_ATTRIBUTE_TESTED,
80 MemoryBase,
81 MemorySize
82 );
83 }
84
85 VOID
86 AddReservedMemoryBaseSizeHob (
87 EFI_PHYSICAL_ADDRESS MemoryBase,
88 UINT64 MemorySize
89 )
90 {
91 BuildResourceDescriptorHob (
92 EFI_RESOURCE_MEMORY_RESERVED,
93 EFI_RESOURCE_ATTRIBUTE_PRESENT |
94 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
95 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
96 EFI_RESOURCE_ATTRIBUTE_TESTED,
97 MemoryBase,
98 MemorySize
99 );
100 }
101
102 VOID
103 AddIoMemoryRangeHob (
104 EFI_PHYSICAL_ADDRESS MemoryBase,
105 EFI_PHYSICAL_ADDRESS MemoryLimit
106 )
107 {
108 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
109 }
110
111
112 VOID
113 AddMemoryBaseSizeHob (
114 EFI_PHYSICAL_ADDRESS MemoryBase,
115 UINT64 MemorySize
116 )
117 {
118 BuildResourceDescriptorHob (
119 EFI_RESOURCE_SYSTEM_MEMORY,
120 EFI_RESOURCE_ATTRIBUTE_PRESENT |
121 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
122 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
123 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
124 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
125 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
126 EFI_RESOURCE_ATTRIBUTE_TESTED,
127 MemoryBase,
128 MemorySize
129 );
130 }
131
132
133 VOID
134 AddMemoryRangeHob (
135 EFI_PHYSICAL_ADDRESS MemoryBase,
136 EFI_PHYSICAL_ADDRESS MemoryLimit
137 )
138 {
139 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
140 }
141
142
143 VOID
144 AddUntestedMemoryBaseSizeHob (
145 EFI_PHYSICAL_ADDRESS MemoryBase,
146 UINT64 MemorySize
147 )
148 {
149 BuildResourceDescriptorHob (
150 EFI_RESOURCE_SYSTEM_MEMORY,
151 EFI_RESOURCE_ATTRIBUTE_PRESENT |
152 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
153 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
154 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
155 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
156 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE,
157 MemoryBase,
158 MemorySize
159 );
160 }
161
162
163 VOID
164 AddUntestedMemoryRangeHob (
165 EFI_PHYSICAL_ADDRESS MemoryBase,
166 EFI_PHYSICAL_ADDRESS MemoryLimit
167 )
168 {
169 AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
170 }
171
172 VOID
173 MemMapInitialization (
174 VOID
175 )
176 {
177 //
178 // Create Memory Type Information HOB
179 //
180 BuildGuidDataHob (
181 &gEfiMemoryTypeInformationGuid,
182 mDefaultMemoryTypeInformation,
183 sizeof(mDefaultMemoryTypeInformation)
184 );
185
186 //
187 // Add PCI IO Port space available for PCI resource allocations.
188 //
189 BuildResourceDescriptorHob (
190 EFI_RESOURCE_IO,
191 EFI_RESOURCE_ATTRIBUTE_PRESENT |
192 EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
193 0xC000,
194 0x4000
195 );
196
197 //
198 // Video memory + Legacy BIOS region
199 //
200 AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
201
202 if (!mXen) {
203 UINT32 TopOfLowRam;
204 TopOfLowRam = GetSystemMemorySizeBelow4gb ();
205
206 //
207 // address purpose size
208 // ------------ -------- -------------------------
209 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
210 // 0xFC000000 gap 44 MB
211 // 0xFEC00000 IO-APIC 4 KB
212 // 0xFEC01000 gap 1020 KB
213 // 0xFED00000 HPET 1 KB
214 // 0xFED00400 gap 1023 KB
215 // 0xFEE00000 LAPIC 1 MB
216 //
217 AddIoMemoryRangeHob (TopOfLowRam < BASE_2GB ?
218 BASE_2GB : TopOfLowRam, 0xFC000000);
219 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
220 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
221 AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
222 }
223 }
224
225
226 VOID
227 MiscInitialization (
228 VOID
229 )
230 {
231 //
232 // Disable A20 Mask
233 //
234 IoOr8 (0x92, BIT1);
235
236 //
237 // Build the CPU hob with 36-bit addressing and 16-bits of IO space.
238 //
239 BuildCpuHob (36, 16);
240
241 //
242 // If PMREGMISC/PMIOSE is set, assume the ACPI PMBA has been configured (for
243 // example by Xen) and skip the setup here. This matches the logic in
244 // AcpiTimerLibConstructor ().
245 //
246 if ((PciRead8 (PCI_LIB_ADDRESS (0, 1, 3, 0x80)) & 0x01) == 0) {
247 //
248 // The PEI phase should be exited with fully accessibe PIIX4 IO space:
249 // 1. set PMBA
250 //
251 PciAndThenOr32 (
252 PCI_LIB_ADDRESS (0, 1, 3, 0x40),
253 (UINT32) ~0xFFC0,
254 PcdGet16 (PcdAcpiPmBaseAddress)
255 );
256
257 //
258 // 2. set PCICMD/IOSE
259 //
260 PciOr8 (
261 PCI_LIB_ADDRESS (0, 1, 3, PCI_COMMAND_OFFSET),
262 EFI_PCI_COMMAND_IO_SPACE
263 );
264
265 //
266 // 3. set PMREGMISC/PMIOSE
267 //
268 PciOr8 (PCI_LIB_ADDRESS (0, 1, 3, 0x80), 0x01);
269 }
270 }
271
272
273 VOID
274 BootModeInitialization (
275 VOID
276 )
277 {
278 EFI_STATUS Status;
279
280 if (CmosRead8 (0xF) == 0xFE) {
281 mBootMode = BOOT_ON_S3_RESUME;
282 }
283
284 Status = PeiServicesSetBootMode (mBootMode);
285 ASSERT_EFI_ERROR (Status);
286
287 Status = PeiServicesInstallPpi (mPpiBootMode);
288 ASSERT_EFI_ERROR (Status);
289 }
290
291
292 VOID
293 ReserveEmuVariableNvStore (
294 )
295 {
296 EFI_PHYSICAL_ADDRESS VariableStore;
297
298 //
299 // Allocate storage for NV variables early on so it will be
300 // at a consistent address. Since VM memory is preserved
301 // across reboots, this allows the NV variable storage to survive
302 // a VM reboot.
303 //
304 VariableStore =
305 (EFI_PHYSICAL_ADDRESS)(UINTN)
306 AllocateAlignedRuntimePages (
307 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)),
308 PcdGet32 (PcdFlashNvStorageFtwSpareSize)
309 );
310 DEBUG ((EFI_D_INFO,
311 "Reserved variable store memory: 0x%lX; size: %dkb\n",
312 VariableStore,
313 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
314 ));
315 PcdSet64 (PcdEmuVariableNvStoreReserved, VariableStore);
316 }
317
318
319 VOID
320 DebugDumpCmos (
321 VOID
322 )
323 {
324 UINTN Loop;
325
326 DEBUG ((EFI_D_INFO, "CMOS:\n"));
327
328 for (Loop = 0; Loop < 0x80; Loop++) {
329 if ((Loop % 0x10) == 0) {
330 DEBUG ((EFI_D_INFO, "%02x:", Loop));
331 }
332 DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
333 if ((Loop % 0x10) == 0xf) {
334 DEBUG ((EFI_D_INFO, "\n"));
335 }
336 }
337 }
338
339
340 /**
341 Perform Platform PEI initialization.
342
343 @param FileHandle Handle of the file being invoked.
344 @param PeiServices Describes the list of possible PEI Services.
345
346 @return EFI_SUCCESS The PEIM initialized successfully.
347
348 **/
349 EFI_STATUS
350 EFIAPI
351 InitializePlatform (
352 IN EFI_PEI_FILE_HANDLE FileHandle,
353 IN CONST EFI_PEI_SERVICES **PeiServices
354 )
355 {
356 DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
357
358 DebugDumpCmos ();
359
360 XenDetect ();
361
362 if (QemuFwCfgS3Enabled ()) {
363 DEBUG ((EFI_D_INFO, "S3 support was detected on QEMU\n"));
364 mS3Supported = TRUE;
365 }
366
367 BootModeInitialization ();
368
369 PublishPeiMemory ();
370
371 InitializeRamRegions ();
372
373 if (mXen) {
374 DEBUG ((EFI_D_INFO, "Xen was detected\n"));
375 InitializeXen ();
376 }
377
378 ReserveEmuVariableNvStore ();
379
380 PeiFvInitialization ();
381
382 MemMapInitialization ();
383
384 MiscInitialization ();
385
386 return EFI_SUCCESS;
387 }