diff options
Diffstat (limited to 'ReferenceCode/Pfat/Smm/PfatServices.c')
-rw-r--r-- | ReferenceCode/Pfat/Smm/PfatServices.c | 759 |
1 files changed, 759 insertions, 0 deletions
diff --git a/ReferenceCode/Pfat/Smm/PfatServices.c b/ReferenceCode/Pfat/Smm/PfatServices.c new file mode 100644 index 0000000..bbd1979 --- /dev/null +++ b/ReferenceCode/Pfat/Smm/PfatServices.c @@ -0,0 +1,759 @@ +/** + This file contains an 'Intel Peripheral Driver' and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +/** + +Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +@file: + + PfatServices.c + +@brief: + + PFAT Driver implements the PFAT Host Controller Compatibility Interface. + +**/ + +/// +/// External include files do NOT need to be explicitly specified in real EDKII +/// environment +/// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueDxe.h" +#include "CpuAccess.h" +#include "PfatServices.h" +#include "SmmIoLib.h" +#endif + +#include <Token.h> +/// +/// Global variables +/// +EFI_SMM_SYSTEM_TABLE *mSmst; +PFAT_PROTOCOL *mPfatProtocol; +PFAT_HOB *mPfatHobPtr; +EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL *mPchIoTrap; + +VOID +PfatUpdateBios ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT *CallbackContext + ) +/** + +@brief + + This function is triggered by the BIOS update tool with an IO trap. It executres + Pfat protocol execute with the true flag indicating that there is an update package + in the DPR region of memory. + + @param[in] DispatchHandle Not used + @param[in] CallbackContext Not used + +**/ +{ + /// + /// Invoke PFAT Services for updating BIOS + /// + mPfatProtocol->Execute(mPfatProtocol, TRUE); + CopyMem (mPfatUpdatePackagePtr, &mPfatFullStatus, sizeof (UINT64)); + + return; +} + +VOID +PfatToolsInterfaceInit ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT *CallbackContext + ) +/** + +@brief + + This method registers and sets up the IOTRAP and NVS area for the PFAT tools interface + + @param[in] DispatchHandle Not used + @param[in] CallbackContext Not used + + +**/ +{ + EFI_STATUS Status; + EFI_GUID EfiGlobalNvsAreaProtocolGuid = EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID; + EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol; + EFI_GLOBAL_NVS_AREA *GlobalNvsArea; + EFI_HANDLE PchIoTrapHandle; + EFI_SMM_IO_TRAP_DISPATCH_REGISTER_CONTEXT PchIoTrapContext; + + /// + /// Locate Global NVS and update PFAT DPR size & Memory address for ACPI tables + /// + Status = gBS->LocateProtocol (&EfiGlobalNvsAreaProtocolGuid, NULL, &GlobalNvsAreaProtocol); + ASSERT_EFI_ERROR (Status); + GlobalNvsArea = GlobalNvsAreaProtocol->Area; + GlobalNvsArea->PfatMemAddress = 0; + GlobalNvsArea->PfatMemSize = 0; + GlobalNvsArea->PfatIoTrapAddress = 0; + /// + /// Locate PFAT SMM Protocol + /// + Status = gBS->LocateProtocol (&gSmmPfatProtocolGuid, NULL, &mPfatProtocol); + ASSERT_EFI_ERROR (Status); + if(mPfatProtocol != NULL) + { + /// + /// Register PFAT IO TRAP handler + /// + PchIoTrapContext.Type = WriteTrap; + PchIoTrapContext.Length = 4; + PchIoTrapContext.Address = 0; + PchIoTrapContext.Context = NULL; + PchIoTrapContext.MergeDisable = FALSE; + Status = mPchIoTrap->Register ( + mPchIoTrap, + PfatUpdateBios, + &PchIoTrapContext, + &PchIoTrapHandle + ); + ASSERT_EFI_ERROR (Status); + /// + /// Initialize ASL manipulation library + /// + InitializeAslUpdateLib (); + Status = UpdateAslCode ( + (EFI_SIGNATURE_32 ('I', 'O', '_', 'P')), + PchIoTrapContext.Address, + (UINT8) PchIoTrapContext.Length + ); + ASSERT_EFI_ERROR (Status); + GlobalNvsArea->PfatMemAddress = mPfatMemAddress; + GlobalNvsArea->PfatMemSize = (UINT8) RShiftU64(mPfatMemSize, 20); + GlobalNvsArea->PfatIoTrapAddress = PchIoTrapContext.Address; + } +} + + + + +EFI_STATUS +EFIAPI +InstallPfatProtocol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/** + +@brief + + Entry point for the PFAT protocol driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + @retval EFI_ERROR Driver exits abnormally. + +**/ +{ + EFI_STATUS Status; + EFI_SMM_BASE_PROTOCOL *SmmBase; + PFAT_INSTANCE *PfatInstance; + VOID *PfatProtocolAddr; + EFI_HANDLE PchIoTrapHandle; + EFI_SMM_IO_TRAP_DISPATCH_REGISTER_CONTEXT PchIoTrapContext; + EFI_GUID EfiSmmIoTrapDispatchProtocolGuid = EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID; +#if defined (Pfat_Enable_Pei) && (Pfat_Enable_Pei==0) + EFI_GUID PfatHobGuid = PFAT_HOB_GUID; + PFAT_HOB *PfatModuleCheck; + UINT8 Data8And = 0; + UINT8 Data8Or = 0; +#endif + + /// + /// Locate SMM Base Protocol + /// + Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, &SmmBase); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize our module variables + /// + Status = SmmBase->GetSmstLocation (SmmBase, &mSmst); + ASSERT_EFI_ERROR (Status); + + /// + /// Allocate pool for PFAT protocol instance + /// + Status = mSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof (PFAT_INSTANCE), + &PfatInstance + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "PFAT SmmAllocatePool failed\n")); + return Status; + } + + if (PfatInstance == NULL) { + DEBUG ((EFI_D_INFO, "PfatInstance = NULL returning\n")); + return EFI_OUT_OF_RESOURCES; + } + +#if defined (Pfat_Enable_Pei) && (Pfat_Enable_Pei==0) + //pfat hob is created when pfat is enabled (pfatinit.c) + //verify presence of pfat hob + + PfatModuleCheck = GetFirstGuidHob (&PfatHobGuid); + + if (PfatModuleCheck != NULL) { + Data8And = 0xFF; + Data8Or = (UINT8) (B_PCH_LPC_BIOS_CNTL_SMM_BWP + B_PCH_LPC_BIOS_CNTL_BLE); + + MmioAndThenOr8 ( + MmPciAddress (0, + 0, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + Data8And, + Data8Or); + } + +#endif + + ZeroMem ((VOID *) PfatInstance, sizeof (PFAT_INSTANCE)); + PfatInstance->Handle = NULL; + PfatProtocolAddr = NULL; + + if ((AsmReadMsr64 (MSR_PLATFORM_INFO)) & B_MSR_PLATFORM_INFO_PFAT_AVAIL) { + if ((AsmReadMsr64 (MSR_PLAT_FRMW_PROT_CTRL)) & B_MSR_PLAT_FRMW_PROT_CTRL_EN) { + /// + /// Initialize the PFAT protocol instance + /// + Status = PfatProtocolConstructor (PfatInstance); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error from Pfat Protocol Constructor\n")); + return Status; + } + PfatProtocolAddr = &(PfatInstance->PfatProtocol); + Status = gBS->LocateProtocol (&EfiSmmIoTrapDispatchProtocolGuid, NULL, &mPchIoTrap); + ASSERT_EFI_ERROR (Status); + + PchIoTrapContext.Type = ReadTrap; + PchIoTrapContext.Length = 4; + PchIoTrapContext.Address = 0; + PchIoTrapContext.Context = NULL; + PchIoTrapContext.MergeDisable = FALSE; + Status = mPchIoTrap->Register ( + mPchIoTrap, + PfatToolsInterfaceInit, + &PchIoTrapContext, + &PchIoTrapHandle + ); + ASSERT_EFI_ERROR (Status); + + mPfatHobPtr->PfatToolsIntIoTrapAdd = PchIoTrapContext.Address; + } else { + DEBUG ((EFI_D_INFO, "PFAT Feature supported but disabled\n")); + } + } else { + DEBUG ((EFI_D_WARN, "PFAT Feature is not supported\n")); + } + + /// + /// Install the SMM PFAT_PROTOCOL interface + /// + Status = gBS->InstallMultipleProtocolInterfaces ( + &(PfatInstance->Handle), + &gSmmPfatProtocolGuid, + PfatProtocolAddr, + NULL + ); + if (EFI_ERROR (Status)) { + mSmst->SmmFreePool (PfatInstance); + DEBUG ((EFI_D_ERROR, "Failure Installing PFAT protocol\n")); + } + + DEBUG ((EFI_D_ERROR, "PFAT protocol Installed\n")); + return Status; +} + + + + +EFI_STATUS +PfatProtocolConstructor ( + PFAT_INSTANCE *PfatInstance + ) +/** + +@brief + + Initialize PFAT protocol instance. + + @param[in] PfatInstance Pointer to PfatInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initialized + @retval EFI_NOT_FOUND PFAT Binary module was not found. + +**/ +{ + EFI_STATUS Status; + PPDT *Ppdt; + UINTN i; + UINTN NumHandles; + EFI_HANDLE *Buffer; + UINTN Size; + UINT32 FvStatus; + EFI_FV_FILETYPE FileType; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN NumPages; + EFI_PHYSICAL_ADDRESS Addr; + EFI_PHYSICAL_ADDRESS PfatModule; + SA_DATA_HOB *SaDataHobPtr; + EFI_GUID PfatModuleGuid = PFAT_MODULE_GUID; + EFI_GUID PfatHobGuid = PFAT_HOB_GUID; + EFI_GUID SaDataHobGuid = SA_DATA_HOB_GUID; + + FwVol = NULL; + Size = 0; + FvStatus = 0; + NumPages = 0; + Addr = 0; + + IoWrite8(0x80, 0xAA); + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &NumHandles, + &Buffer + ); + ASSERT_EFI_ERROR (Status); + + for (i = 0; i < NumHandles; i++) { + Status = gBS->HandleProtocol ( + Buffer[i], + &gEfiFirmwareVolumeProtocolGuid, + &FwVol + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Locate PFAT Binary. + /// + Status = FwVol->ReadFile ( + FwVol, + &PfatModuleGuid, + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + if (Status == EFI_SUCCESS) { + break; + } + } + + FreePool (Buffer); + ASSERT (Size); + if ((FwVol == NULL) || (Size == 0)) { + return EFI_NOT_FOUND; + } + NumPages = PFAT_MEMORY_PAGES + ALIGNMENT_IN_PAGES; + + /// + /// Allocate memory buffer for PFAT Module + /// + Status = (mSmst->SmmAllocatePages) (AllocateAnyPages, EfiRuntimeServicesData, NumPages, &Addr); + ASSERT_EFI_ERROR (Status); + + /// + /// Align address to 256K. + /// + PfatModule = Addr &~(ALIGN_256KB - 1); + PfatModule = PfatModule < Addr ? (PfatModule + ALIGN_256KB) : PfatModule; + + /// + /// Read PFAT Module into prepared buffer. + /// + Status = FwVol->ReadFile ( + FwVol, + &PfatModuleGuid, + &((VOID *) PfatModule), + &Size, + &FileType, + &Attributes, + &FvStatus + ); + ASSERT (Size); + if ((FwVol == NULL) || (Size == 0)) { + return EFI_NOT_FOUND; + } + + mPfatHobPtr = GetFirstGuidHob (&PfatHobGuid); + if (mPfatHobPtr == NULL) { + DEBUG ((EFI_D_ERROR, "PFAT HOB not available\n")); + return EFI_NOT_FOUND; + } + + SaDataHobPtr = GetFirstGuidHob (&SaDataHobGuid); + if (SaDataHobPtr == NULL) { + DEBUG ((EFI_D_ERROR, "SA Data HOB not available\n")); + return EFI_NOT_FOUND; + } + + /// + /// Allocate pool for PPDT Data + /// + Status = mSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + mPfatHobPtr->Ppdt.PpdtSize, + &Ppdt + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem (Ppdt, &mPfatHobPtr->Ppdt, mPfatHobPtr->Ppdt.PpdtSize); + + mPfatMemAddress = SaDataHobPtr->DprDirectory[EnumDprDirectoryPfat].PhysBase; + mPfatMemSize = (UINT32) LShiftU64(SaDataHobPtr->DprDirectory[EnumDprDirectoryPfat].Size, 20); + mPfatUpdatePackagePtr = (PUP *) mPfatMemAddress; + mPupCertificate = (EFI_PHYSICAL_ADDRESS) (mPfatMemAddress + mPfatMemSize - PUPC_MEMORY_OFFSET); + mPfatLogPtr = (PFAT_LOG *) (mPfatMemAddress + mPfatMemSize - PFAT_LOG_MEMORY_OFFSET); + + CopyMem (&mPfatLogTemp, &mPfatHobPtr->PfatLog, sizeof (PFAT_LOG)); + CopyMem (&mPfatUpdatePackagePtr->PupHeader, &mPfatHobPtr->PupHeader, sizeof (PUP_HEADER)); + ZeroMem (mPfatUpdatePackagePtr->PupBuffer, PUP_BUFFER_SIZE); + mPfatUpdatePackagePtr->PupHeader.ScriptSectionSize = 0; + mPfatUpdatePackagePtr->PupHeader.DataSectionSize = 0; + mPfatUpdateCounter = 0; + + /// + /// Set Begin command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = PFAT_COMMAND_BEGIN; + + /// + /// Initialize the PFAT protocol instance + /// + PfatInstance->Signature = PFAT_SIGNATURE; + PfatInstance->PfatProtocol.Write = PfatProtocolWrite; + PfatInstance->PfatProtocol.Erase = PfatProtocolBlockErase; + PfatInstance->PfatProtocol.Execute = PfatProtocolExecute; + PfatInstance->AddrMask = 0; + for (i = 0; i < mPfatHobPtr->NumSpiComponents; i++) { + PfatInstance->AddrMask += (SPI_SIZE_BASE_512KB << mPfatHobPtr->ComponentSize[i]); + } + PfatInstance->AddrMask -= 1; + + PfatInstance->PfatDirectory[EnumPfatModule] = PfatModule; + PfatInstance->PfatDirectory[EnumPfatModule] |= LShiftU64 (PFAT_DIRECTORY_PFAT_MODULE_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPpdt] = (EFI_PHYSICAL_ADDRESS) Ppdt; + PfatInstance->PfatDirectory[EnumPpdt] |= LShiftU64 (PFAT_DIRECTORY_PPDT_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPup] = (EFI_PHYSICAL_ADDRESS) mPfatUpdatePackagePtr; + PfatInstance->PfatDirectory[EnumPup] |= LShiftU64(PFAT_DIRECTORY_PUP_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPupCertificate] = 0; + PfatInstance->PfatDirectory[EnumPupCertificate] |= LShiftU64(PFAT_DIRECTORY_UNDEFINED_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPfatLog] = 0; + PfatInstance->PfatDirectory[EnumPfatLog] |= LShiftU64(PFAT_DIRECTORY_UNDEFINED_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPfatDirectoryEnd] = 0; + PfatInstance->PfatDirectory[EnumPfatDirectoryEnd] |= LShiftU64 (PFAT_DIRECTORY_END_MARKER, 56); + + return EFI_SUCCESS; +} + +VOID +PfatModuleExecute ( + IN PFAT_INSTANCE *PfatInstance + ) +/** + +@brief + + Set MSR 0x115 with PFAT DIRECTORY Address. + Trigger MSR 0x116 to invoke PFAT Binary. + Read MSR 0x115 to get PFAT Binary Status. + + @param[in] PfatInstance Pointer to PfatInstance to initialize + +**/ +{ + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_TRIG_PARAM, (UINT64) PfatInstance->PfatDirectory); + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_TRIGGER, 0); + /// + /// Read MSR_PLAT_FRMW_PROT_TRIG_PARAM to get PFAT Binary status + /// + PfatInstance->MsrValue = AsmReadMsr64 (MSR_PLAT_FRMW_PROT_TRIG_PARAM); + return ; +} + +EFI_STATUS +EFIAPI +PfatProtocolExecute ( + IN PFAT_PROTOCOL *This, + IN BOOLEAN BiosUpdate + ) +/** + +@brief + + Set PFAT DIRECTORY Address and triggers MSR to pass control to PFAT Binary module to execute command script. + This function would be called by runtime driver, please do not use any MMIO macro here + + @param[in] This Pointer to the PFAT_PROTOCOL instance. + @param[in] BiosUpdate Flag to indicate flash update is requested by the Tool + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_UNSUPPORTED The CPU or SPI memory is not supported. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. + +**/ +{ + EFI_STATUS Status; + PFAT_INSTANCE *PfatInstance; + UINT16 PfatStatus; + UINT16 PfatAdditionalData; + UINT16 PfatTerminalLine; + UINT8 PfatSE; + UINTN Index; + UINT8 RetryIteration; + UINTN i=0; + + PfatInstance = PFAT_INSTANCE_FROM_PFATPROTOCOL (This); + + /// + /// If Update Package has been created during runtime then complete the script + /// and create update Pkg + /// + if (BiosUpdate == FALSE) { + /// + /// End command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = PFAT_COMMAND_END; + mPfatUpdatePackagePtr->PupHeader.ScriptSectionSize = (mPfatUpdateCounter * 8); + CopyMem ( + &mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter], + &mPfatUpdateData, + (mPfatUpdatePackagePtr->PupHeader.DataSectionSize) + ); + PfatInstance->PfatDirectory[EnumPfatLog] = (EFI_PHYSICAL_ADDRESS) mPfatLogPtr; + PfatInstance->PfatDirectory[EnumPfatLog] |= LShiftU64(PFAT_DIRECTORY_PFAT_LOG_ENTRY, 56); + + } else { + CopyMem (mPfatLogPtr, &mPfatLogTemp, sizeof (PFAT_LOG)); + if (mPfatUpdatePackagePtr->PupHeader.PkgAttributes) { + PfatInstance->PfatDirectory[EnumPupCertificate] = mPupCertificate; + PfatInstance->PfatDirectory[EnumPupCertificate] |= LShiftU64(PFAT_DIRECTORY_PUP_CERTIFICATE_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPfatLog] = (EFI_PHYSICAL_ADDRESS) mPfatLogPtr; + PfatInstance->PfatDirectory[EnumPfatLog] |= LShiftU64(PFAT_DIRECTORY_PFAT_LOG_ENTRY, 56); + } else { + PfatInstance->PfatDirectory[EnumPupCertificate] = 0; + PfatInstance->PfatDirectory[EnumPupCertificate] |= LShiftU64(PFAT_DIRECTORY_UNDEFINED_ENTRY, 56); + PfatInstance->PfatDirectory[EnumPfatLog] = (EFI_PHYSICAL_ADDRESS) mPfatLogPtr; + PfatInstance->PfatDirectory[EnumPfatLog] |= LShiftU64(PFAT_DIRECTORY_PFAT_LOG_ENTRY, 56); + } + } + + PfatInstance->MsrValue = ERR_LAUNCH_FAIL; + + for (Index = 1; Index < mSmst->NumberOfCpus; Index++) { + Status = EFI_NOT_READY; + for (RetryIteration = 0; (RetryIteration < PFAT_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS); RetryIteration++) { + + Status = mSmst->SmmStartupThisAp (PfatModuleExecute, Index, PfatInstance); + + if (Status != EFI_SUCCESS) { + /// + /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again. + /// + PchPmTimerStall (PFAT_WAIT_PERIOD); + } + } + } + + PfatModuleExecute (PfatInstance); + + if (BiosUpdate == FALSE) { + PfatStatus = (UINT16) RShiftU64 ( + (PfatInstance->MsrValue & LShiftU64 (V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_STATUS_MASK, + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_STATUS_OFFSET)), + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_STATUS_OFFSET + ); + switch (PfatStatus) { + case ERR_OK: + Status = EFI_SUCCESS; + break; + + case ERR_RANGE_VIOLATION: + case ERR_SFAM_VIOLATION: + case ERR_EXEC_LIMIT: + case ERR_INTERNAL_ERROR: + Status = EFI_DEVICE_ERROR; + break; + + case ERR_UNSUPPORTED_CPU: + case ERR_UNDEFINED_FLASH_OBJECT: + case ERR_LAUNCH_FAIL: + Status = EFI_UNSUPPORTED; + break; + + default: + + case ERR_BAD_DIRECTORY: + case ERR_BAD_PPDT: + case ERR_BAD_PUP: + case ERR_SCRIPT_SYNTAX: + case ERR_INVALID_LINE: + case ERR_BAD_PUPC: + case ERR_BAD_SVN: + case ERR_UNEXPECTED_OPCODE: + case ERR_OVERFLOW: + Status = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR (Status)) { + PfatAdditionalData = (UINT16) RShiftU64 ( + (PfatInstance->MsrValue & LShiftU64 (V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_DATA_MASK, + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_DATA_OFFSET)), + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_DATA_OFFSET + ); + PfatTerminalLine = (UINT16) RShiftU64 ( + (PfatInstance->MsrValue & LShiftU64 (V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_TERMINAL_MASK, + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_TERMINAL_OFFSET)), + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_TERMINAL_OFFSET + ); + PfatSE = (UINT8) RShiftU64 ( + (PfatInstance->MsrValue & B_MSR_PLAT_FRMW_PROT_TRIG_PARAM_SE), + N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_SE_OFFSET + ); + DEBUG ((EFI_D_ERROR, "PFAT Status = 0x%X\n", PfatStatus)); + DEBUG ((EFI_D_ERROR, "PFAT Additional Data = 0x%X\n", PfatAdditionalData)); + DEBUG ((EFI_D_ERROR, "PFAT Terminal Line = 0x%X\n", PfatTerminalLine)); + DEBUG ((EFI_D_ERROR, "PFAT SE = 0x%X\n", PfatSE)); + } + + ZeroMem (mPfatUpdatePackagePtr->PupBuffer, PUP_BUFFER_SIZE); + mPfatUpdatePackagePtr->PupHeader.ScriptSectionSize = 0; + mPfatUpdatePackagePtr->PupHeader.DataSectionSize = 0; + mPfatUpdateCounter = 0; + + /// + /// Begin command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = PFAT_COMMAND_BEGIN; + } else { + IoWrite16(0x80, (UINT16)(PfatInstance->MsrValue >> 16)); + mPfatFullStatus = PfatInstance->MsrValue; + Status = EFI_SUCCESS; + } + + return Status; +} + + +VOID +EFIAPI +PfatProtocolWrite ( + IN PFAT_PROTOCOL *This, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer + ) +/** + +@brief + + Fill up Write script data into the PFAT Script buffer. + This function would be called by runtime driver, please do not use any MMIO macro here + + @param[in] This Pointer to the PFAT_PROTOCOL instance. + @param[in] Address This value specifies the offset from the start of the SPI Flash component where + BIOS Image is located. + @param[in] DataByteCount Number of bytes in the data portion. + @param[in] Buffer Pointer to caller-allocated buffer containing the data to be sent. + + +**/ +{ + PFAT_INSTANCE *PfatInstance; + + PfatInstance = PFAT_INSTANCE_FROM_PFATPROTOCOL (This); + + /// + /// Set Buffer Offset Index immediate command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = + (LShiftU64 ((UINTN) mPfatUpdatePackagePtr->PupHeader.DataSectionSize, 32)) | + (LShiftU64 (PFAT_B0_INDEX, 16)) | + PFAT_COMMAND_SET_BUFFER_INDEX; + /// + /// Set Flash Index immediate command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = (LShiftU64 ((Address & PfatInstance->AddrMask), 32)) | (LShiftU64 (PFAT_F0_INDEX, 16)) | PFAT_COMMAND_SET_FLASH_INDEX; + /// + /// Write to Flash Index from Buffer Offset Index with specific Size command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = (LShiftU64 (DataByteCount, 32)) | (LShiftU64 (PFAT_B0_INDEX, 24)) | (LShiftU64 (PFAT_F0_INDEX, 16)) | PFAT_COMMAND_WRITE_IMM; + + CopyMem (&mPfatUpdateData[mPfatUpdatePackagePtr->PupHeader.DataSectionSize], Buffer, DataByteCount); + + mPfatUpdatePackagePtr->PupHeader.DataSectionSize += DataByteCount; + + return ; +} + +VOID +EFIAPI +PfatProtocolBlockErase ( + IN PFAT_PROTOCOL *This, + IN UINTN Address + ) +/** + +@brief + + Fill up Erase script data into the PFAT Script buffer. + This function would be called by runtime driver, please do not use any MMIO macro here + + @param[in] This Pointer to the PFAT_PROTOCOL instance. + @param[in] Address This value specifies the offset from the start of the SPI Flash component where + BIOS Image is located. + +**/ +{ + PFAT_INSTANCE *PfatInstance; + + PfatInstance = PFAT_INSTANCE_FROM_PFATPROTOCOL (This); + + /// + /// Set Flash Index immediate command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = (LShiftU64 ((Address & PfatInstance->AddrMask), 32)) | (LShiftU64 (PFAT_F0_INDEX, 16)) | PFAT_COMMAND_SET_FLASH_INDEX; + /// + /// Erase Flash Index command + /// + mPfatUpdatePackagePtr->PupBuffer[mPfatUpdateCounter++] = (LShiftU64 (PFAT_F0_INDEX, 16)) | PFAT_COMMAND_ERASE_BLK; + + mPfatUpdatePackagePtr->PupHeader.DataSectionSize += 0; + + return ; +} |