Example #1
0
/**
  This function will update any runtime platform specific information.
  This currently includes:
    Setting OEM table values, ID, table ID, creator ID and creator revision.
    Enabling the proper processor entries in the APIC tables.

  @param[in]  Table       The table to update.

  @retval  EFI_SUCCESS    The function completed successfully.

**/
EFI_STATUS
PlatformUpdateTables (
  IN OUT EFI_ACPI_COMMON_HEADER  *Table
  )
{
  EFI_ACPI_DESCRIPTION_HEADER                                 *TableHeader;
  UINT8                                                       *CurrPtr;
  UINT8                                                       *EndPtr;
  ACPI_APIC_STRUCTURE_PTR                                     *ApicPtr;
  UINT8                                                       CurrProcessor;
  EFI_STATUS                                                  Status;
  EFI_MP_SERVICES_PROTOCOL                                    *MpService;
  UINTN                                                       MaximumNumberOfCPUs;
  UINTN                                                       NumberOfEnabledCPUs;
  UINTN                                                       BufferSize;
  ACPI_APIC_STRUCTURE_PTR                                     *ProcessorLocalApicEntry;
  UINTN                                                       BspIndex;
  EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE                          *AsfEntry;
  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER            *HpetTbl;
  UINT64                                                      OemIdValue;
  UINT8                                                       Index;
  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE                   *Facp;
  EFI_ACPI_OSFR_TABLE                                         *OsfrTable;
  EFI_ACPI_OSFR_OCUR_OBJECT                                   *pOcurObject;
  EFI_ACPI_OSFR_OCUR_OBJECT                                   OcurObject = {{0xB46F133D, 0x235F, 0x4634, 0x9F, 0x03, 0xB1, 0xC0, 0x1C, 0x54, 0x78, 0x5B}, 0, 0, 0, 0, 0};
  CHAR16                                                      *OcurMfgStringBuffer = NULL;
  CHAR16                                                      *OcurModelStringBuffer = NULL;
  UINT8                                                       *OcurRefDataBlockBuffer = NULL;
  UINTN                                                       OcurMfgStringBufferSize;
  UINTN                                                       OcurModelStringBufferSize;
  UINTN                                                       OcurRefDataBlockBufferSize;
#if defined (IDCC2_SUPPORTED) && IDCC2_SUPPORTED
  EFI_ACPI_ASPT_TABLE                                         *pSpttTable;
#endif
  UINT16                                                      NumberOfHpets;
  UINT16                                                      HpetCapIdValue;
  UINT32                                                      HpetBlockID;
  UINTN                                                       LocalApicCounter;
  EFI_PROCESSOR_INFORMATION                                   ProcessorInfoBuffer;
  UINT8                                                       TempVal;
  EFI_ACPI_3_0_IO_APIC_STRUCTURE                              *IOApicType;
  EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER         *APICTableHeader;

  CurrPtr                 = NULL;
  EndPtr                  = NULL;
  ApicPtr                 = NULL;
  LocalApicCounter        = 0;
  CurrProcessor           = 0;
  ProcessorLocalApicEntry = NULL;


 if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
    TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
    //
    // Update the OEMID.
    //
    OemIdValue = mPlatformInfo->AcpiOemId;

    *(UINT32 *)(TableHeader->OemId)     = (UINT32)OemIdValue;
    *(UINT16 *)(TableHeader->OemId + 4) = *(UINT16*)(((UINT8 *)&OemIdValue) + 4);

    if ((Table->Signature != EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
    //
    // Update the OEM Table ID.
    //
      TableHeader->OemTableId = mPlatformInfo->AcpiOemTableId;
    }

    //
    // Update the OEM Table ID.
    //
    TableHeader->OemRevision = EFI_ACPI_OEM_REVISION;

    //
    // Update the creator ID.
    //
    TableHeader->CreatorId = EFI_ACPI_CREATOR_ID;

    //
    // Update the creator revision.
    //
    TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
  }

  //
  // Complete this function.
  //
  //
  // Locate the MP services protocol.
  //
  //
  // Find the MP Protocol. This is an MP platform, so MP protocol must be
  // there.
  //
  Status = gBS->LocateProtocol (
                  &gEfiMpServiceProtocolGuid,
                  NULL,
                  (VOID **) &MpService
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Determine the number of processors.
  //
  MpService->GetNumberOfProcessors (
              MpService,
              &MaximumNumberOfCPUs,
              &NumberOfEnabledCPUs
              );

  ASSERT (MaximumNumberOfCPUs <= MAX_CPU_NUM && NumberOfEnabledCPUs >= 1);


  //
  // Assign a invalid intial value for update.
  //
  //
  // Update the processors in the APIC table.
  //
  switch (Table->Signature) {
    case EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE:
      //
      // Update the table if ASF is enabled. Otherwise, return error so caller will not install.
      //
      if (mSystemConfig.Asf == 1) {
        return  EFI_UNSUPPORTED;
      }
      AsfEntry = (EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *) Table;
      TempVal = (mNumberSmbusAddress < ASF_ADDR_DEVICE_ARRAY_LENGTH)? mNumberSmbusAddress : ASF_ADDR_DEVICE_ARRAY_LENGTH;
      for (Index = 0; Index < TempVal; Index++) {
        AsfEntry->AsfAddr.FixedSmbusAddresses[Index] = mSmbusRsvdAddresses[Index];
      }
      break;

    case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:

      Status = MpService->WhoAmI (
                            MpService,
                            &BspIndex
                            );

      //
      // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled.
      //
      APICTableHeader = (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Table;
      APICTableHeader->Flags |= EFI_ACPI_3_0_PCAT_COMPAT;

      CurrPtr = (UINT8 *) &((EFI_ACPI_DESCRIPTION_HEADER *) Table)[1];
      CurrPtr = CurrPtr + 8;

      //
      // Size of Local APIC Address & Flag.
      //
      EndPtr  = (UINT8 *) Table;
      EndPtr  = EndPtr + Table->Length;
      while (CurrPtr < EndPtr) {
        ApicPtr = (ACPI_APIC_STRUCTURE_PTR *) CurrPtr;
        switch (ApicPtr->AcpiApicCommon.Type) {
          case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC:
            //
            // ESS override
            // Fix for Ordering of MADT to be maintained as it is in MADT table.
            //
            // Update processor enabled or disabled and keep the local APIC
            // order in MADT intact.
            //
            // Sanity check to make sure proc-id is not arbitrary.
            //
            DEBUG ((EFI_D_ERROR, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", \
            ApicPtr->AcpiLocalApic.AcpiProcessorId, MaximumNumberOfCPUs));
            if(ApicPtr->AcpiLocalApic.AcpiProcessorId > MaximumNumberOfCPUs) {
              ApicPtr->AcpiLocalApic.AcpiProcessorId = (UINT8)MaximumNumberOfCPUs;
            }

            BufferSize                    = 0;
            ApicPtr->AcpiLocalApic.Flags  = 0;

            for (CurrProcessor = 0; CurrProcessor < MaximumNumberOfCPUs; CurrProcessor++) {
              Status = MpService->GetProcessorInfo (
                                    MpService,
                                    CurrProcessor,
                                    &ProcessorInfoBuffer
                                    );

              if (Status == EFI_SUCCESS && ProcessorInfoBuffer.ProcessorId == ApicPtr->AcpiLocalApic.ApicId) {
                //
                // Check to see whether or not a processor (or thread) is enabled.
                //
                if ((BspIndex == CurrProcessor) || ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0)) {
                  //
                  // Go on and check if Hyper Threading is enabled. If HT not enabled
                  // hide this thread from OS by not setting the flag to 1.  This is the
                  // software way to disable Hyper Threading.  Basically we just hide it
                  // from the OS.
                  //
                  ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_1_0_LOCAL_APIC_ENABLED;


                  if(ProcessorInfoBuffer.Location.Thread != 0) {
                    ApicPtr->AcpiLocalApic.Flags = 0;
                  }

                  AppendCpuMapTableEntry (&(ApicPtr->AcpiLocalApic));
                }
                break;
              }
            }

            //
            // If no APIC-ID match, the cpu may not be populated.
            //
            break;

          case EFI_ACPI_3_0_IO_APIC:

            IOApicType = (EFI_ACPI_3_0_IO_APIC_STRUCTURE *)CurrPtr;
            IOApicType->IoApicId = 0x02;
            //
            // IO APIC entries can be patched here.
            //
            break;
        }

        CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
      }
      break;

    case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:

       Facp = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
       Facp->Flags &= (UINT32)(~(3<<2));

      break;

    case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
      //
      // Patch the memory resource.
      //
      PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *) Table);
      break;

    case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
      //
      // Gv3 support
      //
      // TBD: Need re-design based on the ValleyTrail platform.
      //
      break;

    case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
      //
      // Adjust HPET Table to correct the Base Address.
      //
      // Enable HPET always as Hpet.asi always indicates that Hpet is enabled.
      //
      MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN);


      HpetTbl = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table;
      HpetTbl->BaseAddressLower32Bit.Address = HPET_BASE_ADDRESS;
      HpetTbl->EventTimerBlockId = *((UINT32*)(UINTN)HPET_BASE_ADDRESS);

      HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BASE_ADDRESS);
      NumberOfHpets = HpetCapIdValue & B_PCH_PCH_HPET_GCID_NT;  // Bits [8:12] contains the number of Hpets
      HpetBlockID = EFI_ACPI_EVENT_TIMER_BLOCK_ID;

      if((NumberOfHpets) && (NumberOfHpets & B_PCH_PCH_HPET_GCID_NT)) {
        HpetBlockID |= (NumberOfHpets);
      }
      HpetTbl->EventTimerBlockId = HpetBlockID;

      break;

    case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
      //
      // Update MCFG base and end bus number.
      //
      ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].BaseAddress
        = mPlatformInfo->PciData.PciExpressBase;
      ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].EndBusNumber
        = (UINT8)RShiftU64 (mPlatformInfo->PciData.PciExpressSize, 20) - 1;
      break;


    case EFI_ACPI_OSFR_TABLE_SIGNATURE:
      //
      // Get size of OSFR variable.
      //
      OcurMfgStringBufferSize = 0;
      Status = gRT->GetVariable (
                      gACPIOSFRMfgStringVariableName,
                      &gACPIOSFRMfgStringVariableGuid,
                      NULL,
                      &OcurMfgStringBufferSize,
                      NULL
                      );
      if (Status != EFI_BUFFER_TOO_SMALL) {
        //
        // Variable must not be present on the system.
        //
        return EFI_UNSUPPORTED;
      }

      //
      // Allocate memory for variable data.
      //
      OcurMfgStringBuffer = AllocatePool (OcurMfgStringBufferSize);
      Status = gRT->GetVariable (
                      gACPIOSFRMfgStringVariableName,
                      &gACPIOSFRMfgStringVariableGuid,
                      NULL,
                      &OcurMfgStringBufferSize,
                      OcurMfgStringBuffer
                      );
      if (!EFI_ERROR (Status)) {
        OcurModelStringBufferSize = 0;
        Status = gRT->GetVariable (
                        gACPIOSFRModelStringVariableName,
                        &gACPIOSFRModelStringVariableGuid,
                        NULL,
                        &OcurModelStringBufferSize,
                        NULL
                        );
        if (Status != EFI_BUFFER_TOO_SMALL) {
          //
          // Variable must not be present on the system.
          //
          return EFI_UNSUPPORTED;
        }

        //
        // Allocate memory for variable data.
        //
        OcurModelStringBuffer = AllocatePool (OcurModelStringBufferSize);
        Status = gRT->GetVariable (
                        gACPIOSFRModelStringVariableName,
                        &gACPIOSFRModelStringVariableGuid,
                        NULL,
                        &OcurModelStringBufferSize,
                        OcurModelStringBuffer
                        );
        if (!EFI_ERROR (Status)) {
          OcurRefDataBlockBufferSize = 0;
          Status = gRT->GetVariable (
                          gACPIOSFRRefDataBlockVariableName,
                          &gACPIOSFRRefDataBlockVariableGuid,
                          NULL,
                          &OcurRefDataBlockBufferSize,
                          NULL
                          );
          if (Status == EFI_BUFFER_TOO_SMALL) {
            //
            // Allocate memory for variable data.
            //
            OcurRefDataBlockBuffer = AllocatePool (OcurRefDataBlockBufferSize);
            Status = gRT->GetVariable (
                            gACPIOSFRRefDataBlockVariableName,
                            &gACPIOSFRRefDataBlockVariableGuid,
                            NULL,
                            &OcurRefDataBlockBufferSize,
                            OcurRefDataBlockBuffer
                            );
          }
          OsfrTable = (EFI_ACPI_OSFR_TABLE *) Table;
          //
          // Currently only one object is defined: OCUR_OSFR_TABLE.
          //
          OsfrTable->ObjectCount = 1;
          //
          // Initialize table length to fixed portion of the ACPI OSFR table.
          //
          OsfrTable->Header.Length = sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION);
          *(UINT32 *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION)) = \
            (UINT32) (sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + sizeof (UINT32));
          pOcurObject = (EFI_ACPI_OSFR_OCUR_OBJECT *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + \
            sizeof (UINT32));
          CopyMem (pOcurObject, &OcurObject, sizeof (EFI_ACPI_OSFR_OCUR_OBJECT));
          pOcurObject->ManufacturerNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \
            sizeof (EFI_ACPI_OSFR_OCUR_OBJECT));
          pOcurObject->ModelNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \
            sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize);
          if (OcurRefDataBlockBufferSize > 0) {
            pOcurObject->MicrosoftReferenceOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \
              sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + OcurModelStringBufferSize);
          }
          CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)), OcurMfgStringBuffer, \
            OcurMfgStringBufferSize);
          CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize), \
            OcurModelStringBuffer, OcurModelStringBufferSize);
          if (OcurRefDataBlockBufferSize > 0) {
            CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + \
            OcurModelStringBufferSize),OcurRefDataBlockBuffer, OcurRefDataBlockBufferSize);
          }
          OsfrTable->Header.Length += (UINT32)(OcurMfgStringBufferSize + OcurModelStringBufferSize + OcurRefDataBlockBufferSize);
          OsfrTable->Header.Length += sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + sizeof (UINT32);
        }
      }
      gBS->FreePool (OcurMfgStringBuffer);
      gBS->FreePool (OcurModelStringBuffer);
      gBS->FreePool (OcurRefDataBlockBuffer);
      break;
    default:
      break;
  }

  //
  //
  // Update the hardware signature in the FACS structure.
  //
  //
  // Locate the SPCR table and update based on current settings.
  // The user may change CR settings via setup or other methods.
  // The SPCR table must match.
  //
  return EFI_SUCCESS;
}
Example #2
0
VOID
ApicTableUpdate (
  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
  IN OUT   EFI_ACPI_TABLE_VERSION       *Version
  )
