/** @file This driver provides IHISI interface in SMM mode ;****************************************************************************** ;* Copyright (c) 2014 - 2020, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "IhisiOemExtraDataCommunication.h" #include #include #include #include #include #include STATIC UINT8 mOemExtraDataType; STATIC UINTN mRomBaseAddress; STATIC UINTN mRomSize; STATIC BOOLEAN mEcIdle = FALSE; AP_COMMUNICATION_DATA_TABLE mApCommDataBuffer; STATIC IHISI_REGISTER_TABLE OEM_EXT_COMMON_REGISTER_TABLE[] = { // // AH=41h // { OEMSFOEMExCommunication, "S41Kn_CommuSaveRegs", KernelCommunicationSaveRegs }, \ { OEMSFOEMExCommunication, "S41Cs_ExtDataCommun", ChipsetOemExtraDataCommunication }, \ { OEMSFOEMExCommunication, "S41OemT01Vbios00000", OemIhisiS41T1Vbios }, \ { OEMSFOEMExCommunication, "S41OemT54LogoUpdate", OemIhisiS41T54LogoUpdate }, \ { OEMSFOEMExCommunication, "S41OemT55CheckSignB", OemIhisiS41T55CheckBiosSignBySystemBios }, \ { OEMSFOEMExCommunication, "S41OemReservedFun00", OemIhisiS41ReservedFunction }, \ { OEMSFOEMExCommunication, "S41Kn_T51EcIdelTrue", KernelT51EcIdelTrue }, \ { OEMSFOEMExCommunication, "S41Kn_ExtDataCommun", KernelOemExtraDataCommunication }, \ { OEMSFOEMExCommunication, "S41Kn_T51EcIdelFals", KernelT51EcIdelFalse }, \ { OEMSFOEMExCommunication, "S41OemT50Oa30RWFun0", OemIhisiS41T50a30ReadWrite }, \ // // AH=42h // { OEMSFOEMExDataWrite, "S42Cs_ExtDataWrite0", ChipsetOemExtraDataWrite, }, \ { OEMSFOEMExDataWrite, "S42Kn_T50EcIdelTrue", KernelT50EcIdelTrue, }, \ { OEMSFOEMExDataWrite, "S42Kn_ExtDataWrite0", KernelOemExtraDataWrite, }, \ { OEMSFOEMExDataWrite, "S42Kn_T50EcIdelFals", KernelT50EcIdelFalse, }, \ { OEMSFOEMExDataWrite, "S42Cs_DShutdownMode", ChipsetOemExtraDataDosShutdownMode}, \ // // AH=47h // { OEMSFOEMExDataRead, "S47Cs_ExtDataRead00", ChipsetOemExtraDataRead}, \ { OEMSFOEMExDataRead, "S47Kn_ExtDataRead00", KernelOemExtraDataRead } }; /** Inernal function to check if the application data type is valid @param[in] Datatype Application data type @retval TRUE Application data type is valid. @retval FALSE Application data type is invalid. **/ STATIC BOOLEAN IsValidApDataType ( IN UINT8 Datatype ) { if (Datatype == Vbios || Datatype == Oa30ReadWrite || Datatype == Oa30Erase || Datatype == Oa30PopulateHeader || Datatype == Oa30DePopulateHeader || Datatype == LogoUpdate || Datatype == CheckBiosSignBySystemBios || Datatype == ClaenSecureKey || Datatype == FactoryKeyRestore || Datatype == PfatUpdate || Datatype == BiosPasswordErase || Datatype == PfatReturn || Datatype == StartTimeMeasure || Datatype == QueryTimeInterval || Datatype == GetSpiLockTable || Datatype == AccessViaSpi || Datatype == PassErrorLog || Datatype == RefereExtendDataType) { return TRUE; } return FALSE; } STATIC BOOLEAN MsdmExist ( ) { EFI_STATUS Status; UINTN DataSize; BOOLEAN MsdmExist; UINTN RomBaseAddress; EFI_ACPI_MSDM_DATA_STRUCTURE *MsdmData; MsdmData = NULL; MsdmExist = FALSE; DataSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); RomBaseAddress = (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionMsdmGuid, 1); if (RomBaseAddress == 0) { goto Done; } MsdmData = AllocatePool (DataSize); if (MsdmData == NULL) { goto Done; } Status = mSmmFwBlockService->Read ( mSmmFwBlockService, RomBaseAddress, 0, &DataSize, (UINT8*) MsdmData ); if (EFI_ERROR (Status)) { goto Done; } if ((MsdmData->MsdmVersion == 0xFFFFFFFF) && (MsdmData->MdsmDataType == 0xFFFFFFFF) && (MsdmData->MsdmDataLength == 0xFFFFFFFF)) { goto Done; } MsdmExist = TRUE; Done: if (MsdmData != NULL) { FreePool (MsdmData); } return MsdmExist; } EFI_STATUS EFIAPI SetApandBiosCommDataBuffer ( AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer, BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer ) { if ((ApCommDataBuffer->Signature != AP_COMMUNICATION_SIGNATURE) && (ApCommDataBuffer->Signature != BIOS_COMMUNICATION_SIGNATURE)) { return EFI_UNSUPPORTED; } if (!IhisiProtBufferInCmdBuffer (ApCommDataBuffer, ApCommDataBuffer->StructureSize)){ return IHISI_BUFFER_RANGE_ERROR; } if (ApCommDataBuffer->Signature == BIOS_COMMUNICATION_SIGNATURE) { CopyMem(BiosCommDataBuffer, (VOID *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX), sizeof (BIOS_COMMUNICATION_DATA_TABLE)); CopyMem(ApCommDataBuffer, &mApCommDataBuffer, sizeof (AP_COMMUNICATION_DATA_TABLE)); } else { ZeroMem (BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); BiosCommDataBuffer->Signature = BIOS_COMMUNICATION_SIGNATURE; BiosCommDataBuffer->StructureSize = sizeof (BIOS_COMMUNICATION_DATA_TABLE); BiosCommDataBuffer->BlockSize = OemExtraBlockSize4k; BiosCommDataBuffer->DataSize = OemExtraDataSize64k; BiosCommDataBuffer->PhysicalDataSize = 0; BiosCommDataBuffer->ErrorReturn = 0; } return EFI_SUCCESS; } /** AH=41h, OEM Extra Data Communication type. 50h = Oa30ReadWrite @param[in] ApCommDataBuffer Pointer to AP communication data buffer. @param[out] BiosCommDataBuffer Pointer to BIOS communication data buffer. @retval EFI_SUCCESS Read or write OA3.0 successful. **/ EFI_STATUS EFIAPI Oa30ReadWriteFunction ( IN AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer, OUT BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer ) { UINT32 MsdmDataSize; MsdmDataSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); switch (ApCommDataBuffer->DataSize) { case OemExtraReportReadSize: BiosCommDataBuffer->Signature = BIOS_COMMUNICATION_SIGNATURE; BiosCommDataBuffer->StructureSize = sizeof (BIOS_COMMUNICATION_DATA_TABLE); BiosCommDataBuffer->BlockSize = OemExtraBlockSize4k; BiosCommDataBuffer->DataSize = OemExtraReportReadSize; BiosCommDataBuffer->PhysicalDataSize = MsdmDataSize; break; case OemExtraSkipSizeCheck: BiosCommDataBuffer->Signature = BIOS_COMMUNICATION_SIGNATURE; BiosCommDataBuffer->StructureSize = sizeof (BIOS_COMMUNICATION_DATA_TABLE); BiosCommDataBuffer->BlockSize = OemExtraBlockSize4k; BiosCommDataBuffer->DataSize = OemExtraSkipSizeCheck; //Don't care BiosCommDataBuffer->PhysicalDataSize = 0x00; //Don't care break; case OemExtraReportWriteSize: BiosCommDataBuffer->Signature = BIOS_COMMUNICATION_SIGNATURE; BiosCommDataBuffer->StructureSize = sizeof (BIOS_COMMUNICATION_DATA_TABLE); BiosCommDataBuffer->BlockSize = OemExtraBlockSize4k; BiosCommDataBuffer->DataSize = OemExtraReportWriteSize; BiosCommDataBuffer->PhysicalDataSize = MsdmDataSize; //bin size break; default: break; } if (!MsdmExist ()) { BiosCommDataBuffer->ErrorReturn = (BiosCommDataBuffer->ErrorReturn | ERROR_RETURE_OA30_NOT_EXIST); } return EFI_SUCCESS; } /** AH=41h, OEM Extra Data Communication type. 51h = Oa30Erase Ec Idle true **/ EFI_STATUS EFIAPI KernelT51EcIdelTrue ( VOID ) { EFI_STATUS OemSvcStatus; if (!IsValidApDataType (mOemExtraDataType)) { return IHISI_INVALID_PARAMETER; } mEcIdle = FALSE; if (MsdmExist () && mOemExtraDataType == Oa30Erase) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (TRUE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); mEcIdle = TRUE; } return EFI_SUCCESS; } /** AH=41h, OEM Extra Data Communication type. 51h = Oa30Erase Ec Idle False **/ EFI_STATUS EFIAPI KernelT51EcIdelFalse ( VOID ) { EFI_STATUS OemSvcStatus; if (mEcIdle) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (FALSE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); mEcIdle = FALSE; } return EFI_SUCCESS; } /** AH=41h, OEM Extra Data Communication type. 51h = Oa30Erase @param[in] ApCommDataBuffer Pointer to AP communication data buffer. @param[out] BiosCommDataBuffer Pointer to BIOS communication data buffer. @retval EFI_SUCCESS Erase OA3.0 successful. **/ EFI_STATUS EFIAPI Oa30EraseFunction ( IN AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer, OUT BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer ) { EFI_STATUS Status; UINT8 LoopCount; UINTN RomBaseAddress; UINTN RomSize; LoopCount = 0; Status = EFI_SUCCESS; RomBaseAddress = (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionMsdmGuid, 1); if (RomBaseAddress == 0) { BiosCommDataBuffer->ErrorReturn = (BiosCommDataBuffer->ErrorReturn | ERROR_RETURE_OA30_NOT_EXIST); goto Done; } RomSize = (UINTN) FdmGetNAtSize (&gH2OFlashMapRegionMsdmGuid, 1); if (!MsdmExist ()) { BiosCommDataBuffer->ErrorReturn = (BiosCommDataBuffer->ErrorReturn | ERROR_RETURE_OA30_NOT_EXIST); goto Done; } Status = EFI_UNSUPPORTED; while ((EFI_ERROR (Status)) && (LoopCount < 100)) { Status = mSmmFwBlockService->EraseBlocks ( mSmmFwBlockService, RomBaseAddress, &RomSize ); LoopCount++; } Done: BiosCommDataBuffer->DataSize = ApCommDataBuffer->DataSize; BiosCommDataBuffer->PhysicalDataSize = ApCommDataBuffer->PhysicalDataSize; return Status; } /** AH=41h, OEM Extra Data Communication type. 52h = Oa30PopulateHeader @param[in] ApCommDataBuffer Pointer to AP communication data buffer. @param[out] BiosCommDataBuffer Pointer to BIOS communication data buffer. @retval EFI_SUCCESS populate header successful. **/ EFI_STATUS EFIAPI Oa30PopulateHeaderFunction ( IN AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer, OUT BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer ) { return EFI_SUCCESS; } /** AH=41h, OEM Extra Data Communication type 53h to de-populate header. 53h = Oa30DePopulateHeader @param[in] ApCommDataBuffer Pointer to AP communication data buffer. @param[out] BiosCommDataBuffer Pointer to BIOS communication data buffer. @retval EFI_SUCCESS populate header successful. **/ EFI_STATUS EFIAPI Oa30DePopulateHeaderFunction ( IN AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer, OUT BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer ) { return EFI_SUCCESS; } /** AH=42h, OEM Extra Data Write. 50h = Oa30ReadWrite Ec Idle true **/ EFI_STATUS EFIAPI KernelT50EcIdelTrue ( VOID ) { UINTN WriteSize; UINT32 MsdmDataSize; EFI_STATUS OemSvcStatus; WriteSize = (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); MsdmDataSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); mEcIdle = FALSE; if ((WriteSize == MsdmDataSize) && (mOemExtraDataType == Oa30ReadWrite)) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (TRUE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); mEcIdle = TRUE; } return EFI_SUCCESS; } /** AH=42h, OEM Extra Data Write. 50h = Oa30ReadWrite Ec Idle false **/ EFI_STATUS EFIAPI KernelT50EcIdelFalse ( VOID ) { UINTN WriteSize; UINT32 MsdmDataSize; EFI_STATUS OemSvcStatus; WriteSize = (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); MsdmDataSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); if (mEcIdle) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (FALSE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); mEcIdle = FALSE; } return EFI_SUCCESS; } /** AH=42h, OEM Extra Data Write. 50h = Oa30ReadWrite @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI Oa30DataWrite ( UINT8 *WriteDataBuffer, UINTN WriteSize, UINTN RomBaseAddress ) { EFI_STATUS Status; UINT8 LoopCount; UINT32 MsdmDataSize; MsdmDataSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); if (WriteSize == MsdmDataSize) { UINT8 *ReturnDataBuffer = NULL; UINTN Index2 = 0; UINTN EraseSize = 0x1000; UINT8 *TEMP; ReturnDataBuffer = AllocatePool (0x1000); if (ReturnDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } Status = mSmmFwBlockService->Read ( mSmmFwBlockService, RomBaseAddress, 0, &EraseSize, ReturnDataBuffer ); // // Only modify the first 0x31 bytes // TEMP = ReturnDataBuffer; for (Index2 = 0; Index2 < MsdmDataSize; Index2++) { TEMP[Index2] = WriteDataBuffer[Index2]; } LoopCount = 0; Status = EFI_UNSUPPORTED; *(mSmmFwBlockService->FlashMode) = SMM_FW_FLASH_MODE; while ((EFI_ERROR (Status)) && (LoopCount < 100)) { Status = mSmmFwBlockService->EraseBlocks ( mSmmFwBlockService, RomBaseAddress, &EraseSize ); Status = mSmmFwBlockService->Write ( mSmmFwBlockService, RomBaseAddress, &EraseSize, ReturnDataBuffer ); LoopCount++; } FreePool (ReturnDataBuffer); } else { return EFI_INVALID_PARAMETER; } return IHISI_SUCCESS; } /** AH=47h, OEM Extra Data Read. 50h = Oa30ReadWrite @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI Oa30DataRead ( UINT8 *ReadDataBuffer, UINTN *ReadSize, UINTN RomBaseAddress ) { EFI_STATUS Status; UINT8 *ReturnDataBuffer = NULL; UINTN DataSize = 0x1000; ReturnDataBuffer = AllocatePool (DataSize); if (ReturnDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } Status = mSmmFwBlockService->Read ( mSmmFwBlockService, RomBaseAddress, 0, &DataSize, ReturnDataBuffer ); *ReadSize = sizeof (EFI_ACPI_MSDM_DATA_STRUCTURE); CopyMem (ReadDataBuffer, ReturnDataBuffer, *ReadSize); return Status; } /** AH=41h, OEM Extra Data Communication type. Hook chipset service SmmCsSvcIhisiOemExtCommunication. @retval EFI_SUCCESS OEM Extra Data Write successful. @return Other OEM Extra Data Write failed. **/ EFI_STATUS EFIAPI ChipsetOemExtraDataCommunication ( VOID ) { EFI_STATUS Status; EFI_STATUS OemSvcStatus; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } OemSvcStatus = SmmCsSvcIhisiOemExtCommunication(ApCommDataBuffer, BiosCommDataBuffer); Status = OemSvcStatus; switch (OemSvcStatus) { case EFI_SUCCESS: Status = IHISI_END_FUNCTION_CHAIN; break; case EFI_UNSUPPORTED: case EFI_MEDIA_CHANGED: if ((ApCommDataBuffer->DataType == Oa30ReadWrite) || (ApCommDataBuffer->DataType == Oa30Erase) || (ApCommDataBuffer->DataType == Oa30PopulateHeader) || (ApCommDataBuffer->DataType == Oa30DePopulateHeader)) { Status = IHISI_SUCCESS; } break; } if (OemSvcStatus == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } FreePool (BiosCommDataBuffer); return Status; } /** AH=42h, OEM Extra Data Write. Hook chipset service SmmCsSvcIhisiOemExtDataWrite. @retval EFI_SUCCESS OEM Extra Data Write successful. @return Other OEM Extra Data Write failed. **/ EFI_STATUS EFIAPI ChipsetOemExtraDataWrite ( VOID ) { EFI_STATUS Status; UINTN WriteSize; UINT8 ShutdownMode; UINTN RomBaseAddress; UINT8 *WriteDataBuffer; UINT32 Ecx; WriteDataBuffer = (UINT8 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI); WriteSize = (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); RomBaseAddress = (UINTN) (IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX) >> 8); ShutdownMode = (UINT8) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) WriteDataBuffer, WriteSize)){ return IHISI_BUFFER_RANGE_ERROR; } Status = SmmCsSvcIhisiOemExtDataWrite(mOemExtraDataType, WriteDataBuffer, &WriteSize, &RomBaseAddress, ShutdownMode); switch (Status) { case EFI_SUCCESS: Status = IHISI_END_FUNCTION_CHAIN; break; case EFI_UNSUPPORTED: if (mOemExtraDataType == Oa30ReadWrite) { mRomBaseAddress = (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionMsdmGuid, 1); mRomSize = (UINTN) FdmGetNAtSize (&gH2OFlashMapRegionMsdmGuid, 1); } case EFI_MEDIA_CHANGED: IhisiProtWriteCpuReg32(EFI_SMM_SAVE_STATE_REGISTER_RDI, (UINT32)WriteSize); Ecx = IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); Ecx &=0xFFFF00FF; Ecx |= (RomBaseAddress << 8); IhisiProtWriteCpuReg32(EFI_SMM_SAVE_STATE_REGISTER_RCX, Ecx); Status = IHISI_SUCCESS; break; default: break; } return Status; } /** AH=47h, OEM Extra Data Read. Hook chipset service SmmCsSvcIhisiOemExtDataRead. @retval EFI_SUCCESS OEM Extra Data Read successful. @return Other OEM Extra Data Read failed. **/ EFI_STATUS EFIAPI ChipsetOemExtraDataRead ( VOID ) { EFI_STATUS Status; UINTN ReadSize; UINTN RomBaseAddress; UINT8 *ReadDataBuffer; ReadSize = 0; RomBaseAddress = 0; ReadDataBuffer = (UINT8 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI); if (!IhisiProtBufferInCmdBuffer ((VOID *)(UINTN)IhisiProtReadCpuReg32(EFI_SMM_SAVE_STATE_REGISTER_RDI), sizeof (UINT32))){ return IHISI_BUFFER_RANGE_ERROR; } ReadSize = *(UINT32 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); if (!IhisiProtBufferInCmdBuffer ((VOID *) ReadDataBuffer, ReadSize)){ return IHISI_BUFFER_RANGE_ERROR; } Status = SmmCsSvcIhisiOemExtDataRead(mOemExtraDataType, ReadDataBuffer, &ReadSize, &RomBaseAddress); // // Pass Chipset update parameter to kernel // switch (Status) { case EFI_SUCCESS: Status = IHISI_END_FUNCTION_CHAIN; break; case EFI_MEDIA_CHANGED: mRomBaseAddress = RomBaseAddress; mRomSize = ReadSize; CopyMem ((VOID *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI), &ReadSize, sizeof(UINT32)); Status = IHISI_SUCCESS; break; case EFI_UNSUPPORTED: if (mOemExtraDataType == Oa30ReadWrite) { mRomBaseAddress = (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionMsdmGuid, 1); mRomSize = (UINTN) FdmGetNAtSize (&gH2OFlashMapRegionMsdmGuid, 1); } Status = IHISI_SUCCESS; break; default: Status = IHISI_SUCCESS; break; } return Status; } /** AH=42h, OEM Extra Data Write. Hook chipset service.SmmCsSvcIhisiFbtsShutDown @retval EFI_SUCCESS OEM Extra Data Write successful. @return Other OEM Extra Data Write failed. **/ EFI_STATUS EFIAPI ChipsetOemExtraDataDosShutdownMode ( VOID ) { UINT8 ShutdownMode; EFI_STATUS Status; Status = EFI_SUCCESS; ShutdownMode = (UINT8) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); switch (ShutdownMode) { case DosReboot: Status = SmmCsSvcIhisiFbtsReboot (); break; case DosShutdown: Status = SmmCsSvcIhisiFbtsShutDown (); break; case DoNothing: case WindowsReboot: case WindowsShutdown: case ContinueToFlash: Status = EFI_SUCCESS; break; default: Status = EFI_INVALID_PARAMETER; break; } return Status; } /** AH=41h, Hook OemService OEM Extra Data Communication 01h = VBIOS @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI OemIhisiS41T1Vbios ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(AP_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } Status = IHISI_SUCCESS; if (ApCommDataBuffer->DataType == Vbios) { BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcIhisiS41T1VbiosFunction \n")); Status = OemSvcIhisiS41T1VbiosFunction (ApCommDataBuffer, BiosCommDataBuffer); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcIhisiS41T1VbiosFunction Status: %r\n", Status)); if (Status == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } Status = IHISI_END_FUNCTION_CHAIN; } FreePool (BiosCommDataBuffer); return Status; } /** AH=41h, Oem OEM Extra Data Communication 54h = LogoUpdate @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI OemIhisiS41T54LogoUpdate ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } Status = IHISI_SUCCESS; if (ApCommDataBuffer->DataType == LogoUpdate) { BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcIhisiS41T54LogoUpdateFunction \n")); Status = OemSvcIhisiS41T54LogoUpdateFunction (ApCommDataBuffer, BiosCommDataBuffer); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcIhisiS41T54LogoUpdateFunction Status: %r\n", Status)); if (Status == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } Status = IHISI_END_FUNCTION_CHAIN; } FreePool (BiosCommDataBuffer); return Status; } /** AH=41h, Oem OEM Extra Data Communication 55h = CheckBiosSignBySystemBios @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI OemIhisiS41T55CheckBiosSignBySystemBios ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } Status = EFI_SUCCESS; if (ApCommDataBuffer->DataType == CheckBiosSignBySystemBios) { BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcIhisiS41T55CheckBiosSignBySystemBiosFunction \n")); Status = OemSvcIhisiS41T55CheckBiosSignBySystemBiosFunction (ApCommDataBuffer, BiosCommDataBuffer); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcIhisiS41T55CheckBiosSignBySystemBiosFunction Status: %r\n", Status)); if (Status == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } Status = IHISI_END_FUNCTION_CHAIN; } FreePool (BiosCommDataBuffer); return Status; } /** AH=41h, Oem OEM Extra Data Communication 50h = Oa30ReadWrite @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI OemIhisiS41T50a30ReadWrite ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } Status = IHISI_SUCCESS; if (ApCommDataBuffer->DataType == Oa30ReadWrite) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcIhisiS41T50HookOa30ReadWriteFunction \n")); Status = OemSvcIhisiS41T50HookOa30ReadWriteFunction (ApCommDataBuffer, BiosCommDataBuffer); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcIhisiS41T50HookOa30ReadWriteFunction Status: %r\n", Status)); if (Status == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } Status = IHISI_END_FUNCTION_CHAIN; } FreePool (BiosCommDataBuffer); return Status; } /** AH=41h, Oem OEM Extra Data Communication Resserved @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI OemIhisiS41ReservedFunction ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcIhisiS41ReservedFunction \n")); Status = OemSvcIhisiS41ReservedFunction (ApCommDataBuffer, BiosCommDataBuffer); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcIhisiS41ReservedFunction Status: %r\n", Status)); if (Status == EFI_MEDIA_CHANGED) { CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); } FreePool (BiosCommDataBuffer); return EFI_SUCCESS; } /** AH=41h,OEM Extra Data Communication Save input registers; @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI KernelCommunicationSaveRegs ( VOID ) { AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; mRomBaseAddress = 0; mRomSize = 0; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(AP_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (ApCommDataBuffer->Signature != AP_COMMUNICATION_SIGNATURE) { return IHISI_UNSUPPORTED_FUNCTION; } BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(AP_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(AP_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } mOemExtraDataType = ApCommDataBuffer->DataType; CopyMem(&mApCommDataBuffer, ApCommDataBuffer, sizeof(AP_COMMUNICATION_DATA_TABLE)); IhisiErrorCodeHandler((UINT32)IHISI_SUCCESS); return IHISI_SUCCESS; } /** AH=41h, OEM Extra Data Communication @retval EFI_SUCCESS Process OEM extra data communication successful. @return Other Process OEM extra data communication failed. **/ EFI_STATUS EFIAPI KernelOemExtraDataCommunication ( VOID ) { EFI_STATUS Status; BIOS_COMMUNICATION_DATA_TABLE *BiosCommDataBuffer; AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer; UINTN BufferSize; ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, sizeof(BIOS_COMMUNICATION_DATA_TABLE))) { return IHISI_BUFFER_RANGE_ERROR; } if (!IsValidApDataType (ApCommDataBuffer->DataType)) { return IHISI_INVALID_PARAMETER; } BiosCommDataBuffer = AllocatePool (sizeof (BIOS_COMMUNICATION_DATA_TABLE)); if (BiosCommDataBuffer == NULL) { return IHISI_OUT_OF_RESOURCES; } BufferSize = ApCommDataBuffer->StructureSize; if (BufferSize < sizeof(BIOS_COMMUNICATION_DATA_TABLE)) { BufferSize = sizeof(BIOS_COMMUNICATION_DATA_TABLE); } if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) { FreePool (BiosCommDataBuffer); return IHISI_BUFFER_RANGE_ERROR; } Status = SetApandBiosCommDataBuffer(ApCommDataBuffer, BiosCommDataBuffer); if (EFI_ERROR(Status)) { FreePool (BiosCommDataBuffer); return Status; } switch (ApCommDataBuffer->DataType) { case Oa30ReadWrite: Status = Oa30ReadWriteFunction (ApCommDataBuffer, BiosCommDataBuffer); break; case Oa30Erase: Status = Oa30EraseFunction (ApCommDataBuffer, BiosCommDataBuffer); break; case Oa30PopulateHeader: Status = Oa30PopulateHeaderFunction (ApCommDataBuffer, BiosCommDataBuffer); break; case Oa30DePopulateHeader: Status = Oa30DePopulateHeaderFunction (ApCommDataBuffer, BiosCommDataBuffer); break; default: Status = EFI_SUCCESS; break; } if (EFI_ERROR (Status)) { mOemExtraDataType = 0; FreePool (BiosCommDataBuffer); return Status; } CopyMem (ApCommDataBuffer, BiosCommDataBuffer, sizeof (BIOS_COMMUNICATION_DATA_TABLE)); FreePool (BiosCommDataBuffer); return IHISI_SUCCESS; } /** AH=42h, OEM Extra Data Write. @retval EFI_SUCCESS OEM Extra Data Write successful. @return Other OEM Extra Data Write failed. **/ EFI_STATUS EFIAPI KernelOemExtraDataWrite ( VOID ) { EFI_STATUS Status; UINTN WriteSize; UINTN RomBaseAddress; UINT8 *WriteDataBuffer; WriteDataBuffer = (UINT8 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI); WriteSize = (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); RomBaseAddress = (UINTN) (IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX) >> 8); if (!IhisiProtBufferInCmdBuffer ((VOID *) WriteDataBuffer, WriteSize)){ return IHISI_BUFFER_RANGE_ERROR; } switch (mOemExtraDataType) { case Oa30ReadWrite: if (WriteSize > mRomSize) { Status = EFI_INVALID_PARAMETER; } else { RomBaseAddress = mRomBaseAddress; Status = Oa30DataWrite(WriteDataBuffer, WriteSize, RomBaseAddress); } break; default: Status = EFI_SUCCESS; break; } return Status; } /** AH=47h, OEM Extra Data Read. @retval EFI_SUCCESS OEM Extra Data Read successful. @return Other OEM Extra Data Read failed. **/ EFI_STATUS EFIAPI KernelOemExtraDataRead ( VOID ) { EFI_STATUS Status; UINTN ReadSize; UINTN RomBaseAddress; UINT8 *ReadDataBuffer; ReadSize = 0; RomBaseAddress = mRomBaseAddress; ReadDataBuffer = (UINT8 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI); if (!IhisiProtBufferInCmdBuffer ((VOID *)(UINTN)IhisiProtReadCpuReg32(EFI_SMM_SAVE_STATE_REGISTER_RDI), sizeof (UINT32))) { return IHISI_BUFFER_RANGE_ERROR; } ReadSize = *(UINT32 *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); if (!IhisiProtBufferInCmdBuffer ((VOID *) ReadDataBuffer, ReadSize)){ return IHISI_BUFFER_RANGE_ERROR; } switch (mOemExtraDataType) { case Oa30ReadWrite: Status = Oa30DataRead(ReadDataBuffer, &ReadSize, RomBaseAddress); break; default: Status = EFI_SUCCESS; break; } CopyMem ((VOID *) (UINTN) IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI), &ReadSize, sizeof(UINT32)); return Status; } EFI_STATUS InstallOemExtraDataCommunicationServices ( VOID ) { EFI_STATUS Status; IHISI_REGISTER_TABLE *SubFuncTable; UINT16 TableCount; SubFuncTable = OEM_EXT_COMMON_REGISTER_TABLE; TableCount = sizeof(OEM_EXT_COMMON_REGISTER_TABLE)/sizeof(OEM_EXT_COMMON_REGISTER_TABLE[0]); Status = RegisterIhisiSubFunction (SubFuncTable, TableCount); if (EFI_ERROR(Status)) { ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; }