/** @file Setup functions. @copyright INTEL CONFIDENTIAL Copyright 2010 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SetupPrivate.h" #include #include #include #include "PlatformBoardId.h" #include #include #include #include #include #include #include #define GetSupportedLanguages(HiiHandle) HiiGetSupportedLanguages(HiiHandle) #include #include #if FixedPcdGetBool(PcdITbtEnable) == 1 #include #endif #include #include #include #include #include #include extern UINT8 SetupStrings[]; extern UINT8 MainBin[]; extern UINT8 AdvancedBin[]; extern UINT8 BootBin[]; GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN IsFirstBoot = FALSE; GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN HiiUpdateAtSetupEnter = FALSE; GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_ACCESS SystemAccess; GLOBAL_REMOVE_IF_UNREFERENCED SA_SETUP mSaSetup; GLOBAL_REMOVE_IF_UNREFERENCED ME_SETUP mMeSetup; GLOBAL_REMOVE_IF_UNREFERENCED CPU_SETUP mCpuSetup; GLOBAL_REMOVE_IF_UNREFERENCED PCH_SETUP mPchSetup; GLOBAL_REMOVE_IF_UNREFERENCED SETUP_DATA mSetupData; GLOBAL_REMOVE_IF_UNREFERENCED SETUP_VOLATILE_DATA mSetupVolatileData; GLOBAL_REMOVE_IF_UNREFERENCED EFI_HII_STRING_PROTOCOL *gIfrLibHiiString = NULL; GLOBAL_REMOVE_IF_UNREFERENCED EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase = NULL; GLOBAL_REMOVE_IF_UNREFERENCED EFI_HII_CONFIG_ROUTING_PROTOCOL *mConfigRouting = NULL; GLOBAL_REMOVE_IF_UNREFERENCED ME_PLATFORM_GET_RESET_TYPE_PROTOCOL mMePlatformGetResetType; // // Limited buffer size recommended by RFC4646 (4.3. Length Considerations) // (42 characters plus a NULL terminator) // #define RFC_3066_ENTRY_SIZE (42 + 1) typedef struct { EFI_HII_CONFIG_ACCESS_PROTOCOL Callback; UINT16 Class, SubClass; } SETUP_CALLBACK; typedef struct { EFI_GUID FormSetGuid; UINT8 *IfrPack; UINT16 Class; UINT16 SubClass; EFI_HANDLE DriverHandle; } FORM_SET_INFO; EFI_STATUS EFIAPI Callback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID KeyValue, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ); VOID EFIAPI UpdateCallBack ( CALLBACK_INFO *pCallBackFound ); CHAR8 * EFIAPI HiiLibGetBestLanguage ( IN CHAR8 *SupportedLanguages, IN BOOLEAN Iso639Language, ... ); VOID InstallPlatfromReset ( VOID ); /* Create and update DebugSetupVolatile Data */ extern VOID InitDebugSetupVolatileData ( VOID ); extern EFI_STATUS EFIAPI InitCpuMntrDefault ( IN VOID ); /** This function would update the EC RAM 0x78[bit0] which represent EC CS DEBUG LED function. @param CSEnable Value to indicate the EC CS DEBUG LED enable or not. @retval EFI_SUCCESS Set the value successfully. @retval Others Fail due to EC read or write. **/ EFI_STATUS EFIAPI EcUpdateCsLED ( IN UINT8 CSEnable ); /** Update the Rtd3 setting base on the board type. @param[IN] UINT8 Rtd3Support, @param[IN][OUT] SETUP_DATA *SetupData @retval EFI_SUCCESS Successfully completed updates. @retval Others Fail to update. **/ EFI_STATUS EFIAPI UpdateRtd3Setting ( IN UINT8 Rtd3Support, IN OUT SETUP_DATA *SetupData ); /** This function updates the CPU DMI info. @retval EFI_SUCCESS if the reboot is not required. **/ EFI_STATUS EFIAPI UpdateCpuDmiInfo ( ) { EFI_STATUS Status; UINTN VariableSize; UINT32 VariableAttributes; SETUP_DATA SetupData; CPU_DMI_HOB *CpuDmiInfoHob; UINT8 Index; DEBUG ((EFI_D_VERBOSE, "Cpu Dmi: UpdateCpuDmiInfo\n")); VariableSize = sizeof (SETUP_DATA); Status = gRT->GetVariable ( L"Setup", &gSetupVariableGuid, &VariableAttributes, &VariableSize, &SetupData ); if (EFI_ERROR (Status)) { return Status; } CpuDmiInfoHob = (CPU_DMI_HOB *)GetFirstGuidHob (&gCpuDmiHobGuid); if (CpuDmiInfoHob == NULL) { return EFI_NOT_FOUND; } DEBUG ((EFI_D_INFO, "--------------Before DmiHweq = %x \n",SetupData.DmiHweq)); for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "DmiGen4RtcoCpre = %x \n",SetupData.DmiGen4RtcoCpre[Index])); DEBUG ((EFI_D_INFO, "DmiGen4RtcoCpo = %x \n",SetupData.DmiGen4RtcoCpo[Index])); } if (SetupData.DmiHweq == 0x2) { DEBUG ((EFI_D_INFO, "DmiHweq = %x \n",SetupData.DmiHweq)); for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "CmGen4 = %x \n",CpuDmiInfoHob->CmGen4[Index])); DEBUG ((EFI_D_INFO, "CpGen4 = %x \n",CpuDmiInfoHob->CpGen4[Index])); SetupData.DmiGen4RtcoCpo[Index] = CpuDmiInfoHob->CmGen4[Index]; SetupData.DmiGen4RtcoCpre[Index] = CpuDmiInfoHob->CpGen4[Index]; } Status = gRT->SetVariable ( L"Setup", &gSetupVariableGuid, VariableAttributes, VariableSize, &SetupData ); ASSERT_EFI_ERROR (Status); } DEBUG ((EFI_D_INFO, "--------------After DmiHweq = %x \n",SetupData.DmiHweq)); for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "DmiGen4RtcoCpre = %x \n",SetupData.DmiGen4RtcoCpre[Index])); DEBUG ((EFI_D_INFO, "DmiGen4RtcoCpo = %x \n",SetupData.DmiGen4RtcoCpo[Index])); } return EFI_SUCCESS; } /** This function updates the PCH DMI EQ info. @retval EFI_SUCCESS if the reboot is not required. **/ EFI_STATUS EFIAPI UpdatePchDmiInfo ( ) { EFI_STATUS Status; UINTN VariableSize; UINT32 VariableAttributes; SETUP_DATA SetupData; PCH_DMI_HOB *PchDmiInfoHob; UINT8 Index; DEBUG ((EFI_D_VERBOSE, "Pch Dmi: UpdatePchDmiInfo\n")); VariableSize = sizeof (SETUP_DATA); Status = gRT->GetVariable ( L"Setup", &gSetupVariableGuid, &VariableAttributes, &VariableSize, &SetupData ); if (EFI_ERROR (Status)) { return Status; } DEBUG ((EFI_D_INFO, "--------------PCH Before DmiHweq = %x \n",SetupData.DmiHweq)); PchDmiInfoHob = (PCH_DMI_HOB *)GetFirstGuidHob (&gPchDmiHobGuid); if (PchDmiInfoHob == NULL) { return EFI_NOT_FOUND; } for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpre = %x \n",SetupData.PchDmiGen3RtcoCpre[Index])); DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpo = %x \n",SetupData.PchDmiGen3RtcoCpo[Index])); } if (SetupData.DmiHweq == 0x2) { SetupData.DmiHweq = 0x1; DEBUG ((EFI_D_INFO, "DmiHweq = %x \n",SetupData.DmiHweq)); for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpre = %x \n",PchDmiInfoHob->CmGen3[Index])); DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpo = %x \n",PchDmiInfoHob->CpGen3[Index])); SetupData.PchDmiGen3RtcoCpo[Index] = PchDmiInfoHob->CmGen3[Index]; SetupData.PchDmiGen3RtcoCpre[Index] = PchDmiInfoHob->CpGen3[Index]; } Status = gRT->SetVariable ( L"Setup", &gSetupVariableGuid, VariableAttributes, VariableSize, &SetupData ); ASSERT_EFI_ERROR (Status); } DEBUG ((EFI_D_INFO, "--------------PCH After DmiHweq = %x \n",SetupData.DmiHweq)); for (Index = 0; Index < 8; Index++) { DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpre = %x \n",SetupData.PchDmiGen3RtcoCpre[Index])); DEBUG ((EFI_D_INFO, "PchDmiGen3RtcoCpo = %x \n",SetupData.PchDmiGen3RtcoCpo[Index])); } return EFI_SUCCESS; } SETUP_CALLBACK MainCallbackProtocol = {{NULL,NULL,Callback},MAIN_FORM_SET_CLASS,0}; SETUP_CALLBACK AdvancedCallbackProtocol = {{NULL,NULL,Callback},ADVANCED_FORM_SET_CLASS,0}; SETUP_CALLBACK BootCallbackProtocol = {{NULL,NULL,Callback},BOOT_FORM_SET_CLASS,0}; CALLBACK_INFO SetupCallBack[] = { // Last field in every structure will be filled by the Setup { NULL, &MainCallbackProtocol.Callback, MAIN_FORM_SET_CLASS, 0, 0}, { NULL, &AdvancedCallbackProtocol.Callback, ADVANCED_FORM_SET_CLASS, 0, 0}, { NULL, &BootCallbackProtocol.Callback, BOOT_FORM_SET_CLASS, 0, 0}, }; FORM_SET_INFO SetupFormSets[] = { {MAIN_FORM_SET_GUID, MainBin, MAIN_FORM_SET_CLASS, 0, NULL}, {ADVANCED_FORM_SET_GUID, AdvancedBin, ADVANCED_FORM_SET_CLASS, 0, NULL}, {BOOT_FORM_SET_GUID, BootBin, BOOT_FORM_SET_CLASS, 0, NULL}, }; BOOLEAN FormsetVisible[] = { TRUE, //Main formset is always displayed SHOW_ADVANCED_FORMSET, //Advanced formset TRUE, //Boot formset is always displayed; the Boot Manager part is diabled because of the conflict with EDKII BDS' one TRUE }; #define NUMBER_OF_FORMSETS (sizeof(SetupCallBack) / sizeof(CALLBACK_INFO)) #pragma pack(1) typedef struct { VENDOR_DEVICE_PATH VendorDevicePath; EFI_DEVICE_PATH_PROTOCOL End; } HII_VENDOR_DEVICE_PATH; #pragma pack() HII_VENDOR_DEVICE_PATH mHiiVendorDevicePathTemplate = { { { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { (UINT8) (sizeof (VENDOR_DEVICE_PATH)), (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) } }, ADVANCED_FORM_SET_GUID }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { (UINT8) (END_DEVICE_PATH_LENGTH), (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) } } }; EFI_STATUS LocateHiiStringProtocol ( OUT EFI_HII_STRING_PROTOCOL **HiiStrProtocol ) { EFI_STATUS Status; Status = EFI_SUCCESS; if (NULL == (*HiiStrProtocol)) { Status = gBS->LocateProtocol ( &gEfiHiiStringProtocolGuid, NULL, (VOID **) HiiStrProtocol ); } return Status; } EFI_STATUS LocateHiiDataBaseProtocol ( OUT EFI_HII_DATABASE_PROTOCOL **HiiDataBaseProtocol ) { EFI_STATUS Status; Status = EFI_SUCCESS; if (NULL == (*HiiDataBaseProtocol)) { Status = gBS->LocateProtocol ( &gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) HiiDataBaseProtocol ); } return Status; } VOID EFIAPI InitString ( EFI_HII_HANDLE HiiHandle, EFI_STRING_ID StrRef, CHAR16 *sFormat, ... ) { CHAR16 StringBuffer[1024]; VA_LIST ArgList; CHAR8 PlatformLanguage[RFC_3066_ENTRY_SIZE]; CHAR8 *SupportedLanguages; CHAR8 *BestLanguage; UINTN Size; EFI_STATUS Status; // // Get current language setting // Size = sizeof (PlatformLanguage); Status = gRT->GetVariable ( L"PlatformLang", &gEfiGlobalVariableGuid, NULL, &Size, PlatformLanguage ); if (EFI_ERROR (Status)) { AsciiStrCpyS (PlatformLanguage, sizeof (PlatformLanguage) / sizeof (CHAR8), (CHAR8 *) "en-US"); } SupportedLanguages = GetSupportedLanguages (HiiHandle); if (SupportedLanguages == NULL) { // // No supported language. // return; } // // Get the best matching language from SupportedLanguages // BestLanguage = HiiLibGetBestLanguage ( SupportedLanguages, FALSE, // RFC 4646 mode PlatformLanguage, // Highest priority SupportedLanguages, // Lowest priority NULL ); // // Construct string value. // VA_START(ArgList,sFormat); UnicodeVSPrint (StringBuffer,sizeof(StringBuffer),sFormat,ArgList); VA_END(ArgList); // // Set string // if (NULL == gIfrLibHiiString) { Status = gBS->LocateProtocol ( &gEfiHiiStringProtocolGuid, NULL, (VOID **) &gIfrLibHiiString ); if (EFI_ERROR (Status)) { return; } } gIfrLibHiiString->SetString ( gIfrLibHiiString, HiiHandle, StrRef, BestLanguage, StringBuffer, NULL ); if (SupportedLanguages != NULL) { FreePool (SupportedLanguages); } if (BestLanguage != NULL) { FreePool (BestLanguage); } } EFI_STATUS GetFspInformation ( IN OUT FSP_INFO_HOB **FspInfo ) { EFI_HOB_GUID_TYPE *GuidHob; GuidHob = NULL; GuidHob = GetFirstGuidHob (&gFspInfoGuid); ASSERT (GuidHob != NULL); if (GuidHob == NULL) { return EFI_NOT_FOUND; } *FspInfo = (FSP_INFO_HOB *) GET_GUID_HOB_DATA (GuidHob); return EFI_SUCCESS; } VOID GetFspReleaseTime ( IN OUT FSP_INFO_HOB *FspInfo, CHAR16 FspReleaseDate[17] ) { FspReleaseDate[0] = FspInfo->TimeStamp[8]; FspReleaseDate[1] = FspInfo->TimeStamp[9]; FspReleaseDate[2] = (CHAR16) ((UINT8) (':')); FspReleaseDate[3] = FspInfo->TimeStamp[10]; FspReleaseDate[4] = FspInfo->TimeStamp[11]; FspReleaseDate[5] = ' '; FspReleaseDate[6] = FspInfo->TimeStamp[4]; FspReleaseDate[7] = FspInfo->TimeStamp[5]; FspReleaseDate[8] = (CHAR16) ((UINT8) ('/')); FspReleaseDate[9] = FspInfo->TimeStamp[6]; FspReleaseDate[10] = FspInfo->TimeStamp[7]; FspReleaseDate[11] = (CHAR16) ((UINT8) ('/')); FspReleaseDate[12] = FspInfo->TimeStamp[0]; FspReleaseDate[13] = FspInfo->TimeStamp[1]; FspReleaseDate[14] = FspInfo->TimeStamp[2]; FspReleaseDate[15] = FspInfo->TimeStamp[3]; FspReleaseDate[16] = (CHAR16) ((UINT8) ('\0')); } EFI_STATUS InitMain(EFI_HII_HANDLE HiiHandle, UINT16 Class) { EFI_STATUS Status; CHAR16 Version[100]; //Assuming that strings are < 100 UCHAR CHAR16 ReleaseDate[100]; //Assuming that strings are < 100 UCHAR CHAR16 ReleaseTime[100]; //Assuming that strings are < 100 UCHAR CHAR16 FspReleaseTime[17]; FSP_INFO_HOB *FspInfo; if (Class != MAIN_FORM_SET_CLASS) { return EFI_SUCCESS; } ///////////////// BIOS ///////////////////////////////////// if (gST->FirmwareVendor) InitString( HiiHandle,STRING_TOKEN(STR_BIOS_VENDOR_VALUE), L"%s", gST->FirmwareVendor ); else InitString( HiiHandle,STRING_TOKEN(STR_BIOS_VENDOR_VALUE), L"%s", L"Intel " ); InitString( HiiHandle,STRING_TOKEN(STR_BIOS_SILICON_VERSION_VALUE), L"%02x.%02x.%02x.%02x", PcdGet8 (PcdSiliconInitVersionMajor), PcdGet8 (PcdSiliconInitVersionMinor), PcdGet8 (PcdSiliconInitVersionRevision), PcdGet8 (PcdSiliconInitVersionBuild) ); Status = GetBiosVersionDateTime (Version, ReleaseDate, ReleaseTime); if (!EFI_ERROR (Status)) { InitString( HiiHandle,STRING_TOKEN(STR_BIOS_VERSION_VALUE), L"%s", Version ); InitString( HiiHandle,STRING_TOKEN(STR_BIOS_DATE_VALUE), L"%s %s", ReleaseTime, ReleaseDate ); } // // Update FSP Information. // Status = GetFspInformation (&FspInfo); if (! EFI_ERROR (Status)) { InitString ( HiiHandle,STRING_TOKEN (STR_FSP_VERSION_VALUE), L"%02x.%02x.%02x.%02x", FspInfo->SiliconInitVersionMajor, FspInfo->FspVersionMinor, FspInfo->FspVersionRevision, FspInfo->FspVersionBuild ); InitString ( HiiHandle,STRING_TOKEN (STR_RC_VERSION_VALUE), L"%02x.%02x.%02x.%02x", FspInfo->SiliconInitVersionMajor, FspInfo->SiliconInitVersionMinor, FspInfo->SiliconInitVersionRevision, FspInfo->SiliconInitVersionBuild ); GetFspReleaseTime (FspInfo,FspReleaseTime); InitString ( HiiHandle,STRING_TOKEN (STR_BUILD_DATE_VALUE), L"%s", FspReleaseTime ); if(PcdGet8 (PcdFspModeSelection) == 0) { InitString ( HiiHandle,STRING_TOKEN (STR_FSP_MODE_VALUE), L"Dispatch Mode" ); } else { InitString ( HiiHandle,STRING_TOKEN (STR_FSP_MODE_VALUE), L"API Mode" ); } } else { DEBUG ((DEBUG_ERROR, "Get FSP Information Failed : %r\n", Status)); } return EFI_SUCCESS; } typedef EFI_STATUS (INIT_FUNCTION)(EFI_HII_HANDLE HiiHandle, UINT16 Class); extern INIT_FUNCTION INIT_LIST EndOfInitList; #if FixedPcdGetBool(PcdNct677FPresent) == 1 extern INIT_FUNCTION NctUpdateHwmonString; #endif INIT_FUNCTION* InitList[] = { InitMain, INIT_LIST #if FixedPcdGetBool(PcdNct677FPresent) == 1 NctUpdateHwmonString, #endif NULL }; VOID InitParts(EFI_HII_HANDLE HiiHandle, UINT16 Class) { UINTN i; for(i=0; InitList[i]; i++) InitList[i](HiiHandle,Class); } VOID EFIAPI InitStrings ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; UINTN Index; VOID *Protocol; if (!HiiUpdateAtSetupEnter) { Status = gBS->LocateProtocol( &gBdsAllDriversConnectedProtocolGuid, NULL, &Protocol ); if (EFI_ERROR (Status)) { return ; } } else { Status = gBS->LocateProtocol( &gSetupEnterGuid, NULL, &Protocol ); if (EFI_ERROR (Status)) { return ; } } for (Index = 0; Index < NUMBER_OF_FORMSETS; Index ++) { if (SetupCallBack[Index].HiiHandle == NULL) { continue; } InitParts(SetupCallBack[Index].HiiHandle, SetupCallBack[Index].Class); } gBS->CloseEvent (Event); } VOID InstallHiiResources ( VOID ) { CALLBACK_INFO *pCallBackFound; UINTN Index; EFI_HII_HANDLE HiiHandle; EFI_HANDLE DriverHandle; EFI_STATUS Status; HII_VENDOR_DEVICE_PATH *mHiiVendorDevicePath; pCallBackFound = NULL; for (Index = 0; Index < NUMBER_OF_FORMSETS; Index++) { pCallBackFound = &SetupCallBack[Index]; UpdateCallBack (pCallBackFound); DEBUG ((DEBUG_INFO, " InstallHiiResources: UpdateCallBack was done.\n")); DriverHandle = NULL; mHiiVendorDevicePath = NULL; mHiiVendorDevicePath = AllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH), &mHiiVendorDevicePathTemplate); ASSERT (mHiiVendorDevicePath != NULL); if (mHiiVendorDevicePath == NULL) { return; } mHiiVendorDevicePath->VendorDevicePath.Guid = SetupFormSets[Index].FormSetGuid; // // Install Config Access protocol // Status = gBS->InstallMultipleProtocolInterfaces ( &DriverHandle, &gEfiDevicePathProtocolGuid, mHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, pCallBackFound->pFormCallback, NULL ); ASSERT_EFI_ERROR (Status); // // Publish our HII data // HiiHandle = HiiAddPackages ( &SetupFormSets[Index].FormSetGuid, DriverHandle, SetupStrings, SetupFormSets[Index].IfrPack, NULL ); ASSERT (HiiHandle != NULL); DEBUG ((DEBUG_INFO, " InstallHiiResources: HiiPackages was added.\n")); if (pCallBackFound) { pCallBackFound->HiiHandle = HiiHandle; } pCallBackFound = NULL; } } VOID EFIAPI BackupSetupDataAndCheckForPassword ( IN EFI_EVENT Event, IN VOID *Context ) { UINTN VariableSize; SA_SETUP SaSetup; ME_SETUP MeSetup; CPU_SETUP CpuSetup; PCH_SETUP PchSetup; SI_SETUP SiSetup; SETUP_DATA SetupData; EFI_STATUS Status; VOID *Protocol; Status = gBS->LocateProtocol ( &gSetupEnterGuid, NULL, &Protocol ); if (EFI_ERROR (Status)) { return ; } // // Signal check for password // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) ); VariableSize = sizeof (SETUP_DATA); Status = gRT->GetVariable ( L"Setup", &gSetupVariableGuid, NULL, &VariableSize, &SetupData ); ASSERT_EFI_ERROR (Status); Status = gRT->SetVariable ( L"ColdReset", &gSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &SetupData ); ASSERT_EFI_ERROR (Status); VariableSize = sizeof (SA_SETUP); Status = gRT->GetVariable ( L"SaSetup", &gSaSetupVariableGuid, NULL, &VariableSize, &SaSetup ); ASSERT_EFI_ERROR (Status); Status = gRT->SetVariable ( L"SaColdReset", &gSaSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &SaSetup ); ASSERT_EFI_ERROR (Status); VariableSize = sizeof (ME_SETUP); Status = gRT->GetVariable ( L"MeSetup", &gMeSetupVariableGuid, NULL, &VariableSize, &MeSetup ); ASSERT_EFI_ERROR (Status); Status = gRT->SetVariable ( L"MeColdReset", &gMeSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &MeSetup ); ASSERT_EFI_ERROR (Status); VariableSize = sizeof (CPU_SETUP); Status = gRT->GetVariable ( L"CpuSetup", &gCpuSetupVariableGuid, NULL, &VariableSize, &CpuSetup ); ASSERT_EFI_ERROR (Status); Status = gRT->SetVariable ( L"CpuColdReset", &gCpuSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &CpuSetup ); ASSERT_EFI_ERROR (Status); VariableSize = sizeof (PCH_SETUP); Status = gRT->GetVariable ( L"PchSetup", &gPchSetupVariableGuid, NULL, &VariableSize, &PchSetup ); ASSERT_EFI_ERROR (Status); Status = gRT->SetVariable ( L"PchColdReset", &gPchSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &PchSetup ); ASSERT_EFI_ERROR (Status); VariableSize = sizeof (SI_SETUP); Status = gRT->GetVariable( L"SiSetup", &gSiSetupVariableGuid, NULL, &VariableSize, &SiSetup ); ASSERT_EFI_ERROR(Status); Status = gRT->SetVariable( L"SiColdReset", &gSiSetupVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, VariableSize, &SiSetup ); ASSERT_EFI_ERROR(Status); gBS->CloseEvent (Event); } VOID SetupCallback ( IN EFI_EVENT Event, IN VOID *Context ) { static BOOLEAN ResourcesLoaded = FALSE; UINT32 Index; EFI_STATUS Status; UINTN VariableSize; SETUP_DATA SetupData; VOID *SetupRegistration; VOID *BdsDriverConnectRegistration; EFI_BOOT_MODE BootMode; if (!ResourcesLoaded) { ResourcesLoaded = TRUE; Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mConfigRouting ); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, " SetupCallback: EfiHiiConfigRoutingProtocolGuid was found.\n")); InitCpuMntrDefault(); InstallHiiResources(); DEBUG ((DEBUG_INFO, " SetupCallback: HiiResources was installed.\n")); VariableSize = sizeof(SETUP_DATA); Status = gRT->GetVariable ( L"Setup", &gSetupVariableGuid, NULL, &VariableSize, &SetupData ); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, " SetupCallback: SetupVar was found.\n")); if (!EFI_ERROR(Status) && (SetupData.FastBoot)) { BootMode = GetBootModeHob(); DEBUG ((DEBUG_INFO, " BootModeHob was found.\n")); if ((SetupData.SkipHIIUpdate) && ((BootMode == BOOT_WITH_MINIMAL_CONFIGURATION) || (BootMode == BOOT_ON_S4_RESUME) || (BootMode == BOOT_ASSUMING_NO_CONFIGURATION_CHANGES))) { HiiUpdateAtSetupEnter = TRUE; } } if (!HiiUpdateAtSetupEnter) { EfiCreateProtocolNotifyEvent( &gBdsAllDriversConnectedProtocolGuid, TPL_CALLBACK, InitStrings, NULL, &BdsDriverConnectRegistration ); } else { EfiCreateProtocolNotifyEvent( &gSetupEnterGuid, TPL_CALLBACK, InitStrings, NULL, &SetupRegistration ); } EfiCreateProtocolNotifyEvent( &gSetupEnterGuid, TPL_CALLBACK, BackupSetupDataAndCheckForPassword, NULL, &SetupRegistration ); } for (Index = 0; Index < NUMBER_OF_FORMSETS; Index++) { if (!FormsetVisible[Index] && SetupCallBack[Index].HiiHandle != NULL) { gIfrLibHiiDatabase->RemovePackageList (gIfrLibHiiDatabase, SetupCallBack[Index].HiiHandle); SetupCallBack[Index].HiiHandle = NULL; } } DEBUG ((DEBUG_INFO, " SetupCallback was done.\n")); } EFI_STATUS EFIAPI SetupEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { #if ( FORCE_USER_TO_SETUP_ON_FIRST_BOOT || FORCE_USER_TO_SETUP_IF_BOOT_WITH_DEFAULT ) static UINT32 BootFlow = BOOT_FLOW_CONDITION_FIRST_BOOT; #endif UINTN Size; EFI_STATUS Status; UINT32 RegEAX, RegEBX, RegECX, RegEDX; SA_SETUP *pSaSetup; PCH_SETUP *pPchSetup; CPU_SETUP_VOLATILE_DATA CpuSetupVolData; CPU_SETUP_VOLATILE_DATA *pCpuSetupVolData; UINT8 InitSetupFlag; OS_PROFILE OsProfileData; UINTN OsProfileSize; UINT32 OsProfileAttr; UINT32 VariableAttributes; UINT32 SetupVolVarAttr; UINT32 CpuSetupVolVarAttr; UINT32 TbtSetupVolatileDataAttr; TBT_SETUP_VOLATILE_DATA TbtSetupVolatileVar; TBT_SETUP_VOLATILE_DATA *pTbtSetupVolatileVar; UINT32 InitSetupVolVarAttr; EFI_HANDLE DriverHandle; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; UINT64 HbPciD0F0RegBase; UINT8 Index; CPU_INFO_PROTOCOL *CpuInfo; CPU_INFO *BigCoreInfo; BOOLEAN SetupItbtDataModified; #if FixedPcdGetBool(PcdITbtEnable) == 1 TCSS_DATA_HOB *TcssHob; UINT8 TcssCpuXhciPortSupportMap; #endif VMD_INFO_HOB *VmdInfoHob; BOOLEAN SetupDTBTDpMuxDataModified; #if FixedPcdGetBool(PcdITbtEnable) == 1 TcssHob = NULL; TcssCpuXhciPortSupportMap = PcdGet8 (PcdCpuXhciPortSupportMap); // Get Board Capability Map set Cpu Xhci Port. #endif VmdInfoHob = NULL; CpuInfo = NULL; ZeroMem (&mSetupData, sizeof(mSetupData)); ZeroMem (&mSetupVolatileData, sizeof(mSetupVolatileData)); ZeroMem (&SystemAccess, sizeof(SystemAccess)); ZeroMem (&TbtSetupVolatileVar, sizeof(TbtSetupVolatileVar)); // Init gIfrLibHiiString Status = LocateHiiStringProtocol (&gIfrLibHiiString); if (EFI_ERROR (Status)) { return Status; } // Init gIfrLibHiiDatabase Status = LocateHiiDataBaseProtocol (&gIfrLibHiiDatabase); if (EFI_ERROR (Status)) { return Status; } // Locate CPU Info Protocol. Status = gBS->LocateProtocol (&gCpuInfoProtocolGuid, NULL, (VOID **) &CpuInfo); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Located CpuInfo Protocol Status = %r\n", Status)); return Status; } // // Get SetupVolatileData Variable // Size = sizeof (SETUP_VOLATILE_DATA); Status = gRT->GetVariable ( L"SetupVolatileData", &gSetupVariableGuid, &SetupVolVarAttr, &Size, &mSetupVolatileData ); ASSERT_EFI_ERROR (Status); CpuSetupVolVarAttr = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; Size = sizeof (CPU_SETUP_VOLATILE_DATA); Status = gRT->GetVariable ( L"CpuSetupVolatileData", &gCpuSetupVariableGuid, &CpuSetupVolVarAttr, &Size, &CpuSetupVolData ); if (Status == EFI_NOT_FOUND) { Status = gRT->SetVariable ( L"CpuSetupVolatileData", &gCpuSetupVariableGuid, CpuSetupVolVarAttr, sizeof (CpuSetupVolData), &CpuSetupVolData ); ASSERT_EFI_ERROR (Status); } TbtSetupVolatileDataAttr = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; Size = sizeof(TBT_SETUP_VOLATILE_DATA); Status = gRT->GetVariable( L"TbtSetupVolatileData", &gSetupVariableGuid, &TbtSetupVolatileDataAttr, &Size, &TbtSetupVolatileVar ); if (Status == EFI_NOT_FOUND) { Status = gRT->SetVariable( L"TbtSetupVolatileData", &gSetupVariableGuid, TbtSetupVolatileDataAttr, sizeof(TbtSetupVolatileVar), &TbtSetupVolatileVar ); ASSERT_EFI_ERROR(Status); } InitDebugSetupVolatileData (); // // Get VTd status // HbPciD0F0RegBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, 0); mSetupVolatileData.VTdAvailable = (PciSegmentRead32 (HbPciD0F0RegBase + 0xe4) & BIT23) ? 0 : 1; // // Set SetupVolatileData Variable // Status = gRT->SetVariable ( L"SetupVolatileData", &gSetupVariableGuid, SetupVolVarAttr, sizeof (mSetupVolatileData), &mSetupVolatileData ); ASSERT_EFI_ERROR (Status); // // Check whether first boot. // InitSetupVolVarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; Size = sizeof (InitSetupFlag); Status = gRT->GetVariable (L"InitSetupVariable", &gSetupVariableGuid, &InitSetupVolVarAttr, &Size, &InitSetupFlag); if (Status == EFI_NOT_FOUND) { IsFirstBoot = TRUE; InitSetupFlag = 1; gRT->SetVariable ( L"InitSetupVariable", &gSetupVariableGuid, InitSetupVolVarAttr, sizeof (InitSetupFlag), &InitSetupFlag ); } // // Check Setup Variable. // Setup Variable should always exist, because post build will create the default setup variable. // Size = sizeof (mSetupData); Status = gRT->GetVariable(L"Setup", &gSetupVariableGuid, &VariableAttributes, &Size, &mSetupData); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { // // Update EC CS debug light value // Status = EcUpdateCsLED (mSetupData.CSDebugLightEC); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "Fail to initialize the EC CS Debug light 0x78[bit0], Status: %r\n", Status)); } // // Update Rtd3 setting // Status = UpdateRtd3Setting (mSetupData.Rtd3Support, &mSetupData); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "Fail to update the RTD3 setting: %r!\n", Status)); } else { Status = gRT->SetVariable (L"Setup", &gSetupVariableGuid, VariableAttributes, Size, &mSetupData); ASSERT_EFI_ERROR (Status); } // // DTBT Dp Mux // SetupDTBTDpMuxDataModified = FALSE; if (PcdGet32 (PcdDpMuxGpio)) { if (mSetupData.DTbtDpInSupport != 1){ mSetupData.DTbtDpInSupport = 1; SetupDTBTDpMuxDataModified = TRUE; DEBUG ((EFI_D_INFO, "Setup dTBT DpMux Data is Modified\n")); } } SetupItbtDataModified = FALSE; #if FixedPcdGetBool(PcdITbtEnable) == 1 // // Get status of each iTBT PCIe RP is enabled or not. // TcssHob = (TCSS_DATA_HOB *)GetFirstGuidHob (&gTcssHobGuid); if (TcssHob != NULL) { for (Index = 0; Index < MAX_ITBT_PCIE_PORT; Index++) { // // Check each iTBT PCIe RP is enabled or not. // if (mSetupData.ITbtPcieRootPortSupported[Index] != TcssHob->TcssData.ItbtPcieRpEn[Index]) { mSetupData.ITbtPcieRootPortSupported[Index] = TcssHob->TcssData.ItbtPcieRpEn[Index]; SetupItbtDataModified = TRUE; } } } #endif if (SetupItbtDataModified || SetupDTBTDpMuxDataModified) { gRT->SetVariable ( L"Setup", &gSetupVariableGuid, VariableAttributes, sizeof (mSetupData), &mSetupData ); DEBUG ((EFI_D_INFO, "Save the data back to mSetupData\n")); } } else { DEBUG ((EFI_D_INFO, "mSetupData is NULL\n")); } Size = sizeof (mMeSetup); Status = gRT->GetVariable(L"MeSetup", &gMeSetupVariableGuid, &VariableAttributes, &Size, &mMeSetup); ASSERT_EFI_ERROR (Status); Size = sizeof (mCpuSetup); Status = gRT->GetVariable(L"CpuSetup", &gCpuSetupVariableGuid, &VariableAttributes, &Size, &mCpuSetup); ASSERT_EFI_ERROR (Status); // // Update CpuSetup info according the CPU info. // BigCoreInfo = &(CpuInfo->CpuInfo[BIG_CORE]); mCpuSetup.CoreVfPointCount = BigCoreInfo->CoreVfPointCount; mCpuSetup.RingVfPointCount = BigCoreInfo->RingVfPointCount; gRT->SetVariable ( L"CpuSetup", &gCpuSetupVariableGuid, VariableAttributes, sizeof (mCpuSetup), &mCpuSetup ); Size = sizeof (mPchSetup); Status = gRT->GetVariable(L"PchSetup", &gPchSetupVariableGuid, &VariableAttributes, &Size, &mPchSetup); ASSERT_EFI_ERROR (Status); // // Check whether exist the "SystemAccess" info, if not exist, initialize it to Zero. // Size = sizeof (SystemAccess); Status = gRT->GetVariable(L"SystemAccess", &gSystemAccessGuid, NULL, &Size, &SystemAccess); // // Need to lock SystemAccess variable to prevent changing by some malicious software // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); if (!EFI_ERROR (Status)) { Status = VariableLockProtocol->RequestToLock ( VariableLockProtocol, L"SystemAccess", &gSystemAccessGuid ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "System Access Variable unable to be locked: Status = %r\n", Status)); } } DEBUG ((DEBUG_INFO, " SetupEntry: Setup variables were found\n")); // // Update SaSetup variables // Size = sizeof (mSaSetup); Status = gRT->GetVariable(L"SaSetup", &gSaSetupVariableGuid, &VariableAttributes, &Size, &mSaSetup); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { pSaSetup = (SA_SETUP *) &mSaSetup; pSaSetup->GtDid = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (0, 0, 2, 0, 2)); if (IsAdlPch () ) { UpdateCpuDmiInfo (); UpdatePchDmiInfo (); } // VMD: Check if VMD is supported if (IsVmdSupported() == TRUE) { // VMD is supported pSaSetup->VmdSupported = 1; // // Update VMD Volatile variables // VmdInfoHob = (VMD_INFO_HOB *) GetFirstGuidHob (&gVmdInfoHobGuid); if (VmdInfoHob != NULL) { for (Index=0; Index < VMD_MAX_DEVICES; ++Index) { pSaSetup->VmdPortPresent[Index] = VmdInfoHob->VmdPortInfo.PortInfo[Index].DeviceDetected; pSaSetup->VmdPort[Index] = VmdInfoHob->VmdPortInfo.PortInfo[Index].PortEn; // Also update the device and func pSaSetup->VmdPortDev[Index] = VmdInfoHob->VmdPortInfo.PortInfo[Index].RpDev; pSaSetup->VmdPortFunc[Index] = VmdInfoHob->VmdPortInfo.PortInfo[Index].RpFunc; } DEBUG ((EFI_D_INFO, "Vmd: Printing updated setup info\n")); for (Index=0; Index < VMD_MAX_DEVICES; ++Index) { if (pSaSetup->VmdPortPresent[Index]) { //print only if device is discovered DEBUG ((EFI_D_INFO, "Vmd For Rp %d VmdPortPresent is %d VmdPort-En is %d VmdPortDev is %d VmdPortFunc is %d\n", Index, pSaSetup->VmdPortPresent[Index], pSaSetup->VmdPort[Index], pSaSetup->VmdPortDev[Index], pSaSetup->VmdPortFunc[Index] )); } } } else { DEBUG ((EFI_D_INFO, "Vmd Info Hob not found\n")); } } for (Index = 0; Index < GetMaxCpuPciePortNum(); Index++) { pSaSetup->PcieRootPortMultiVcSupported[Index] = (UINT8) IsRpMultiVc(Index); } gRT->SetVariable ( L"SaSetup", &gSaSetupVariableGuid, VariableAttributes, sizeof (mSaSetup), &mSaSetup ); } // // Update CPU Volatile variables // AsmCpuid(1, &RegEAX, &RegEBX, &RegECX, &RegEDX); pPchSetup = (PCH_SETUP *) &mPchSetup; pCpuSetupVolData = (CPU_SETUP_VOLATILE_DATA *) &CpuSetupVolData; pTbtSetupVolatileVar = (TBT_SETUP_VOLATILE_DATA *)&TbtSetupVolatileVar; pPchSetup->RootPortDid = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (0, 0, 0, 0, 2)); // @todo: fix RP DID. pCpuSetupVolData->CpuFamilyModel = (UINT16) RegEAX & 0x3FF0; // @todo to use the CPU lib instead of reading the registers directly pCpuSetupVolData->CpuExtendedFamilyModel = (UINT16) ((RegEAX >> 16) & 0x0FFF); pCpuSetupVolData->CpuStepping = (UINT8) RegEAX & 0xF; pCpuSetupVolData->EdramSupported = IsEdramEnable (); pCpuSetupVolData->TccSupported = IsTccSku(); pTbtSetupVolatileVar->ITbtRootPortsNumber = PcdGet8 (PcdITbtRootPortNumber); pTbtSetupVolatileVar->DTbtContollersNumber = PcdGet8 (PcdDTbtControllerNumber); #if FixedPcdGetBool(PcdITbtEnable) == 1 for (Index = 0; Index < MAX_TCSS_USB3_PORTS; Index++) { pTbtSetupVolatileVar->TcssCpuXhciPortSupport[Index] = ((TcssCpuXhciPortSupportMap >> Index) & BIT0); } #endif gRT->SetVariable ( L"PchSetup", &gPchSetupVariableGuid, VariableAttributes, sizeof (mPchSetup), &mPchSetup ); gRT->SetVariable ( L"CpuSetupVolatileData", &gCpuSetupVariableGuid, CpuSetupVolVarAttr, sizeof (CpuSetupVolData), &CpuSetupVolData ); Status = gRT->SetVariable( L"TbtSetupVolatileData", &gSetupVariableGuid, TbtSetupVolatileDataAttr, sizeof(TbtSetupVolatileVar), &TbtSetupVolatileVar ); DEBUG ((DEBUG_INFO, " SetupEntry: Setup variables were updated\n")); // // Always install HII resources // SetupCallback(NULL, NULL); DEBUG ((DEBUG_INFO, " SetupEntry: SetupCallback was done.\n")); Status = gIfrLibHiiDatabase->GetPackageListHandle (gIfrLibHiiDatabase, SetupCallBack[1].HiiHandle, &DriverHandle); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, " SetupEntry: Not found driver handle for SetupCallBack[1]\n")); return EFI_INVALID_PARAMETER; } #if FORCE_USER_TO_SETUP_ON_FIRST_BOOT if (IsFirstBoot) { Status = gRT->GetVariable(L"BootFlow", &gBootFlow, NULL, &Size, NULL); if (Status == EFI_NOT_FOUND) { ClearDiagnosticStatus (); return gRT->SetVariable ( L"BootFlow", &gBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow ); } } #endif DEBUG ((DEBUG_INFO, " SetupEntry: HII resources was installed\n")); // // Register platform reset callback // InstallPlatfromReset (); DEBUG ((DEBUG_INFO, " SetupEntry: PlatformReset was installed\n")); #if FORCE_USER_TO_SETUP_IF_BOOT_WITH_DEFAULT if (IsChecksumBad() || (BOOT_WITH_DEFAULT_SETTINGS == GetBootModeHob())) { DEBUG ((DEBUG_INFO, "Secondary NvRam bad, force user to enter setup.\n")); ClearDiagnosticStatus (); if (!IsChecksumBad()) { // // Setup configuration is changed to default, system reset is required // gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); } return gRT->SetVariable ( L"BootFlow", &gBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow ); } #endif // OS Profile related update: // Need to check this in every boot OsProfileSize = sizeof (OS_PROFILE); Status = gRT->GetVariable( L"OsProfile", &gOsProfileGuid, &OsProfileAttr, &OsProfileSize, &OsProfileData ); DEBUG((DEBUG_INFO, "\n In Setup Entry, GetVariable OsProfile Status = %r, attributes = %X \n", Status, OsProfileAttr)); if (EFI_ERROR(Status)) { if (Status == EFI_NOT_FOUND) { OsProfileData.OsProfile = OsNone; OsProfileData.PrevOs = OsNone; OsProfileAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; OsProfileSize = sizeof (OS_PROFILE); Status = gRT->SetVariable ( L"OsProfile", &gOsProfileGuid, OsProfileAttr, OsProfileSize, &OsProfileData ); DEBUG(( DEBUG_INFO, "SetVariable OsProfile Status = %r \n", Status )); } } else if ( OsProfileData.PrevOs != OsProfileData.OsProfile ) { OsProfileData.PrevOs = OsProfileData.OsProfile; Status = gRT->SetVariable ( L"OsProfile", &gOsProfileGuid, OsProfileAttr, OsProfileSize, &OsProfileData ); DEBUG(( DEBUG_INFO, "SetVariable OsProfile Status = %r \n", Status )); } return EFI_SUCCESS; } typedef VOID (UPDATE_ITEM)(EFI_HII_HANDLE HiiHandle, UINT16 Class, UINT16 SubClass, UINT16 Key); typedef struct { UINT16 Class, SubClass, Key; UPDATE_ITEM *UpdateItem; } SETUP_ITEM_CALLBACK; #define ITEM_CALLBACK(Class,Subclass,Key,Callback) Callback extern UPDATE_ITEM SETUP_ITEM_CALLBACK_LIST EndOfList; #undef ITEM_CALLBACK #define ITEM_CALLBACK(Class,Subclass,Key,Callback) {Class,Subclass,Key,&Callback} SETUP_ITEM_CALLBACK SetupItemCallback[] = { SETUP_ITEM_CALLBACK_LIST {0,0,0,NULL} }; #undef ITEM_CALLBACK typedef EFI_STATUS (UPDATE_ITEM_EX)(CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, EFI_BROWSER_ACTION Action, EFI_QUESTION_ID KeyValue, UINT8 Type, EFI_IFR_TYPE_VALUE *Value, EFI_BROWSER_ACTION_REQUEST *ActionRequest ); typedef struct { UINT16 Class, SubClass, Key; UPDATE_ITEM_EX *UpdateItemEx; } SETUP_ITEM_CALLBACK_EX; #define ITEM_CALLBACK_EX(Class,Subclass,Key,Callback) Callback extern UPDATE_ITEM_EX SETUP_ITEM_CALLBACK_LIST_EX EndOfListEx; #undef ITEM_CALLBACK_EX #define ITEM_CALLBACK_EX(Class,Subclass,Key,Callback) {Class,Subclass,Key,&Callback} SETUP_ITEM_CALLBACK_EX SetupItemCallbackEx[] = { SETUP_ITEM_CALLBACK_LIST_EX {0,0,0,NULL} }; #undef ITEM_CALLBACK_EX EFI_STATUS EFIAPI Callback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID KeyValue, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { UINTN Index; SETUP_CALLBACK *pCallback = (SETUP_CALLBACK*)This; EFI_STATUS Status = EFI_UNSUPPORTED; SETUP_ITEM_CALLBACK *pItemCallback = SetupItemCallback; SETUP_ITEM_CALLBACK_EX *pItemCallbackEx = SetupItemCallbackEx; for (Index = 0; Index < NUMBER_OF_FORMSETS; Index++) { if (SetupCallBack[Index].Class == pCallback->Class && SetupCallBack[Index].SubClass == pCallback->SubClass) { while (pItemCallback->UpdateItem) { if (pItemCallback->Class == pCallback->Class && pItemCallback->SubClass == pCallback->SubClass && pItemCallback->Key == KeyValue) { pItemCallback->UpdateItem ( SetupCallBack[Index].HiiHandle, pItemCallback->Class, pItemCallback->SubClass, KeyValue ); } pItemCallback++; } while (pItemCallbackEx->UpdateItemEx) { if (pItemCallbackEx->Class == pCallback->Class && pItemCallbackEx->SubClass == pCallback->SubClass && pItemCallbackEx->Key == KeyValue) { Status = pItemCallbackEx->UpdateItemEx(This, Action, KeyValue, Type, Value, ActionRequest); } pItemCallbackEx++; } } } return Status; }