/** Read information from the CPU save state. @param This EFI_SMM_CPU_PROTOCOL instance @param Width The number of bytes to read from the CPU save state. @param Register Specifies the CPU register to read form the save state. @param CpuIndex Specifies the zero-based index of the CPU save state. @param Buffer Upon return, this holds the CPU register value read from the save state. @retval EFI_SUCCESS The register was read from Save State @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor @retval EFI_INVALID_PARAMTER This or Buffer is NULL. **/ EFI_STATUS EFIAPI SmmReadSaveState ( IN CONST EFI_SMM_CPU_PROTOCOL *This, IN UINTN Width, IN EFI_SMM_SAVE_STATE_REGISTER Register, IN UINTN CpuIndex, OUT VOID *Buffer ) { EFI_STATUS Status; // // Retrieve pointer to the specified CPU's SMM Save State buffer // if ((CpuIndex >= gSmst->NumberOfCpus) || (Buffer == NULL)) { return EFI_INVALID_PARAMETER; } // // Check for special EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID // if (Register == EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID) { // // The pseudo-register only supports the 64-bit size specified by Width. // if (Width != sizeof (UINT64)) { return EFI_INVALID_PARAMETER; } // // If the processor is in SMM at the time the SMI occurred, // the pseudo register value for EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID is returned in Buffer. // Otherwise, EFI_NOT_FOUND is returned. // if (*(mSmmMpSyncData->CpuData[CpuIndex].Present)) { *(UINT64 *)Buffer = gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId; return EFI_SUCCESS; } else { return EFI_NOT_FOUND; } } if (!(*(mSmmMpSyncData->CpuData[CpuIndex].Present))) { return EFI_INVALID_PARAMETER; } Status = SmmCpuFeaturesReadSaveStateRegister (CpuIndex, Register, Width, Buffer); if (Status == EFI_UNSUPPORTED) { Status = ReadSaveStateRegister (CpuIndex, Register, Width, Buffer); } return Status; }
/** Read a CPU Save State register on the target processor. This function abstracts the differences that whether the CPU Save State register is in the IA32 CPU Save State Map or X64 CPU Save State Map. This function supports reading a CPU Save State register in SMBase relocation handler. @param[in] CpuIndex Specifies the zero-based index of the CPU save state. @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table. @param[in] Width The number of bytes to read from the CPU save state. @param[out] Buffer Upon return, this holds the CPU register value read from the save state. @retval EFI_SUCCESS The register was read from Save State. @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor. @retval EFI_INVALID_PARAMTER This or Buffer is NULL. **/ EFI_STATUS EFIAPI ReadSaveStateRegister ( IN UINTN CpuIndex, IN EFI_SMM_SAVE_STATE_REGISTER Register, IN UINTN Width, OUT VOID *Buffer ) { UINT32 SmmRevId; SMRAM_SAVE_STATE_IOMISC IoMisc; EFI_SMM_SAVE_STATE_IO_INFO *IoInfo; VOID *IoMemAddr; // // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA // if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) { // // Only byte access is supported for this register // if (Width != 1) { return EFI_INVALID_PARAMETER; } *(UINT8 *)Buffer = mSmmSaveStateRegisterLma; return EFI_SUCCESS; } // // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO // if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) { // // Get SMM Revision ID // ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof(SmmRevId), &SmmRevId); // // See if the CPU supports the IOMisc register in the save state // if (SmmRevId < SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC) { return EFI_NOT_FOUND; } // // Get the IOMisc register value // ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof(IoMisc.Uint32), &IoMisc.Uint32); // // Check for the SMI_FLAG in IOMisc // if (IoMisc.Bits.SmiFlag == 0) { return EFI_NOT_FOUND; } // // Compute index for the I/O Length and I/O Type lookup tables // if (mSmmCpuIoWidth[IoMisc.Bits.Length].Width == 0 || mSmmCpuIoType[IoMisc.Bits.Type] == 0) { return EFI_NOT_FOUND; } // // Zero the IoInfo structure that will be returned in Buffer // IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer; ZeroMem (IoInfo, sizeof(EFI_SMM_SAVE_STATE_IO_INFO)); // // Use lookup tables to help fill in all the fields of the IoInfo structure // IoInfo->IoPort = (UINT16)IoMisc.Bits.Port; IoInfo->IoWidth = mSmmCpuIoWidth[IoMisc.Bits.Length].IoWidth; IoInfo->IoType = mSmmCpuIoType[IoMisc.Bits.Type]; if (IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT || IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) { ReadSaveStateRegister (CpuIndex, EFI_SMM_SAVE_STATE_REGISTER_RAX, mSmmCpuIoWidth[IoMisc.Bits.Length].Width, &IoInfo->IoData); } else { ReadSaveStateRegisterByIndex(CpuIndex, SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX, sizeof(IoMemAddr), &IoMemAddr); CopyMem(&IoInfo->IoData, IoMemAddr, mSmmCpuIoWidth[IoMisc.Bits.Length].Width); } return EFI_SUCCESS; } // // Convert Register to a register lookup table index // return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex (Register), Width, Buffer); }