2 QuarkNcSocId module initialization module
4 Copyright (c) 2013-2015 Intel Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "CommonHeader.h"
11 #include "LegacyRegion.h"
12 #include "DxeQNCSmbus.h"
19 #define QNC_RESERVED_ITEM_IO 0
20 #define QNC_RESERVED_ITEM_MEMORYIO 1
21 #define DXE_DEVICE_DISABLED 0
22 #define DXE_DEVICE_ENABLED 1
24 typedef struct _QNC_SPACE_TABLE_ITEM
{
27 EFI_PHYSICAL_ADDRESS BaseAddress
;
31 } QNC_SPACE_TABLE_ITEM
;
34 ACPI_CPU_DATA AcpuCpuData
;
35 MTRR_SETTINGS MtrrTable
;
36 IA32_DESCRIPTOR GdtrProfile
;
37 IA32_DESCRIPTOR IdtrProfile
;
38 CPU_REGISTER_TABLE RegisterTable
;
39 CPU_REGISTER_TABLE PreSmmInitRegisterTable
;
43 // Spaces to be reserved in GCD
44 // Expand it to add more
46 const QNC_SPACE_TABLE_ITEM mQNCReservedSpaceTable
[] = {
48 QNC_RESERVED_ITEM_MEMORYIO
,
49 EfiGcdMemoryTypeMemoryMappedIo
,
50 FixedPcdGet64 (PcdIoApicBaseAddress
),
51 FixedPcdGet64 (PcdIoApicSize
),
56 QNC_RESERVED_ITEM_MEMORYIO
,
57 EfiGcdMemoryTypeMemoryMappedIo
,
58 FixedPcdGet64 (PcdHpetBaseAddress
),
59 FixedPcdGet64 (PcdHpetSize
),
66 // Global variable for ImageHandle of QNCInit driver
68 EFI_HANDLE gQNCInitImageHandle
;
69 QNC_DEVICE_ENABLES mQNCDeviceEnables
;
73 QNCInitializeResource (
83 Allocate EfiACPIMemoryNVS below 4G memory address.
85 This function allocates EfiACPIMemoryNVS below 4G memory address.
87 @param Size Size of memory to allocate.
89 @return Allocated address for output.
93 AllocateAcpiNvsMemoryBelow4G (
98 EFI_PHYSICAL_ADDRESS Address
;
102 Pages
= EFI_SIZE_TO_PAGES (Size
);
103 Address
= 0xffffffff;
105 Status
= gBS
->AllocatePages (
111 if (EFI_ERROR (Status
)) {
115 Buffer
= (VOID
*) (UINTN
) Address
;
116 ZeroMem (Buffer
, Size
);
122 Prepare ACPI NVS memory below 4G memory for use of S3 resume.
124 This function allocates ACPI NVS memory below 4G memory for use of S3 resume,
125 and saves data into the memory region.
134 ACPI_CPU_DATA_EX
*AcpiCpuDataEx
;
135 ACPI_CPU_DATA
*AcpiCpuData
;
142 // Allocate ACPI NVS memory below 4G memory for use of S3 resume.
144 AcpiCpuDataEx
= AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX
));
145 AcpiCpuData
= &AcpiCpuDataEx
->AcpuCpuData
;
150 AcpiCpuData
->NumberOfCpus
= 1;
151 AcpiCpuData
->StackSize
= PcdGet32 (PcdCpuApStackSize
);
152 AcpiCpuData
->ApMachineCheckHandlerBase
= 0;
153 AcpiCpuData
->ApMachineCheckHandlerSize
= 0;
154 AcpiCpuData
->GdtrProfile
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->GdtrProfile
;
155 AcpiCpuData
->IdtrProfile
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->IdtrProfile
;
156 AcpiCpuData
->MtrrTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->MtrrTable
;
157 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->RegisterTable
;
158 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->PreSmmInitRegisterTable
;
161 // Allocate stack space for all CPUs
163 AcpiCpuData
->StackAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData
->NumberOfCpus
* AcpiCpuData
->StackSize
);
166 // Get MTRR settings from currently executing CPU
168 MtrrGetAllMtrrs (&AcpiCpuDataEx
->MtrrTable
);
171 // Get the BSP's data of GDT and IDT
173 AsmReadGdtr ((IA32_DESCRIPTOR
*) &AcpiCpuDataEx
->GdtrProfile
);
174 AsmReadIdtr ((IA32_DESCRIPTOR
*) &AcpiCpuDataEx
->IdtrProfile
);
177 // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents
179 GdtSize
= AcpiCpuDataEx
->GdtrProfile
.Limit
+ 1;
180 IdtSize
= AcpiCpuDataEx
->IdtrProfile
.Limit
+ 1;
181 Gdt
= AllocateAcpiNvsMemoryBelow4G (GdtSize
+ IdtSize
);
182 Idt
= (VOID
*)((UINTN
)Gdt
+ GdtSize
);
183 CopyMem (Gdt
, (VOID
*)AcpiCpuDataEx
->GdtrProfile
.Base
, GdtSize
);
184 CopyMem (Idt
, (VOID
*)AcpiCpuDataEx
->IdtrProfile
.Base
, IdtSize
);
185 AcpiCpuDataEx
->GdtrProfile
.Base
= (UINTN
)Gdt
;
186 AcpiCpuDataEx
->IdtrProfile
.Base
= (UINTN
)Idt
;
189 // No RegisterTable entries
191 AcpiCpuDataEx
->RegisterTable
.TableLength
= 0;
194 // No PreSmmInitRegisterTable entries
196 AcpiCpuDataEx
->PreSmmInitRegisterTable
.TableLength
= 0;
199 // Set the base address of CPU S3 data to PcdCpuS3DataAddress
201 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
202 ASSERT_EFI_ERROR (Status
);
206 The entry function for QNCInit driver.
208 This function just call initialization function for PciHostBridge,
209 LegacyRegion and QNCSmmAccess module.
211 @param ImageHandle The driver image handle for GmchInit driver
212 @param SystemTable The pointer to System Table
214 @retval EFI_SUCCESS Success to initialize every module for GMCH driver.
215 @return EFI_STATUS The status of initialization work.
221 IN EFI_HANDLE ImageHandle
,
222 IN EFI_SYSTEM_TABLE
*SystemTable
227 S3BootScriptSaveInformationAsciiString (
228 "QNCInitDxeEntryBegin"
231 gQNCInitImageHandle
= ImageHandle
;
233 mQNCDeviceEnables
.Uint32
= PcdGet32 (PcdDeviceEnables
);
237 // Initialize PCIE root ports
239 Status
= QncInitRootPorts ();
240 if (EFI_ERROR (Status
)) {
241 DEBUG ((EFI_D_ERROR
, "QNC Root Port initialization is failed!\n"));
245 Status
= LegacyRegionInit ();
246 if (EFI_ERROR (Status
)) {
247 DEBUG ((EFI_D_ERROR
, "QNC LegacyRegion initialization is failed!\n"));
252 Status
= InitializeQNCPolicy ();
253 if (EFI_ERROR (Status
)) {
254 DEBUG ((EFI_D_ERROR
, "QNC Policy initialization is failed!\n"));
258 Status
= InitializeQNCSmbus (ImageHandle
,SystemTable
);
259 if (EFI_ERROR (Status
)) {
260 DEBUG ((EFI_D_ERROR
, "QNC Smbus driver is failed!\n"));
264 QNCInitializeResource ();
268 S3BootScriptSaveInformationAsciiString (
277 Reserve I/O or memory space in GCD
279 @param IoOrMemory Switch of I/O or memory.
280 @param GcdType Type of the space.
281 @param BaseAddress Base address of the space.
282 @param Length Length of the space.
283 @param Alignment Align with 2^Alignment
284 @param RuntimeOrNot For runtime usage or not
285 @param ImageHandle Handle for the image of this driver.
287 @retval EFI_SUCCESS Reserve successful
290 QNCReserveSpaceInGcd(
293 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
296 IN BOOLEAN RuntimeOrNot
,
297 IN EFI_HANDLE ImageHandle
302 if (IoOrMemory
== QNC_RESERVED_ITEM_MEMORYIO
) {
303 Status
= gDS
->AddMemorySpace (
309 if (EFI_ERROR (Status
)) {
312 "Failed to add memory space :0x%x 0x%x\n",
317 ASSERT_EFI_ERROR (Status
);
318 Status
= gDS
->AllocateMemorySpace (
319 EfiGcdAllocateAddress
,
327 ASSERT_EFI_ERROR (Status
);
329 Status
= gDS
->SetMemorySpaceAttributes (
332 EFI_MEMORY_RUNTIME
| EFI_MEMORY_UC
334 ASSERT_EFI_ERROR (Status
);
337 Status
= gDS
->AddIoSpace (
342 ASSERT_EFI_ERROR (Status
);
343 Status
= gDS
->AllocateIoSpace (
344 EfiGcdAllocateAddress
,
352 ASSERT_EFI_ERROR (Status
);
359 Initialize the memory and io resource which belong to QNC.
360 1) Report and allocate all BAR's memory to GCD.
361 2) Report PCI memory and I/O space to GCD.
362 3) Set memory attribute for <1M memory space.
365 QNCInitializeResource (
368 EFI_PHYSICAL_ADDRESS BaseAddress
;
370 UINT64 ExtraRegionLength
;
371 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
375 // This range maybe has been reportted in PEI phase via Resource Hob.
377 QNCGetTSEGMemoryRange (&BaseAddress
, &ExtraRegionLength
);
378 if (ExtraRegionLength
!= 0) {
379 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
380 if (Status
== EFI_NOT_FOUND
) {
381 Status
= gDS
->AddMemorySpace (
382 EfiGcdMemoryTypeReserved
,
391 // < 1M resource setting. The memory ranges <1M has been added into GCD via
392 // resource hob produced by PEI phase. Here will set memory attribute of these
393 // ranges for DXE phase.
397 // Dos Area (0 ~ 0x9FFFFh)
399 Status
= gDS
->GetMemorySpaceDescriptor (0, &Descriptor
);
402 "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
403 Descriptor
.BaseAddress
,
405 Descriptor
.Attributes
407 ASSERT_EFI_ERROR (Status
);
408 Status
= gDS
->SetMemorySpaceAttributes(
413 ASSERT_EFI_ERROR (Status
);
416 // Default SMRAM UnCachable until SMBASE relocated.
418 Status
= gDS
->SetMemorySpaceAttributes(
423 ASSERT_EFI_ERROR (Status
);
426 // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)
428 Status
= gDS
->GetMemorySpaceDescriptor (0xA0000, &Descriptor
);
431 "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
432 Descriptor
.BaseAddress
,
434 Descriptor
.Attributes
436 ASSERT_EFI_ERROR (Status
);
437 Status
= gDS
->SetMemorySpaceAttributes(
442 ASSERT_EFI_ERROR (Status
);
445 // Expansion BIOS area.
447 Status
= gDS
->GetMemorySpaceDescriptor (0xC0000, &Descriptor
);
450 "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",
451 Descriptor
.BaseAddress
,
453 Descriptor
.Attributes
455 ASSERT_EFI_ERROR (Status
);
456 Status
= gDS
->SetMemorySpaceAttributes(
461 ASSERT_EFI_ERROR (Status
);
464 // Report other IO resources from mQNCReservedSpaceTable in GCD
466 for (Index
= 0; Index
< sizeof (mQNCReservedSpaceTable
) / sizeof (QNC_SPACE_TABLE_ITEM
); Index
++) {
467 Status
= QNCReserveSpaceInGcd (
468 mQNCReservedSpaceTable
[Index
].IoOrMemory
,
469 mQNCReservedSpaceTable
[Index
].Type
,
470 mQNCReservedSpaceTable
[Index
].BaseAddress
,
471 mQNCReservedSpaceTable
[Index
].Length
,
472 mQNCReservedSpaceTable
[Index
].Alignment
,
473 mQNCReservedSpaceTable
[Index
].RuntimeOrNot
,
476 ASSERT_EFI_ERROR (Status
);
480 // Report unused PCIe config space as reserved.
482 if (PcdGet64 (PcdPciExpressSize
) < SIZE_256MB
) {
483 Status
= QNCReserveSpaceInGcd (
484 QNC_RESERVED_ITEM_MEMORYIO
,
485 EfiGcdMemoryTypeMemoryMappedIo
,
486 (PcdGet64(PcdPciExpressBaseAddress
) + PcdGet64(PcdPciExpressSize
)),
487 (SIZE_256MB
- PcdGet64(PcdPciExpressSize
)),
492 ASSERT_EFI_ERROR (Status
);
497 Use the platform PCD to initialize devices in the QNC
499 @param ImageHandle Handle for the image of this driver.
500 @retval EFI_SUCCESS Initialize successful
503 InitializeQNCPolicy (
506 UINT32 PciD31F0RegBase
; // LPC
508 PciD31F0RegBase
= PciDeviceMmBase (PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_QNC_LPC
, PCI_FUNCTION_NUMBER_QNC_LPC
);
513 if (mQNCDeviceEnables
.Bits
.Smbus
== DXE_DEVICE_DISABLED
) {
514 S3MmioAnd32 (PciD31F0RegBase
+ R_QNC_LPC_SMBUS_BASE
, (~B_QNC_LPC_SMBUS_BASE_EN
));