/***************************************************************************** * * * Copyright (c) 2012 - 2015, Hefei LCFC Information Technology Co.Ltd. * And/or its affiliates. All rights reserved. * Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL. * Use is subject to license terms. * *****************************************************************************/ /* Data Name Version Description 2014.04.23 dahai.zhou v1.00 Initial release it for EDK2 projects 2014.07.22 dahai.zhou v1.01 Add new routine LfcEcLibTellEcDisOrUma 2014.07.23 dahai.zhou v1.10 Unify all routine name to LfcEcLibXxxxx 2014.08.28 dahai.zhou v1.11 Use PCD to save NOVO button and crisis status 2015.02.02 cissie.gu v1.12 Fix the issue that OS will hung up when we use PcdLcfcEcLibSupport whose type is PcdsDynamicEx in SMM mode in OS runtime. 2015.03.26 cissie.gu v1.13 Add function named LfcEcLibEnableEcPower. Make both of the functions, LfcEcLibNotifyEcMachineSize and LfcEcLibTellEcDisOrUma,functional. 2015.04.17 cissie.gu v1.14 Add two funciotions,one named LfcEcLibSetAlwaysOnUsbMode for BIOS to notify EC change usb charge mode, another one named LfcEcLibGetBatteryFirstUsedDate for battery to get System time. 2015.06.03 dahai.zhou v1.15 Update EcCommand routine, and modify all code that call it 2015.07.14 dahai.zhou v1.16 Update LfcEcLibGetBatteryPercentage to remove workaround for Insyde 2016.09.23 cissie.gu v1.17 To make all kind of keyboards fully functional,we notify EC with four KeyboardIDs. */ #include #include #include //[-start-211014-BAIN000051-add]// #ifdef LCFC_SUPPORT #include #endif //[-end-211014-BAIN000051-add]// //[-start-211104-YUNLEI0152-modify]// #if defined(C770_SUPPORT) #include #include #include #endif //[-end-211104-YUNLEI0152-modify]// BOOLEAN mLcfcEcLibSupport = TRUE; //[-start-211014-YUNLEI0142-add]////For use PackageTdp to distinguish CPU U15/U28 U15:15 U28:28 #if defined(C770_SUPPORT) EFI_STATUS OemSvcLfcGetCpuIdentifier( OUT UINT8 *LfcCpuId ) { EFI_STATUS Status; UINT16 PackageTdp; UINT16 PackageTdpWatt; UINT16 TempPackageTdp; UINT8 ProcessorPowerUnit; MSR_PACKAGE_POWER_SKU_REGISTER PackagePowerSkuMsr; MSR_PACKAGE_POWER_SKU_UNIT_REGISTER PackagePowerSkuUnitMsr; PackagePowerSkuMsr.Uint64 = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU); PackagePowerSkuUnitMsr.Uint64 = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU_UNIT); ProcessorPowerUnit = (UINT8) (PackagePowerSkuUnitMsr.Bits.PwrUnit); if (ProcessorPowerUnit == 0) { ProcessorPowerUnit = 1; } else { ProcessorPowerUnit = (UINT8) LShiftU64 (2, (ProcessorPowerUnit - 1)); if (IsSimicsEnvironment () && ProcessorPowerUnit == 0) { ProcessorPowerUnit = 1; } } TempPackageTdp = (UINT16) PackagePowerSkuMsr.Bits.PkgTdp; PackageTdpWatt = (UINT16) DivU64x32 (TempPackageTdp, ProcessorPowerUnit); PackageTdp = (PackageTdpWatt * 100); if ((TempPackageTdp % ProcessorPowerUnit) !=0) { PackageTdp += ((TempPackageTdp % ProcessorPowerUnit) * 100) / ProcessorPowerUnit; } *LfcCpuId=(UINT8)(PackageTdp/100); Status = EFI_SUCCESS; return Status; } #endif //[-end-211014-YUNLEI0142-add] EFI_STATUS EFIAPI BaseLfcEcLibConstructor ( VOID ) { mLcfcEcLibSupport = PcdGetBool (PcdLcfcEcLibSupport); return EFI_SUCCESS; } EFI_STATUS WaitIBE ( IN UINT16 CommandPort ) /*++ Routine Description: Wait for input buffer empty Arguments: CommandState - the Io to read. Returns: EFI_SUCCESS - input buffer empty. --*/ { UINT8 CmdPort = 0; UINTN Index; for (Index = 0; Index < KBC_TIME_OUT; Index++) { CmdPort = IoRead8 (CommandPort); if (!(CmdPort & KEY_IBF)) { return EFI_SUCCESS; } else { EcAcpiStall(15); } } return EFI_DEVICE_ERROR; } EFI_STATUS WaitOBF ( IN UINT16 CommandPort ) /*++ Routine Description: Wait for output buffer full Arguments: CommandState - the Io to read. Returns: EFI_SUCCESS - output buffer full. --*/ { UINT8 CmdPort = 0; UINTN Index; for (Index = 0; Index < KBC_TIME_OUT; Index++) { CmdPort = IoRead8 (CommandPort); if (CmdPort & KEY_OBF) { return EFI_SUCCESS; } else { EcAcpiStall(15); } } return EFI_DEVICE_ERROR; } EFI_STATUS WaitOBE ( IN UINT16 CommandPort ) /*++ Routine Description: Wait for output buffer empty Arguments: CommandState - the Io to read. Returns: EFI_SUCCESS - output buffer empty. --*/ { UINT8 CmdPort = 0; UINTN Index; for (Index = 0; Index < KBC_TIME_OUT; Index++) { CmdPort = IoRead8 (CommandPort); if (CmdPort & KEY_OBF) { //Read data out from data port IoRead8 (CommandPort - 4); EcAcpiStall(15); } else { return EFI_SUCCESS; } } return EFI_DEVICE_ERROR; } EFI_STATUS EcCommand ( IN UINT16 CommandPort, IN UINT16 DataPort, IN UINTN NumOfReturnData, IN UINT8 *ReturnData, IN UINT8 Command, IN UINTN NumOfArgs, ... ) /*++ Routine Description: This function send command and data to EC. Arguments: CommandPort - EC command port DataPort - EC data port NumOfReturnData - Number for return data, 0 will not return data *ReturnData - Pointer to return data if NumOfReturnData > 0, caller must make sure there is enough space Command - EC command NumOfArgs - Number of variable arguments for EC data ... - Variable argument(s),each contain a UINT8 EC data Returns: EFI_SUCCESS - Command successfully finish. --*/ { EFI_STATUS Status; VA_LIST Marker; UINT8 Index; UINT8 *Data; Status = WaitIBE (CommandPort); if (EFI_ERROR (Status)) { return Status; } Status = WaitOBE (CommandPort); if (EFI_ERROR (Status)) { return Status; } //Send command IoWrite8 (CommandPort, Command); Status = WaitIBE (CommandPort); if (EFI_ERROR(Status)) { return Status; } if (NumOfArgs > 0){ VA_START (Marker, NumOfArgs); for(Index = 0; Index < NumOfArgs; Index++){ Data = VA_ARG (Marker, UINT8*); //Send data IoWrite8 (DataPort, *Data); Status = WaitIBE (CommandPort); if (EFI_ERROR(Status)) { return Status; } } VA_END (Marker); //Get return data } if (NumOfReturnData > 0) { for (Index = 0; Index < NumOfReturnData; Index++) { Status = WaitOBF (CommandPort); if (EFI_ERROR(Status)) { return Status; } *(ReturnData + Index) = IoRead8 (DataPort); } } return Status; } EFI_STATUS EcAcpiStall ( IN UINTN Microseconds ) /*++ Routine Description: Waits for at least the given number of microseconds. Arguments: Microseconds - Desired length of time to wait Returns: EFI_SUCCESS - If the desired amount of time passed. --*/ { UINTN Ticks; UINTN Counts; UINT32 CurrentTick; UINT32 OriginalTick; UINT32 RemainingTick; if (Microseconds == 0) { return EFI_SUCCESS; } OriginalTick = IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF; CurrentTick = OriginalTick; // // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks // Ticks = Microseconds * 358 / 100 + OriginalTick + 1; // // The loops needed by timer overflow // Counts = Ticks / ACPI_TIMER_MAX_VALUE; // // remaining clocks within one loop // RemainingTick = Ticks % ACPI_TIMER_MAX_VALUE; // // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra // one I/O operation, and maybe generate SMI // while (Counts != 0) { CurrentTick = IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF; if (CurrentTick <= OriginalTick) { Counts--; } OriginalTick = CurrentTick; } while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) { OriginalTick = CurrentTick; CurrentTick = (IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF); } return EFI_SUCCESS; } EFI_STATUS LfcCleanUpKbcAndEcBuffer ( ) /*++ Routine Description: Clean up KBC and EC buffer before hand off to OS, avoid abnormal behavior in OS, such as KB no function, shutdown... Arguments: N/A Returns: EFI_SUCCESS - If the desired amount of time passed. --*/ { EFI_STATUS Status; //Clean up EC 60/64 buffer Status = WaitIBE (KBC_CMD_STATE); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_6064_IBE_ERROR); } Status = WaitOBE (KBC_CMD_STATE); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_6064_OBE_ERROR); } //Clean up EC 62/66 buffer Status = WaitIBE (EC_CMD_STATE); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_6266_IBE_ERROR); } Status = WaitOBE (EC_CMD_STATE); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_6266_OBE_ERROR); } //Clean up EC 68/6C buffer Status = WaitIBE (EC_CMD_STATE2); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_686C_IBE_ERROR); } Status = WaitOBE (EC_CMD_STATE2); if (EFI_ERROR (Status)) { LfcLibLogError (LFC_LOG_CLEAR_EC_BUFFER_686C_OBE_ERROR); } return EFI_SUCCESS; } /* Routine Description : Notify EC to keep power. Suggest to use this function before do fullreset in case shutdown when do fullret under DC in. BIT 7: For command use to cut power bit (for BIOS Use Only). */ EFI_STATUS LfcEcLibEnableEcPower ( ) { UINT8 Data; EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } //Enable EC power Status = LfcEcLibEcRamRead(0xA1, &Data); if (EFI_ERROR(Status)) { return Status; } Data |= BIT7; //Set BIT7 LfcEcLibEcRamWrite(0xA1,Data); // EECP return EFI_SUCCESS; } /* Routine Description : Notify EC Not Keep Power. Suggest to use this function before do fullreset in case shutdown when do fullret under DC in. BIT 6: For command use to cut power bit (For App Use Only). BIT 7: For command use to cut power bit (for BIOS Use Only). */ EFI_STATUS LfcEcLibDisableEcPower ( VOID ) { UINT8 Data; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } //Disable EC power LfcEcLibEcRamRead(0xA1, &Data); Data &= (UINT8)~(BIT6|BIT7); // Clear BIT6 and BIT7 LfcEcLibEcRamWrite(0xA1,Data); // CCPW, EECP return EFI_SUCCESS; } EFI_STATUS LfcEcLibPowerStateIsAc ( OUT BOOLEAN *PowerStateIsAc ) { EFI_STATUS Status; UINT8 AcStatus = TRUE; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } // // Get AC State bit // Status = LfcEcLibEcRamRead (0xA3, &AcStatus); if (EFI_ERROR (Status)) { return Status; } if ((AcStatus & (1 << 7)) == 0) { // ADPT *PowerStateIsAc = FALSE; } else { *PowerStateIsAc = TRUE; } return Status; } /* ECMajorVersion = 0 before golden, = 1 after golden ECMinorVersion = xx in A7ECxxWW, display it with %02d ECTestVersion = 00 for formal EC, non-zero (yy) for test EC, should display A7ECxxWW(Tyy) if non-zero */ EFI_STATUS LfcEcLibReadEcVersion( IN OUT UINT8 *EcMajorVersion, IN OUT UINT8 *EcMinorVersion, IN OUT UINT8 *EcTestVersion ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = WaitIBE (EC_CMD_STATE); if (EFI_ERROR(Status)) { return Status; } Status = WaitOBE (EC_CMD_STATE); if (EFI_ERROR(Status)) { return Status; } //Send command IoWrite8 (EC_CMD_STATE, GET_EC_REVISION_CMD); Status = WaitIBE (EC_CMD_STATE); if (EFI_ERROR(Status)) { return Status; } Status = WaitOBF (EC_CMD_STATE); if (EFI_ERROR(Status)) { return Status; } *EcMajorVersion = IoRead8 (EC_DATA); WaitOBF (EC_CMD_STATE); *EcMinorVersion = IoRead8 (EC_DATA); WaitOBF (EC_CMD_STATE); *EcTestVersion = IoRead8 (EC_DATA); return EFI_SUCCESS; } EFI_STATUS LfcEcLibGetTouchpadID ( IN OUT UINT8 *TouchpadID ) /*++ Routine Description: Get touchpad ID from EC. Arguments: Offset Eeprom offset TouchpadID 1 - PS/2 Touch Pad of Elantech 2 - PS/2 Touch Pad of Synaptics 3 - PS/2 Touch Pad of ALPS Returns: EFI_SUCCESS - Get touchpad ID Success --*/ { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0x8B, &Data); // TPDV if (EFI_ERROR (Status)) { return Status; } *TouchpadID = Data; return EFI_SUCCESS; } EFI_STATUS LfcEcLibGetBatterySerial ( IN OUT UINT8 *DataLength, IN OUT UINT8 *DataBuffer ) /*++ Routine Description: Get Battery Serial from EC. Arguments: Returns: EFI_SUCCESS - Get Battery Serial Success --*/ { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; if (*DataLength < 4) { return EFI_BUFFER_TOO_SMALL; } Status = LfcEcLibEcRamRead (MANUFACTURE_DATE_1, &(DataBuffer[0])); // B1DA if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (MANUFACTURE_DATE_0, &(DataBuffer[1])); // B1DA if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (SERIAL_NUMBER_1, &(DataBuffer[2])); // B1SN if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (SERIAL_NUMBER_0, &(DataBuffer[3])); // B1SN if (EFI_ERROR(Status)) { return Status; } *DataLength = 4; return Status; } EFI_STATUS LfcEcLibGetBatteryPercentage ( IN OUT UINT8 *BatteryPercentage ) { UINT16 RemainingCap, FullChargeCap; EFI_STATUS Status; UINT8 Data1 = 1, Data2 = 1, Data3 = 1, Data4 = 1; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (REMAINING_CAPACITY_1, &Data1); // B1RC if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (REMAINING_CAPACITY_0, &Data2); // B1RC if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (FULL_CHARGE_CAPACITY_1, &Data3); // B1FC if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (FULL_CHARGE_CAPACITY_0, &Data4); // B1FC if (EFI_ERROR(Status)) { return Status; } RemainingCap = (((UINT16)(Data1))<<8) + (UINT16)Data2; FullChargeCap = (((UINT16)(Data3))<<8) + (UINT16)Data4; //If battery not exist or battery error if (FullChargeCap == 0 || 100*RemainingCap/FullChargeCap > 100) { //If error //*BatteryPercentage = 15; return EFI_DEVICE_ERROR; } *BatteryPercentage = (UINT8)(100*RemainingCap/FullChargeCap); //if (*BatteryPercentage >=20 && *BatteryPercentage <= 30) { // *BatteryPercentage = 15; //Make it under 20 to meet flashit's error condition //} return EFI_SUCCESS; } //[-start-201125-WITAID0021-modify]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) || defined(S570_SUPPORT) || defined(S370_SUPPORT) || defined(S77014IAH_SUPPORT) /*++ // //KeyboardID, follow Lenovo Yx60 darfon spec V1.2 in future. //But still keep here in order to keep compliance with previous projects // --*/ EFI_STATUS LfcEcLibNotifyEcKeyboardId ( IN UINT8 KeyboardID ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } switch (KeyboardID) { case 0x00: EcData = EC_ENG_KEYBOARD_MATRIX; break; case 0x01: EcData = EC_GRE_KEYBOARD_MATRIX; break; case 0x02: EcData = EC_EUR_KEYBOARD_MATRIX; break; case 0x03: EcData = EC_KOP_KEYBOARD_MATRIX; break; case 0x04: EcData = EC_TCH_KEYBOARD_MATRIX; break; case 0x05: EcData = EC_RUS_KEYBOARD_MATRIX; break; case 0x06: EcData = EC_ARA_KEYBOARD_MATRIX; break; case 0x07: EcData = EC_HBW_KEYBOARD_MATRIX; break; case 0x08: EcData = EC_THA_KEYBOARD_MATRIX; break; case 0x09: EcData = EC_HIN_KEYBOARD_MATRIX; break; case 0x10: //[-start-220802-QINGLIN0171-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) case 'K': case 'U': #endif //[-end-220802-QINGLIN0171-add]// EcData = EC_UKE_KEYBOARD_MATRIX; break; case 0x11: EcData = EC_ITA_KEYBOARD_MATRIX; break; case 0x12: EcData = EC_SPA_KEYBOARD_MATRIX; break; case 0x13: EcData = EC_TUR_KEYBOARD_MATRIX; break; case 0x14: EcData = EC_POR_KEYBOARD_MATRIX; break; case 0x15: EcData = EC_LAS_KEYBOARD_MATRIX; break; case 0x16: EcData = EC_FRE_KEYBOARD_MATRIX; break; case 0x17: EcData = EC_NOR_KEYBOARD_MATRIX; break; case 0x18: //[-start-220802-QINGLIN0171-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) case 'F': #endif //[-end-220802-QINGLIN0171-add]// EcData = EC_FRA_KEYBOARD_MATRIX; break; case 0x19: EcData = EC_GER_KEYBOARD_MATRIX; break; case 0x20: //[-start-220802-QINGLIN0171-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) case 'B': #endif //[-end-220802-QINGLIN0171-add]// EcData = EC_BRL_KEYBOARD_MATRIX; break; //[-start-220824-Skywang0824-add]// case 0xA0: EcData = EC_BRL_Alexa_KEYBOARD_MATRIX; break; //[-End-220824-Skywang0824-add]// case 0x21: EcData = EC_HUN_KEYBOARD_MATRIX; break; case 0x22: EcData = EC_BEL_KEYBOARD_MATRIX; break; case 0x23: EcData = EC_ILD_KEYBOARD_MATRIX; break; case 0x24: EcData = EC_SLV_KEYBOARD_MATRIX; break; case 0x25: EcData = EC_SWS_KEYBOARD_MATRIX; break; case 0x26: EcData = EC_BUL_KEYBOARD_MATRIX; break; case 0x27: EcData = EC_CZE_KEYBOARD_MATRIX; break; case 0x28: EcData = EC_ARF_KEYBOARD_MATRIX; break; case 0x29: //[-start-220802-QINGLIN0171-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) case 'P': case 'J': #endif //[-end-220802-QINGLIN0171-add]// EcData = EC_JPN_KEYBOARD_MATRIX; break; case 0x30: EcData = EC_UKR_KEYBOARD_MATRIX; break; //[-start-220321-YUNLEI0163-modify]// #ifdef LCFC_SUPPORT case 0x31: //[-start-220802-QINGLIN0171-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77014_SUPPORT) || defined(S77013_SUPPORT) case 'S': #endif //[-end-220802-QINGLIN0171-add]// EcData = EC_USA_KEYBOARD_MATRIX; break; #endif //[-end-220321-YUNLEI0163-modify]// default: EcData = EC_ENG_KEYBOARD_MATRIX; break; } //[-start-220415-SHAONN0032-modify]// Status = EcCommand ( #ifdef S370_SUPPORT EC_CMD_STATE, EC_DATA, #else KBC_CMD_STATE, KBC_DATA, #endif //[-end-220415-SHAONN0032-modify]// 0, NULL, EC_SYSTEM_NOTIFI_DARFON_CMD, 1, &EcData); return Status; } #else /*++ // //KeyboardID, 'P' 'K' will be removed in future. //But still keep here in order to keep compliance with previous projects // --*/ EFI_STATUS LfcEcLibNotifyEcKeyboardId ( IN UINT8 KeyboardID ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } switch (KeyboardID) { case 'B': EcData = EC_EX_KEYBOARD_MATRIX; break; case 'S': EcData = EC_US_KEYBOARD_MATRIX; break; case 'P': case 'J': EcData = EC_JP_KEYBOARD_MATRIX; break; case 'K': case 'U': EcData = EC_UK_KEYBOARD_MATRIX; break; case 'F': EcData = EC_FR_KEYBOARD_MATRIX; break; default: EcData = EC_US_KEYBOARD_MATRIX; break; } Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 0, NULL, EC_SYSTEM_NOTIFI_CMD, 1, &EcData); return Status; } #endif //[-end-201125-WITAID0021-modify]// /* Routine Description : Notify EC the Board ID (Size). Arguments: MachineSize -Board ID (Size). Value:14 means 14" 15 means 15" 17 means 17" Return: EFI_STATUS Value: EFI_SUCCESS means success EFI_DEVICE_ERROR means timeout */ EFI_STATUS LfcEcLibNotifyEcMachineSize ( IN UINT8 MachineSize ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, EC_SYSTEM_NOTIFI_MACHINE_SIZE_CMD, 1, &MachineSize); return Status; } EFI_STATUS LfcEcLibEcReboot ( IN UINT16 CommandPort, IN UINT16 DataPort ) { UINT8 EcData; EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } EcData = 0xF7; Status = EcCommand ( CommandPort, DataPort, 0, NULL, 0x59, 1, &EcData); return Status; } EFI_STATUS LfcEcLibEcShutdown ( VOID ) /*++ Routine Description: This routine is used to shutdown the machine. Arguments: None. Returns: SUCCESS as passed Others as failed --*/ { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } EcData = EC_SYSTEM_NOTIFI_CMD_SHUTDOWN; Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 0, NULL, EC_SYSTEM_NOTIFI_CMD, 1, &EcData ); return Status; } EFI_STATUS LfcEcLibEcReset ( VOID ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } EcData = 0x01; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, 0x40, 1, &EcData ); return Status; } EFI_STATUS LfcEcLibAcInOutBeepControl ( IN BOOLEAN EnableEcBeep ) /*++ Routine Description: This routine is used to turn on or off power beep. Arguments: PowerBeepEnable - TRUE: Enable AC in/out beep FALSE: Disable AC in/out beep Returns: SUCCESS as passed Others as failed --*/ { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (EnableEcBeep) { EcData = BEEP_ENABLE_DATA; } else { EcData = BEEP_DISABLE_DATA; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_HOOK_CMD, 1, &EcData ); return Status; } EFI_STATUS LfcEcLibSetHotKeyMode ( IN UINT8 HotKeyMode ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0xa1, &Data); if (EFI_ERROR (Status)) { return Status; } if (HotKeyMode) { if (Data & BIT3) { Data &= (UINT8)~BIT3; Status = LfcEcLibEcRamWrite (0xa1, Data); // HKDB if (EFI_ERROR (Status)) { } } } else { if ((Data & BIT3) != BIT3) { Data |= BIT3; Status = LfcEcLibEcRamWrite (0xa1, Data); // HKDB if (EFI_ERROR (Status)) { } } } return EFI_SUCCESS; } EFI_STATUS LfcEcLibSetAlwaysOnUsbMode ( IN UINT8 AlwaysOnUsbMode ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0x8a, &Data); if (EFI_ERROR (Status)) { return Status; } if (AlwaysOnUsbMode) { if ((Data & BIT1) != BIT1) { Data |= BIT1; Status = LfcEcLibEcRamWrite (0x8a, Data); // UCHE } } else { if (Data & BIT1) { Data &= (UINT8)~BIT1; Status = LfcEcLibEcRamWrite (0x8a, Data); // UCHE } } return Status; } EFI_STATUS LfcEcLibSetChargeInBatteryMode ( IN UINT8 ChargeInBatteryMode ) { EFI_STATUS Status; UINT8 EcData = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead(0x8a, &EcData); if (EFI_ERROR (Status)) { return Status; } if (ChargeInBatteryMode) { if ((EcData & BIT6) != BIT6) { EcData |= (UINT8)BIT6; //BIT6 Status = LfcEcLibEcRamWrite (0x8a, EcData); // CIBM } } else { if (EcData & BIT6) { EcData &= (UINT8)~BIT6; //BIT6 Status = LfcEcLibEcRamWrite (0x8a, EcData); // CIBM } } return Status; } EFI_STATUS LfcEcLibSetOneKayBattery ( IN UINT8 OneKeyBattery ) { EFI_STATUS Status; UINT8 EcData=0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } LfcEcLibEcRamRead(0x8C, &EcData); //[-start-210702-Dongxu0008-modify]// if (OneKeyBattery) { EcData |= (UINT8)BIT5; //BIT5 } else { EcData &= (UINT8)~BIT5; //BIT5 } //[-end-210702-Dongxu0008-modify]// Status = LfcEcLibEcRamWrite(0x8C,EcData); // QCBX return Status; } EFI_STATUS LfcEcLibCheckEcDebugFlag( IN UINT16 CommandPort, IN UINT16 DataPort, IN BOOLEAN *EcDebugFlag ) { EFI_STATUS Status; UINT8 Data; UINT8 EcData = GET_EC_DEBUGFLAG_DATA; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } *EcDebugFlag = FALSE; Status = EcCommand ( CommandPort, DataPort, 1, &Data, GET_EC_DEBUGFLAG_CMD, 1, &EcData ); if(EFI_ERROR (Status)) { return Status; } // Debug Flag == TRUE if (Data & EC_DEBUGFLAG_TRUE) { *EcDebugFlag = TRUE; } return Status; } EFI_STATUS LfcEcLibDumpEcPostCode ( IN UINT16 CommandPort, IN UINT16 DataPort, IN UINT8 *OemPostCode ) { EFI_STATUS Status; UINT8 Index; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = WaitIBE (CommandPort); if(EFI_ERROR (Status)) { return Status; } Status = WaitOBE (CommandPort); if(EFI_ERROR (Status)) { return Status; } //Send command IoWrite8 (CommandPort, GET_EC_POSTCODE_CMD); Status = WaitIBE (CommandPort); if(EFI_ERROR (Status)) { return Status; } for ( Index = 0; Index < EC_POSTCODE_MAX_LENGTH; Index ++ ) { Status = WaitOBF (CommandPort); if(EFI_ERROR (Status)) { return Status; } OemPostCode[Index] = IoRead8 (DataPort); } { UINT8 Index1, Current, Temp, Buffer[EC_POSTCODE_MAX_LENGTH]; // OemPostCode[0] is for EC post code current index Current = OemPostCode[0]; // Copy OemPostCode to Buffer CopyMem(Buffer + 1, OemPostCode + 1, (EC_POSTCODE_MAX_LENGTH - 1));//Replace for loops with EDKII CopyMem. //for (Index = 1; Index < EC_POSTCODE_MAX_LENGTH; Index ++) { // Buffer[Index] = OemPostCode[Index]; //} // Sort OemPostCode for (Index1 = 1; Index1 < EC_POSTCODE_MAX_LENGTH; Index1 ++) { Temp = Current + Index1; if (Temp > (EC_POSTCODE_MAX_LENGTH - 1)) Temp -= (EC_POSTCODE_MAX_LENGTH - 1); OemPostCode[Index1] = Buffer[Temp]; } OemPostCode[0] = EC_POSTCODE_MAX_LENGTH - 1; } Status = WaitOBE (CommandPort); if(EFI_ERROR (Status)) { return Status; } Status = WaitIBE (CommandPort); return Status; } /* Routine Description : Notify EC the graphic configuration,Discrete or Uma. Arguments: Dis12Uma0 -graphic configuration. Value:0 means Uma 1 means external graphic card:Nvidia 2 means external graphic card:Amd Return: EFI_STATUS Value: EFI_SUCCESS means success EFI_DEVICE_ERROR means timeout */ EFI_STATUS LfcEcLibTellEcDisOrUma ( IN UINT8 Uma0Nv1Amd2 ) { UINT8 EcData; //[-start-211104-YUNLEI0152-add]// #if defined(C770_SUPPORT) UINT8 PTdpCpuIdentifier; UINT8 Panel_Size; OemSvcLfcGetBoardID(PANEL_SIZE, &Panel_Size); OemSvcLfcGetCpuIdentifier(&PTdpCpuIdentifier); #endif //[-end-211104-YUNLEI0152-add]// if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } //[-start-211104-YUNLEI0152-modify]// #if defined(C770_SUPPORT) if (Uma0Nv1Amd2 == 0) { if(Panel_Size==PANEL_SIZE_14) { if(PTdpCpuIdentifier==0x0f) { EcData = 0xf3; //14 UMA U15 } else { EcData = 0xf4; //14 UMA U28 } }else{ EcData = 0xe7; //16 Uma U28 } } else{ EcData = 0xf2; //16 dis H45 } #else if (Uma0Nv1Amd2 == 0) { EcData = 0xe7; //Uma } else if (Uma0Nv1Amd2 == 1) { EcData = 0xf0; //Dis&Nvidia } else if (Uma0Nv1Amd2 == 2) { EcData = 0xf1; //Dis&Amd } else if (Uma0Nv1Amd2 == 4) { EcData = 0xf2; } #endif //[-end-211104-YUNLEI0152-modify]// return EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_HOOK_CMD, 1, &EcData ); } EFI_STATUS LfcEcLibGetRecoverMode ( OUT BOOLEAN *RecoverMode ) /*++ Routine Description: Check whether is recovery mode Arguments: Returns: TRUE - indicate the boot mode is recovery mode. FALSE- indicate thd boot mode is not recovery mode. --*/ { // Lenovo SPEC requires to use FN+R as the crisis hot key, but I think // that Novo button is one good Crisis hot key during bring up life phase. #ifdef L05_CRISIS_HOTKEY_NOVO BOOLEAN NovoStatus; EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibGetNovoStatus (&NovoStatus); if (EFI_ERROR (Status)) { NovoStatus = FALSE; } if (NovoStatus) { *RecoverMode = TRUE; return EFI_SUCCESS; } *RecoverMode = FALSE; return EFI_SUCCESS; #else EFI_STATUS Status; UINT8 Data; UINT8 EcData = EC_CRITICAL_STATUS; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (PcdGet8 (PcdCrisisStatus) != 0xff) { // Restore crisis status from PCD *RecoverMode = (BOOLEAN) (PcdGet8 (PcdCrisisStatus)); return EFI_SUCCESS; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 1, &Data, EC_PLATFORM_CMD, 1, &EcData); if (EFI_ERROR (Status)) { *RecoverMode = FALSE; return Status; } if (Data == EC_CRITICAL_STATUS_CRISIS_MODE) { *RecoverMode = TRUE; } else { *RecoverMode = FALSE; } // Save crisis status into PCD PcdSet8S (PcdCrisisStatus, (UINT8) (*RecoverMode)); return EFI_SUCCESS; #endif } /*++ Routine Description: Novo Status detect Arguments: INPUT - NONE OUTPUT BOOLEAN - TRUE : Novo Key pressed, FALSE : Novo Key not pressed Returns: --*/ EFI_STATUS LfcEcLibGetNovoStatus ( OUT BOOLEAN *NovoKeyStatus ) { EFI_STATUS Status; UINT8 EcData; UINT8 Data; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (PcdGet8 (PcdNovoButtonStatus) != 0xff) { // Restore NOVO button status from PCD *NovoKeyStatus = (BOOLEAN) (PcdGet8 (PcdNovoButtonStatus)); return EFI_SUCCESS; } // Don't need this,EcCommand already use this mechanism. // Status = WaitIBE (EC_CMD_STATE); // if (EFI_ERROR(Status)) { // return Status; // } // // Status = WaitOBE (EC_CMD_STATE); // if (EFI_ERROR(Status)) { // return Status; // } EcData = EC_DETECT_NOVO; Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 1, &Data, EC_HOOK_CMD, 1, &EcData); if (!EFI_ERROR (Status)) { if(Data == 0x01) { *NovoKeyStatus = TRUE; } else { *NovoKeyStatus = FALSE; } // Save NOVO button status into PCD PcdSet8S (PcdNovoButtonStatus, (UINT8) (*NovoKeyStatus)); return EFI_SUCCESS; } else { *NovoKeyStatus = FALSE; return Status; } } EFI_STATUS LfcEcLibGetBatteryFirstUsedDate ( VOID ) { UINT8 Data; UINT8 EcData; UINT8 Temp; EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } // 1. Get EC Battery First Used ready flag EcData = EC_BATTERY_FIRST_USE_GET_FLAG; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 1, &Data, EC_BATTERY_FIRST_USE_DATE_STATUS_CMD , 1, &EcData ); if (Data == 1) { // 2. Get CMOS time and Set to EC IoWrite8(0x70,0x09);//Year Temp = IoRead8(0x71); Temp = ((Temp >> 4) & 0x0F)*10 + (Temp & 0x0F) + 20;//from 1980 EcData = EC_BATTERY_FIRST_USE_GET_YEAR; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, EC_BATTERY_FIRST_USE_GET_TIME , 2, &EcData, &Temp ); IoWrite8(0x70,0x08);//Month Temp = IoRead8(0x71); Temp = ((Temp >> 4) & 0x0F)*10 + (Temp & 0x0F); EcData = EC_BATTERY_FIRST_USE_GET_MONTH; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, EC_BATTERY_FIRST_USE_GET_TIME , 2, &EcData, &Temp ); IoWrite8(0x70,0x07);//Date Temp = IoRead8(0x71); Temp = ((Temp >> 4) & 0x0F)*10 + (Temp & 0x0F); EcData = EC_BATTERY_FIRST_USE_GET_DATE; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, EC_BATTERY_FIRST_USE_GET_TIME , 2, &EcData, &Temp ); // 3. Set EC Battery First Used ready EcData = EC_BATTERY_FIRST_USE_SET_READY; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, EC_BATTERY_FIRST_USE_DATE_STATUS_CMD, 1, &EcData ); } return Status; } EFI_STATUS LfcEcLibEcInit ( VOID ) { if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } return EFI_SUCCESS; } EFI_STATUS LfcEcLibEcWait ( IN BOOLEAN EnableWrites ) /*++ Routine Description: Platform specific function to enable flash / hardware for OEM EC Arguments: EnableWrites - Boolean to enable/disable wait Returns: EFI_SUCCESS --*/ { EFI_STATUS Status; UINT8 EcData = EC_ENTER_IDLE_MODE; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SYSTEM_NOTIFI_CMD, 1, &EcData); return Status; } EFI_STATUS LfcEcLibEcIdle ( IN BOOLEAN EnableWrites ) /*++ Routine Description: Platform specific function to enable flash / hardware for OEM EC Arguments: EnableWrites - Boolean to enable/disable idle Returns: EFI_SUCCESS --*/ { EFI_STATUS Status; UINT8 EcData = EC_ENTER_IDLE_MODE; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SYSTEM_NOTIFI_CMD, 1, &EcData); return Status; } EFI_STATUS LfcEcLibEcRamRead( IN UINT8 Index, OUT UINT8 *Data ) { EFI_STATUS Status; UINT8 Data8; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 1, &Data8, EC_READ_ECRAM_CMD, 1, &Index); *Data = Data8; return Status; } EFI_STATUS LfcEcLibEcRamWrite( IN UINT8 Index, IN UINT8 Value ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_WRITE_ECRAM_CMD, 2, &Index, &Value); return Status; } EFI_STATUS LfcEcLibEcAcpiMode ( IN BOOLEAN EnableEcMode ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (EnableEcMode) { EcData = EC_ACPI_MODE_EN_DATA; } else { EcData = EC_ACPI_MODE_DIS_DATA; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SYSTEM_NOTIFI_CMD, 1, &EcData); Status = LfcCleanUpKbcAndEcBuffer (); return Status; } EFI_STATUS LfcEcLibSaveRestoreKbc ( IN BOOLEAN SaveRestoreFlag ) /*++ Routine Description: This function either writes to or read from KBC IO registers. Arguments: SaveRestoreFlag - True: write data to SMM KBC IO. False: read data from IO to global registers. Returns: EFI_SUCCESS - if read or write is successful. --*/ { UINT8 KbdIrqState = 0; UINT8 SaveKbdIrqState = 0; EFI_STATUS Status; static UINT8 KbcCmdByte; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (SaveRestoreFlag) { // // Restore Keyboard command byte // Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 0, NULL, KBC_WRITE_CMD_BYTE, 1, &KbcCmdByte); } else { // Disable KBD IRQ KbdIrqState = IoRead8 (IRQ_8259_MASK); SaveKbdIrqState = KbdIrqState; KbdIrqState |= 2; IoWrite8 (IRQ_8259_MASK, KbdIrqState); Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 1, &KbcCmdByte, KBC_READ_CMD_BYTE, 0); IoWrite8 (IRQ_8259_MASK, SaveKbdIrqState); } return EFI_SUCCESS; } EFI_STATUS LfcEcLibDisableKeyBoard ( VOID ) /*++ Routine Description: This routine will set 0xAD Command to EC and EC will disable KeyBoard. Arguments: VOID Returns: SUCCESS as passed Others as failed --*/ { EFI_STATUS Status = EFI_SUCCESS; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = WaitIBE (KEY_CMD_STATE); IoWrite8 (KEY_CMD_STATE, 0xAD); return Status; } EFI_STATUS LfcEcLibPowerButtonControl ( IN BOOLEAN EnablePowerButton ) /*++ Routine Description: This routine is used to turn on or off Power Button 4s. Arguments: EnablePowerButton - TRUE: Enable Power Button FALSE: Disable Power Button Returns: SUCCESS as passed Others as failed --*/ { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (EnablePowerButton) { EcData = ENABLE_POWER_BUTTON; } else { EcData = DISABLE_POWER_BUTTON; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_HOOK_CMD, 1, &EcData ); return Status; } /*++ Routine Description : Notify EC to start to light shine. --*/ EFI_STATUS LfcEcLibStartLight( ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } EcData = 0xb7; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, 0x55, 1, &EcData); return Status; } /*++ Routine Description : Notify EC to stop to light shine. --*/ EFI_STATUS LfcEcLibStopLight( ) { EFI_STATUS Status; UINT8 EcData; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } EcData = 0xb8; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 0, NULL, 0x55, 1, &EcData); return Status; } /*++ Routine Description: This routine is used to get hotkey F2/F12 during POST. Arguments: Selection - 0x00: KEY_NONE 0x01: KEY_F2 0x02: KEY_F12 Returns: SUCCESS as passed Others as failed --*/ EFI_STATUS LfcEcLibGetHotkeyFromEc( IN OUT HOTKEY_TYPE *Selection ) { UINT8 Data = 0x00; UINT8 Value = 0x00; EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (PcdGet8 (PcdHotkeyStatus) != 0xff) { // Restore NOVO button status from PCD *Selection = (HOTKEY_TYPE)(PcdGet8 (PcdHotkeyStatus)); return EFI_SUCCESS; } Status = LfcEcLibEcRamRead (POST_HOTKEY, &Data); if (Status == EFI_SUCCESS){ Value = Data & (BIT1|BIT0); switch(Value) { case 0: *Selection = KEY_NONE; break; case 1: *Selection = KEY_F2; break; case 2: *Selection = KEY_F12; break; default: //EC always return one key value at any time and remove other key value, //so never jump into default. // Do Nothing break; } // Save Hotkey value into PCD PcdSet8S (PcdHotkeyStatus, (UINT8)(*Selection)); if(Value) { Data &= ~(BIT1|BIT0); Status = LfcEcLibEcRamWrite (POST_HOTKEY, Data); } return Status; } else { return Status; } } // Set Max Fan speed while flash BIOS EFI_STATUS LfcEcLibNotifyFanMaxSpeed() { EFI_STATUS Status; UINT8 Cmd; UINT8 Data; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Cmd = 0x59; Data = 0x77; Status = EcCommand ( 0x66, 0x62, FALSE, NULL, Cmd, 1, &Data); return Status; } EFI_STATUS LfcEcLibSwapFnCtrlMode ( IN UINT8 SwapMode ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0xa1, &Data); if (EFI_ERROR (Status)) { return Status; } if (SwapMode) { if ((Data & BIT0) != BIT0) { Data |= BIT0; Status = LfcEcLibEcRamWrite (0xa1, Data); // FPFC } } else { if (Data & BIT0) { Data &= (UINT8)~BIT0; Status = LfcEcLibEcRamWrite (0xa1, Data); // FPFC } } return EFI_SUCCESS; } EFI_STATUS LfcEcLibSetPerformanceMode ( IN UINT8 PerformanceMode ) { EFI_STATUS Status; UINT8 EcData = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } LfcEcLibEcRamRead (0x1D, &EcData); if (PerformanceMode == QUIET_MODE) { //Quiet Mode EcData = QUIET_MODE; } else if (PerformanceMode == HIGH_PERFORMANCE_MODE) { //High Performance mode EcData = HIGH_PERFORMANCE_MODE; } else { //Balance Mode EcData = BALANCE_MODE; } Status = LfcEcLibEcRamWrite (0x1D,EcData); // SPMO return Status; } EFI_STATUS LfcEcLibSetFlipToBootMode ( IN UINT8 L05FlipToBoot ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0x8d, &Data); if (EFI_ERROR (Status)) { return Status; } if (L05FlipToBoot) { if ((Data & BIT0) != BIT0) { Data |= BIT0; Status = LfcEcLibEcRamWrite (0x8d, Data); } } else { if (Data & BIT0) { Data &= (UINT8)~BIT0; Status = LfcEcLibEcRamWrite (0x8d, Data); } } return Status; } //[-start-211222-JOYID00009-add]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77013_SUPPORT) || defined(S77014_SUPPORT) || defined(S77014IAH_SUPPORT) EFI_STATUS LfcEcLibEnableWatchDogForMemoryTrainning ( VOID ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, 0x1B, 0); return Status; } EFI_STATUS LfcEcLibDisableWatchDogForMemoryTrainning ( VOID ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, 0x1C, 0); return Status; } #endif //[-end-211222-JOYID00009-add]// EFI_STATUS LfcEcLibGetBatteryTimerCount ( IN OUT UINT16 *BatteryTimerCount ) /*++ Routine Description: Get Battery Timer Count from EC - hours. Arguments: Returns: EFI_SUCCESS - Get Battery Timer Count Success --*/ { EFI_STATUS Status; UINT8 Data0 = 0, Data1 = 0; UINT16 Data; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (BATTERY_TIMER_COUNT_L, &Data0); // BACT if (EFI_ERROR(Status)) { return Status; } Status = LfcEcLibEcRamRead (BATTERY_TIMER_COUNT_H, &Data1); // BACT if (EFI_ERROR(Status)) { return Status; } Data = (((UINT16)(Data1))<<8) + (UINT16)Data0; //If battery timer count is 0 or full if (Data == 0 || Data == 0xFFFF) { return EFI_UNSUPPORTED; } *BatteryTimerCount = Data; return EFI_SUCCESS; } //[-start-220210-Dongxu0040-Modify]// EFI_STATUS LfcCheckValidTool ( OUT UINT8 *Data ) { EFI_STATUS Status; UINT8 Data8,ECCommand; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } ECCommand = 0x7F; Status = EcCommand ( EC_CMD_STATE2, EC_DATA2, 1, &Data8, ECCommand, 0 ); *Data = Data8; return Status; } //[-end-220210-Dongxu0040-Modify]// EFI_STATUS LNVEcBatterySetting ( IN UINT8 Function, IN UINT8 Action, IN UINT8 ExValue ) { UINT8 Status =0; UINT8 CMDData1 = 0, CMDData2 = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } switch (Function) { //function case 0x01: //ship mode if(Action == 1){ //enable CMDData1 = EC_ENABLE_SHIPMODE_DATA; } break; case 0x02: //conversation mode if(Action == 1){ //enable CMDData1 = EC_ENTER_CONVERSATIONMODE_DATA; } else if(Action == 0) { //disable CMDData1 = EC_EXIT_CONVERSATIONMODE_DATA; } else { CMDData1 = EC_CHECK_CONVERSATIONMODE_DATA; } break; case 0x03: //first use data if(Action == 1){ //clear first use data CMDData1 = EC_CLEAR_FIRSTUSEDATA_DATA; } else if(Action == 0) { //read first use data CMDData1 = EC_CHECK_FIRSTUSEDATA_DATA; } break; case 0x04: //LED control switch(Action){ case 0x01: //power led on CMDData1 = EC_OSCONTROL_POWERLEDON; break; case 0x10: //power led off CMDData1 = EC_OSCONTROL_POWERLEDOFF; break; case 0x02: //charge led on CMDData1 = EC_OSCONTROL_CHARGELEDON; break; case 0x20: //charge led off CMDData1 = EC_OSCONTROL_CHARGELEDOFF; break; case 0x03: //discharge led on CMDData1 = EC_OSCONTROL_DISCHARGELEDON; break; case 0x30: //discharge led off CMDData1 = EC_OSCONTROL_DISCHARGELEDOFF; break; case 0x04: //numlock led on CMDData1 = EC_OSCONTROL_NUMLOCKLEDON; break; case 0x40: //numlock led off CMDData1 = EC_OSCONTROL_NUMLOCKLEDOFF; break; case 0x05: //capslock led on CMDData1 = EC_OSCONTROL_CPSLOCKLEDON; break; case 0x50: //capslock led off CMDData1 = EC_OSCONTROL_CPSLOCKLEDOFF; break; case 0x06: //KB backlight led on CMDData1 = EC_OSCONTROL_KBBACKLIGHTLEDON; break; case 0x60: //KB backlight led off CMDData1 = EC_OSCONTROL_KBBACKLIGHTLEDOFF; break; case 0x07: //FP led1 on CMDData1 = EC_OSCONTROL_FPLED1ON; break; case 0x70: //FP led1 off CMDData1 = EC_OSCONTROL_FPLED1OFF; break; case 0x08: //FP led2 on CMDData1 = EC_OSCONTROL_FPLED2ON; break; case 0x80: //FP led2 off CMDData1 = EC_OSCONTROL_FPLED2OFF; break; case 0x09: //Fn Lock led on CMDData1 = EC_OSCONTROL_FNLOCKLED1ON; break; case 0x90: //Fn Lock led off CMDData1 = EC_OSCONTROL_FNLOCKLED1OFF; break; case 0x0A: //All led off CMDData1 = EC_OSCONTROL_ALLLEDOFF; break; case 0xA0: //All led on CMDData1 = EC_OSCONTROL_ALLLEDON; break; case 0x0B: //All led control right back to EC CMDData1 = EC_ALLLEDCONTROL_BACKTOEC; break; default: break; } break; case 0x05: //get CPU/GPU temp CMDData1 = EC_GETCPUGPU_TEMP; switch(Action){ case 0x01: //get CPU temp CMDData2 = EC_GETCPU_TEMP_EXVALUE; break; case 0x02: //get GPU temp CMDData2 = EC_GETGPU_TEMP_EXVALUE; break; case 0x03: //get near CPU temp CMDData2 = EC_NEARCPU_TEMP_EXVALUE; break; case 0x04: //get near GPU temp CMDData2 = EC_NEARGPU_TEMP_EXVALUE; break; case 0x05: //get charge temp CMDData2 = EC_CHARGE_TEMP_EXVALUE; break; case 0x06: //get Environment temp CMDData2 = EC_ENVIRONMENT_TEMP_EXVALUE; break; case 0x07: //get SSD temp CMDData2 = EC_GETSSD_TEMP_EXVALUE; break; case 0x08: //get RAM temp CMDData2 = EC_GETRAM_TEMP_EXVALUE; break; default: break; } break; case 0x06: switch(Action){ case 01: //set fan1 speed CMDData1 = EC_SETFAN1_SPEED; break; case 02: //set fan2 speed CMDData1 = EC_SETFAN2_SPEED; break; case 03: //get fan1 speed CMDData1 = EC_GETFAN_SPEED; break; case 04: //get fan2 speed CMDData1 = EC_GETFAN_SPEED; break; case 05: //set fan speed auto CMDData1 = EC_FANCONTROL_TOEC; break; case 06: //get fan num CMDData1 = EC_GET_FANNUM; break; default: break; } break; case 0x07: //check AC/DC status switch(Action){ case 01: //check AC/DC status CMDData1 = EC_CHECK_ACDC_MODE; break; case 02: //AC enable CMDData1 = EC_ENABLE_AC; break; case 03: //AC disable CMDData1 = EC_DISABLE_AC; break; default: break; } break; case 0x08: //Set battery charge/discharge capacity switch(Action){ case 01: //Battery charge to 100% then discharge to require capacity level and keep CMDData1 = EC_CHARGE_CAP; break; case 02: //Battery charge or discharge to require capacity level directly and keep CMDData1 = EC_CHARGE_DISCHARGE_CAP; break; default: break; } break; case 0x09://auto power on from MFG ship mode CMDData1 = EC_AUTOPOWERON; break; case 0x0A://Lid control switch(Action){ case 01: //Lid disable CMDData1 = EC_LID_DISABLE; break; case 02: //Lid enable CMDData1 = EC_LID_ENABLE; break; case 03: //read Lid status CMDData1 = EC_LID_STATUS; break; case 04: //read Lid open status CMDData1 = EC_GETLIDOPEN_STATUS; break; default: break; } break; case 0x0B://Backlight control switch(Action){ case 01: //Backlight control disable CMDData1 = EC_BKL_DISABLE; break; case 02: //Backlight control enable CMDData1 = EC_BKL_ENABLE; break; default: break; } break; case 0x0C: switch(Action){ case 01: //Enable scancode for power button test, (Button press scancode set1: E0 05, Button release scancode set1: E0 85) CMDData1 = EC_EN_SCAN_PWRBUTTON_TEST; break; case 02: //Disable scancode for power button test CMDData1 = EC_DIS_SCAN_PWRBUTTON_TEST; break; case 03: Status = IoRead8(0x60); goto exit; default: break; } break; case 0x0D: switch(Action){ case 01: //Watch dog disable CMDData1 = EC_WATCHDOG_DIS; break; case 02: //watchdog enable CMDData1 = EC_WATCHDOG_EN; break; default: break; } break; case 0x0E: //Get PD FW Version CMDData1 = EC_GET_PD_VERSION; break; case 0xED: //read EC ram LfcEcLibEcRamRead (Action, &Status); goto exit; break; case 0xEE: //write EC ram LfcEcLibEcRamWrite (ExValue,Action); goto exit; break; case 0xEF://manual command CMDData1 = Action; CMDData2 = ExValue; break; default: break; } if(CMDData2 == 0) { CMDData2 = ExValue; } EcCommand ( EC_CMD_STATE2, EC_DATA2, 1, &Status, EC_TOOl_CMD, 2, &CMDData1, &CMDData2); exit: return Status; } //[-start-200821-BAIN000035-add]// //[-start-210903-YUNLEI0129-modify]// //[-start-210906-SHAONN0005-modify]// //[-start-211110-GEORGE0021-modify]// //#if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S370_SUPPORT) || defined(S570_SUPPORT) #ifdef LCFC_SUPPORT //[-end-211110-GEORGE0021-modify]// EFI_STATUS LfcEcLibNotifyThermalMax() { EFI_STATUS Status = EFI_SUCCESS; UINT8 Command = 0x59; UINT8 Data = 0x77; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, Command, 1, &Data); return Status; } EFI_STATUS LfcEcLibNotifyThermalMaxStop() { EFI_STATUS Status = EFI_SUCCESS; UINT8 Command = 0x59; UINT8 Data = 0x76; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, Command, 1, &Data); return Status; } #endif //[-end-210906-SHAONN0005-modify]// //[-end-210903-YUNLEI0129-modify]// //[-end-200821-BAIN000035-add]// //[-start-210929-SHAONN0010-add]// #if defined(S370_SUPPORT) EFI_STATUS LfcEcLibNotifyEcProjectType ( IN UINT8 ProjectType ) { EFI_STATUS Status; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } switch(ProjectType){ // case 0x00 : // ProjectType = 0x00; // break; // case 0x01 : // ProjectType = 0x10; // break; case 0x02 : ProjectType = 0x20; break; case 0x03 : ProjectType = 0x40; break; default: ProjectType = 0x00; break; } LfcEcLibEcRamWrite(0xA2,0x00); Status = LfcEcLibEcRamWrite(0xA2,ProjectType); return Status; } #endif //[-end-210929-SHAONN0010-add]// //[-start-211014-BAIN000051-add]// //#ifdef LCFC_SUPPORT //#if defined(C970_BSH_SUPPORT) //[-start-21119-TAMT000032-modify]// //[-start-211203-QINGLIN0125-modify]// //[-start-211206-OWENWU0029-modify]// //[-start-211214-Ching000017-modify]// #if defined(C970_BSH_SUPPORT) || defined(C770_BSH_SUPPORT) || defined(S77014_BSH_SUPPORT) || defined(S370_BSH_SUPPORT) || defined(S570_BSH_SUPPORT) || defined(S77013_BSH_SUPPORT) || defined(S77014IAH_BSH_SUPPORT) //[-end-211214-Ching000017-modify]// //[-end-211206-OWENWU0029-modify]// //[-end-211203-QINGLIN0125-modify]// /*++ Routine Description : Notify EC to Set WDT Flag (EC power Off/8S reset set 15S WD,time out set top-swap pin flag, EC reset and power on) for Self-healing. --*/ EFI_STATUS LfcEcLibSetWDTFlagForSelfHealing ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data = Data | 0x01; //Set Bit0 = 1 Status = LfcEcLibEcRamWrite(0x22,Data); //[-start-211027-JAYAN00004-remove]// // MicroSecondDelay(2000000); //[-end-21119-TAMT000032-modify]// //[-end-211027-JAYAN00004-remove] return Status; } /*++ Routine Description : Notify EC to Disable current WDT and next boot follow 81for Self-healing. --*/ EFI_STATUS LfcEcLibDisableCurrentWDTForSelfHealing ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data = Data | 0x02; //Set Bit1 = 1 Status = LfcEcLibEcRamWrite(0x22,Data); //[-start-211027-JAYAN00004-remove]// // MicroSecondDelay(2000000); //[-end-211027-JAYAN00004-remove] return Status; } /*++ Routine Description : Notify EC to always clear the WDT flag for Self-healing. --*/ EFI_STATUS LfcEcLibClearWDTFlagForSelfHealing ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data &= ~BIT0; //Set Bit0 = 0 Status = LfcEcLibEcRamWrite(0x22,Data); //[-start-211027-JAYAN00004-remove]// // MicroSecondDelay(2000000); //[-end-211027-JAYAN00004-remove] return Status; } /*++ Routine Description : Notify EC to Disable Top-swap pin and always clear the Top-swap flag for Self-healing. --*/ EFI_STATUS LfcEcLibDisableAndClearTopSwapForSelfHealing ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data = Data | 0x08; //Set Bit3 = 1 Status = LfcEcLibEcRamWrite(0x22,Data); //[-start-211027-JAYAN00004-remove]// // MicroSecondDelay(2000000); //[-end-211027-JAYAN00004-remove] return Status; } /*++ Routine Description : Notify EC to clear cmos pin for Self-healing. Byte: 0X48 --*/ EFI_STATUS LfcEcLibClearCmosForSelfHealing ( VOID ) //[-start-211223-BAIN000072-modify]// //[-start-211223-QINGLIN0132-modify]// { EFI_STATUS Status = EFI_SUCCESS; UINT8 Data = 0x01; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SET_CLEAN_CMOS, 1, &Data); return Status; } //[-end-211223-QINGLIN0132-modify]// //[-end-211223-BAIN000072-modify]// #endif //[-end-211014-BAIN000051-add]// //[-start-211231-JOYID00010-add] //[-start-220117-QINGLIN0146-modify]// //[-start-220119-OWENWU0036-modify]// #if defined(C970_SUPPORT) || defined(C770_SUPPORT) || defined(S77013_SUPPORT) || defined(S77014_SUPPORT) || defined(S370_SUPPORT) || defined(S570_SUPPORT) || defined(S77014IAH_SUPPORT) EFI_STATUS LfcEcLibStopWDT ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data = Data | 0x10;//Set Bit4 = 1 Status = LfcEcLibEcRamWrite(0x22,Data); return Status; } EFI_STATUS LfcEcLibStartWDT ( VOID ) { EFI_STATUS Status; UINT8 Data; Status = LfcEcLibEcRamRead(0x22,&Data); Data &= ~BIT4; //Set Bit4 = 0 Status = LfcEcLibEcRamWrite(0x22,Data); return Status; } #endif //[-end-220119-OWENWU0036-modify]// //[-end-220117-QINGLIN0146-modify]// //[-end-211231-JOYID00010-add] //[-start-211109-BAIN000054-add]// #if defined(C970_SUPPORT)||defined(C770_SUPPORT)||defined(S77013_SUPPORT)||defined(S77014_SUPPORT)||defined(S77014IAH_SUPPORT) /*++ Routine Description: This routine will set 0x1D Command to EC and EC will Enable/Disable PD Controller Mode Arguments: PdControllerMode Set 0x00 Disable PD_1 Disable PD_2 Controller Mode Set 0x01 Enable PD_1 Disable PD_2 Controller Mode Set 0x02 Disable PD_1 Enable PD_2 Controller Mode Set 0x03 Enable PD_1 Enable PD_2 Controller Mode Returns: EFI_SUCCESS Command executed successfully Other Command executed failed --*/ EFI_STATUS LfcEcLibSetPdControllerMode( IN UINT8 PdControllerMode ) { EFI_STATUS Status = EFI_SUCCESS; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SET_PD_MODE_CMD, 1, &PdControllerMode); return Status; } /*++ Routine Description: This routine will set 0x1D Command to EC and EC will Enable/Disable PD Controller Mode Arguments: PdControllerModeBuffer Get 0x00 PD_1 Disable PD_2 Disable Controller Mode Get 0x01 PD_1 Enable PD_2 Disable Controller Mode Get 0x02 PD_1 Disable PD_2 Enable Controller Mode Get 0x03 PD_1 Enable PD_2 Enable Controller Mode Returns: EFI_SUCCESS Command executed successfully Other Command executed failed --*/ EFI_STATUS LfcEcLibGetPdControllerMode( OUT UINT8 *PdControllerMode ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 EcData = 0; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 1, &EcData, EC_GET_PD_MODE_CMD, 0); *PdControllerMode = EcData; return Status; } //[-start-211227-BAIN000077-add]// /*++ Routine Description: This routine will set 0x1F Command to EC execute compliance mode. --*/ EFI_STATUS LfcEcLibSetCOMPLMode( ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 Data = 0x07; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_SET_COMPL_MODE_CMD, 1, &Data); return Status; } //[-end-211227-BAIN000077-add]// #endif //[-end-211109-BAIN000054-add]// //[-start-211220-BAIN000070-add]// #ifdef LCFC_SUPPORT EFI_STATUS LfcEcLibSetRestWDGCMD( ) { EFI_STATUS Status = EFI_SUCCESS; Status = EcCommand ( KBC_CMD_STATE, KBC_DATA, 0, NULL, EC_SET_WDG_REST_CMD, 0); return Status; } #endif //[-end-211220-BAIN000070-add]// //[-start-220104-Dongxu0040-add]// EFI_STATUS LfcEcLibi7i5( IN UINT8 CpuType ) { EFI_STATUS Status = EFI_SUCCESS; Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_CPU_TYPE_CMD, 1, &CpuType); return Status; } //[-end-220104-Dongxu0040-add]// //[-start-220120-QINGLIN0151-add]// #if defined(S370_SUPPORT) /*++ Routine Description: This routine will notify EC CPU type. Arguments: CpuType 1 Celeron 2 Pentium 3 i3 5 i5 7 i7 Returns: EFI_SUCCESS Command executed successfully Other Command executed failed --*/ EFI_STATUS LfcEcLibNotifyEcCpuType ( IN UINT8 CpuType ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 EcData8 = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } if (CpuType == 0x07) { //i7 EcData8 = 0xC7; } else if (CpuType == 0x05) { //i5 EcData8 = 0xC5; } else if (CpuType == 0x03) { //i3 EcData8 = 0xC3; } else if (CpuType == 0x02) { //Pentium EcData8 = 0xC2; } else if (CpuType == 0x01) { //Celeron EcData8 = 0xC1; } Status = EcCommand ( EC_CMD_STATE, EC_DATA, 0, NULL, EC_CPU_TYPE_CMD, 1, &EcData8); return Status; } EFI_STATUS LfcEcLibSetUltraQuietMode ( IN UINT8 UltraQuietMode ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0x8D, &Data); if (EFI_ERROR (Status)) { return Status; } if (UltraQuietMode) { if ((Data & BIT5) != BIT5) { Data |= BIT5; Status = LfcEcLibEcRamWrite (0x8D, Data); } } else { if (Data & BIT5) { Data &= (UINT8)~BIT5; Status = LfcEcLibEcRamWrite (0x8D, Data); } } return Status; } EFI_STATUS LfcEcLibSwitchFoolProofFnCtrl ( IN UINT8 FoolProofFnCtrl ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0xA1, &Data); if (EFI_ERROR (Status)) { return Status; } if (FoolProofFnCtrl) { if ((Data & BIT0) != BIT0) { Data |= BIT0; Status = LfcEcLibEcRamWrite (0xA1, Data); } } else { if (Data & BIT0) { Data &= (UINT8)~BIT0; Status = LfcEcLibEcRamWrite (0xA1, Data); } } return Status; } #endif //[-end-220120-QINGLIN0151-add]// //[-start-220407-JEPLIUT219-add]// #if defined(S570_SUPPORT) /*---------------------------------------------------------------- @Brief : LfcEcLibGetAdapter65WAcOnlyMode @Descrip: Get the EC flag when adapter is 45W 65W & None battery at power on. @Input : none @Output : 1 = Available 0 = none --------------------------------------------------------------- -*/ EFI_STATUS LfcEcLibGetAdapter65WAcOnlyMode ( OUT UINT8 * Adapter65WAc ) { EFI_STATUS Status; UINT8 Data = 0; if (!mLcfcEcLibSupport) { return EFI_UNSUPPORTED; } Status = LfcEcLibEcRamRead (0x23, &Data); if (EFI_ERROR (Status)) { return Status; } if (Data & BIT1) { *Adapter65WAc = 1; } else { *Adapter65WAc = 0; } return Status; } #endif //[-end-220407-JEPLIUT219-add]//