diff options
Diffstat (limited to 'Board/EM/MeWrapper/Icc/IccSetup/IccCallbacks.c')
-rw-r--r-- | Board/EM/MeWrapper/Icc/IccSetup/IccCallbacks.c | 1272 |
1 files changed, 1272 insertions, 0 deletions
diff --git a/Board/EM/MeWrapper/Icc/IccSetup/IccCallbacks.c b/Board/EM/MeWrapper/Icc/IccSetup/IccCallbacks.c new file mode 100644 index 0000000..8dcd104 --- /dev/null +++ b/Board/EM/MeWrapper/Icc/IccSetup/IccCallbacks.c @@ -0,0 +1,1272 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* +//********************************************************************** +// +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/ME/MeWrapper/Icc/IccSetup/IccCallbacks.c 11 5/14/14 9:57p Tristinchou $ +// +// $Revision: 11 $ +// +// $Date: 5/14/14 9:57p $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/ME/MeWrapper/Icc/IccSetup/IccCallbacks.c $ +// +// 11 5/14/14 9:57p Tristinchou +// [TAG] EIP167030 +// [Category] Improvement +// [Description] Remove the variable runtime attribute and keep original +// attributes. +// +// 10 8/09/13 2:17a Klzhan +// [TAG] EIP131037 +// [Category] Improvement +// [Description] Skip Using Icc Protocol after End of Post. +// +// 9 5/13/13 2:42a Klzhan +// [TAG] EIPNone +// [Category] Improvement +// [Description] FIx build error when Icc_OverClocking_Support is +// disabled. +// +// 8 12/27/12 6:36a Klzhan +// [TAG] EIP104882 +// [Category] Improvement +// [Description] Avoid running ICC callbacks when Load Default. +// +// 7 10/30/12 8:37a Klzhan +// Support DMI Ratio for new ICC. +// +// 6 9/19/12 5:58a Klzhan +// Avoid time-out in ICC setup Page when return from Shell. +// +// 5 7/02/12 11:43p Klzhan +// [TAG] EIP94113 +// [Category] Spec Update +// [Severity] Important +// [Description] Update ME RC0.6 +// +// 4 5/14/12 5:29a Klzhan +// Remove Debug code +// +// 3 5/14/12 4:47a Klzhan +// [TAG] EIP89676 +// [Category] Spec Update +// [Severity] Important +// [Description] Support New ICC library +// [Files] IccSetup.mak +// IccSetup.sdl +// IccCallbacks.c +// IccCallbacks.h +// IccSetup.h +// IccSetupMenu.sd +// IccSetupSubmenu.sd +// IccStrings.uni +// IccLoadDefault.c +// IccSetup.cif +// +// 2 4/24/12 12:30a Klzhan +// Update modulepart to latest +// +// 1 2/08/12 1:07a Klzhan +// Initial Check in +// +// 6 9/06/11 6:11a Klzhan +// [TAG] EIP67462 +// [Category] Spec Update +// [Severity] Important +// [Description] Update ICC 08.00.00.022.1 +// [Files] IccSetup.mak +// IccSetup.sdl +// IccCallbacks.c +// IccCallbacks.h +// IccSetup.h +// IccSetupMenu.sd +// IccSetupSubmenu.sd +// IccStrings.uni +// IccLoadDefault.c +// IccSetup.cif +// +// 5 7/26/11 5:58a Klzhan +// Support EFI 2.3 +// +// 4 6/27/11 3:22a Klzhan +// Correct SscMode when Set frequency. +// +// 3 6/24/11 7:20a Klzhan +// Remove un-use debug message. +// +// 2 6/23/11 11:31p Klzhan +// [TAG] EIP62129 +// [Category] Spec Update +// [Severity] Important +// [Description] Support ICC Control Library 8.0.0.19. +// [Files] IccCallbacks.c, IccCallbacks.h +// +// 1 2/25/11 1:42a Klzhan +// Initial Check-in +// +// 1 12/03/10 5:10a Klzhan +// Initial Check-in. +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: IccCallbacks.c +// +// Description: Setup hooks for ICC. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> +/*++ +Copyright (c) 2009 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. + +Module Name: + + IccCallbacks.c + +Abstract: + + Setup hooks for ICC. + +--*/ + +#include <AmiDxeLib.h> +#include <Setup.h> +#include <SetupStrTokens.h> +#include "AUTOID.h" +#include "Protocol\AMIPostMgr.h" +#include "Protocol\IccOverClocking\IccOverClocking.h" +#include "IccSetup.h" +#include "IccCallbacks.h" +#include "PchAccess.h" +#ifdef CougarPoint_SUPPORT +#include "Protocol\Wdt\Wdt.h" +#include "Protocol\WdtApp\WdtApp.h" +#endif +#include "Protocol\MePlatformPolicy\MePlatformPolicy.h" + +UINT8 mActiveSubmenu = ICC_CLOCK_COUNT; +ICC_OVERCLOCKING_PROTOCOL* gIccOverClockingProtocol; +ICC_CLOCK_RANGES mRanges[ICC_CLOCK_COUNT]; +CLOCK_DISPLAY_VALUES values; // Store clock Infomations of current page. +UINT16 mBootTimeClkDiv[ICC_CLOCK_COUNT]; +UINT8 mWatchdogEnabled; + +CHAR16* mClockUsageName[] = { + L"BCLK", + L"DMI", + L"PEG", + L"PCIe", + L"PCI33", + L"RESERVED", + L"SATA", + L"USB3", + L"IGD", + L"IGD Bending", + L"RESERVED", + L"GFX", + L"USB Legacy", + L"PCH Legacy" +}; + +CHAR16* mClockName[] = { + L"Clock1", + L"Clock2", + L"Clock3", + L"Clock4", + L"Clock5", + L"Clock6", + L"Clock7", + L"Clock8" +}; + +CHAR16* mClockUsageNone = L"Not used"; + +UINT16* mModeName[] = { + L"Down", + L"Center", + L"Up", + L"None" +}; + +EFI_HII_HANDLE gHiiHandle; +// +// Blocks entry to ICC clock submenus after End Of Post event +// +UINT8 mAfterEndOfPost = 0; + +#define NAME_ARRAY_SIZE (( sizeof(mClockUsageName)/sizeof(mClockUsageName[0]) )) + +#if (SUPPORTED_CLOCKS != ICC_CLOCK_COUNT) +#error Ambiguous number of supported clocks +#endif + +#ifndef StrCat +#define StrCat(a,b) Wcscpy (a + Wcslen (a), b) +#endif + +#define AMI_CALLBACK_CONTROL_UPDATE 1 +#define AMI_CALLBACK_RETRIEVE 2 +#define AMI_CALLBACK_FORM_OPEN 3 +#define AMI_CALLBACK_FORM_CLOSE 4 +#define AMI_CALLBACK_FORM_DEFAULT_STANDARD 0x1000 +#define AMI_CALLBACK_FORM_DEFAULT_MANUFACTURING 0x1001 + +EFI_STATUS +OnReadyToBoot ( +IN EFI_EVENT Event, +IN VOID *Context +) +/*++ +Routine Description: + + This function is executed on ReadyToBoot event. + If permanent or temporary ICC modifications were made, platform needs to be restarted. + Unlike ordinary setup options, ICC modifications can't be programmed to cause automatic reset. + Instead this function, executed on ReadyToBoot event, causes reset. + +Arguments: + Event pointer to event that caused this function to be executed + Context not used here + +Returns: + always SUCCESS +--*/ +{ + mAfterEndOfPost = 1; + pBS->CloseEvent(Event); + if (GetIccPersistentData() == ICC_SETTINGS_RECENTLY_MODIFIED) { + pRS->ResetSystem(EfiResetCold, 0, 0, 0); + } else if (GetIccPersistentData() == ICC_SETTINGS_PREVIOUSLY_MODIFIED) { + SetIccPersistentData(ICC_SETTINGS_NOT_MODIFIED); + } + return EFI_SUCCESS; +} + +VOID +InitICCStrings ( + EFI_HII_HANDLE HiiHandle, + UINT16 Class + ) +/*++ +Routine Description: + + This function is executed when Setup module loads. + Registers OnReadyToBoot function to be executed on ReadyToBoot event. + Remembers HiiHandle, pointer to setup browser's runtime variable store + +Arguments: + HiiHandle + Class + +Returns: + always SUCCESS +--*/ +{ + static UINT8 mInitStringComplete = 0; + EFI_EVENT Event; + EFI_GUID EfiEventReadyToBootGuid = EFI_EVENT_GROUP_READY_TO_BOOT; + + if (mInitStringComplete == 1) { + return; + } else { + if(Class == ADVANCED_FORM_SET_CLASS) { + mInitStringComplete = 1; + gHiiHandle = HiiHandle; + + if (GetIccPersistentData() == ICC_SETTINGS_RECENTLY_MODIFIED) { + SetIccPersistentData(ICC_SETTINGS_PREVIOUSLY_MODIFIED); + } + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + pBS->CreateEvent ( + EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL, + TPL_CALLBACK, + OnReadyToBoot, + NULL, + &Event + ); +#else + pBS->CreateEventEx ( + EFI_EVENT_NOTIFY_SIGNAL, + TPL_CALLBACK, + OnReadyToBoot, + NULL, + &EfiEventReadyToBootGuid, + &Event + ); +#endif + + } + } +} + +EFI_STATUS +InitIccMenu ( + IN ICC_VOLATILE_SETUP_DATA* IccSetupData + ) +/*++ +Routine Description: + Initializes text strings and setup variables connected with ICC menu. + If there is an error during initialization, displays messagebox with error details +Arguments: + Pointer to Icc setup data structure +Returns: + EFI_SUCCESS if everything went OK + otherwise, an ERROR +--*/ +{ + UINTN VariableSize; + UINT8 i; + EFI_STATUS Status; +#if IccOverClocking_SUPPORT + ICC_LIB_STATUS IccStatus; +#endif + ICC_LIB_VERSION Version; + SETUP_DATA SetupData; + EFI_GUID IccOverClockingProtocolGuid = ICC_OVERCLOCKING_PROTOCOL_GUID; + EFI_GUID IccSetupDataGuid = ICC_VOLATILE_SETUP_DATA_GUID; + EFI_GUID SetupGuid = SETUP_GUID; + CALLBACK_PARAMETERS *CallbackParameter = GetCallbackParameters(); + +#if EFI_SPECIFICATION_VERSION >= 0x2001E + if ((CallbackParameter->Action == AMI_CALLBACK_RETRIEVE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_OPEN) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_CLOSE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_STANDARD) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_MANUFACTURING)) + return EFI_SUCCESS; +#endif + + VariableSize = sizeof (SETUP_DATA); + + Status = pRS->GetVariable ( + L"Setup", + &SetupGuid, + NULL, + &VariableSize, + &SetupData + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VariableSize = sizeof(UINT8); + Status = pRS->GetVariable ( + L"AfterReadyToBoot", + &IccSetupDataGuid, + NULL, + &VariableSize, + &mAfterEndOfPost); +#if IccOverClocking_SUPPORT + Status = pBS->LocateProtocol(&IccOverClockingProtocolGuid, NULL, &gIccOverClockingProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + VariableSize = sizeof (UINTN); + mWatchdogEnabled = SetupData.IccWdtEnabled; + + IccStatus = IccInitOverclocking(&Version); + + if ( IccStatus != ICC_LIB_STATUS_SUCCESS ) { + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_INIT_ERROR_STRANGE), IccStatus); + IccSetupData->AllowAdvancedOptions = 0; + return EFI_DEVICE_ERROR; + } +#else + return EFI_SUCCESS; +#endif + // If init success, Set allowadvancedOption true +// IccSetupData->AllowAdvancedOptions = 1; + + InitString( + gHiiHandle, + STRING_TOKEN(STR_ICC_LIB_VERSION_NR), + L"%d.%d.%d.%d", + Version.Major, + Version.Minor, + Version.Hotfix, + Version.Build + ); + if(mAfterEndOfPost != 1) + { + IccSetupData->AllowAdvancedOptions = 1; + for (i=0; i<ICC_CLOCK_COUNT; i++) { + IccGetFrequencies(i, &values); + IccSetupData->Frequency[i] = values.ClkFreqCurrent; + IccSetupData->SscPercent[i] = values.SscPercentCurrent; + IccSetupData->SscMode[i] = values.SscModeCurrent; + // Workaround for architecture bugs: read - don't modify - write sequence doesn't work for some clocks + // These clocks must not be allowed to be modified - they'll cause ICC Lib to return misleading errors + if (/* (values.ClockUsage & (1<<ICC_CLOCK_USAGE_GFX)) || + (values.ClockUsage & (1<<ICC_CLOCK_USAGE_GFX_BENDING)) ||*/ + (values.ClockUsage == 0) + ) { + IccSetupData->ShowSsc[i] = 0; + IccSetupData->ShowClock[i] = 0; + } else { + IccSetupData->ShowSsc[i] = values.SscChangeAllowed; + if (values.ClkFreqMax == values.ClkFreqMin) { + IccSetupData->ShowClock[i] = 0; + } else { + IccSetupData->ShowClock[i] = 1; + } + } + } + }else + IccSetupData->AllowAdvancedOptions = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IccMenuEntry ( + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 Class, + IN UINT16 SubClass, + IN UINT16 Key +) +/*++ +Routine Description: + Setup callback executed when user enters Advanced->ICC menu + Think of it as an entry point to efi overclocking module + Initializes ICC OverClocking and if there are errors, disables entry into submenus + Without access to submenus, it is guaranteed no other callback will be executed. +Arguments: +Returns: + always SUCCESS, but in case of errors entry into submenus is disabled +--*/ +{ + static UINT8 FirstEntry = 1; + static UINT8 EopReported = 0; + ICC_VOLATILE_SETUP_DATA* IccSetupData = NULL; + EFI_STATUS Status; + EFI_GUID IccSetupDataGuid = ICC_VOLATILE_SETUP_DATA_GUID; + UINTN SelectionBufferSize = sizeof(ICC_VOLATILE_SETUP_DATA); + CALLBACK_PARAMETERS *CallbackParameter = GetCallbackParameters(); + EFI_GUID DxePlatformMePolicyGuid = DXE_PLATFORM_ME_POLICY_GUID; + DXE_ME_POLICY_PROTOCOL *DxePlatformMePolicy; + +#if EFI_SPECIFICATION_VERSION >= 0x2001E + if ((CallbackParameter->Action == AMI_CALLBACK_RETRIEVE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_OPEN) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_CLOSE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_STANDARD) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_MANUFACTURING)) + return EFI_SUCCESS; +#endif + + if(mAfterEndOfPost == 0) { + Status = pBS->LocateProtocol(&DxePlatformMePolicyGuid, NULL, &DxePlatformMePolicy); + if(!EFI_ERROR (Status)) { + if(DxePlatformMePolicy->MeConfig.EndOfPostDone) { + mAfterEndOfPost = 1; + } + } + } + // + // No changes to ICC menu display + // + if (EopReported == 1 || (FirstEntry ==0 && mAfterEndOfPost == 0)) { + return EFI_SUCCESS; + } + + FirstEntry = 0; + +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = pBS->AllocatePool(EfiBootServicesData, SelectionBufferSize, &IccSetupData); + if(EFI_ERROR(Status)) { + return Status; + } + + Status = HiiLibGetBrowserData(&SelectionBufferSize, + IccSetupData, + &IccSetupDataGuid, + ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); + +#else + IccSetupData = (ICC_VOLATILE_SETUP_DATA*)CallbackParameter->Data->NvRamMap; +#endif + + if (mAfterEndOfPost == 1 && EopReported == 0) { + IccSetupData->AllowAdvancedOptions = 0; + EopReported = 1; + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_AFTER_EOP)); + } else { + Status = InitIccMenu(IccSetupData); + if (EFI_ERROR(Status)) { +// IccSetupData->AllowAdvancedOptions = 0; + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_INIT_ERROR_STRANGE)); + } else { +// IccSetupData->AllowAdvancedOptions = 1; + } + } + + Status = pRS->SetVariable( + ICC_VOLATILE_SETUP_DATA_C_NAME, + &IccSetupDataGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + sizeof(ICC_VOLATILE_SETUP_DATA), + IccSetupData ); + +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = HiiLibSetBrowserData( + SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); + pBS->FreePool(IccSetupData); + +#endif; + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +IccSubmenuEntry ( + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 Class, + IN UINT16 SubClass, + IN UINT16 Key +) + +/*++ +Routine Description: + Setup callback executed when user enters any submenu of Advanced->ICC + Personalizes common strings for that particular clock submenu + Stores information on which submenu we're in, that's needed for other callbacks +Arguments: +Returns: + always SUCCESS +--*/ +{ + UINT8 SubMenuNumber = ICC_CLOCK_COUNT; + CHAR16 StringBuffer[100]; + UINT8 i; + UINT8 NeedComma; + UINT8 LineOverflow; + CALLBACK_PARAMETERS *CallbackParameter = GetCallbackParameters(); + +#if EFI_SPECIFICATION_VERSION >= 0x2001E + if ((CallbackParameter->Action == AMI_CALLBACK_RETRIEVE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_OPEN) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_CLOSE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_STANDARD) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_MANUFACTURING)) + return EFI_SUCCESS; +#endif + + switch (Key) { + case KEY_FORM1: + SubMenuNumber = 0; + break; + case KEY_FORM2: + SubMenuNumber = 1; + break; + case KEY_FORM3: + SubMenuNumber = 2; + break; + case KEY_FORM4: + SubMenuNumber = 3; + break; + case KEY_FORM5: + SubMenuNumber = 4; + break; + case KEY_FORM6: + SubMenuNumber = 5; + break; + case KEY_FORM7: + SubMenuNumber = 6; + break; + case KEY_FORM8: + SubMenuNumber = 7; + break; + default: + ASSERT(FALSE); + } + + if (SubMenuNumber == mActiveSubmenu) { + // + //strings already personalized for this menu, no need to change them + // + return EFI_SUCCESS; + } + + mActiveSubmenu = SubMenuNumber; + + IccGetFrequencies(mActiveSubmenu, &values); + StringBuffer[0] = 0; + NeedComma = 0; + LineOverflow = 0; + + // + // Concatenate all clock usages into two strings. If first string gets too long, second will be written + // + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CLOCK_USAGE_2), L"%s", StringBuffer); + if (values.ClockUsage != 0) { + for (i=0; i<NAME_ARRAY_SIZE; i++) { + if (values.ClockUsage & (1<<i)) { + if (NeedComma == 1) { + StrCat(StringBuffer, L", "); + } + if ( Wcslen(StringBuffer) + Wcslen(mClockUsageName[i]) > 25 ) { + LineOverflow = 1; + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CLOCK_USAGE_1), L"%s", StringBuffer); + StringBuffer[0] = 0; + NeedComma = 0; + } + StrCat(StringBuffer, mClockUsageName[i]); + NeedComma = 1; + } + } + } else { + StrCat(StringBuffer, mClockUsageNone); + } + if (LineOverflow) { + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CLOCK_USAGE_2), L"%s", StringBuffer); + } else { + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CLOCK_USAGE_1), L"%s", StringBuffer); + } + + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CLOCK_NUMBER), L"%s", mClockName[SubMenuNumber]); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_MAX_FREQUENCY_VALUE), L"%d.%02d MHz", values.ClkFreqMax/100, values.ClkFreqMax%100); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_MIN_FREQUENCY_VALUE), L"%d.%02d MHz", values.ClkFreqMin/100, values.ClkFreqMin%100); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CURRENT_FREQUENCY_VALUE), L"%d.%02d MHz", values.ClkFreqCurrent/100, values.ClkFreqCurrent%100); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_MODES_VALUE), L"%s%s%s", + (values.SscModeDownAvailable) ? L"Down " : L" ", + (values.SscModeCenterAvailable)? L"Center " : L" ", + (values.SscModeUpAvailable) ? L"Up " : L" " + ); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_CURRENT_MODE_VALUE), L"%s", mModeName[values.SscModeCurrent]); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_MAX_VALUE), L"%d.%02d%%", values.SscPercentMax/100, values.SscPercentMax%100); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_CURRENT_VALUE), L"%d.%02d%%", values.SscPercentCurrent/100, values.SscPercentCurrent%100); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IccAccept ( + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 Class, + IN UINT16 SubClass, + IN UINT16 Key +) +/*++ +Routine Description: + Setup callback executed when user chooses 'Accept' + Sends requested clock parameters to ICC OverClocking +Arguments: + interface to ITEM_CALLBACK_EX +Returns: + always SUCCESS +--*/ +{ + EFI_STATUS Status; + ICC_VOLATILE_SETUP_DATA* IccSetupData = NULL; + CLOCK_DISPLAY_VALUES values; + UINT8 TypeOfChange; + UINTN VarSize = 0; +#if EFI_SPECIFICATION_VERSION>0x20000 + UINTN SelectionBufferSize = sizeof(ICC_VOLATILE_SETUP_DATA); + EFI_GUID IccSetupDataGuid = ICC_VOLATILE_SETUP_DATA_GUID; +#endif + CALLBACK_PARAMETERS *CallbackParameter = GetCallbackParameters(); + +#if EFI_SPECIFICATION_VERSION >= 0x2001E + if ((CallbackParameter->Action == AMI_CALLBACK_RETRIEVE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_OPEN) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_CLOSE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_STANDARD) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_DEFAULT_MANUFACTURING)) + return EFI_SUCCESS; +#endif + + switch (Key) { + case KEY_CHANGE_NOW1: + case KEY_CHANGE_NOW2: + case KEY_CHANGE_NOW3: + case KEY_CHANGE_NOW4: + case KEY_CHANGE_NOW5: + case KEY_CHANGE_NOW6: + TypeOfChange = IMMEDIATE; + break; + case KEY_CHANGE_ONCE1: + case KEY_CHANGE_ONCE2: + case KEY_CHANGE_ONCE3: + case KEY_CHANGE_ONCE4: + case KEY_CHANGE_ONCE5: + case KEY_CHANGE_ONCE6: + TypeOfChange = TEMPORARY; + break; + case KEY_CHANGE_PERM1: + case KEY_CHANGE_PERM2: + case KEY_CHANGE_PERM3: + case KEY_CHANGE_PERM4: + case KEY_CHANGE_PERM5: + case KEY_CHANGE_PERM6: + TypeOfChange = PERMANENT; + break; + default: + ASSERT(FALSE); + TypeOfChange = 0; //prevent compilator warning + } + +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = pBS->AllocatePool(EfiBootServicesData, SelectionBufferSize, &IccSetupData); + if(EFI_ERROR(Status)) + return Status; + + Status = HiiLibGetBrowserData( + &SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); +#else + IccSetupData = (ICC_VOLATILE_SETUP_DATA*)CallbackParameter->Data->NvRamMap; +#endif + Status = SendClockChangeRequest(IccSetupData, mActiveSubmenu, TypeOfChange); + IccGetFrequencies(mActiveSubmenu, &values); + + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_CURRENT_FREQUENCY_VALUE), L"%d.%02d MHz", values.ClkFreqCurrent/100, values.ClkFreqCurrent%100); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_CURRENT_MODE_VALUE), L"%s", mModeName[values.SscModeCurrent]); + InitString(gHiiHandle, STRING_TOKEN(STR_ICC_SSC_CURRENT_VALUE), L"%d.%02d%%", values.SscPercentCurrent/100, values.SscPercentCurrent%100); + +#if EFI_SPECIFICATION_VERSION>0x20000 + pBS->FreePool(IccSetupData); +#endif; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IccFreqChange ( + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 Class, + IN UINT16 SubClass, + IN UINT16 Key +) +/*++ +Routine Description: + Setup callback executed when user changes frequency + Calls IccFrequencyRounding() which fixes frequency and SSC parameters to allowed values + Having these parameters fixed decreases number of errors caused by sending wrong parameters +Arguments: +Returns: + always SUCCESS +--*/ +{ + EFI_STATUS Status; + ICC_VOLATILE_SETUP_DATA* IccSetupData = NULL; + ICC_CLOCK_FREQUENCY ExpectFrequency, UserFrequency; + BOOLEAN HigherFrequency = FALSE; + ICC_LIB_STATUS IccStatus; +#if EFI_SPECIFICATION_VERSION>0x20000 + UINTN SelectionBufferSize = sizeof(ICC_VOLATILE_SETUP_DATA); + EFI_GUID IccSetupDataGuid = ICC_VOLATILE_SETUP_DATA_GUID; +#endif + + CALLBACK_PARAMETERS *CallbackParameter = GetCallbackParameters(); + +#if EFI_SPECIFICATION_VERSION >= 0x2001E + if ((CallbackParameter->Action == AMI_CALLBACK_RETRIEVE) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_OPEN) || + (CallbackParameter->Action == AMI_CALLBACK_FORM_CLOSE)) + return EFI_SUCCESS; +#endif + +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = pBS->AllocatePool(EfiBootServicesData, SelectionBufferSize, &IccSetupData); + if(EFI_ERROR(Status)) + return Status; + + Status = HiiLibGetBrowserData( + &SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); +#else + IccSetupData = (ICC_VOLATILE_SETUP_DATA*)CallbackParameter->Data->NvRamMap; +#endif + + UserFrequency = IccSetupData->Frequency[mActiveSubmenu]; + + if(UserFrequency >= values.ClkFreqMax) + { + IccSetupData->Frequency[mActiveSubmenu] = values.ClkFreqMax; +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = HiiLibSetBrowserData( + SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); + + pBS->FreePool(IccSetupData); +#endif; + return EFI_SUCCESS; + } + + if(UserFrequency <= values.ClkFreqMin) + { + IccSetupData->Frequency[mActiveSubmenu] = values.ClkFreqMin; +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = HiiLibSetBrowserData( + SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); + + pBS->FreePool(IccSetupData); +#endif; + return EFI_SUCCESS; + } + + if(UserFrequency > values.ClkFreqCurrent) + HigherFrequency = TRUE; + + { + UserFrequency = (UserFrequency) * 10000; + gIccOverClockingProtocol->GetNextFrequency(mActiveSubmenu, + UserFrequency, + &UserFrequency, + &IccStatus); + + gIccOverClockingProtocol->GetPreviousFrequency(mActiveSubmenu, + UserFrequency, + &ExpectFrequency, + &IccStatus); + } + + if (IccStatus == ICC_LIB_STATUS_SUCCESS) { + IccSetupData->Frequency[mActiveSubmenu] = ExpectFrequency/10000; + } + +#if EFI_SPECIFICATION_VERSION>0x20000 + Status = HiiLibSetBrowserData( + SelectionBufferSize, IccSetupData, + &IccSetupDataGuid, ICC_VOLATILE_SETUP_DATA_C_NAME + ); + ASSERT_EFI_ERROR(Status); + + pBS->FreePool(IccSetupData); +#endif; + + return EFI_SUCCESS; +} + +EFI_STATUS +SendClockChangeRequest ( + IN ICC_VOLATILE_SETUP_DATA* IccSetupData, + IN UINT8 ClockID, + IN UINT8 TypeOfChange + ) +/*++ +Routine Description: + Executed by setup calback function + Based on data entered by user, sends clock change requests to ICC OverClocking + Writing to susram or flash requires that old susram and flash contents be invalidated + In case of any problem, messagebox is displayed so user can know what corrective action is required +Arguments: + initial clock divider value +Returns: + validated clock divider value +--*/ +{ + + UINT8 answer = 1; + ICC_LIB_STATUS IccStatus; + ICC_CLOCK_SETTINGS RequestSetting; + BOOLEAN freqConsolidationBypass = TRUE, permanentChange; + + if(TypeOfChange == PERMANENT) + permanentChange = TRUE; + + if(TypeOfChange == TEMPORARY) + permanentChange = FALSE; + + // Prepare Setting + gIccOverClockingProtocol->GetCurrentClockSettings(ClockID, &RequestSetting, &IccStatus); + RequestSetting.Frequency = IccSetupData->Frequency[ClockID] * 10000; + RequestSetting.SscMode = SscNumberToSscMode(IccSetupData->SscMode[ClockID]); + RequestSetting.SscPercent = (UINT8)IccSetupData->SscPercent[ClockID]; + // Only ICC_DMI_PEG_RATIO_5_TO_5 is support in PPT. + RequestSetting.DmiPegRatio = (UINT8)IccSetupData->DmiPegRatio[ClockID]; + + if(TypeOfChange == IMMEDIATE) + { + gIccOverClockingProtocol->SetCurrentClockSettings(ClockID, + RequestSetting, + &IccStatus); + }else + { + gIccOverClockingProtocol->SetBootClockSettings(ClockID, + RequestSetting, + &IccStatus); + } + + if (IccStatus != ICC_LIB_STATUS_SUCCESS) { + if (TypeOfChange == TEMPORARY) { + MessageBox (MSGBOX_TYPE_OKCANCEL, &answer, STRING_TOKEN(STR_ICC_MSGBOX_ONCE_OVERWRITE)); + } else if (TypeOfChange == PERMANENT) { + MessageBox (MSGBOX_TYPE_OKCANCEL, &answer, STRING_TOKEN(STR_ICC_MSGBOX_PERM_OVERWRITE)); + } + if (answer != MSGBOX_YES) { + return ICC_LIB_STATUS_SUCCESS; + } + } + + switch (IccStatus) { + case ICC_LIB_STATUS_DYNAMIC_CHANGE_NOT_ALLOWED: + MessageBox (MSGBOX_TYPE_OKCANCEL, &answer, STRING_TOKEN(STR_ICC_MSGBOX_NO_DYNAMIC), mClockName[ClockID]); + break; + case ICC_LIB_STATUS_REGISTER_IS_LOCKED: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_LOCKED)); + break; + case ICC_LIB_STATUS_FREQ_TOO_HIGH: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_FREQ_HIGH), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_FREQ_TOO_LOW: + MessageBox (MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_FREQ_LOW), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_SSC_TOO_HIGH: + case ICC_LIB_STATUS_SSC_OUT_OF_RANGE: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SSC_HIGH), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_SSC_TOO_LOW: + MessageBox (MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SSC_LOW), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_SSC_MODE_NOT_SUPPORTED: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SSC_MODE), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_FREQ_MUST_HAVE_ZERO_SSC: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SSC_DISABLED), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_SSC_CHANGE_NOT_ALLOWED: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SSC_CONSTANT), mClockName[ClockID] ); + break; + case ICC_LIB_STATUS_MEI_INITIALIZATION_FAILED: + case ICC_LIB_STATUS_MEI_CONNECTION_FAILED: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_HECI)); + break; + case ICC_LIB_STATUS_SUCCESS: + if (TypeOfChange == IMMEDIATE) { + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SUCCESS)); + } else { + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_SUCCESS_NEED_REBOOT)); + } + break; + default: + MessageBox ( MSGBOX_TYPE_OK, NULL, STRING_TOKEN(STR_ICC_MSGBOX_UNKNOWN), IccStatus ); + break; + } + + return IccStatus; +} + +EFI_STATUS +MessageBox ( + IN UINT8 type, + OPTIONAL OUT UINT8* answer, + IN UINT16 StringId, + ... + ) +/*++ +Routine Description: + Wrapper function that displays messagebox. Text for Messagebox is specified with printf-like parameters. + Arguments: + type - messagebox type + answer - pointer to where user's answer will be stored + format, ... - parameters to printf +Returns: +--*/ +{ + static AMI_POST_MANAGER_PROTOCOL* pAmiPostMgr = NULL; + EFI_GUID AmiPostManagerProtocolGuid = AMI_POST_MANAGER_PROTOCOL_GUID; + EFI_STATUS Status; + UINT8 LocalAnswer; + CHAR16* StrBuffer = 0; + CHAR16* LocalBuffer; + UINTN LocalBufferSize; + UINTN StrLen = 0; + va_list ArgList = va_start(ArgList,StringId); + + if (pAmiPostMgr == NULL) { + Status = pBS->LocateProtocol(&AmiPostManagerProtocolGuid, NULL, &pAmiPostMgr); + ASSERT (pAmiPostMgr); + ASSERT_EFI_ERROR (Status); + } + + HiiLibGetString(gHiiHandle, StringId, &StrLen, StrBuffer); + Status = pBS->AllocatePool(EfiBootServicesData, StrLen, &StrBuffer); + ASSERT_EFI_ERROR(Status); + HiiLibGetString(gHiiHandle, StringId, &StrLen, StrBuffer); + + LocalBufferSize = (StrLen+1)*2; + + while (1) { + Status = pBS->AllocatePool(EfiBootServicesData, LocalBufferSize, &LocalBuffer); + ASSERT_EFI_ERROR(Status); + if (LocalBufferSize <= Swprintf_s_va_list(LocalBuffer, LocalBufferSize, StrBuffer, ArgList) ) { + Status = pBS->FreePool(LocalBuffer); + ASSERT_EFI_ERROR(Status); + LocalBufferSize*=2; + } else { + break; + } + } + + va_end(ArgList); + + Status = pAmiPostMgr->DisplayMsgBox(L"Intel ICC", LocalBuffer, type, &LocalAnswer); + pBS->FreePool(StrBuffer); + pBS->FreePool(LocalBuffer); + + ASSERT_EFI_ERROR (Status); + if (answer != NULL) { + *answer = LocalAnswer; + } + return Status; +} + +ICC_LIB_STATUS +EFIAPI +IccInitOverclocking ( + ICC_LIB_VERSION* Version + ) +/*++ +Routine Description: + Initializes ICC OverClocking and asks about initial clock-related data. The data is: + clock parameters from CURRENT record (will be displayed as current and boot-time frequencies) + clock parameters from FLASH record (needed in case we try to write flash record later) + clock ranges - max/min supported frequencies +Arguments: + +Returns: + EFI_SUCCESS - if there were no errors, updates global variables + EFI_DEVICE_ERROR - if there were errors when interfacing ICC OverClocking + +--*/ +{ + UINT8 i; + ICC_LIB_STATUS IccStatus; + + gIccOverClockingProtocol->GetInfo(Version, &i, &IccStatus); + + if (IccStatus != ICC_LIB_STATUS_SUCCESS) { + TRACE ((TRACE_ALWAYS, "(ICC) IccOverClocking failed to start. IccStatus=0x%x, version = %d.%d.%d.%d\n", IccStatus, Version->Major, Version->Minor, Version->Hotfix, Version->Build)); + return IccStatus; + } + + return 0; +} + +VOID +IccGetFrequencies ( + IN UINT8 ClockNumber, + OUT CLOCK_DISPLAY_VALUES* Values + ) +/*++ +Routine Description: + Called by Setup module, feeds it with clock data required to display all clock related information on bios setup screen + Converts data from clock divider value to clock frequency +Arguments: + ClockNumber - data for which clock should be returned +Returns: + values - clock-related data required to display values on ICC setup screen +--*/ +{ + ICC_LIB_STATUS IccStatus; + ICC_CLOCK_RANGES ClockRange; + ICC_CLOCK_SETTINGS Clocksetting; + + gIccOverClockingProtocol->GetClockRanges(ClockNumber, &ClockRange, &IccStatus); + Values->ClockUsage = (UINT16)ClockRange.UsageMask; + Values->ClkFreqMax = ClockRange.FrequencyMax/10000; + Values->ClkFreqMin = ClockRange.FrequencyMin/10000; + Values->SscChangeAllowed = (UINT8)ClockRange.SscChangeAllowed; + Values->SscModeCenterAvailable = (UINT8)ClockRange.SscCenterAllowed; + Values->SscModeUpAvailable = (UINT8)ClockRange.SscUpAllowed; + Values->SscModeDownAvailable = (UINT8)ClockRange.SscDownAllowed; + Values->SscPercentMax = (UINT16)ClockRange.SscPercentMax; + + gIccOverClockingProtocol->GetCurrentClockSettings(ClockNumber, &Clocksetting, &IccStatus); + Values->ClkFreqCurrent = Clocksetting.Frequency/10000; + Values->SscPercentCurrent = (UINT16)Clocksetting.SscPercent; + Values->SscModeCurrent = SscModeToSscNumber(Clocksetting.SscMode); + +} + +UINT32 +SscNumberToSscMode ( + IN UINT8 SscModeNumber + ) +/*++ +Routine Description: + Converts SSC mode description. ICC OverClocking uses 3 bit one-hot format. + For displaying things in BIOS setup, numeric value is more convenient + This function should be called 3 times, once for each bit in ICC OverClocking format. +Arguments: + SscModeNumber - mode number from BIOS setup + Mode - particular mode we're checking for +Returns: + 0 - SSC number does not represent Mode + 1 - SSC number represents Mode +--*/ +{ + switch(SscModeNumber) + { + case SSC_MODE_NONE: + return ICC_SSC_NONE; + + case SSC_MODE_UP: + return ICC_SSC_UP; + + case SSC_MODE_CENTER: + return ICC_SSC_CENTER; + + case SSC_MODE_DOWN: + return ICC_SSC_DOWN; + + default: + TRACE ((TRACE_ALWAYS, "(ICC) Invalid SscModeNumber value \n")); + EFI_DEADLOOP(); + return 0; + } +}; + +UINT8 +SscModeToSscNumber ( + IN UINT8 SscMode + ) +/*++ +Routine Description: + Converts SSC mode description. ICC OverClocking uses 3 bit one-hot format. BIOS setup requires 8bit numeric value. +Arguments: + three bits from ICC OverClocking format +Returns: + SSC mode in BIOS setup format +--*/ +{ + switch(SscMode) + { + case ICC_SSC_NONE: + return SSC_MODE_NONE; + + case ICC_SSC_UP: + return SSC_MODE_UP; + + case ICC_SSC_CENTER: + return SSC_MODE_CENTER; + + case ICC_SSC_DOWN: + return SSC_MODE_DOWN; + + default: + TRACE ((TRACE_ALWAYS, "(ICC) Invalid SscMode value \n")); + EFI_DEADLOOP(); + return 0; + } +} + +VOID +SetIccPersistentData ( + IN UINT8 FlowPhase +) +/*++ +Routine Description: + Sets ClocksModified field of IccPersistentData EFI variable +Arguments: + new value of IccPersistentData +Returns: + none +--*/ +{ + + EFI_GUID IccPersistentDataGuid = ICC_PERSISTENT_DATA_GUID; + ICC_PERSISTENT_DATA IccPersistentData; + + IccPersistentData.ClocksModified = FlowPhase; + + pRS->SetVariable( + L"IccPersistentData", + &IccPersistentDataGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(IccPersistentData), + &IccPersistentData ); +} + +UINT8 +GetIccPersistentData ( + VOID +) +/*++ +Routine Description: + Reads IccPersistentData EFI variable +Arguments: + none +Returns: + value of ClocksModified field +--*/ +{ + EFI_GUID IccPersistentDataGuid = ICC_PERSISTENT_DATA_GUID; + ICC_PERSISTENT_DATA IccPersistentData; + UINTN VariableSize; + EFI_STATUS Status; + VariableSize = sizeof(IccPersistentData); + + Status = pRS->GetVariable( + L"IccPersistentData", + &IccPersistentDataGuid, + NULL, + &VariableSize, + &IccPersistentData ); + if(EFI_ERROR(Status)) + return ICC_SETTINGS_NOT_MODIFIED; + else + return IccPersistentData.ClocksModified; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* |