]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/Platform.c
OvmfPkg: PlatformPei: Platform specific ACPI power management setup
[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 #include <OvmfPlatforms.h>
39
40 #include "Platform.h"
41 #include "Cmos.h"
42
43 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
44 { EfiACPIMemoryNVS, 0x004 },
45 { EfiACPIReclaimMemory, 0x008 },
46 { EfiReservedMemoryType, 0x004 },
47 { EfiRuntimeServicesData, 0x024 },
48 { EfiRuntimeServicesCode, 0x030 },
49 { EfiBootServicesCode, 0x180 },
50 { EfiBootServicesData, 0xF00 },
51 { EfiMaxMemoryType, 0x000 }
52 };
53
54
55 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
56 {
57 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
58 &gEfiPeiMasterBootModePpiGuid,
59 NULL
60 }
61 };
62
63
64 EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
65
66 BOOLEAN mS3Supported = FALSE;
67
68
69 VOID
70 AddIoMemoryBaseSizeHob (
71 EFI_PHYSICAL_ADDRESS MemoryBase,
72 UINT64 MemorySize
73 )
74 {
75 BuildResourceDescriptorHob (
76 EFI_RESOURCE_MEMORY_MAPPED_IO,
77 EFI_RESOURCE_ATTRIBUTE_PRESENT |
78 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
79 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
80 EFI_RESOURCE_ATTRIBUTE_TESTED,
81 MemoryBase,
82 MemorySize
83 );
84 }
85
86 VOID
87 AddReservedMemoryBaseSizeHob (
88 EFI_PHYSICAL_ADDRESS MemoryBase,
89 UINT64 MemorySize
90 )
91 {
92 BuildResourceDescriptorHob (
93 EFI_RESOURCE_MEMORY_RESERVED,
94 EFI_RESOURCE_ATTRIBUTE_PRESENT |
95 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
96 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
97 EFI_RESOURCE_ATTRIBUTE_TESTED,
98 MemoryBase,
99 MemorySize
100 );
101 }
102
103 VOID
104 AddIoMemoryRangeHob (
105 EFI_PHYSICAL_ADDRESS MemoryBase,
106 EFI_PHYSICAL_ADDRESS MemoryLimit
107 )
108 {
109 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
110 }
111
112
113 VOID
114 AddMemoryBaseSizeHob (
115 EFI_PHYSICAL_ADDRESS MemoryBase,
116 UINT64 MemorySize
117 )
118 {
119 BuildResourceDescriptorHob (
120 EFI_RESOURCE_SYSTEM_MEMORY,
121 EFI_RESOURCE_ATTRIBUTE_PRESENT |
122 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
123 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
124 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
125 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
126 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
127 EFI_RESOURCE_ATTRIBUTE_TESTED,
128 MemoryBase,
129 MemorySize
130 );
131 }
132
133
134 VOID
135 AddMemoryRangeHob (
136 EFI_PHYSICAL_ADDRESS MemoryBase,
137 EFI_PHYSICAL_ADDRESS MemoryLimit
138 )
139 {
140 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
141 }
142
143
144 VOID
145 AddUntestedMemoryBaseSizeHob (
146 EFI_PHYSICAL_ADDRESS MemoryBase,
147 UINT64 MemorySize
148 )
149 {
150 BuildResourceDescriptorHob (
151 EFI_RESOURCE_SYSTEM_MEMORY,
152 EFI_RESOURCE_ATTRIBUTE_PRESENT |
153 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
154 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
155 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
156 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
157 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE,
158 MemoryBase,
159 MemorySize
160 );
161 }
162
163
164 VOID
165 AddUntestedMemoryRangeHob (
166 EFI_PHYSICAL_ADDRESS MemoryBase,
167 EFI_PHYSICAL_ADDRESS MemoryLimit
168 )
169 {
170 AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
171 }
172
173 VOID
174 MemMapInitialization (
175 VOID
176 )
177 {
178 //
179 // Create Memory Type Information HOB
180 //
181 BuildGuidDataHob (
182 &gEfiMemoryTypeInformationGuid,
183 mDefaultMemoryTypeInformation,
184 sizeof(mDefaultMemoryTypeInformation)
185 );
186
187 //
188 // Add PCI IO Port space available for PCI resource allocations.
189 //
190 BuildResourceDescriptorHob (
191 EFI_RESOURCE_IO,
192 EFI_RESOURCE_ATTRIBUTE_PRESENT |
193 EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
194 0xC000,
195 0x4000
196 );
197
198 //
199 // Video memory + Legacy BIOS region
200 //
201 AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
202
203 if (!mXen) {
204 UINT32 TopOfLowRam;
205 TopOfLowRam = GetSystemMemorySizeBelow4gb ();
206
207 //
208 // address purpose size
209 // ------------ -------- -------------------------
210 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
211 // 0xFC000000 gap 44 MB
212 // 0xFEC00000 IO-APIC 4 KB
213 // 0xFEC01000 gap 1020 KB
214 // 0xFED00000 HPET 1 KB
215 // 0xFED00400 gap 1023 KB
216 // 0xFEE00000 LAPIC 1 MB
217 //
218 AddIoMemoryRangeHob (TopOfLowRam < BASE_2GB ?
219 BASE_2GB : TopOfLowRam, 0xFC000000);
220 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
221 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
222 AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
223 }
224 }
225
226
227 VOID
228 MiscInitialization (
229 VOID
230 )
231 {
232 UINT16 HostBridgeDevId;
233 UINTN PmCmd;
234 UINTN Pmba;
235 UINTN PmRegMisc;
236
237 //
238 // Disable A20 Mask
239 //
240 IoOr8 (0x92, BIT1);
241
242 //
243 // Build the CPU hob with 36-bit addressing and 16-bits of IO space.
244 //
245 BuildCpuHob (36, 16);
246
247 //
248 // Query Host Bridge DID to determine platform type
249 //
250 HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
251 switch (HostBridgeDevId) {
252 case INTEL_82441_DEVICE_ID:
253 PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
254 Pmba = POWER_MGMT_REGISTER_PIIX4 (0x40);
255 PmRegMisc = POWER_MGMT_REGISTER_PIIX4 (0x80);
256 break;
257 case INTEL_Q35_MCH_DEVICE_ID:
258 PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
259 Pmba = POWER_MGMT_REGISTER_Q35 (0x40);
260 PmRegMisc = POWER_MGMT_REGISTER_Q35 (0x80);
261 break;
262 default:
263 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
264 __FUNCTION__, HostBridgeDevId));
265 ASSERT (FALSE);
266 return;
267 }
268
269 //
270 // If PMREGMISC/PMIOSE is set, assume the ACPI PMBA has been configured (for
271 // example by Xen) and skip the setup here. This matches the logic in
272 // AcpiTimerLibConstructor ().
273 //
274 if ((PciRead8 (PmRegMisc) & 0x01) == 0) {
275 //
276 // The PEI phase should be exited with fully accessibe PIIX4 IO space:
277 // 1. set PMBA
278 //
279 PciAndThenOr32 (Pmba, (UINT32) ~0xFFC0, PcdGet16 (PcdAcpiPmBaseAddress));
280
281 //
282 // 2. set PCICMD/IOSE
283 //
284 PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
285
286 //
287 // 3. set PMREGMISC/PMIOSE
288 //
289 PciOr8 (PmRegMisc, 0x01);
290 }
291 }
292
293
294 VOID
295 BootModeInitialization (
296 VOID
297 )
298 {
299 EFI_STATUS Status;
300
301 if (CmosRead8 (0xF) == 0xFE) {
302 mBootMode = BOOT_ON_S3_RESUME;
303 }
304
305 Status = PeiServicesSetBootMode (mBootMode);
306 ASSERT_EFI_ERROR (Status);
307
308 Status = PeiServicesInstallPpi (mPpiBootMode);
309 ASSERT_EFI_ERROR (Status);
310 }
311
312
313 VOID
314 ReserveEmuVariableNvStore (
315 )
316 {
317 EFI_PHYSICAL_ADDRESS VariableStore;
318
319 //
320 // Allocate storage for NV variables early on so it will be
321 // at a consistent address. Since VM memory is preserved
322 // across reboots, this allows the NV variable storage to survive
323 // a VM reboot.
324 //
325 VariableStore =
326 (EFI_PHYSICAL_ADDRESS)(UINTN)
327 AllocateAlignedRuntimePages (
328 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)),
329 PcdGet32 (PcdFlashNvStorageFtwSpareSize)
330 );
331 DEBUG ((EFI_D_INFO,
332 "Reserved variable store memory: 0x%lX; size: %dkb\n",
333 VariableStore,
334 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
335 ));
336 PcdSet64 (PcdEmuVariableNvStoreReserved, VariableStore);
337 }
338
339
340 VOID
341 DebugDumpCmos (
342 VOID
343 )
344 {
345 UINTN Loop;
346
347 DEBUG ((EFI_D_INFO, "CMOS:\n"));
348
349 for (Loop = 0; Loop < 0x80; Loop++) {
350 if ((Loop % 0x10) == 0) {
351 DEBUG ((EFI_D_INFO, "%02x:", Loop));
352 }
353 DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
354 if ((Loop % 0x10) == 0xf) {
355 DEBUG ((EFI_D_INFO, "\n"));
356 }
357 }
358 }
359
360
361 /**
362 Perform Platform PEI initialization.
363
364 @param FileHandle Handle of the file being invoked.
365 @param PeiServices Describes the list of possible PEI Services.
366
367 @return EFI_SUCCESS The PEIM initialized successfully.
368
369 **/
370 EFI_STATUS
371 EFIAPI
372 InitializePlatform (
373 IN EFI_PEI_FILE_HANDLE FileHandle,
374 IN CONST EFI_PEI_SERVICES **PeiServices
375 )
376 {
377 DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
378
379 DebugDumpCmos ();
380
381 XenDetect ();
382
383 if (QemuFwCfgS3Enabled ()) {
384 DEBUG ((EFI_D_INFO, "S3 support was detected on QEMU\n"));
385 mS3Supported = TRUE;
386 }
387
388 BootModeInitialization ();
389
390 PublishPeiMemory ();
391
392 InitializeRamRegions ();
393
394 if (mXen) {
395 DEBUG ((EFI_D_INFO, "Xen was detected\n"));
396 InitializeXen ();
397 }
398
399 if (mBootMode != BOOT_ON_S3_RESUME) {
400 ReserveEmuVariableNvStore ();
401
402 PeiFvInitialization ();
403
404 MemMapInitialization ();
405 }
406
407 MiscInitialization ();
408
409 return EFI_SUCCESS;
410 }