/** @file Provide functions for sync WMI update HDD Password ;****************************************************************************** ;* Copyright (c) 2018, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "WmiSetupUnderOsDxe.h" BOOLEAN mHddPasswordExist = FALSE; // // Hexadecimal to Unicode char // STATIC UINT16 HexToChar16[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; /** Get WMI HDD password variable. @param HddPasswordExist A pointer to the HDD password exist. @param HddPasswordTable A pointer to the HDD password table. @param PasswordType A pointer to the password type. @param HddPasswordNumber A pointer to the HDD password number. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS GetWmiHddPasswordVariable ( OUT BOOLEAN *HddPasswordExist, OUT HDD_PASSWORD_TABLE *HddPasswordTable, OUT UINT8 *PasswordType, OUT UINT8 *HddPasswordNumber ) { EFI_STATUS Status; UINTN NumberLength; CHAR16 *VariableName; UINTN BufferSize; UINTN Index; // // Initialization // Status = EFI_SUCCESS; VariableName = NULL; BufferSize = 0; *HddPasswordNumber = 0; // // Set WMI HDD password variable name // L05_GET_NUMBER_LENGTH (L05_MAX_HDD_PASSWORD_NUMBER, NumberLength); BufferSize = StrSize (L05_WMI_HDD_PASWORD_DATA_VARIABLE_NAME) + (NumberLength * sizeof (CHAR16)); VariableName = AllocateZeroPool (BufferSize); for (Index = 1; Index <= L05_MAX_HDD_PASSWORD_NUMBER; Index++) { UnicodeSPrint (VariableName, BufferSize, L"%s%d", L05_WMI_HDD_PASWORD_DATA_VARIABLE_NAME, Index); // // Get WMI HDD password table // BufferSize = sizeof (HDD_PASSWORD_TABLE) * WmiHddPasswordMaxSection; Status = gRT->GetVariable ( VariableName, &gL05WmiSetupUnderOsSetupVariableGuid, NULL, &BufferSize, HddPasswordTable ); if (!EFI_ERROR (Status) && (HddPasswordTable[WmiHddPasswordCurrentSection].PasswordType == HddPasswordTable[WmiHddPasswordNewSection].PasswordType)) { *HddPasswordExist = TRUE; *PasswordType = HddPasswordTable[WmiHddPasswordCurrentSection].PasswordType; *HddPasswordNumber = (UINT8) Index; } // // Clean HDD password variable // gRT->SetVariable ( VariableName, &gL05WmiSetupUnderOsSetupVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL ); } if (VariableName != NULL) { FreePool (VariableName); } if (*HddPasswordExist == TRUE) { Status = EFI_SUCCESS; } return Status; } /** Refer from ResetAllSecuirtyStatus() at HddPasswordDialog.c WMI reset all secuirty status. @param HddPasswordService A pointer to the HDD password service. @param NumOfHdd Number of HDD. @param HddInfoArray A pointer to the HDD info array. @param DisabledNumOfHdd A pointer to the disable number of HDD. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiL05ResetAllSecuirtyStatus ( EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService, UINTN NumOfHdd, HDD_PASSWORD_HDD_INFO *HddInfoArray, UINTN *DisabledNumOfHdd ) { EFI_STATUS Status; UINTN Index; UINT8 SkipCounter; if (HddPasswordService == NULL || HddInfoArray == NULL) { return EFI_INVALID_PARAMETER; } SkipCounter = 0; for (Index = 0; Index < NumOfHdd; Index++) { if (((HddInfoArray[Index].HddSecurityStatus & HDD_LOCKED_BIT) != HDD_LOCKED_BIT) && ((HddInfoArray[Index].HddSecurityStatus & HDD_ENABLE_BIT) == HDD_ENABLE_BIT)) { Status = HddPasswordService->ResetSecurityStatus ( HddPasswordService, &(HddInfoArray[Index]) ); } if (((HddInfoArray[Index].HddSecurityStatus & HDD_LOCKED_BIT) != HDD_LOCKED_BIT) || ((HddInfoArray[Index].HddSecurityStatus & HDD_FROZEN_BIT) == HDD_FROZEN_BIT)) { SkipCounter++; } if (SkipCounter == NumOfHdd) { // // No any HDD having to be unlock // return EFI_SUCCESS; } } *DisabledNumOfHdd = SkipCounter; return EFI_NOT_READY; } /** Refer from SetSecurityStatus() at Password.c WMI unlock HDD password. @param HddPasswordService A pointer to the HDD password service. @param NumOfHdd Number of HDD. @param HddInfo A pointer to the HDD info. @param PasswordType HDD Master or User password. @param PasswordStr A pointer to the password string. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiL05UnlockHddPassword ( EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService, UINTN NumOfHdd, HDD_PASSWORD_HDD_INFO *HddInfo, UINT8 PasswordType, CHAR16 *PasswordStr ) { EFI_STATUS Status; UINT8 PasswordToHdd[HDD_PASSWORD_MAX_NUMBER + 1]; UINTN PasswordToHddLength; UINTN Index; Status = EFI_SUCCESS; #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE for (Index = 0; Index < NumOfHdd; Index++) { #else if (NumOfHdd == 0) { return Status; } Index = NumOfHdd - 1; #endif //_Start_L05_HDD_PASSWORD_ENABLE_ // // eMMC does not support all functions of HDD password. // if (HddInfo[Index].ControllerMode == eMMC_MODE) { #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE continue; #else return Status; #endif } //_End_L05_HDD_PASSWORD_ENABLE_ ZeroMem (PasswordToHdd, (HDD_PASSWORD_MAX_NUMBER + 1)); Status = HddPasswordService->PasswordStringProcess ( HddPasswordService, PasswordType, PasswordStr, StrLen (PasswordStr), (VOID **) &PasswordToHdd, &PasswordToHddLength ); if (PasswordToHddLength == 0) { return Status; } Status = HddPasswordService->UnlockHddPassword ( HddPasswordService, &HddInfo[Index], PasswordType, PasswordToHdd, PasswordToHddLength ); #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE } #endif return Status; } /** Refer from SetSecurityStatus() at Password.c WMI change HDD password. @param HddPasswordService A pointer to the HDD password service. @param NumOfHdd Number of HDD. @param HddInfo A pointer to the HDD info. @param PasswordType HDD Master or User password. @param PasswordStr A pointer to the password string. @param HddPasswordTable A pointer to the HDD password table. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiL05ChangeHddPassword ( EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService, UINTN NumOfHdd, HDD_PASSWORD_HDD_INFO *HddInfo, UINT8 PasswordType, CHAR16 *PasswordStr, HDD_PASSWORD_TABLE *HddPasswordTable ) { EFI_STATUS Status; UINT8 PasswordToHdd[HDD_PASSWORD_MAX_NUMBER + 1]; UINTN PasswordToHddLength; UINTN Index; Status = EFI_SUCCESS; #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE for (Index = 0; Index < NumOfHdd; Index++) { #else if (NumOfHdd == 0) { return Status; } Index = NumOfHdd - 1; #endif //_Start_L05_HDD_PASSWORD_ENABLE_ // // eMMC does not support all functions of HDD password. // if (HddInfo[Index].ControllerMode == eMMC_MODE) { #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE continue; #else return Status; #endif } //_End_L05_HDD_PASSWORD_ENABLE_ ZeroMem (PasswordToHdd, (HDD_PASSWORD_MAX_NUMBER + 1)); Status = HddPasswordService->PasswordStringProcess ( HddPasswordService, PasswordType, PasswordStr, StrLen (PasswordStr), (VOID **) &PasswordToHdd, &PasswordToHddLength ); if (PasswordToHddLength == 0) { return Status; } Status = HddPasswordService->SetHddPassword ( HddPasswordService, &HddInfo[Index], PasswordType, PasswordToHdd, PasswordToHddLength ); if ((Status == EFI_SUCCESS) && (PasswordType == USER_PSW)) { CopyMem ( HddPasswordTable[Index].PasswordStr, PasswordStr, StrSize (PasswordStr) ); HddPasswordTable[Index].PasswordType = USER_PSW; HddPasswordTable[Index].ControllerNumber = HddInfo[Index].ControllerNumber; HddPasswordTable[Index].PortNumber = HddInfo[Index].PortNumber; HddPasswordTable[Index].PortMulNumber = HddInfo[Index].PortMulNumber; } #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE } #endif return Status; } /** Refer from SetSecurityStatus() at Password.c WMI disable HDD password. @param HddPasswordService A pointer to the HDD password service. @param NumOfHdd Number of HDD. @param HddInfo A pointer to the HDD info. @param PasswordType HDD Master or User password. @param PasswordStr A pointer to the password string. @param HddPasswordTable A pointer to the HDD password table. @param DisabledNumOfHdd A pointer to the disable number of HDD. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiL05DisableHddPassword ( EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService, UINTN NumOfHdd, HDD_PASSWORD_HDD_INFO *HddInfo, UINT8 PasswordType, CHAR16 *PasswordStr, HDD_PASSWORD_TABLE *HddPasswordTable, UINTN *DisabledNumOfHdd ) { EFI_STATUS Status; UINT8 PasswordToHdd[HDD_PASSWORD_MAX_NUMBER + 1]; UINTN PasswordToHddLength; UINTN Index; Status = EFI_SUCCESS; #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE for (Index = 0; Index < NumOfHdd; Index++) { #else if (NumOfHdd == 0) { return Status; } Index = NumOfHdd - 1; #endif //_Start_L05_HDD_PASSWORD_ENABLE_ // // eMMC does not support all functions of HDD password. // if (HddInfo[Index].ControllerMode == eMMC_MODE) { #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE continue; #else return Status; #endif } //_End_L05_HDD_PASSWORD_ENABLE_ ZeroMem (PasswordToHdd, (HDD_PASSWORD_MAX_NUMBER + 1)); Status = HddPasswordService->PasswordStringProcess ( HddPasswordService, PasswordType, PasswordStr, StrLen (PasswordStr), (VOID **) &PasswordToHdd, &PasswordToHddLength ); if (PasswordToHddLength == 0) { return Status; } Status = HddPasswordService->DisableHddPassword ( HddPasswordService, &HddInfo[Index], PasswordType, PasswordToHdd, PasswordToHddLength ); if (Status == EFI_SUCCESS) { (*DisabledNumOfHdd)++; } #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE } #endif return Status; } /** Copy from HddPasswordDialog.c Replace the original ResetSystem function to prevent USB keyboard reset command. @param ResetType Unused. @param ResetStatus Unused. @param DataSize Unused. @param ResetData Unused. @retval None **/ VOID ResetSystemHook ( IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus, IN UINTN DataSize, IN CHAR16 *ResetData OPTIONAL ) { } /** Show incorrect password message and system stop. @param PasswordType HDD Master or User password. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS ShowIncorrectPasswordMessageAndSystemStop ( UINT8 PasswordType ) { EFI_STATUS Status; H2O_DIALOG_PROTOCOL *H2oDialogProtocol; CHAR16 TempStr[100]; UINTN BufferSize; CHAR16 *ErrorMsg1 = L"WMI HDD Password Error"; CHAR16 *ErrorMsg2 = L"Enter incorrect %s current password"; CHAR16 *ErrorMsg3 = L"Please power-off your system and reboot it again"; CHAR16 *ErrorMsg4 = L"System Halted"; // // Initialization // BufferSize = 0; ZeroMem (TempStr, sizeof (TempStr)); Status = gBS->LocateProtocol ( &gH2ODialogProtocolGuid, NULL, (VOID **) &H2oDialogProtocol ); if (Status != EFI_SUCCESS) { return Status; } // // Set incorrect current password is "Master" or "User" // UnicodeSPrint (TempStr, sizeof (TempStr), ErrorMsg2, (PasswordType == MASTER_PSW ? L"Master" : L"User")); ErrorMsg2 = TempStr; DisableQuietBoot (); gST->ConOut->EnableCursor (gST->ConOut, FALSE); gST->ConOut->ClearScreen (gST->ConOut); // // Replace the original ResetSystem function to prevent USB keyboard reset command // gRT->ResetSystem = ResetSystemHook; PcdSetBoolS (PcdL05PasswordErrorFlag, TRUE); H2oDialogProtocol->CreateMsgPopUp ( 50, 4, ErrorMsg1, ErrorMsg2, ErrorMsg3, ErrorMsg4 ); gBS->RaiseTPL (TPL_HIGH_LEVEL); CpuDeadLoop (); return EFI_SUCCESS; } #ifdef L05_NATURAL_FILE_GUARD_ENABLE /** Disable Natural File Guard function. @retval EFI_SUCCESS The operation completed successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS DisableNaturalFileGuard ( VOID ) { EFI_STATUS Status; UINTN BufferSize; SYSTEM_CONFIGURATION SetupNvData; BufferSize = sizeof (SYSTEM_CONFIGURATION); Status = gRT->GetVariable ( L"Setup", &gSystemConfigurationGuid, NULL, &BufferSize, &SetupNvData ); if (EFI_ERROR (Status)) { return Status; } // // [Natural File Guard Design Guide V1.01] // When Master HDP is disabled, auto disabled & grayout. // SetupNvData.L05NaturalFileGuard = 0; // 0:Disable, 1:Enable Status = gRT->SetVariable ( L"Setup", &gSystemConfigurationGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (SYSTEM_CONFIGURATION), &SetupNvData ); return Status; } #endif /** Refer from SetSecurityStatus() at Password.c WMI HDD password sync. @param None @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiL05HddPasswordSync ( VOID ) { EFI_STATUS Status; HDD_PASSWORD_TABLE WmiHddPasswordTable[WmiHddPasswordMaxSection]; UINT8 PasswordType; UINT8 HddPasswordNumber; UINTN BufferSize; EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService; HDD_PASSWORD_HDD_INFO *HddInfoArray; UINTN NumOfHdd; HDD_PASSWORD_TABLE *HddPasswordTable; UINTN HddPasswordTableSize; UINTN DisabledNumOfHdd; // // Initialization // Status = EFI_SUCCESS; BufferSize = 0; HddPasswordService = NULL; HddInfoArray = NULL; NumOfHdd = 0; HddPasswordTable = NULL; HddPasswordTableSize = 0; DisabledNumOfHdd = 0; ZeroMem (WmiHddPasswordTable, sizeof (WmiHddPasswordTable)); // // Get WMI HDD password variable // Status = GetWmiHddPasswordVariable ( &mHddPasswordExist, WmiHddPasswordTable, &PasswordType, &HddPasswordNumber ); if (!mHddPasswordExist) { // // There is no need to update L05 hdd password // return EFI_SUCCESS; } Status = gBS->LocateProtocol ( &gEfiHddPasswordServiceProtocolGuid, NULL, &HddPasswordService ); if (EFI_ERROR (Status)) { return Status; } // // Get HDD info // Status = HddPasswordService->GetHddInfo ( HddPasswordService, &HddInfoArray, &NumOfHdd ); if (EFI_ERROR (Status)) { return Status; } if (NumOfHdd == 0) { return EFI_SUCCESS; } // // Reset all secuirty status // Status = WmiL05ResetAllSecuirtyStatus ( HddPasswordService, NumOfHdd, HddInfoArray, &DisabledNumOfHdd ); if (Status != EFI_NOT_READY) { return Status; } // // Get save HDD passwird Variable // Status = CommonGetVariableDataAndSize ( SAVE_HDD_PASSWORD_VARIABLE_NAME, &gSaveHddPasswordGuid, &HddPasswordTableSize, (VOID **) &HddPasswordTable ); if (EFI_ERROR (Status)) { // // Create new table // HddPasswordTable = NULL; HddPasswordTableSize = sizeof (HDD_PASSWORD_TABLE) * (NumOfHdd + 1); HddPasswordTable = AllocateZeroPool (HddPasswordTableSize); if (HddPasswordTable == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Unlock HDD password // Status = WmiL05UnlockHddPassword ( HddPasswordService, #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE NumOfHdd, #else HddPasswordNumber, #endif HddInfoArray, PasswordType, WmiHddPasswordTable[WmiHddPasswordCurrentSection].PasswordStr ); if (EFI_ERROR (Status)) { // // When unlock HDD fail will show incorrect password message and system stop // ShowIncorrectPasswordMessageAndSystemStop (PasswordType); return Status; } // // Change HDD password // if (StrLen (WmiHddPasswordTable[WmiHddPasswordNewSection].PasswordStr) != 0) { Status = WmiL05ChangeHddPassword ( HddPasswordService, #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE NumOfHdd, #else HddPasswordNumber, #endif HddInfoArray, PasswordType, WmiHddPasswordTable[WmiHddPasswordNewSection].PasswordStr, HddPasswordTable ); } // // Disable User & Master Password // if ((PasswordType == MASTER_PSW) && (StrLen (WmiHddPasswordTable[WmiHddPasswordNewSection].PasswordStr) == 0)) { Status = WmiL05DisableHddPassword ( HddPasswordService, #ifndef L05_NOTEBOOK_PASSWORD_V1_1_ENABLE NumOfHdd, #else HddPasswordNumber, #endif HddInfoArray, PasswordType, WmiHddPasswordTable[WmiHddPasswordCurrentSection].PasswordStr, HddPasswordTable, &DisabledNumOfHdd ); #ifdef L05_NATURAL_FILE_GUARD_ENABLE // // [Natural File Guard Design Guide V1.01] // When Master HDP is disabled, auto disabled & grayout. // Status = DisableNaturalFileGuard (); #endif } if (DisabledNumOfHdd == NumOfHdd) { Status = CommonSetVariable ( SAVE_HDD_PASSWORD_VARIABLE_NAME, &gSaveHddPasswordGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 0, NULL ); #ifdef L05_NOTEBOOK_PASSWORD_ENABLE #if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_ALDERLAKE) Status = L05DeleteEncodeHddPasswordTable (); #endif #endif } else { Status = CommonSetVariable ( SAVE_HDD_PASSWORD_VARIABLE_NAME, &gSaveHddPasswordGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, HddPasswordTableSize, HddPasswordTable ); #ifdef L05_NOTEBOOK_PASSWORD_ENABLE #if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_ALDERLAKE) Status = L05SetEncodeHddPasswordTable (HddPasswordService, HddPasswordTable, (UINT32) NumOfHdd); #endif #endif // // Reset all storage device security status to locked if security enabled // Status = WmiL05ResetAllSecuirtyStatus ( HddPasswordService, NumOfHdd, HddInfoArray, &DisabledNumOfHdd ); } if (HddPasswordTable != NULL) { FreePool (HddPasswordTable); } if (HddInfoArray != NULL) { FreePool (HddInfoArray); } gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); return Status; } /** Notify function for WMI L05 HDD pasword. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context. @retval None **/ VOID EFIAPI HddPasswordDialogProtocolNotify ( IN EFI_EVENT Event, IN VOID *Context ) { // // WMI HDD pasword synchronization // WmiL05HddPasswordSync (); // // There is no necessary to trigger this notify function again in any case, // and this notify function will not useing Registration of RegisterProtocolNotify. // gBS->CloseEvent (Event); return; } /** WMI HDD password sync init. @param None @retval None **/ EFI_STATUS WmiL05HddPasswordSyncInit ( VOID ) { EFI_STATUS Status; VOID *Interface; VOID *Registration; EFI_EVENT Event; // // HDD password need after gEfiHddPasswordDialogProtocolGuid be install // Status = gBS->LocateProtocol ( &gEfiHddPasswordDialogProtocolGuid, NULL, &Interface ); if (!EFI_ERROR (Status)) { Status = WmiL05HddPasswordSync (); } else { // // Create notify event for Hdd Password Dialog Protocol // Registration = NULL; Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL , TPL_CALLBACK, HddPasswordDialogProtocolNotify, NULL, &Event ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->RegisterProtocolNotify ( &gEfiHddPasswordDialogProtocolGuid, Event, &Registration ); } return Status; }