1534 lines
40 KiB
C
1534 lines
40 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* 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 "WmiSetupUnderOsSmm.h"
|
|
|
|
BOOLEAN mAdminPasswordExist = FALSE;
|
|
BOOLEAN mUserPasswordExist = FALSE;
|
|
BOOLEAN mHddPasswordExist = FALSE;
|
|
BOOLEAN mPasswordChange = FALSE;
|
|
UINTN mPasswordErrorCount = 0;
|
|
WMI_PASSWORD_DATA_MAP mPasswordCheckData;
|
|
|
|
//
|
|
// 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'
|
|
};
|
|
|
|
//
|
|
// Refer from EFI_KEYBOARD_SCANCODE_LIST at SetupMenuService.c
|
|
//
|
|
// WMI keyboard scancode list
|
|
//
|
|
WMI_KEYBOARD_SCANCODE_LIST mScanCodeMap[] = {
|
|
{'a', 0x1E},
|
|
{'b', 0x30},
|
|
{'c', 0x2E},
|
|
{'d', 0x20},
|
|
{'e', 0x12},
|
|
{'f', 0x21},
|
|
{'g', 0x22},
|
|
{'h', 0x23},
|
|
{'i', 0x17},
|
|
{'j', 0x24},
|
|
{'k', 0x25},
|
|
{'l', 0x26},
|
|
{'m', 0x32},
|
|
{'n', 0x31},
|
|
{'o', 0x18},
|
|
{'p', 0x19},
|
|
{'q', 0x10},
|
|
{'r', 0x13},
|
|
{'s', 0x1F},
|
|
{'t', 0x14},
|
|
{'u', 0x16},
|
|
{'v', 0x2F},
|
|
{'w', 0x11},
|
|
{'x', 0x2D},
|
|
{'y', 0x15},
|
|
{'z', 0x2C},
|
|
{'1', 0x02},
|
|
{'2', 0x03},
|
|
{'3', 0x04},
|
|
{'4', 0x05},
|
|
{'5', 0x06},
|
|
{'6', 0x07},
|
|
{'7', 0x08},
|
|
{'8', 0x09},
|
|
{'9', 0x0A},
|
|
{'0', 0x0B},
|
|
#ifdef L05_SMB_BIOS_ENABLE
|
|
{' ', 0x39},
|
|
#endif
|
|
};
|
|
|
|
//
|
|
// WMI password type map
|
|
//
|
|
WMI_PASSWORD_TYPE_MAP mWmiPasswordTypeMap[] = {
|
|
// PasswordType, PasswordTypeStr
|
|
{WmiSystemAdminType, WMI_BIOS_PASSWORD_ADMIN_TYPE },
|
|
{WmiSystemUserType, WMI_BIOS_PASSWORD_USER_TYPE },
|
|
{WmiHddUserType, WMI_BIOS_PASSWORD_HDD_USER_TYPE },
|
|
{WmiHddMasterType, WMI_BIOS_PASSWORD_HDD_MASTER_TYPE},
|
|
};
|
|
|
|
//
|
|
// WMI password encoding map
|
|
//
|
|
WMI_PASSWORD_ENCODING_MAP mWmiPasswordEncodingMap[] = {
|
|
// PasswordEncoding, PasswordEncodingStr
|
|
{WmiAsciiEncoding, WMI_BIOS_PASSWORD_ASCII_ENCODING },
|
|
{WmiScancodeEncoding, WMI_BIOS_PASSWORD_SCANCODE_ENCODING},
|
|
};
|
|
|
|
//
|
|
// WMI password language map
|
|
//
|
|
WMI_PASSWORD_LANGUAGE_MAP mWmiPasswordLanguageMap[] = {
|
|
// PasswordLanguage, PasswordLanguageStr
|
|
{WmiUsLanguage, WMI_BIOS_PASSWORD_US_LANGUAGE},
|
|
{WmiFrLanguage, WMI_BIOS_PASSWORD_FR_LANGUAGE},
|
|
{WmiGrLanguage, WMI_BIOS_PASSWORD_GR_LANGUAGE},
|
|
};
|
|
|
|
//
|
|
// Map List Count
|
|
//
|
|
UINT16 mWmiPasswordTypeMapListCount = sizeof (mWmiPasswordTypeMap) / sizeof (WMI_PASSWORD_TYPE_MAP);
|
|
UINT16 mWmiPasswordEncodingMapListCount = sizeof (mWmiPasswordEncodingMap) / sizeof (WMI_PASSWORD_ENCODING_MAP);
|
|
UINT16 mWmiPasswordLanguageMapListCount = sizeof (mWmiPasswordLanguageMap) / sizeof (WMI_PASSWORD_LANGUAGE_MAP);
|
|
|
|
/**
|
|
Refer from ConvertUnicodeCharToKeyboardScancode() at SetupMenuService.c
|
|
|
|
Convert Ascii Char to Keyboard Scancode(Normal).
|
|
|
|
@param KeyData Point to Key Data(Ascii).
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_NOT_FOUND The Ascii Char can't map to Keyboard Scancode.
|
|
**/
|
|
EFI_STATUS
|
|
ConvertAsciiCharToKeyboardScancode (
|
|
OUT CHAR8 *KeyData
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
for (Index = 0; Index < (sizeof (mScanCodeMap) / sizeof (WMI_KEYBOARD_SCANCODE_LIST)); Index++) {
|
|
#ifdef L05_SMB_BIOS_ENABLE
|
|
//
|
|
// [Lenovo SMB BIOS Special Requirements V1.1]
|
|
// 2.1 BIOS Password Characters
|
|
// Supported characters
|
|
// - Alphabet (case insensitive)
|
|
//
|
|
if (*KeyData >= L'A' && *KeyData <= L'Z') {
|
|
*KeyData += 0x20;
|
|
}
|
|
#endif
|
|
if (*KeyData == mScanCodeMap[Index].AsciiChar) {
|
|
*KeyData = mScanCodeMap[Index].KeyboardScanCode;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
This function uses to check password type.
|
|
|
|
@param PasswordTypeStr A pointer to the password type string.
|
|
@param PasswordType A pointer to the system admin password or user password.
|
|
|
|
@retval TRUE Password type is valid.
|
|
@retval FALSE Password type is not valid.
|
|
**/
|
|
BOOLEAN
|
|
CheckPasswordTypeIsValid (
|
|
IN CHAR8 *PasswordTypeStr,
|
|
OUT WMI_PASSWORD_TYPE *PasswordType
|
|
)
|
|
{
|
|
BOOLEAN IsValid;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
IsValid = FALSE;
|
|
|
|
//
|
|
// Compare password type string to get password type
|
|
//
|
|
for (Index = 0; Index < mWmiPasswordTypeMapListCount; Index++) {
|
|
if (AsciiStrnCmp (PasswordTypeStr, mWmiPasswordTypeMap[Index].PasswordTypeStr, AsciiStrLen (mWmiPasswordTypeMap[Index].PasswordTypeStr)) == 0) {
|
|
*PasswordType = mWmiPasswordTypeMap[Index].PasswordType;
|
|
IsValid = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return IsValid;
|
|
}
|
|
|
|
/**
|
|
Refer from IsValidKeyData() at SetupMenuService.c
|
|
|
|
Check password is valid.
|
|
|
|
@param Password A pointer to the Password buffer.
|
|
@param PasswordType Type of password.
|
|
|
|
@retval TRUE Password is valid.
|
|
@retval FALSE Password is not valid.
|
|
**/
|
|
BOOLEAN
|
|
CheckPasswordIsValid (
|
|
IN CHAR8 **Password,
|
|
IN WMI_PASSWORD_TYPE PasswordType
|
|
)
|
|
{
|
|
BOOLEAN IsValid;
|
|
EFI_STATUS Status;
|
|
UINTN MaxPasswordLen;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
IsValid = TRUE;
|
|
MaxPasswordLen = 0;
|
|
|
|
//
|
|
// Step 1. Check password length
|
|
//
|
|
switch (PasswordType) {
|
|
|
|
case WmiSystemAdminType:
|
|
case WmiSystemUserType:
|
|
MaxPasswordLen = L05_WMI_PASSWORD_MAX_LENGTH;
|
|
break;
|
|
|
|
case WmiHddUserType:
|
|
case WmiHddMasterType:
|
|
MaxPasswordLen = HDD_PASSWORD_MAX_NUMBER;
|
|
break;
|
|
}
|
|
|
|
if (AsciiStrLen (*Password) > MaxPasswordLen) {
|
|
IsValid = FALSE;
|
|
}
|
|
|
|
//
|
|
// Step 2. Only 'a'~'z', '0'~'9' are valid key data for password Character
|
|
//
|
|
for (Index = 0; Index < AsciiStrLen (*Password); Index++) {
|
|
if (((*Password)[Index] < L'a' || (*Password)[Index] > L'z')
|
|
&& ((*Password)[Index] < L'0' || (*Password)[Index] > L'9')
|
|
#ifdef L05_SMB_BIOS_ENABLE
|
|
//
|
|
// [Lenovo SMB BIOS Special Requirements V1.1]
|
|
// 2.1 BIOS Password Characters
|
|
// Supported characters
|
|
// - Alphabet (case insensitive)
|
|
// - Space ' '
|
|
//
|
|
&& ((*Password)[Index] < L'A' || (*Password)[Index] > L'Z')
|
|
&& ((*Password)[Index] != L' ')
|
|
#endif
|
|
) {
|
|
|
|
IsValid = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Step 3. Convert ASCII char to keyboard scancode
|
|
//
|
|
Status = ConvertAsciiCharToKeyboardScancode (&((*Password)[Index]));
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
IsValid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return IsValid;
|
|
}
|
|
|
|
/**
|
|
This function uses to check password encoding.
|
|
|
|
@param PasswordEncodingStr A pointer to the password encoding string.
|
|
@param PasswordEncoding A pointer to the password encoding.
|
|
|
|
@retval TRUE Password encoding is valid.
|
|
@retval FALSE Password encoding is not valid.
|
|
**/
|
|
BOOLEAN
|
|
CheckPasswordEncodingIsValid (
|
|
IN CHAR8 *PasswordEncodingStr,
|
|
OUT WMI_PASSWORD_TYPE *PasswordEncoding
|
|
)
|
|
{
|
|
BOOLEAN IsValid;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
IsValid = FALSE;
|
|
|
|
//
|
|
// Compare password encoding string to get password encoding
|
|
//
|
|
for (Index = 0; Index < mWmiPasswordEncodingMapListCount; Index++) {
|
|
if (AsciiStrCmp (PasswordEncodingStr, mWmiPasswordEncodingMap[Index].PasswordEncodingStr) == 0) {
|
|
*PasswordEncoding = mWmiPasswordEncodingMap[Index].PasswordEncoding;
|
|
IsValid = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return IsValid;
|
|
}
|
|
|
|
/**
|
|
This function uses to check password language.
|
|
|
|
@param PasswordLanguageStr A pointer to the password language string.
|
|
@param PasswordLanguage A pointer to the password language.
|
|
|
|
@retval TRUE Password language is valid.
|
|
@retval FALSE Password language is not valid.
|
|
**/
|
|
BOOLEAN
|
|
CheckPasswordLanguageIsValid (
|
|
IN CHAR8 *PasswordLanguageStr,
|
|
OUT WMI_PASSWORD_LANGUAGE *PasswordLanguage
|
|
)
|
|
{
|
|
BOOLEAN IsValid;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
IsValid = FALSE;
|
|
|
|
//
|
|
// Compare password language string to get password language
|
|
//
|
|
for (Index = 0; Index < mWmiPasswordLanguageMapListCount; Index++) {
|
|
if (AsciiStrCmp (PasswordLanguageStr, mWmiPasswordLanguageMap[Index].PasswordLanguageStr) == 0) {
|
|
*PasswordLanguage = mWmiPasswordLanguageMap[Index].PasswordLanguage;
|
|
IsValid = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return IsValid;
|
|
}
|
|
|
|
/**
|
|
Analyze WMI set password input buffer.
|
|
|
|
@param PasswordType Assign a pointer to the password type.
|
|
@param CurrentPassword Assign a pointer to the current password.
|
|
@param NewPassword Assign a pointer to the new password.
|
|
@param PasswordEncodingStr Assign a pointer to the password encoding string.
|
|
@param PasswordLanguageStr Assign a pointer to the password keyboard language string.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
AnalyzeWmiSetPasswordInputBuffer (
|
|
OUT CHAR8 **PasswordType,
|
|
OUT CHAR8 **CurrentPassword,
|
|
OUT CHAR8 **NewPassword,
|
|
OUT CHAR8 **PasswordEncodingStr,
|
|
OUT CHAR8 **PasswordLanguageStr
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BufferOffset;
|
|
UINTN TempBufferOffset;
|
|
UINTN SectionCount;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_INVALID_PARAMETER;
|
|
BufferOffset = 0;
|
|
|
|
//
|
|
// Part section
|
|
//
|
|
SectionCount = 0;
|
|
TempBufferOffset = 0;
|
|
|
|
for (BufferOffset = 0; BufferOffset < mL05GlobalNVSArea->L05WmiBufferLen; BufferOffset++) {
|
|
|
|
if ((mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] != ',')
|
|
&&(mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] != ';')) {
|
|
continue;
|
|
}
|
|
|
|
mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] = 0;
|
|
|
|
switch (SectionCount) {
|
|
|
|
case SetBiosPasswordType:
|
|
*PasswordType = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset];
|
|
break;
|
|
|
|
case SetBiosPasswordCurrentPassword:
|
|
*CurrentPassword = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset];
|
|
break;
|
|
|
|
case SetBiosPasswordNewPassword:
|
|
*NewPassword = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset];
|
|
break;
|
|
|
|
case SetBiosPasswordEncoding:
|
|
*PasswordEncodingStr = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset];
|
|
break;
|
|
|
|
case SetBiosPasswordLanguage:
|
|
*PasswordLanguageStr = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset];
|
|
break;
|
|
}
|
|
|
|
TempBufferOffset = BufferOffset;
|
|
TempBufferOffset++;
|
|
SectionCount++;
|
|
}
|
|
|
|
//
|
|
// Check section number is valid
|
|
//
|
|
if (SectionCount == SetBiosPasswordMaxSection) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check WMI password format.
|
|
|
|
@param PasswordTypeStr A pointer to the password type string.
|
|
@param PasswordType A pointer to the password type.
|
|
@param PasswordEncodingStr A pointer to the password encoding string.
|
|
@param PasswordEncoding A pointer to the password encoding.
|
|
@param PasswordLanguageStr A pointer to the password keyboard language string.
|
|
@param PasswordLanguage A pointer to the password keyboard language.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval EFI_INVALID_PARAMETER Input invalid password format.
|
|
@retval EFI_ACCESS_DENIED Input invalid password rule.
|
|
**/
|
|
EFI_STATUS
|
|
CheckWmiPasswordFormat (
|
|
IN CHAR8 *PasswordTypeStr,
|
|
OUT WMI_PASSWORD_TYPE *PasswordType,
|
|
IN CHAR8 *PasswordEncodingStr,
|
|
IN OUT WMI_PASSWORD_ENCODING *PasswordEncoding,
|
|
IN CHAR8 *PasswordLanguageStr,
|
|
IN OUT WMI_PASSWORD_LANGUAGE *PasswordLanguage
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Check password type is valid
|
|
//
|
|
if (!CheckPasswordTypeIsValid (PasswordTypeStr, PasswordType)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check password encoding is valid
|
|
//
|
|
if (!CheckPasswordEncodingIsValid (PasswordEncodingStr, PasswordEncoding)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// L05 only support ascii encoding
|
|
//
|
|
if (*PasswordEncoding != WmiAsciiEncoding) {
|
|
Status = EFI_UNSUPPORTED;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check password keyboard languages is valid
|
|
//
|
|
if (!CheckPasswordLanguageIsValid (PasswordLanguageStr, PasswordLanguage)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// L05 only support us language
|
|
//
|
|
if (*PasswordLanguage != WmiUsLanguage) {
|
|
Status = EFI_UNSUPPORTED;
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check WMI password input buffer.
|
|
|
|
@param PasswordTypeStr A pointer to the password type string.
|
|
@param PasswordType A pointer to the password type.
|
|
@param CurrentPassword A pointer to the current password.
|
|
@param NewPassword A pointer to the new password.
|
|
@param PasswordEncodingStr A pointer to the password encoding string.
|
|
@param PasswordEncoding A pointer to the password encoding.
|
|
@param PasswordLanguageStr A pointer to the password keyboard language string.
|
|
@param PasswordLanguage A pointer to the password keyboard language.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval EFI_INVALID_PARAMETER Input invalid password format.
|
|
@retval EFI_ACCESS_DENIED Input invalid password rule.
|
|
**/
|
|
EFI_STATUS
|
|
CheckWmiPasswordInputBuffer (
|
|
IN CHAR8 *PasswordTypeStr,
|
|
OUT WMI_PASSWORD_TYPE *PasswordType,
|
|
IN OUT CHAR8 *CurrentPassword,
|
|
IN OUT CHAR8 *NewPassword,
|
|
IN CHAR8 *PasswordEncodingStr,
|
|
IN OUT WMI_PASSWORD_ENCODING *PasswordEncoding,
|
|
IN CHAR8 *PasswordLanguageStr,
|
|
IN OUT WMI_PASSWORD_LANGUAGE *PasswordLanguage
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Check WMI password format
|
|
//
|
|
Status = CheckWmiPasswordFormat (
|
|
PasswordTypeStr,
|
|
PasswordType,
|
|
PasswordEncodingStr,
|
|
PasswordEncoding,
|
|
PasswordLanguageStr,
|
|
PasswordLanguage
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check current password is valid
|
|
//
|
|
if (!CheckPasswordIsValid (&CurrentPassword, *PasswordType)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check NewPassword password is valid
|
|
//
|
|
if (!CheckPasswordIsValid (&NewPassword, *PasswordType)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// [Lenovo BIOS Setup using WMI Deployment Guide - Third Edition (February 2016)]
|
|
// 2. A password cannot be set using this method when one does not already exist.
|
|
// Passwords can only be updated or cleared.
|
|
//
|
|
if (AsciiStrLen (CurrentPassword) == 0) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// [Lenovo China Minimum BIOS Spec Version 1.37]
|
|
// [3.4.1 Rules for BIOS CMOS password]
|
|
// When user did not set any password,the security menu have one submenu:
|
|
// Set Administrator Password.
|
|
//
|
|
if (!mAdminPasswordExist && (*PasswordType == WmiSystemUserType)) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check WMI input password is repeat.
|
|
|
|
@param None
|
|
|
|
@retval TRUE WMI input password is repeat.
|
|
@retval FALSE WMI input password is not repeat.
|
|
**/
|
|
BOOLEAN
|
|
WmiInputPasswordIsRepeat (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR8 *PasswordTypeStr;
|
|
WMI_PASSWORD_TYPE PasswordType;
|
|
CHAR8 *CurrentPassword;
|
|
CHAR8 *NewPassword;
|
|
CHAR8 *PasswordEncodingStr;
|
|
WMI_PASSWORD_ENCODING PasswordEncoding;
|
|
CHAR8 *PasswordLanguageStr;
|
|
WMI_PASSWORD_LANGUAGE PasswordLanguage;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
PasswordTypeStr = NULL;
|
|
PasswordType = WmiPasswoedMaxType;
|
|
CurrentPassword = NULL;
|
|
NewPassword = NULL;
|
|
PasswordEncodingStr = NULL;
|
|
PasswordEncoding = WmiPasswoedMaxEncoding;
|
|
PasswordLanguageStr = NULL;
|
|
PasswordLanguage = WmiPasswoedMaxLanguage;
|
|
|
|
//
|
|
// Analyze WMI set password input buffer
|
|
//
|
|
Status = AnalyzeWmiSetPasswordInputBuffer (
|
|
&PasswordTypeStr,
|
|
&CurrentPassword,
|
|
&NewPassword,
|
|
&PasswordEncodingStr,
|
|
&PasswordLanguageStr
|
|
);
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check WMI password input buffer is valid
|
|
//
|
|
Status = CheckWmiPasswordInputBuffer (
|
|
PasswordTypeStr,
|
|
&PasswordType,
|
|
CurrentPassword,
|
|
NewPassword,
|
|
PasswordEncodingStr,
|
|
&PasswordEncoding,
|
|
PasswordLanguageStr,
|
|
&PasswordLanguage
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check password type is the same
|
|
//
|
|
if (PasswordType != mPasswordCheckData.PasswordType) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check current password is the same
|
|
//
|
|
if (AsciiStrCmp (CurrentPassword, mPasswordCheckData.CurrentPassword) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check new password is the same
|
|
//
|
|
if (AsciiStrCmp (NewPassword, mPasswordCheckData.NewPassword) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Clean password check data
|
|
//
|
|
ZeroMem (&mPasswordCheckData, sizeof (WMI_PASSWORD_DATA_MAP));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Refer from ReadPassword() at SysPasswordDxe.c
|
|
|
|
WMI get admin or user password.
|
|
|
|
@param PasswordType System admin or user password.
|
|
@param Password Assign a pointer to the password buffer.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_UNSUPPORTED Invalid system password type.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
WmiReadPassword (
|
|
IN WMI_PASSWORD_TYPE PasswordType,
|
|
OUT UINT8 **Password
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN DataSize;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
#ifndef L05_NOTEBOOK_PASSWORD_ENABLE
|
|
DataSize = L05_WMI_PASSWORD_MAX_LENGTH + 2;
|
|
|
|
#else
|
|
DataSize = SHA256_DIGEST_SIZE;
|
|
#endif
|
|
|
|
//
|
|
// Allocate resources
|
|
//
|
|
*Password = AllocateRuntimeZeroPool (DataSize);
|
|
|
|
//
|
|
// Get system passwords by password type
|
|
//
|
|
Status = OemSvcGetSystemPasswords (PasswordType, DataSize, *Password);
|
|
|
|
if (Status != EFI_MEDIA_CHANGED) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Refer from GetPasswordStatus() at SysPasswordDxe.c
|
|
|
|
Check admin or user password is set or not.
|
|
|
|
@param PasswordType System admin or user password.
|
|
|
|
@retval EFI_SUCCESS Password is set.
|
|
@retval EFI_NOT_FOUND Password isn't set.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
WmiGetPasswordStatus (
|
|
IN WMI_PASSWORD_TYPE PasswordType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *Password;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Password = NULL;
|
|
|
|
//
|
|
// Read password by password type
|
|
//
|
|
Status = WmiReadPassword (PasswordType, &Password);
|
|
|
|
if (EFI_ERROR (Status) || (Password == NULL)) {
|
|
if (Password != NULL) {
|
|
FreePool (Password);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
#ifndef L05_NOTEBOOK_PASSWORD_ENABLE
|
|
//
|
|
// Check password Checksum is valid
|
|
//
|
|
if (!IsSystemPasswordChecksumValid (Password)) {
|
|
#else
|
|
//
|
|
// Check system has system password or not.
|
|
//
|
|
if (!L05HaveSystemPassword (Password)) {
|
|
#endif
|
|
FreePool (Password);
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
FreePool (Password);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Refer from IsPasswordExist() at Password.c
|
|
|
|
This function uses to check admin password is exist.
|
|
|
|
@param None
|
|
|
|
@retval TRUE Admin password is in locked state.
|
|
@retval FALSE Admin password is in unloced state.
|
|
**/
|
|
BOOLEAN
|
|
WmiIsAdminPasswordExist (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = WmiGetPasswordStatus (WmiSystemAdminType);
|
|
|
|
return Status == EFI_SUCCESS ? TRUE : FALSE;
|
|
}
|
|
|
|
/**
|
|
Refer from IsPasswordExist() at Password.c
|
|
|
|
This function uses to check user password is exist.
|
|
|
|
@param None
|
|
|
|
@retval TRUE User password is in locked state.
|
|
@retval FALSE User password is in unloced state.
|
|
**/
|
|
BOOLEAN
|
|
WmiIsUserPasswordExist (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = WmiGetPasswordStatus (WmiSystemUserType);
|
|
|
|
return Status == EFI_SUCCESS ? TRUE : FALSE;
|
|
}
|
|
|
|
/**
|
|
This function uses to check HDD password is exist.
|
|
|
|
@param None
|
|
|
|
@retval TRUE Hdd password is in locked state.
|
|
@retval FALSE Hdd password is in unloced state.
|
|
**/
|
|
BOOLEAN
|
|
WmiIsHddPasswordExist (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HDD_PASSWORD_TABLE *HddPasswordTable;
|
|
UINTN HddPasswordTableSize;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
HddPasswordTableSize = 0;
|
|
HddPasswordTable = NULL;
|
|
|
|
//
|
|
// Get save HDD password
|
|
//
|
|
HddPasswordTable = SmmGetVariableAndSize (
|
|
SAVE_HDD_PASSWORD_VARIABLE_NAME,
|
|
&gSaveHddPasswordGuid,
|
|
&HddPasswordTableSize
|
|
);
|
|
|
|
if (HddPasswordTable == NULL) {
|
|
Status = EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
if (HddPasswordTable != NULL) {
|
|
FreePool (HddPasswordTable);
|
|
}
|
|
|
|
return Status == EFI_SUCCESS ? TRUE : FALSE;
|
|
}
|
|
|
|
/**
|
|
Refer from CheckPassword() at SysPasswordDxe.c
|
|
|
|
Check admin or user password is correct or not.
|
|
|
|
@param None
|
|
|
|
@param PasswordType System admin or user password.
|
|
@param Password A pointer to the password.
|
|
|
|
@retval
|
|
**/
|
|
EFI_STATUS
|
|
WmiCheckPassword (
|
|
WMI_PASSWORD_TYPE PasswordType,
|
|
CHAR8 *Password
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *SavePassword;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
SavePassword = NULL;
|
|
|
|
//
|
|
// Read password by password type
|
|
//
|
|
Status = WmiReadPassword (PasswordType, &SavePassword);
|
|
|
|
if (EFI_ERROR (Status) || (SavePassword == NULL)) {
|
|
if (SavePassword != NULL) {
|
|
FreePool (SavePassword);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
#ifndef L05_NOTEBOOK_PASSWORD_ENABLE
|
|
//
|
|
// Check password Checksum is valid
|
|
//
|
|
if (!IsSystemPasswordChecksumValid (SavePassword)) {
|
|
#else
|
|
//
|
|
// Check system has system password or not.
|
|
//
|
|
if (!L05HaveSystemPassword (SavePassword)) {
|
|
#endif
|
|
FreePool (SavePassword);
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Compare input password with save password
|
|
//
|
|
if (!L05PasswordCmp (Password, SavePassword)) {
|
|
Status = EFI_CRC_ERROR;
|
|
}
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
FreePool (SavePassword);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Clear System password.
|
|
|
|
@param PasswordType System admin or user password.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
ClearSystemPassword (
|
|
WMI_PASSWORD_TYPE PasswordType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
#ifndef L05_NOTEBOOK_PASSWORD_ENABLE
|
|
UINT8 EmptyPassword[2];
|
|
#else
|
|
UINT8 EmptyPassword[SHA256_DIGEST_SIZE];
|
|
#endif
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Clear Password
|
|
//
|
|
ZeroMem (EmptyPassword, sizeof (EmptyPassword));
|
|
Status = OemSvcSetSystemPasswords (PasswordType, sizeof (EmptyPassword), EmptyPassword);
|
|
|
|
if (Status == EFI_MEDIA_CHANGED) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Re-init security item
|
|
//
|
|
Status = SecurityDataInit (FALSE);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check admin password.
|
|
|
|
@param Password A pointer to the password buffer.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval EFI_ACCESS_DENIED WMI input admin password is invalid.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
WmiCheckAdminPassword (
|
|
CHAR8 *Password,
|
|
CHAR8 *PasswordEncodingStr,
|
|
CHAR8 *PasswordLanguageStr
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR8 *NewPassword;
|
|
UINT8 *EncodeAdminPassword;
|
|
UINT8 *EncodeAdminPasswordTemp;
|
|
CHAR8 *PasswordTypeStr = WMI_BIOS_PASSWORD_ADMIN_TYPE;
|
|
WMI_PASSWORD_TYPE PasswordType;
|
|
WMI_PASSWORD_ENCODING PasswordEncoding;
|
|
WMI_PASSWORD_LANGUAGE PasswordLanguage;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
NewPassword = "";
|
|
EncodeAdminPassword = NULL;
|
|
EncodeAdminPasswordTemp = NULL;
|
|
PasswordType = WmiPasswoedMaxType;
|
|
PasswordEncoding = WmiPasswoedMaxEncoding;
|
|
PasswordLanguage = WmiPasswoedMaxLanguage;
|
|
|
|
//
|
|
// Check WMI password input buffer is valid
|
|
//
|
|
Status = CheckWmiPasswordInputBuffer (
|
|
PasswordTypeStr,
|
|
&PasswordType,
|
|
Password,
|
|
NewPassword,
|
|
PasswordEncodingStr,
|
|
&PasswordEncoding,
|
|
PasswordLanguageStr,
|
|
&PasswordLanguage
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Encode password
|
|
//
|
|
EncodeAdminPasswordTemp = L05SysPasswordPacket (Password, AsciiStrLen (Password));
|
|
EncodeAdminPassword = L05SysPasswordEncode (EncodeAdminPasswordTemp, AsciiStrLen (Password));
|
|
|
|
if (EncodeAdminPassword == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Compare current password with save password
|
|
//
|
|
Status = WmiCheckPassword (WmiSystemAdminType, EncodeAdminPassword);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
mPasswordErrorCount++;
|
|
Status = EFI_ACCESS_DENIED;
|
|
|
|
} else {
|
|
//
|
|
// Clean password error count
|
|
//
|
|
mPasswordErrorCount = 0;
|
|
}
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
FreePool (EncodeAdminPassword);
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINTN
|
|
WmiGetNumOfHdd (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService;
|
|
HDD_PASSWORD_HDD_INFO *HddInfoArray;
|
|
UINTN NumOfHdd;
|
|
|
|
HddPasswordService = NULL;
|
|
HddInfoArray = NULL;
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiHddPasswordServiceProtocolGuid,
|
|
NULL,
|
|
&HddPasswordService
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Get HDD info
|
|
//
|
|
Status = HddPasswordService->GetHddInfo (
|
|
HddPasswordService,
|
|
&HddInfoArray,
|
|
&NumOfHdd
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return 0;
|
|
}
|
|
|
|
return NumOfHdd;
|
|
}
|
|
|
|
|
|
/**
|
|
This function uses to get HDD password type number.
|
|
|
|
@param PasswordType HDD master or user password.
|
|
@param PasswordTypeStr A pointer to the password type string.
|
|
@param HddPasswordTypeNumber A pointer to the HDD password type number.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
WmiGetHddPasswordTypeNumber (
|
|
IN WMI_PASSWORD_TYPE PasswordType,
|
|
IN CHAR8 *PasswordTypeStr,
|
|
OUT UINT8 *HddPasswordTypeNumber
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
CHAR8 *HddPasswordTypeNumberStr;
|
|
UINTN NumOfHdd;
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
HddPasswordTypeNumberStr = NULL;
|
|
|
|
if (PasswordTypeStr == NULL || HddPasswordTypeNumber == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
NumOfHdd = WmiGetNumOfHdd ();
|
|
*HddPasswordTypeNumber = 0;
|
|
|
|
for (Index = 0; Index < mWmiPasswordTypeMapListCount; Index++) {
|
|
if (PasswordType == mWmiPasswordTypeMap[Index].PasswordType) {
|
|
HddPasswordTypeNumberStr = PasswordTypeStr + AsciiStrLen (mWmiPasswordTypeMap[Index].PasswordTypeStr);
|
|
|
|
while ((*HddPasswordTypeNumberStr >= L'0' && *HddPasswordTypeNumberStr <= L'9')) {
|
|
*HddPasswordTypeNumber *= 10;
|
|
*HddPasswordTypeNumber += *HddPasswordTypeNumberStr - L'0';
|
|
HddPasswordTypeNumberStr++;
|
|
}
|
|
|
|
if (*HddPasswordTypeNumber == 0 || *HddPasswordTypeNumberStr != 0) {
|
|
*HddPasswordTypeNumber = 0;
|
|
break;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*HddPasswordTypeNumber > NumOfHdd) {
|
|
*HddPasswordTypeNumber = 0;
|
|
Status = EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
WMI Set HDD Passwords.
|
|
|
|
@param PasswordType HDD master or user password.
|
|
@param HddPasswordTypeNumber HDD password type number.
|
|
@param HddPasswordBuffer A pointer to the HDD current password.
|
|
@param HddNewPassword A pointer to the HDD new password.
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
WmiSetHddPasswords (
|
|
IN WMI_PASSWORD_TYPE PasswordType,
|
|
IN UINT8 HddPasswordTypeNumber,
|
|
IN UINT8 *HddCurrentPassword,
|
|
IN UINT8 *HddNewPassword
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HDD_PASSWORD_TABLE HddPasswordTable[WmiHddPasswordMaxSection];
|
|
UINTN NumberLength;
|
|
CHAR16 *VariableName;
|
|
UINTN BufferSize;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
VariableName = NULL;
|
|
BufferSize = 0;
|
|
ZeroMem (HddPasswordTable, sizeof (HddPasswordTable));
|
|
|
|
//
|
|
// Put HDD current password
|
|
//
|
|
AsciiStrToUnicodeStrS (HddCurrentPassword, HddPasswordTable[WmiHddPasswordCurrentSection].PasswordStr, HDD_PASSWORD_MAX_NUMBER + 1);
|
|
HddPasswordTable[WmiHddPasswordCurrentSection].PasswordType = (UINT8) (PasswordType - WmiHddUserType);
|
|
|
|
//
|
|
// Put HDD new password
|
|
//
|
|
AsciiStrToUnicodeStrS (HddNewPassword, HddPasswordTable[WmiHddPasswordNewSection].PasswordStr, HDD_PASSWORD_MAX_NUMBER + 1);
|
|
HddPasswordTable[WmiHddPasswordNewSection].PasswordType = (UINT8) (PasswordType - WmiHddUserType);
|
|
|
|
//
|
|
// Allocate resources
|
|
//
|
|
L05_GET_NUMBER_LENGTH (HddPasswordTypeNumber, NumberLength);
|
|
BufferSize = StrSize (L05_WMI_HDD_PASWORD_DATA_VARIABLE_NAME) + (NumberLength * sizeof (CHAR16));
|
|
VariableName = AllocateZeroPool (BufferSize);
|
|
|
|
if (VariableName == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Set WMI HDD password variable name
|
|
//
|
|
UnicodeSPrint (VariableName, BufferSize, L"%s%d", L05_WMI_HDD_PASWORD_DATA_VARIABLE_NAME, HddPasswordTypeNumber);
|
|
|
|
//
|
|
// Set WMI HDD password variable
|
|
//
|
|
Status = mSmmVariable->SmmSetVariable (
|
|
VariableName,
|
|
&gL05WmiSetupUnderOsSetupVariableGuid,
|
|
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
|
(sizeof (HDD_PASSWORD_TABLE) * WmiHddPasswordMaxSection),
|
|
(VOID *) HddPasswordTable
|
|
);
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
FreePool (VariableName);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
WMI Method for Set BIOS password -
|
|
|
|
Mapping to WMI class : Lenovo_SetBiosPassword
|
|
Mapping to ASL method : WMA6
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS This function execute successfully.
|
|
@retval EFI_INVALID_PARAMETER Input invalid password format.
|
|
@retval EFI_ACCESS_DENIED Input invalid password rule or password is invalid.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
WmiSetBiosPasswordA6 (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR8 *PasswordTypeStr;
|
|
WMI_PASSWORD_TYPE PasswordType;
|
|
CHAR8 *CurrentPassword;
|
|
CHAR8 *NewPassword;
|
|
CHAR8 *PasswordEncodingStr;
|
|
WMI_PASSWORD_ENCODING PasswordEncoding;
|
|
CHAR8 *PasswordLanguageStr;
|
|
WMI_PASSWORD_LANGUAGE PasswordLanguage;
|
|
UINT8 *EncodeCurrentPassword;
|
|
UINT8 *EncodeCurrentPasswordTemp;
|
|
UINT8 *EncodeNewPassword;
|
|
UINT8 *EncodeNewPasswordTemp;
|
|
UINT8 HddPasswordTypeNumber;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
PasswordTypeStr = NULL;
|
|
PasswordType = WmiPasswoedMaxType;
|
|
CurrentPassword = NULL;
|
|
NewPassword = NULL;
|
|
PasswordEncodingStr = NULL;
|
|
PasswordEncoding = WmiPasswoedMaxEncoding;
|
|
PasswordLanguageStr = NULL;
|
|
PasswordLanguage = WmiPasswoedMaxLanguage;
|
|
EncodeCurrentPassword = NULL;
|
|
EncodeCurrentPasswordTemp = NULL;
|
|
EncodeNewPassword = NULL;
|
|
EncodeNewPasswordTemp = NULL;
|
|
|
|
mAdminPasswordExist = WmiIsAdminPasswordExist ();
|
|
mUserPasswordExist = WmiIsUserPasswordExist ();
|
|
mHddPasswordExist = WmiIsHddPasswordExist ();
|
|
|
|
//
|
|
// Analyze WMI set password input buffer
|
|
//
|
|
Status = AnalyzeWmiSetPasswordInputBuffer (
|
|
&PasswordTypeStr,
|
|
&CurrentPassword,
|
|
&NewPassword,
|
|
&PasswordEncodingStr,
|
|
&PasswordLanguageStr
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check WMI password input buffer is valid
|
|
//
|
|
Status = CheckWmiPasswordInputBuffer (
|
|
PasswordTypeStr,
|
|
&PasswordType,
|
|
CurrentPassword,
|
|
NewPassword,
|
|
PasswordEncodingStr,
|
|
&PasswordEncoding,
|
|
PasswordLanguageStr,
|
|
&PasswordLanguage
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
switch (PasswordType) {
|
|
|
|
case WmiSystemAdminType:
|
|
case WmiSystemUserType:
|
|
|
|
//
|
|
// Encode password
|
|
//
|
|
EncodeCurrentPasswordTemp = L05SysPasswordPacket (CurrentPassword, AsciiStrLen (CurrentPassword));
|
|
EncodeCurrentPassword = L05SysPasswordEncode (EncodeCurrentPasswordTemp, AsciiStrLen (CurrentPassword));
|
|
|
|
EncodeNewPasswordTemp = L05SysPasswordPacket (NewPassword, AsciiStrLen (NewPassword));
|
|
EncodeNewPassword = L05SysPasswordEncode (EncodeNewPasswordTemp, AsciiStrLen (NewPassword));
|
|
|
|
if (EncodeCurrentPassword == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (EncodeNewPassword == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Compare current password with old password
|
|
//
|
|
Status = WmiCheckPassword (PasswordType, EncodeCurrentPassword);
|
|
|
|
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
|
mPasswordErrorCount++;
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Avoid password don't exist but when current password exist can set new password
|
|
//
|
|
if ((!(PasswordType ? mUserPasswordExist : mAdminPasswordExist)) && (AsciiStrLen (CurrentPassword) != 0)) {
|
|
mPasswordErrorCount++;
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// [Lenovo China Minimum BIOS Spec Version 1.37]
|
|
// When the user password set, there is an additional submenu added.
|
|
// Clear user password menu just appeared in the security menu when
|
|
// user entered CMOS setup menu with administrator password.
|
|
//
|
|
if ((PasswordType == WmiSystemUserType) && (AsciiStrLen (NewPassword) == 0)) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set new password.
|
|
//
|
|
if (AsciiStrLen (NewPassword) != 0) {
|
|
#ifndef L05_NOTEBOOK_PASSWORD_ENABLE
|
|
Status = OemSvcSetSystemPasswords (PasswordType, (EncodeNewPassword[0] + 2), EncodeNewPassword);
|
|
|
|
#else
|
|
Status = OemSvcSetSystemPasswords (PasswordType, SHA256_DIGEST_SIZE, EncodeNewPassword);
|
|
#endif
|
|
|
|
if (Status == EFI_MEDIA_CHANGED) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// When clear admin password also need clear user password
|
|
//
|
|
if ((PasswordType == WmiSystemAdminType) && (AsciiStrLen (NewPassword) == 0)) {
|
|
Status = ClearSystemPassword (WmiSystemAdminType);
|
|
Status = ClearSystemPassword (WmiSystemUserType);
|
|
}
|
|
|
|
//
|
|
// Re-init security item
|
|
//
|
|
Status = SecurityDataInit (FALSE);
|
|
break;
|
|
|
|
case WmiHddUserType:
|
|
case WmiHddMasterType:
|
|
|
|
#ifdef L05_HDD_PASSWORD_ENABLE
|
|
//
|
|
// Avoid HDD password don't exist but when current password exist can set new password
|
|
//
|
|
if (!mHddPasswordExist) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// By L05 Spec., User hdd password can not disable hdd password function.
|
|
// return EFI_ACCESS_DENIED for L05 only.
|
|
//
|
|
if ((PasswordType == WmiHddUserType) && (AsciiStrLen (NewPassword) == 0)) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get HDD Number
|
|
//
|
|
Status = WmiGetHddPasswordTypeNumber (PasswordType, PasswordTypeStr, &HddPasswordTypeNumber);
|
|
if (EFI_ERROR (Status) || HddPasswordTypeNumber == 0) {
|
|
Status = EFI_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set HDD password.
|
|
//
|
|
Status = WmiSetHddPasswords (PasswordType, HddPasswordTypeNumber, CurrentPassword, NewPassword);
|
|
break;
|
|
|
|
#else
|
|
Status = EFI_UNSUPPORTED;
|
|
break;
|
|
|
|
#endif
|
|
}
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// [Lenovo BIOS Setup using WMI Deployment Guide - Third Edition (February 2016)]
|
|
// Limitations and Notes:
|
|
// 1. BIOS settings cannot be changed at the same boot as power-on passwords (POP) and hard disk passwords
|
|
// (HDP). If you want to change BIOS settings and POP or HDP, you must reboot the system after changing
|
|
// one of them.
|
|
//
|
|
mPasswordChange = TRUE;
|
|
|
|
//
|
|
// Init password check data
|
|
//
|
|
mPasswordCheckData.PasswordType = PasswordType;
|
|
AsciiStrCpyS (mPasswordCheckData.CurrentPassword, sizeof (mPasswordCheckData.CurrentPassword), CurrentPassword);
|
|
AsciiStrCpyS (mPasswordCheckData.NewPassword, sizeof (mPasswordCheckData.NewPassword), NewPassword);
|
|
}
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
if (EncodeCurrentPassword != NULL) {
|
|
FreePool (EncodeCurrentPassword);
|
|
}
|
|
|
|
if (EncodeNewPassword != NULL) {
|
|
FreePool (EncodeNewPassword);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|