Esempio n. 1
0
/**
  Get Protected mode code segment from current GDT table.

  @return  Protected mode code segment value.
**/
UINT16
GetProtectedModeCS (
  VOID
  )
{
  IA32_DESCRIPTOR          GdtrDesc;
  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;
  UINTN                    GdtEntryCount;
  UINT16                   Index;

  Index = (UINT16) -1;
  AsmReadGdtr (&GdtrDesc);
  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
  for (Index = 0; Index < GdtEntryCount; Index++) {
    if (GdtEntry->Bits.L == 0) {
      if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {
        break;
      }
    }
    GdtEntry++;
  }
  ASSERT (Index != -1);
  return Index * 8;
}
Esempio n. 2
0
/**

  This function initialize basic context for FRM.

**/
VOID
InitBasicContext (
  VOID
  )
{
  UINT32  RegEax;

  mHostContextCommon.CpuNum = GetCpuNumFromAcpi ();

  GetPciExpressInfoFromAcpi (&mHostContextCommon.PciExpressBaseAddress, &mHostContextCommon.PciExpressLength);
  PcdSet64 (PcdPciExpressBaseAddress, mHostContextCommon.PciExpressBaseAddress);
  if (mHostContextCommon.PciExpressBaseAddress == 0) {
    CpuDeadLoop ();
  }

  mHostContextCommon.AcpiTimerIoPortBaseAddress = GetAcpiTimerPort (&mHostContextCommon.AcpiTimerWidth);
  PcdSet16 (PcdAcpiTimerIoPortBaseAddress, mHostContextCommon.AcpiTimerIoPortBaseAddress);
  PcdSet8 (PcdAcpiTimerWidth, mHostContextCommon.AcpiTimerWidth);
  if (mHostContextCommon.AcpiTimerIoPortBaseAddress == 0) {
    CpuDeadLoop ();
  }

  mHostContextCommon.ResetIoPortBaseAddress = GetAcpiResetPort ();

  mHostContextCommon.AcpiPmControlIoPortBaseAddress = GetAcpiPmControlPort ();
  if (mHostContextCommon.AcpiPmControlIoPortBaseAddress == 0) {
    CpuDeadLoop ();
  }

  mHostContextCommon.HostContextPerCpu = AllocatePages (FRM_SIZE_TO_PAGES(sizeof(FRM_HOST_CONTEXT_PER_CPU)) * mHostContextCommon.CpuNum);
  mGuestContextCommon.GuestContextPerCpu = AllocatePages (FRM_SIZE_TO_PAGES(sizeof(FRM_GUEST_CONTEXT_PER_CPU)) * mHostContextCommon.CpuNum);

  mHostContextCommon.LowMemoryBase = mCommunicationData.LowMemoryBase;
  mHostContextCommon.LowMemorySize = mCommunicationData.LowMemorySize;
  mHostContextCommon.LowMemoryBackupBase = (UINT64)(UINTN)AllocatePages (FRM_SIZE_TO_PAGES ((UINTN)mCommunicationData.LowMemorySize));

  //
  // Save current context
  //
  mBspIndex = ApicToIndex (ReadLocalApicId ());
  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0 = AsmReadCr0 ();
  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr3 = AsmReadCr3 ();
  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr4 = AsmReadCr4 ();
  AsmReadGdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr);
  AsmReadIdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr);

  AsmCpuid (CPUID_EXTENDED_INFORMATION, &RegEax, NULL, NULL, NULL);
  if (RegEax >= CPUID_EXTENDED_ADDRESS_SIZE) {
    AsmCpuid (CPUID_EXTENDED_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
    mHostContextCommon.PhysicalAddressBits = (UINT8)RegEax;
  } else {
    mHostContextCommon.PhysicalAddressBits = 36;
  }
}
Esempio n. 3
0
/**

  This function initialize guest BSP in S3.

**/
VOID
BspS3Init (
  VOID
  )
{
  UINT32  Index;

  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0 = AsmReadCr0 ();
  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr3 = AsmReadCr3 ();
  mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr4 = AsmReadCr4 ();
  AsmReadGdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr);
  AsmReadIdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr);

  InitHostContextPerCpu (mBspIndex);

  for (Index = 0; Index < mHostContextCommon.CpuNum; Index++) {
    mGuestContextCommon.GuestContextPerCpu[Index].Cr0 = mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0;
    mGuestContextCommon.GuestContextPerCpu[Index].Cr3 = mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr3;
    mGuestContextCommon.GuestContextPerCpu[Index].Cr4 = mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr4;
    CopyMem (&mGuestContextCommon.GuestContextPerCpu[Index].Gdtr, &mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr, sizeof(IA32_DESCRIPTOR));
  }
  InitGuestContextPerCpu (mBspIndex);
}
Esempio n. 4
0
File: DlEntry.c Progetto: jyao1/STM
/**

  This function set TXT HEAP.

  @param MleLoadAddress  MLE address
  @param MleLoadSize     MLE size
  @param PageTableBase   page table base

**/
VOID
TxtSetupHeap (
  IN UINT64  MleLoadAddress,
  IN UINT64  MleLoadSize,
  IN UINT64  PageTableBase
  )
{
  VOID                              *TxtOsMleData;
  MLE_PRIVATE_DATA                  *MlePrivateData;
  DCE_PRIVATE_DATA                  *DcePrivateData;
  TXT_OS_TO_SINIT_DATA              *OsSinitData;
  TXT_SINIT_TO_MLE_DATA             *SinitMleData;
  TXT_ACM_FORMAT                    *SinitAcm;
  TXT_CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable;
  UINTN                             TxtHeapSize;
  UINTN                             TxtHeapOccupiedSize;

  //
  // MlePrivateData
  //
  TxtOsMleData = GetTxtOsToMleData();
  DEBUG((EFI_D_INFO, "(TXT) TxtOsMleData - 0x%x\n", TxtOsMleData));
  *((UINT64 *)TxtOsMleData - 1) = sizeof(UINT64) + sizeof(TXT_OS_TO_MLE_DATA_STRUCT);

  MlePrivateData = GetMlePrivateData ();
  DcePrivateData = &MlePrivateData->DcePrivateData;
  AsmReadGdtr (&MlePrivateData->Gdtr);
  AsmReadIdtr (&MlePrivateData->Idtr);
  MlePrivateData->Ds = AsmReadDs ();

  MlePrivateData->TempEsp = (UINT32)(UINT32)((UINTN)GetTxtHeap () + GetTxtHeapSize () - MLE_TEMP_STACK_SIZE_RLP - 0x20);

  //
  // Patch CS/Offset in stack
  //
  // +---------+
  // |  Offset |
  // +---------+
  // |    CS   |
  // +---------+
  // |  Dummy  |
  // +---------+
  // |  Dummy  |
  // +---------+
  // |  Dummy  |
  // +---------+
  // |  Dummy  |
  // +---------+ <- TempEsp
  if (PostInitAddr != 0) {
    MlePrivateData->PostSinitOffset  = (UINT32)((UINTN)AsmMleEntryPoint + PostInitAddr);
    MlePrivateData->PostSinitSegment = (UINT32)AsmReadCs();
  }

  MlePrivateData->Lock = 0;
  MlePrivateData->RlpInitializedNumber = 0;

  //
  // OsSinitData
  //
  OsSinitData = GetTxtOsToSinitData ();
  DEBUG((EFI_D_INFO, "(TXT) OsSinitData - 0x%x\n", OsSinitData));
  *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData);
  OsSinitData->Version = TXT_OS_TO_SINIT_DATA_VERSION;
  OsSinitData->Flags = 0;
  OsSinitData->MLEPageTableBase = PageTableBase;

  //
  // We copy MleHeader to DPR
  //
  {
    TXT_MLE_HEADER   *MleHeader;

    MleHeader = (TXT_MLE_HEADER *)(UINTN)MleLoadAddress;
    CopyMem (&MleHeader->Uuid, &gMleHeaderUuid, sizeof(gMleHeaderUuid));
    MleHeader->HeaderLen = sizeof(*MleHeader);
    MleHeader->Version = TXT_MLE_HEADER_VERSION;

    MleHeader->EntryPoint = (UINT32)(UINTN)MleHeader + sizeof(*MleHeader);
    if (MleHeader->Version < TXT_MLE_HEADER_VERSION_2_1) {
      MleHeader->EntryPoint -= (sizeof(MleHeader->CmdlineStart) + sizeof(MleHeader->CmdlineEnd));
    }
    //
    // Patch the instruction for ILP
    //
    *(UINT8 *)(UINTN)MleHeader->EntryPoint = 0x90; // nop
    *(UINT8 *)((UINTN)MleHeader->EntryPoint + 1) = 0xE9; // near jmp
    *(UINT32 *)((UINTN)MleHeader->EntryPoint + 2) = (UINT32)((UINTN)AsmMleEntryPoint - ((UINTN)MleHeader->EntryPoint + 6)); // minus next instruction
    //
    // Patch the instrution for RLPs: cli, hlt, and jmp $-2
    //
    *(UINT32 *)((UINTN)MleHeader->EntryPoint + 6) = 0xFCEBF4FA;

    MleHeader->EntryPoint -= (UINT32)PageTableBase;

    if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_1_1) {
      MleHeader->FirstValidPage = (UINT32)MleLoadAddress;
      MleHeader->FirstValidPage -= (UINT32)PageTableBase;
      MleHeader->MleStart = MleHeader->FirstValidPage;
      //MleHeader->MleEnd = MleHeader->MleStart + sizeof(*MleHeader) + 10; // Offset (1 nop + 5 jmp + 4 deadloop)
      MleHeader->MleEnd = MleHeader->MleStart + (UINT32)MleLoadSize;
    }

    if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_2) {
      MleHeader->Capabilities = TXT_MLE_SINIT_CAPABILITY_GETSET_WAKEUP | TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP;
      MleHeader->Capabilities |= TXT_MLE_SINIT_CAPABILITY_ECX_HAS_PAGE_TABLE;
#ifdef STM_SUPPORT
      MleHeader->Capabilities |= TXT_MLE_SINIT_CAPABILITY_STM;
#endif
    }

    if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_2_1) {
      MleHeader->CmdlineStart = 0; // Not use
      MleHeader->CmdlineEnd   = 0; // Not use
    }

    //
    // Done
    //
    OsSinitData->MLEHeaderBase = (UINT64)(UINTN)MleHeader;
    OsSinitData->MLEHeaderBase -= PageTableBase;
    OsSinitData->MLESize = (UINT64)(MleHeader->MleEnd - MleHeader->MleStart);
  }

  OsSinitData->PMRLowBase  = MlePrivateData->DcePrivateData.PmrLowBase;
  OsSinitData->PMRLowSize  = MlePrivateData->DcePrivateData.PmrLowSize;
  OsSinitData->PMRHighBase = MlePrivateData->DcePrivateData.PmrHighBase;
  OsSinitData->PMRHighSize = MlePrivateData->DcePrivateData.PmrHighSize;
  OsSinitData->LCPPOBase   = MlePrivateData->DcePrivateData.LcpPoBase;
  OsSinitData->LCPPOSize   = MlePrivateData->DcePrivateData.LcpPoSize;

  SinitAcm = (TXT_ACM_FORMAT *)(UINTN)TxtPubRead32 (TXT_SINIT_BASE);
  ChipsetAcmInformationTable = (TXT_CHIPSET_ACM_INFORMATION_TABLE *) \
                               ((UINTN)(SinitAcm + 1) + 
                               SinitAcm->KeySize * 4 + 
                               sizeof(UINT32) + 
                               ACM_PKCS_1_5_RSA_SIGNATURE_SIZE + 
                               SinitAcm->ScratchSize * 4
                               );

  if ((ChipsetAcmInformationTable->Capabilities & TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP) != 0) {
    OsSinitData->Capabilities = TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP;
  } else {
    OsSinitData->Capabilities = TXT_MLE_SINIT_CAPABILITY_GETSET_WAKEUP;
  }
  OsSinitData->Version = ChipsetAcmInformationTable->OsSinitTableVer;
  if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_5) {
    OsSinitData->RsdpPtr = (UINT64)(UINTN)FindAcpiRsdPtr ();
    if (OsSinitData->RsdpPtr == 0) {
      OsSinitData->RsdpPtr = (UINT64)(UINTN)&MlePrivateData->UefiRsdp;
    }
    if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_6) {
      if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_7) {
        OsSinitData->Flags = TXT_OS_TO_SINIT_DATA_FLAGS_MAX_AGILE_POLICY;
      }
      //
      // Fill Event Log data there
      //
      TXT_HEAP_EXT_DATA_ELEMENT             *Element;
      TXT_HEAP_EVENTLOG_EXT_ELEMENT         *EventLogElement;
      TXT_EVENT_LOG_CONTAINER               *EventLog;
      TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2   *EventLogPointerElement2;
      TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2_1 *EventLogPointerElement2_1;
      TXT_HEAP_EVENT_LOG_DESCR              *EventLogDesc;
      UINTN                                 Index;
      TCG_LOG_DESCRIPTOR                    *TcgLogDesc;
      TCG_PCR_EVENT_HDR                     *PcrEvent;

      *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData);

      Element = (TXT_HEAP_EXT_DATA_ELEMENT *)(OsSinitData + 1);

      if (DcePrivateData->TpmType == FRM_TPM_TYPE_TPM12) {
        // TPM1.2
        Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENTLOG_PTR;
        Element->Size = sizeof(TXT_HEAP_EXT_DATA_ELEMENT) + sizeof(TXT_HEAP_EVENTLOG_EXT_ELEMENT);
        EventLogElement = (TXT_HEAP_EVENTLOG_EXT_ELEMENT *)(Element + 1);
        DcePrivateData->EventLogElement = EventLogElement;

        //
        // Init EventLogContainer
        //
        EventLog = (TXT_EVENT_LOG_CONTAINER *)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase);
        ZeroMem(EventLog, MAX_EVENT_LOG_BUFFER_SIZE);
        CopyMem(EventLog->Signature, TXT_EVENTLOG_SIGNATURE, sizeof(TXT_EVENTLOG_SIGNATURE));
        EventLog->ContainerVersionMajor = TXT_EVENTLOG_CONTAINER_MAJOR_VERSION;
        EventLog->ContainerVersionMinor = TXT_EVENTLOG_CONTAINER_MINOR_VERSION;
        EventLog->PcrEventVersionMajor = TXT_EVENTLOG_EVENT_MAJOR_VERSION;
        EventLog->PcrEventVersionMinor = TXT_EVENTLOG_EVENT_MINOR_VERSION;
        EventLog->Size = MAX_EVENT_LOG_BUFFER_SIZE;
        EventLog->PcrEventsOffset = sizeof(*EventLog);
        EventLog->NextEventOffset = sizeof(*EventLog);

        EventLogElement->EventLogAddress = (UINT64)(UINTN)EventLog;

        *((UINT64 *)OsSinitData - 1) += Element->Size;
        Element = (TXT_HEAP_EXT_DATA_ELEMENT *)((UINTN)Element + Element->Size);

      }
      if (DcePrivateData->TpmType == FRM_TPM_TYPE_TPM2) {
        // TPM2.0
        UINT16 TpmHashAlgo[] = { TPM_ALG_SHA1, TPM_ALG_SHA256, TPM_ALG_SHA384, TPM_ALG_SHA512, TPM_ALG_SM3_256 };
        UINTN  SubIndex;

        DcePrivateData->EventHashAlgoIDCount = 0;
        for (Index = 0; Index < sizeof(TpmHashAlgo) / sizeof(TpmHashAlgo[0]); Index++) {
          if ((DcePrivateData->ActivePcrBanks & (1 << Index)) != 0) {
            for (SubIndex = 0; SubIndex < DcePrivateData->AcmTpmHashAlgoIDCount; SubIndex++) {
              if (DcePrivateData->AcmTpmHashAlgoID[SubIndex] == TpmHashAlgo[Index]) {
                // Both TPM and ACM support this hash algo.
                DcePrivateData->EventHashAlgoID[DcePrivateData->EventHashAlgoIDCount] = TpmHashAlgo[Index];
                DcePrivateData->EventHashAlgoIDCount++;
              }
            }
          }
        }

        if ((DcePrivateData->AcmCapabilities & TXT_MLE_SINIT_CAPABILITY_TCG2_COMPATIBILE_EVENTLOG) == 0) {
          Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2;
          EventLogPointerElement2 = (TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2 *)(Element + 1);
          DcePrivateData->EventLogPointerElement2 = EventLogPointerElement2;
          EventLogPointerElement2->Count = DcePrivateData->EventHashAlgoIDCount;
          EventLogDesc = (TXT_HEAP_EVENT_LOG_DESCR *)(EventLogPointerElement2 + 1);

          Element->Size = sizeof(TXT_HEAP_EXT_DATA_ELEMENT) + sizeof(TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2) + EventLogPointerElement2->Count * sizeof(TXT_HEAP_EVENT_LOG_DESCR);

          for (Index = 0; Index < EventLogPointerElement2->Count; Index++, EventLogDesc++) {
            EventLogDesc->HashAlgID = DcePrivateData->EventHashAlgoID[Index];
            EventLogDesc->Reserved = 0;
            EventLogDesc->PhysicalAddress = (UINT64)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase + MAX_EVENT_LOG_BUFFER_SIZE * (Index + 1));
            ZeroMem((VOID *)(UINTN)EventLogDesc->PhysicalAddress, MAX_EVENT_LOG_BUFFER_SIZE);
            EventLogDesc->AllocatedEventContainerSize = MAX_EVENT_LOG_BUFFER_SIZE;
            if (EventLogDesc->HashAlgID == TPM_ALG_SHA) {
              PcrEvent = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogDesc->PhysicalAddress;
              TcgLogDesc = (TCG_LOG_DESCRIPTOR *)(PcrEvent + 1);
              PcrEvent->PCRIndex = 0;
              PcrEvent->EventType = EV_NO_ACTION;
              ZeroMem(&PcrEvent->Digest, sizeof(PcrEvent->Digest));
              PcrEvent->EventSize = sizeof(TCG_LOG_DESCRIPTOR);
              CopyMem(TcgLogDesc->Signature, TCG_LOG_DESCRIPTOR_SIGNATURE, sizeof(TCG_LOG_DESCRIPTOR_SIGNATURE));
              TcgLogDesc->Revision    = TCG_LOG_DESCRIPTOR_REVISION;
              TcgLogDesc->DigestAlgID = DIGEST_ALG_ID_SHA_1;
              TcgLogDesc->DigestSize  = SHA1_DIGEST_SIZE;
              EventLogDesc->FirstRecordOffset = sizeof(TCG_PCR_EVENT_HDR) + PcrEvent->EventSize;
              EventLogDesc->NextRecordOffset = sizeof(TCG_PCR_EVENT_HDR) + PcrEvent->EventSize;
            } else {
              EventLogDesc->FirstRecordOffset = 0;
              EventLogDesc->NextRecordOffset = 0;
            }
          }
        } else {
          Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1;
          EventLogPointerElement2_1 = (TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2_1 *)(Element + 1);
          DcePrivateData->EventLogPointerElement2_1 = EventLogPointerElement2_1;
          EventLogPointerElement2_1->PhysicalAddress = (UINT64)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase + MAX_EVENT_LOG_BUFFER_SIZE);
          ZeroMem((VOID *)(UINTN)EventLogPointerElement2_1->PhysicalAddress, MAX_EVENT_LOG_BUFFER_SIZE);
          EventLogPointerElement2_1->AllocatedEventContainerSize = MAX_EVENT_LOG_BUFFER_SIZE * 5;
          EventLogPointerElement2_1->FirstRecordOffset = 0;
          EventLogPointerElement2_1->NextRecordOffset = 0;
        }

        *((UINT64 *)OsSinitData - 1) += Element->Size;
        Element = (TXT_HEAP_EXT_DATA_ELEMENT *)((UINTN)Element + Element->Size);

      }

      Element->Type = TXT_HEAP_EXTDATA_TYPE_END;
      Element->Size = sizeof(TXT_HEAP_END_ELEMENT);

      *((UINT64 *)OsSinitData - 1) += sizeof(TXT_HEAP_END_ELEMENT);
    }
  } else {
    // Version 4
    *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData) - sizeof(UINT64);
  }

  //
  // SinitMleData
  //
  SinitMleData = GetTxtSinitToMleData ();
  DEBUG((EFI_D_INFO, "(TXT) SinitMleData - 0x%x\n", SinitMleData));
  *((UINT64 *)SinitMleData - 1) = 0;
  ZeroMem (SinitMleData, sizeof(*SinitMleData));

  TxtHeapSize = GetTxtHeapSize ();
  TxtHeapOccupiedSize = GetTxtHeapOccupiedSize ();
  DEBUG ((EFI_D_INFO, "(TXT) TXT Heap base    - %08x\n", GetTxtHeap ()));
  DEBUG ((EFI_D_INFO, "(TXT) TXT Heap size    - %08x\n", TxtHeapSize));
  DEBUG ((EFI_D_INFO, "(TXT) TXT BiosOsData   - %08x\n", GetTxtBiosToOsData()));
  DEBUG ((EFI_D_INFO, "(TXT) TXT OsMleData    - %08x\n", (UINTN)TxtOsMleData));
  DEBUG ((EFI_D_INFO, "(TXT) TXT OsSinitData  - %08x\n", (UINTN)OsSinitData));
  DEBUG ((EFI_D_INFO, "(TXT) TXT SinitMleData - %08x\n", (UINTN)SinitMleData));
  DEBUG ((EFI_D_INFO, "(TXT) TXT OccupiedSize - %08x\n", TxtHeapOccupiedSize));

  //
  // Check heap
  //
  if (TxtHeapOccupiedSize >= TxtHeapSize) {
    DEBUG ((EFI_D_ERROR, "(TXT) ERROR: TXT Heap overflow - Occupied (%08x), Allocated (%08x)\n", TxtHeapOccupiedSize, TxtHeapSize));
    ASSERT(FALSE);
  }

  if (OsSinitData->RsdpPtr != 0) {
    EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *Rsdp;
    EFI_ACPI_DESCRIPTION_HEADER                    *Rsdt;
    EFI_ACPI_DESCRIPTION_HEADER                    *Xsdt;
    // validate ACPI RSDP/RSDT/XSDT
    Rsdp = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)OsSinitData->RsdpPtr;
    DEBUG ((EFI_D_INFO, "(TXT) RSDP Address  - %08x\n", Rsdp));
    DEBUG ((EFI_D_INFO, "(TXT) RSDP Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdp, sizeof(EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER))));
    if (Rsdp->Revision >= 2) {
      DEBUG ((EFI_D_INFO, "(TXT) RSDP Length   - %08x\n", Rsdp->Length));
      DEBUG ((EFI_D_INFO, "(TXT) RSDP ExtendedChecksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdp, Rsdp->Length)));
    }
    Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
    DEBUG ((EFI_D_INFO, "(TXT) RSDT Address  - %08x\n", Rsdt));
    DEBUG ((EFI_D_INFO, "(TXT) RSDT Length   - %08x\n", Rsdt->Length));
    DEBUG ((EFI_D_INFO, "(TXT) RSDT Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdt, Rsdt->Length)));
    if (Rsdp->Revision >= 2) {
      Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
      DEBUG ((EFI_D_INFO, "(TXT) XSDT Address  - %016lx\n", Xsdt));
      DEBUG ((EFI_D_INFO, "(TXT) XSDT Length   - %08x\n", Xsdt->Length));
      DEBUG ((EFI_D_INFO, "(TXT) XSDT Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Xsdt, Xsdt->Length)));
    }
  }

  return ;
}
Esempio n. 5
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;
}