--- /dev/null
+/** @file\r
+ACPI CPU Data initialization module\r
+\r
+This module initializes the ACPI_CPU_DATA structure and registers the address\r
+of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple\r
+version of this module. It does not provide a machine check handler or CPU\r
+register initialization tables for ACPI S3 resume. It also only supports the\r
+number of CPUs reported by the MP Services Protocol, so this module does not\r
+support hot plug CPUs. This module can be copied into a CPU specific package\r
+and customized if these additional features are required.\r
+\r
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2015, Red Hat, Inc.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <AcpiCpuData.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MtrrLib.h>\r
+\r
+#include <Protocol/MpService.h>\r
+#include <Guid/EventGroup.h>\r
+\r
+//\r
+// Data structure used to allocate ACPI_CPU_DATA and its supporting structures\r
+//\r
+typedef struct {\r
+ ACPI_CPU_DATA AcpiCpuData;\r
+ MTRR_SETTINGS MtrrTable;\r
+ IA32_DESCRIPTOR GdtrProfile;\r
+ IA32_DESCRIPTOR IdtrProfile;\r
+} ACPI_CPU_DATA_EX;\r
+\r
+/**\r
+ Allocate EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ This function allocates EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ @param[in] 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
+ EFI_PHYSICAL_ADDRESS Address;\r
+ EFI_STATUS Status;\r
+ VOID *Buffer;\r
+\r
+ Address = BASE_4GB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (Size),\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
+ Callback function executed when the EndOfDxe event group is signaled.\r
+\r
+ We delay saving the MTRR settings until BDS signals EndOfDxe.\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[out] Context Pointer to the MTRR_SETTINGS buffer to fill in.\r
+**/\r
+VOID\r
+EFIAPI\r
+SaveMtrrsOnEndOfDxe (\r
+ IN EFI_EVENT Event,\r
+ OUT VOID *Context\r
+ )\r
+{\r
+ DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));\r
+ MtrrGetAllMtrrs (Context);\r
+\r
+ //\r
+ // Close event, so it will not be invoked again.\r
+ //\r
+ gBS->CloseEvent (Event);\r
+}\r
+\r
+/**\r
+ The entry function of the CpuS3Data driver.\r
+\r
+ Allocate and initialize all fields of the ACPI_CPU_DATA structure except the\r
+ MTRR settings. Register an event notification on gEfiEndOfDxeEventGroupGuid\r
+ to capture the ACPI_CPU_DATA MTRR settings. The PcdCpuS3DataAddress is set\r
+ to the address that ACPI_CPU_DATA is allocated at.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuS3DataInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ACPI_CPU_DATA_EX *AcpiCpuDataEx;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ UINTN NumberOfCpus;\r
+ UINTN NumberOfEnabledProcessors;\r
+ VOID *Stack;\r
+ UINTN TableSize;\r
+ CPU_REGISTER_TABLE *RegisterTable;\r
+ UINTN Index;\r
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
+ UINTN GdtSize;\r
+ UINTN IdtSize;\r
+ VOID *Gdt;\r
+ VOID *Idt;\r
+ EFI_EVENT Event;\r
+\r
+ //\r
+ // Allocate ACPI NVS memory below 4G memory for use on ACPI S3 resume.\r
+ //\r
+ AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX));\r
+ ASSERT (AcpiCpuDataEx != NULL);\r
+ AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData;\r
+\r
+ //\r
+ // Get MP Services Protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiMpServiceProtocolGuid,\r
+ NULL,\r
+ (VOID **)&MpServices\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Allocate a 4KB reserved page below 1MB\r
+ //\r
+ AcpiCpuData->StartupVector = BASE_1MB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ 1,\r
+ &AcpiCpuData->StartupVector\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Get the number of CPUs\r
+ //\r
+ Status = MpServices->GetNumberOfProcessors (\r
+ MpServices,\r
+ &NumberOfCpus,\r
+ &NumberOfEnabledProcessors\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
+\r
+ //\r
+ // Initialize ACPI_CPU_DATA fields\r
+ //\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
+\r
+ //\r
+ // Allocate stack space for all CPUs\r
+ //\r
+ Stack = AllocateAcpiNvsMemoryBelow4G (NumberOfCpus * AcpiCpuData->StackSize);\r
+ ASSERT (Stack != NULL);\r
+ AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack;\r
+\r
+ //\r
+ // Get the boot processor's GDT and IDT\r
+ //\r
+ AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile);\r
+ AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile);\r
+\r
+ //\r
+ // Allocate GDT and IDT in ACPI NVS and copy current GDT and IDT contents\r
+ //\r
+ GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;\r
+ IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;\r
+ Gdt = AllocateAcpiNvsMemoryBelow4G (GdtSize + IdtSize);\r
+ ASSERT (Gdt != NULL);\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
+ // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs\r
+ //\r
+ TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);\r
+ RegisterTable = (CPU_REGISTER_TABLE *)AllocateAcpiNvsMemoryBelow4G (TableSize);\r
+ ASSERT (RegisterTable != NULL);\r
+ for (Index = 0; Index < NumberOfCpus; Index++) {\r
+ Status = MpServices->GetProcessorInfo (\r
+ MpServices,\r
+ Index,\r
+ &ProcessorInfoBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
+ RegisterTable[Index].TableLength = 0;\r
+ RegisterTable[Index].AllocatedSize = 0;\r
+ RegisterTable[Index].RegisterTableEntry = NULL;\r
+\r
+ RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
+ RegisterTable[NumberOfCpus + Index].TableLength = 0;\r
+ RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;\r
+ RegisterTable[NumberOfCpus + Index].RegisterTableEntry = NULL;\r
+ }\r
+ AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;\r
+ AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);\r
+\r
+ //\r
+ // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
+ //\r
+ Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.\r
+ // The notification function saves MTRRs for ACPI_CPU_DATA\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ SaveMtrrsOnEndOfDxe,\r
+ &AcpiCpuDataEx->MtrrTable,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &Event\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+## @file\r
+# ACPI CPU Data initialization module\r
+#\r
+# This module initializes the ACPI_CPU_DATA structure and registers the address\r
+# of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple\r
+# version of this module. It does not provide a machine check handler or CPU\r
+# register initialization tables for ACPI S3 resume. It also only supports the\r
+# number of CPUs reported by the MP Services Protocol, so this module does not\r
+# support hot plug CPUs. This module can be copied into a CPU specific package\r
+# and customized if these additional features are required.\r
+#\r
+# Copyright (c) 2013-2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2015, Red Hat, Inc.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = CpuS3DataDxe\r
+ FILE_GUID = 4D2E57EE-0E3F-44DD-93C4-D3B57E96945D\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = CpuS3DataInitialize\r
+\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+\r
+[Sources]\r
+ CpuS3Data.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ BaseLib\r
+ MtrrLib\r
+\r
+[Guids]\r
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES\r
+\r
+[Protocols]\r
+ gEfiMpServiceProtocolGuid ## CONSUMES\r
+\r
+[Pcd]\r
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES\r
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress ## PRODUCES\r
+\r
+[Depex]\r
+ gEfiMpServiceProtocolGuid\r