/*++

  Routine Description:

    Update the processors information in the APIC table

  Arguments:

    Table   - The table to be set
    Version - Version to publish

  Returns:

    None

--*/
{
  EFI_STATUS                 Status;
  EFI_MP_SERVICES_PROTOCOL   *MpService;
  UINT8                      *CurrPtr;
  UINT8                      *EndPtr;
  UINT8                      CurrIoApic;
  UINT8                      CurrProcessor;
  UINTN                      NumberOfCPUs;
  UINTN                      NumberOfEnabledCPUs;
  UINTN                      BufferSize;
  EFI_PROCESSOR_INFORMATION  MpContext;
  ACPI_APIC_STRUCTURE_PTR    *ApicPtr;  

  CurrIoApic    = 0;
  CurrProcessor = 0;
  //
  // Find the MP Protocol. This is an MP platform, so MP protocol must be
  // there.
  //
  Status = gBS->LocateProtocol (
                   &gEfiMpServiceProtocolGuid,
                   NULL,
                  (VOID**)&MpService
                   );
  if (EFI_ERROR (Status)) {
    //
    // Failed to get MP information, doesn't publish the invalid table
    //
    *Version = EFI_ACPI_TABLE_VERSION_NONE;
    return;
  }

  //
  // Determine the number of processors
  //
  MpService->GetNumberOfProcessors (
              MpService,
              &NumberOfCPUs,
              &NumberOfEnabledCPUs
              );

  CurrPtr = (UINT8*) &(TableHeader[1]);
  CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
  EndPtr  = (UINT8*) TableHeader;
  EndPtr  = EndPtr + TableHeader->Length;

  while (CurrPtr < EndPtr) {
  
    ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
    switch (ApicPtr->AcpiApicCommon.Type) {

      case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
        BufferSize = sizeof (EFI_PROCESSOR_INFORMATION);
        ApicPtr->AcpiLocalApic.Flags = 0;
        ApicPtr->AcpiLocalApic.ApicId = 0;
        Status = MpService->GetProcessorInfo (
                              MpService,
                              CurrProcessor,
                              &MpContext
                              );

        if (!EFI_ERROR (Status)) {
          if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
            ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
          }
          ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
        }
        CurrProcessor++;
        break;

      case EFI_ACPI_1_0_IO_APIC:
        //
        // IO APIC entries can be patched here
        //
        if (CurrIoApic == 0) {
          //
          // Update SOC internel IOAPIC base
          //
          ApicPtr->AcpiIoApic.IoApicId      =  PcdGet8 (PcdIoApicSettingIoApicId);
          ApicPtr->AcpiIoApic.IoApicAddress =  (UINT32)FixedPcdGet64(PcdIoApicBaseAddress);
          ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
        } else {
          //
          // Porting is required to update other IOAPIC entries if available
          //
          ASSERT (0);
        }
        CurrIoApic++;
        break;
          
      default:
        break;
      };
    CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
  }
}
Example #3
0
File: TcgDxe.c Project: OznOg/edk2
/**
  Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
  Caller is responsible to free LocationBuf.

  @param[out] LocationBuf          Returns Processor Location Buffer.
  @param[out] Num                  Returns processor number.

  @retval EFI_SUCCESS              Operation completed successfully.
  @retval EFI_UNSUPPORTED       MpService protocol not found.

**/
EFI_STATUS
GetProcessorsCpuLocation (
    OUT  EFI_CPU_PHYSICAL_LOCATION   **LocationBuf,
    OUT  UINTN                       *Num
  )
{
  EFI_STATUS                        Status;
  EFI_MP_SERVICES_PROTOCOL          *MpProtocol;
  UINTN                             ProcessorNum;
  UINTN                             EnabledProcessorNum;
  EFI_PROCESSOR_INFORMATION         ProcessorInfo;
  EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;
  UINTN                             Index;

  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);
  if (EFI_ERROR (Status)) {
    //
    // MP protocol is not installed
    //
    return EFI_UNSUPPORTED;
  }

  Status = MpProtocol->GetNumberOfProcessors(
                         MpProtocol,
                         &ProcessorNum,
                         &EnabledProcessorNum
                         );
  if (EFI_ERROR(Status)){
    return Status;
  }

  Status = gBS->AllocatePool(
                  EfiBootServicesData,
                  sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,
                  (VOID **) &ProcessorLocBuf
                  );
  if (EFI_ERROR(Status)){
    return Status;
  }

  //
  // Get each processor Location info
  //
  for (Index = 0; Index < ProcessorNum; Index++) {
    Status = MpProtocol->GetProcessorInfo(
                           MpProtocol,
                           Index,
                           &ProcessorInfo
                           );
    if (EFI_ERROR(Status)){
      FreePool(ProcessorLocBuf);
      return Status;
    }

    //
    // Get all Processor Location info & measure
    //
    CopyMem(
      &ProcessorLocBuf[Index],
      &ProcessorInfo.Location,
      sizeof(EFI_CPU_PHYSICAL_LOCATION)
      );
  }

  *LocationBuf = ProcessorLocBuf;
  *Num = ProcessorNum;

  return Status;
}
Example #4
0
/**
   The entry function of the CpuS3Data driver.

   Allocate and initialize all fields of the ACPI_CPU_DATA structure except the
   MTRR settings.  Register an event notification on gEfiEndOfDxeEventGroupGuid
   to capture the ACPI_CPU_DATA MTRR settings.  The PcdCpuS3DataAddress is set
   to the address that ACPI_CPU_DATA is allocated at.

   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
   @param[in] SystemTable  A pointer to the EFI System Table.

   @retval EFI_SUCCESS     The entry point is executed successfully.
   @retval EFI_UNSUPPORTED Do not support ACPI S3.
   @retval other           Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
CpuS3DataInitialize (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                 Status;
  ACPI_CPU_DATA_EX           *AcpiCpuDataEx;
  ACPI_CPU_DATA              *AcpiCpuData;
  EFI_MP_SERVICES_PROTOCOL   *MpServices;
  UINTN                      NumberOfCpus;
  UINTN                      NumberOfEnabledProcessors;
  VOID                       *Stack;
  UINTN                      TableSize;
  CPU_REGISTER_TABLE         *RegisterTable;
  UINTN                      Index;
  EFI_PROCESSOR_INFORMATION  ProcessorInfoBuffer;
  UINTN                      GdtSize;
  UINTN                      IdtSize;
  VOID                       *Gdt;
  VOID                       *Idt;
  EFI_EVENT                  Event;
  ACPI_CPU_DATA              *OldAcpiCpuData;

  if (!PcdGetBool (PcdAcpiS3Enable)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
  //
  OldAcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);

  AcpiCpuDataEx = AllocateZeroPages (sizeof (ACPI_CPU_DATA_EX));
  ASSERT (AcpiCpuDataEx != NULL);
  AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData;

  //
  // Get MP Services Protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiMpServiceProtocolGuid,
                  NULL,
                  (VOID **)&MpServices
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Get the number of CPUs
  //
  Status = MpServices->GetNumberOfProcessors (
                         MpServices,
                         &NumberOfCpus,
                         &NumberOfEnabledProcessors
                         );
  ASSERT_EFI_ERROR (Status);
  AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;

  //
  // Initialize ACPI_CPU_DATA fields
  //
  AcpiCpuData->StackSize                 = PcdGet32 (PcdCpuApStackSize);
  AcpiCpuData->ApMachineCheckHandlerBase = 0;
  AcpiCpuData->ApMachineCheckHandlerSize = 0;
  AcpiCpuData->GdtrProfile  = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->GdtrProfile;
  AcpiCpuData->IdtrProfile  = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->IdtrProfile;
  AcpiCpuData->MtrrTable    = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->MtrrTable;

  //
  // Allocate stack space for all CPUs.
  // Use ACPI NVS memory type because this data will be directly used by APs
  // in S3 resume phase in long mode. Also during S3 resume, the stack buffer
  // will only be used as scratch space. i.e. we won't read anything from it
  // before we write to it, in PiSmmCpuDxeSmm.
  //
  Stack = AllocateAcpiNvsMemory (NumberOfCpus * AcpiCpuData->StackSize);
  ASSERT (Stack != NULL);
  AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack;

  //
  // Get the boot processor's GDT and IDT
  //
  AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile);
  AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile);

  //
  // Allocate GDT and IDT and copy current GDT and IDT contents
  //
  GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;
  IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;
  Gdt = AllocateZeroPages (GdtSize + IdtSize);
  ASSERT (Gdt != NULL);
  Idt = (VOID *)((UINTN)Gdt + GdtSize);
  CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);
  CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);
  AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;
  AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;

  if (OldAcpiCpuData != NULL) {
    AcpiCpuData->RegisterTable           = OldAcpiCpuData->RegisterTable;
    AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable;
    AcpiCpuData->ApLocation              = OldAcpiCpuData->ApLocation;
    CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
  } else {
    //
    // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
    //
    TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
    RegisterTable = (CPU_REGISTER_TABLE *)AllocateZeroPages (TableSize);
    ASSERT (RegisterTable != NULL);

    for (Index = 0; Index < NumberOfCpus; Index++) {
      Status = MpServices->GetProcessorInfo (
                           MpServices,
                           Index,
                           &ProcessorInfoBuffer
                           );
      ASSERT_EFI_ERROR (Status);

      RegisterTable[Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
      RegisterTable[Index].TableLength        = 0;
      RegisterTable[Index].AllocatedSize      = 0;
      RegisterTable[Index].RegisterTableEntry = 0;

      RegisterTable[NumberOfCpus + Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
      RegisterTable[NumberOfCpus + Index].TableLength        = 0;
      RegisterTable[NumberOfCpus + Index].AllocatedSize      = 0;
      RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
    }
    AcpiCpuData->RegisterTable           = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
    AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
  }

  //
  // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
  //
  Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
  ASSERT_EFI_ERROR (Status);

  //
  // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
  // The notification function allocates StartupVector and saves MTRRs for ACPI_CPU_DATA
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_CALLBACK,
                  CpuS3DataOnEndOfDxe,
                  AcpiCpuData,
                  &gEfiEndOfDxeEventGroupGuid,
                  &Event
                  );
  ASSERT_EFI_ERROR (Status);

  return EFI_SUCCESS;
}