/** 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; } }
/** Programs processor registers according to register tables. This function programs processor registers according to register tables. **/ VOID SettingPhase ( VOID ) { UINT8 CallbackSignalValue; UINTN Index; UINTN ProcessorNumber; CPU_REGISTER_TABLE *RegisterTable; BOOLEAN NeedCpuOnlyReset; // // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back. // CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_SETTING_SIGNAL); // // Checks whether the callback function requests to bypass Setting phase. // if (CallbackSignalValue == CPU_BYPASS_SIGNAL) { return; } // // Check if CPU-only reset is needed // NeedCpuOnlyReset = FALSE; for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) { RegisterTable = &mCpuConfigConextBuffer.RegisterTable[Index]; if (RegisterTable->NumberBeforeReset > 0) { NeedCpuOnlyReset = TRUE; break; } } // // if CPU-only reset is needed, then program corresponding registers, and // trigger CPU-only reset. // if (NeedCpuOnlyReset) { mSetBeforeCpuOnlyReset = TRUE; DispatchAPAndWait ( TRUE, 0, SetProcessorRegister ); SetProcessorRegister (mCpuConfigConextBuffer.BspNumber); CpuOnlyResetAndRestore (); } // // Program processors' registers in sequential mode. // mSetBeforeCpuOnlyReset = FALSE; for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) { ProcessorNumber = mCpuConfigConextBuffer.SettingSequence[Index]; if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) { SetProcessorRegister (ProcessorNumber); } else { DispatchAPAndWait ( FALSE, GET_CPU_MISC_DATA (ProcessorNumber, ApicID), SetProcessorRegister ); } RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber]; RegisterTable->InitialApicId = GetInitialLocalApicId (ProcessorNumber); } // // Set PcdCpuCallbackSignal to trigger callback function // PcdSet8 (PcdCpuCallbackSignal, CPU_PROCESSOR_SETTING_END_SIGNAL); // // From now on, SetProcessorRegister() will be called only by SimpleApProcWrapper() // and ApProcWrapper to restore register settings after INIT signal, so switch // this flag from FALSE to TRUE. // mRestoreSettingAfterInit = TRUE; }
/** This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration. @param SetupTpmDevice TpmDevice configuration in setup driver @return TpmDevice configuration **/ UINT8 DetectTpmDevice ( IN UINT8 SetupTpmDevice ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; TREE_DEVICE_DETECTION TrEEDeviceDetection; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; UINTN Size; Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); // // In S3, we rely on normal boot Detection, because we save to ReadOnly Variable in normal boot. // if (BootMode == BOOT_ON_S3_RESUME) { DEBUG ((EFI_D_ERROR, "DetectTpmDevice: S3 mode\n")); Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi); ASSERT_EFI_ERROR (Status); Size = sizeof(TREE_DEVICE_DETECTION); ZeroMem (&TrEEDeviceDetection, sizeof(TrEEDeviceDetection)); Status = VariablePpi->GetVariable ( VariablePpi, TREE_DEVICE_DETECTION_NAME, &gTrEEConfigFormSetGuid, NULL, &Size, &TrEEDeviceDetection ); if (!EFI_ERROR (Status) && (TrEEDeviceDetection.TpmDeviceDetected >= TPM_DEVICE_MIN) && (TrEEDeviceDetection.TpmDeviceDetected <= TPM_DEVICE_MAX)) { DEBUG ((EFI_D_ERROR, "TpmDevice from DeviceDetection: %x\n", TrEEDeviceDetection.TpmDeviceDetected)); return TrEEDeviceDetection.TpmDeviceDetected; } } DEBUG ((EFI_D_ERROR, "DetectTpmDevice:\n")); if (!IsDtpmPresent ()) { // dTPM not available return TPM_DEVICE_NULL; } // dTPM available and not disabled by setup // We need check if it is TPM1.2 or TPM2.0 // So try TPM1.2 command at first Status = Tpm12RequestUseTpm (); if (EFI_ERROR (Status)) { return TPM_DEVICE_2_0_DTPM; } if (BootMode == BOOT_ON_S3_RESUME) { Status = Tpm12Startup (TPM_ST_STATE); } else { Status = Tpm12Startup (TPM_ST_CLEAR); } if (EFI_ERROR (Status)) { return TPM_DEVICE_2_0_DTPM; } // NO initialization needed again. PcdSet8 (PcdTpmInitializationPolicy, 0); return TPM_DEVICE_1_2; }