-/** @file\r
-QuarkNcSocId module initialization module\r
-\r
-Copyright (c) 2013-2015 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-#include "CommonHeader.h"\r
-\r
-#include "LegacyRegion.h"\r
-#include "DxeQNCSmbus.h"\r
-\r
-#include "QNCInit.h"\r
-\r
-//\r
-// Definitions\r
-//\r
-#define QNC_RESERVED_ITEM_IO 0\r
-#define QNC_RESERVED_ITEM_MEMORYIO 1\r
-#define DXE_DEVICE_DISABLED 0\r
-#define DXE_DEVICE_ENABLED 1\r
-\r
-typedef struct _QNC_SPACE_TABLE_ITEM {\r
- UINTN IoOrMemory;\r
- UINTN Type;\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- UINT64 Length;\r
- UINTN Alignment;\r
- BOOLEAN RuntimeOrNot;\r
-} QNC_SPACE_TABLE_ITEM;\r
-\r
-typedef struct {\r
- ACPI_CPU_DATA AcpuCpuData;\r
- MTRR_SETTINGS MtrrTable;\r
- IA32_DESCRIPTOR GdtrProfile;\r
- IA32_DESCRIPTOR IdtrProfile;\r
- CPU_REGISTER_TABLE RegisterTable;\r
- CPU_REGISTER_TABLE PreSmmInitRegisterTable;\r
-} ACPI_CPU_DATA_EX;\r
-\r
-//\r
-// Spaces to be reserved in GCD\r
-// Expand it to add more\r
-//\r
-const QNC_SPACE_TABLE_ITEM mQNCReservedSpaceTable[] = {\r
- {\r
- QNC_RESERVED_ITEM_MEMORYIO,\r
- EfiGcdMemoryTypeMemoryMappedIo,\r
- FixedPcdGet64 (PcdIoApicBaseAddress),\r
- FixedPcdGet64 (PcdIoApicSize),\r
- 0,\r
- FALSE\r
- },\r
- {\r
- QNC_RESERVED_ITEM_MEMORYIO,\r
- EfiGcdMemoryTypeMemoryMappedIo,\r
- FixedPcdGet64 (PcdHpetBaseAddress),\r
- FixedPcdGet64 (PcdHpetSize),\r
- 0,\r
- FALSE\r
- }\r
-};\r
-\r
-//\r
-// Global variable for ImageHandle of QNCInit driver\r
-//\r
-EFI_HANDLE gQNCInitImageHandle;\r
-QNC_DEVICE_ENABLES mQNCDeviceEnables;\r
-\r
-\r
-VOID\r
-QNCInitializeResource (\r
- VOID\r
- );\r
-\r
-EFI_STATUS\r
-InitializeQNCPolicy (\r
- VOID\r
- );\r
-\r
-/**\r
- Allocate EfiACPIMemoryNVS below 4G memory address.\r
-\r
- This function allocates EfiACPIMemoryNVS below 4G memory address.\r
-\r
- @param Size Size of memory to allocate.\r
-\r
- @return Allocated address for output.\r
-\r
-**/\r
-VOID *\r
-AllocateAcpiNvsMemoryBelow4G (\r
- IN UINTN Size\r
- )\r
-{\r
- UINTN Pages;\r
- EFI_PHYSICAL_ADDRESS Address;\r
- EFI_STATUS Status;\r
- VOID* Buffer;\r
-\r
- Pages = EFI_SIZE_TO_PAGES (Size);\r
- Address = 0xffffffff;\r
-\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
- Pages,\r
- &Address\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- Buffer = (VOID *) (UINTN) Address;\r
- ZeroMem (Buffer, Size);\r
-\r
- return Buffer;\r
-}\r
-\r
-/**\r
- Prepare ACPI NVS memory below 4G memory for use of S3 resume.\r
-\r
- This function allocates ACPI NVS memory below 4G memory for use of S3 resume,\r
- and saves data into the memory region.\r
-\r
-**/\r
-VOID\r
-SaveCpuS3Data (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- ACPI_CPU_DATA_EX *AcpiCpuDataEx;\r
- ACPI_CPU_DATA *AcpiCpuData;\r
- UINTN GdtSize;\r
- UINTN IdtSize;\r
- VOID *Gdt;\r
- VOID *Idt;\r
-\r
- //\r
- // Allocate ACPI NVS memory below 4G memory for use of S3 resume.\r
- //\r
- AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX));\r
- AcpiCpuData = &AcpiCpuDataEx->AcpuCpuData;\r
-\r
- //\r
- //\r
- //\r
- AcpiCpuData->NumberOfCpus = 1;\r
- AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize);\r
- AcpiCpuData->ApMachineCheckHandlerBase = 0;\r
- AcpiCpuData->ApMachineCheckHandlerSize = 0;\r
- AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->GdtrProfile;\r
- AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->IdtrProfile;\r
- AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->MtrrTable;\r
- AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->RegisterTable;\r
- AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->PreSmmInitRegisterTable;\r
-\r
- //\r
- // Allocate stack space for all CPUs\r
- //\r
- AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData->NumberOfCpus * AcpiCpuData->StackSize);\r
-\r
- //\r
- // Get MTRR settings from currently executing CPU\r
- //\r
- MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);\r
-\r
- //\r
- // Get the BSP's data of GDT and IDT\r
- //\r
- AsmReadGdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->GdtrProfile);\r
- AsmReadIdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->IdtrProfile);\r
-\r
- //\r
- // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents\r
- //\r
- GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;\r
- IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;\r
- Gdt = AllocateAcpiNvsMemoryBelow4G (GdtSize + IdtSize);\r
- Idt = (VOID *)((UINTN)Gdt + GdtSize);\r
- CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);\r
- CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);\r
- AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;\r
- AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;\r
-\r
- //\r
- // No RegisterTable entries\r
- //\r
- AcpiCpuDataEx->RegisterTable.TableLength = 0;\r
-\r
- //\r
- // No PreSmmInitRegisterTable entries\r
- //\r
- AcpiCpuDataEx->PreSmmInitRegisterTable.TableLength = 0;\r
-\r
- //\r
- // Set the base address of CPU S3 data to PcdCpuS3DataAddress\r
- //\r
- Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-/**\r
- The entry function for QNCInit driver.\r
-\r
- This function just call initialization function for PciHostBridge,\r
- LegacyRegion and QNCSmmAccess module.\r
-\r
- @param ImageHandle The driver image handle for GmchInit driver\r
- @param SystemTable The pointer to System Table\r
-\r
- @retval EFI_SUCCESS Success to initialize every module for GMCH driver.\r
- @return EFI_STATUS The status of initialization work.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-QNCInit (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- S3BootScriptSaveInformationAsciiString (\r
- "QNCInitDxeEntryBegin"\r
- );\r
-\r
- gQNCInitImageHandle = ImageHandle;\r
-\r
- mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);\r
-\r
-\r
- //\r
- // Initialize PCIE root ports\r
- //\r
- Status = QncInitRootPorts ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "QNC Root Port initialization is failed!\n"));\r
- return Status;\r
- }\r
-\r
- Status = LegacyRegionInit ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "QNC LegacyRegion initialization is failed!\n"));\r
- return Status;\r
- }\r
-\r
-\r
- Status = InitializeQNCPolicy ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "QNC Policy initialization is failed!\n"));\r
- return Status;\r
- }\r
-\r
- Status = InitializeQNCSmbus (ImageHandle,SystemTable);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "QNC Smbus driver is failed!\n"));\r
- return Status;\r
- }\r
-\r
- QNCInitializeResource ();\r
-\r
- SaveCpuS3Data ();\r
-\r
- S3BootScriptSaveInformationAsciiString (\r
- "QNCInitDxeEntryEnd"\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Reserve I/O or memory space in GCD\r
-\r
- @param IoOrMemory Switch of I/O or memory.\r
- @param GcdType Type of the space.\r
- @param BaseAddress Base address of the space.\r
- @param Length Length of the space.\r
- @param Alignment Align with 2^Alignment\r
- @param RuntimeOrNot For runtime usage or not\r
- @param ImageHandle Handle for the image of this driver.\r
-\r
- @retval EFI_SUCCESS Reserve successful\r
-**/\r
-EFI_STATUS\r
-QNCReserveSpaceInGcd(\r
- IN UINTN IoOrMemory,\r
- IN UINTN GcdType,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINTN Alignment,\r
- IN BOOLEAN RuntimeOrNot,\r
- IN EFI_HANDLE ImageHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- if (IoOrMemory == QNC_RESERVED_ITEM_MEMORYIO) {\r
- Status = gDS->AddMemorySpace (\r
- GcdType,\r
- BaseAddress,\r
- Length,\r
- EFI_MEMORY_UC\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "Failed to add memory space :0x%x 0x%x\n",\r
- BaseAddress,\r
- Length\r
- ));\r
- }\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gDS->AllocateMemorySpace (\r
- EfiGcdAllocateAddress,\r
- GcdType,\r
- Alignment,\r
- Length,\r
- &BaseAddress,\r
- ImageHandle,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (RuntimeOrNot) {\r
- Status = gDS->SetMemorySpaceAttributes (\r
- BaseAddress,\r
- Length,\r
- EFI_MEMORY_RUNTIME | EFI_MEMORY_UC\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- } else {\r
- Status = gDS->AddIoSpace (\r
- GcdType,\r
- BaseAddress,\r
- Length\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gDS->AllocateIoSpace (\r
- EfiGcdAllocateAddress,\r
- GcdType,\r
- Alignment,\r
- Length,\r
- &BaseAddress,\r
- ImageHandle,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Initialize the memory and io resource which belong to QNC.\r
- 1) Report and allocate all BAR's memory to GCD.\r
- 2) Report PCI memory and I/O space to GCD.\r
- 3) Set memory attribute for <1M memory space.\r
-**/\r
-VOID\r
-QNCInitializeResource (\r
- )\r
-{\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- EFI_STATUS Status;\r
- UINT64 ExtraRegionLength;\r
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
- UINTN Index;\r
-\r
- // Report TSEG range\r
- // This range maybe has been reportted in PEI phase via Resource Hob.\r
- //\r
- QNCGetTSEGMemoryRange (&BaseAddress, &ExtraRegionLength);\r
- if (ExtraRegionLength != 0) {\r
- Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
- if (Status == EFI_NOT_FOUND) {\r
- Status = gDS->AddMemorySpace (\r
- EfiGcdMemoryTypeReserved,\r
- BaseAddress,\r
- ExtraRegionLength,\r
- EFI_MEMORY_UC\r
- );\r
- }\r
- }\r
-\r
- //\r
- // < 1M resource setting. The memory ranges <1M has been added into GCD via\r
- // resource hob produced by PEI phase. Here will set memory attribute of these\r
- // ranges for DXE phase.\r
- //\r
-\r
- //\r
- // Dos Area (0 ~ 0x9FFFFh)\r
- //\r
- Status = gDS->GetMemorySpaceDescriptor (0, &Descriptor);\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
- Descriptor.BaseAddress,\r
- Descriptor.Length,\r
- Descriptor.Attributes\r
- ));\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gDS->SetMemorySpaceAttributes(\r
- 0,\r
- 0xA0000,\r
- EFI_MEMORY_WB\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Default SMRAM UnCachable until SMBASE relocated.\r
- //\r
- Status = gDS->SetMemorySpaceAttributes(\r
- 0x30000,\r
- 0x10000,\r
- EFI_MEMORY_UC\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)\r
- //\r
- Status = gDS->GetMemorySpaceDescriptor (0xA0000, &Descriptor);\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
- Descriptor.BaseAddress,\r
- Descriptor.Length,\r
- Descriptor.Attributes\r
- ));\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gDS->SetMemorySpaceAttributes(\r
- 0xA0000,\r
- 0x20000,\r
- EFI_MEMORY_UC\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Expansion BIOS area.\r
- //\r
- Status = gDS->GetMemorySpaceDescriptor (0xC0000, &Descriptor);\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
- Descriptor.BaseAddress,\r
- Descriptor.Length,\r
- Descriptor.Attributes\r
- ));\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gDS->SetMemorySpaceAttributes(\r
- 0xC0000,\r
- 0x30000,\r
- EFI_MEMORY_UC\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Report other IO resources from mQNCReservedSpaceTable in GCD\r
- //\r
- for (Index = 0; Index < sizeof (mQNCReservedSpaceTable) / sizeof (QNC_SPACE_TABLE_ITEM); Index++) {\r
- Status = QNCReserveSpaceInGcd (\r
- mQNCReservedSpaceTable[Index].IoOrMemory,\r
- mQNCReservedSpaceTable[Index].Type,\r
- mQNCReservedSpaceTable[Index].BaseAddress,\r
- mQNCReservedSpaceTable[Index].Length,\r
- mQNCReservedSpaceTable[Index].Alignment,\r
- mQNCReservedSpaceTable[Index].RuntimeOrNot,\r
- gQNCInitImageHandle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- //\r
- // Report unused PCIe config space as reserved.\r
- //\r
- if (PcdGet64 (PcdPciExpressSize) < SIZE_256MB) {\r
- Status = QNCReserveSpaceInGcd (\r
- QNC_RESERVED_ITEM_MEMORYIO,\r
- EfiGcdMemoryTypeMemoryMappedIo,\r
- (PcdGet64(PcdPciExpressBaseAddress) + PcdGet64(PcdPciExpressSize)),\r
- (SIZE_256MB - PcdGet64(PcdPciExpressSize)),\r
- 0,\r
- FALSE,\r
- gQNCInitImageHandle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-}\r
-\r
-/**\r
- Use the platform PCD to initialize devices in the QNC\r
-\r
- @param ImageHandle Handle for the image of this driver.\r
- @retval EFI_SUCCESS Initialize successful\r
-**/\r
-EFI_STATUS\r
-InitializeQNCPolicy (\r
- )\r
-{\r
- UINT32 PciD31F0RegBase; // LPC\r
-\r
- PciD31F0RegBase = PciDeviceMmBase (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC);\r
-\r
- //\r
- // Disable for smbus\r
- //\r
- if (mQNCDeviceEnables.Bits.Smbus == DXE_DEVICE_DISABLED) {\r
- S3MmioAnd32 (PciD31F0RegBase + R_QNC_LPC_SMBUS_BASE, (~B_QNC_LPC_SMBUS_BASE_EN));\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r