From 0c18794ea4289f03fefc7117b56740414cc0536c Mon Sep 17 00:00:00 2001 From: gdong1 Date: Fri, 2 Sep 2011 07:49:32 +0000 Subject: Add security package to repository. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524 --- .../UserIdentifyManagerDxe/LoadDeferredImage.c | 148 + .../UserIdentifyManagerDxe/UserIdentifyManager.c | 4381 ++++++++++++++++++++ .../UserIdentifyManagerDxe/UserIdentifyManager.h | 413 ++ .../UserIdentifyManagerData.h | 42 + .../UserIdentifyManagerDxe.inf | 62 + .../UserIdentifyManagerStrings.uni | Bin 0 -> 2696 bytes .../UserIdentifyManagerVfr.Vfr | 44 + 7 files changed, 5090 insertions(+) create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr (limited to 'SecurityPkg/UserIdentification/UserIdentifyManagerDxe') diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c new file mode 100644 index 0000000000..da1201a5f9 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c @@ -0,0 +1,148 @@ +/** @file + Load the deferred images after user is identified. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManager.h" + +EFI_HANDLE mDeferredImageHandle; + +/** + The function will load all the deferred images again. If the deferred image is loaded + successfully, try to start it. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +LoadDeferredImage ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *DeferredImage; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + UINTN DriverIndex; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + VOID *DriverImage; + UINTN ImageSize; + BOOLEAN BootOption; + EFI_HANDLE ImageHandle; + UINTN ExitDataSize; + CHAR16 *ExitData; + + // + // Find all the deferred image load protocols. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDeferredImageLoadProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return ; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuf[Index], + &gEfiDeferredImageLoadProtocolGuid, + (VOID **) &DeferredImage + ); + if (EFI_ERROR (Status)) { + continue ; + } + + DriverIndex = 0; + do { + // + // Load all the deferred images in this protocol instance. + // + Status = DeferredImage->GetImageInfo( + DeferredImage, + DriverIndex, + &ImageDevicePath, + (VOID **) &DriverImage, + &ImageSize, + &BootOption + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Load and start the image. + // + Status = gBS->LoadImage ( + BootOption, + mDeferredImageHandle, + ImageDevicePath, + NULL, + 0, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + // + // Before calling the image, enable the Watchdog Timer for + // a 5 Minute period + // + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData); + + // + // Clear the Watchdog Timer after the image returns. + // + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + } + DriverIndex++; + } while (TRUE); + } + FreePool (HandleBuf); +} + + +/** + Register an event notification function for user profile changed. + + @param[in] ImageHandle Image handle this driver. + +**/ +VOID +LoadDeferredImageInit ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + mDeferredImageHandle = ImageHandle; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LoadDeferredImage, + NULL, + &gEfiEventUserProfileChangedGuid, + &Event + ); + + ASSERT (Status == EFI_SUCCESS); +} diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c new file mode 100644 index 0000000000..e105579115 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c @@ -0,0 +1,4381 @@ +/** @file + This driver manages user information and produces user manager protocol. + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManager.h" + +// +// Guid used in user profile saving and in form browser. +// +EFI_GUID mUserManagerGuid = USER_IDENTIFY_MANAGER_GUID; + +// +// Default user name. +// +CHAR16 mUserName[] = L"Administrator"; + +// +// Points to the user profile database. +// +USER_PROFILE_DB *mUserProfileDb = NULL; + +// +// Points to the credential providers found in system. +// +CREDENTIAL_PROVIDER_INFO *mProviderDb = NULL; + +// +// Current user shared in multi function. +// +EFI_USER_PROFILE_HANDLE mCurrentUser = NULL; + +// +// Flag indicates a user is identified. +// +BOOLEAN mIdentified = FALSE; +USER_MANAGER_CALLBACK_INFO *mCallbackInfo = NULL; +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {ACA7C06F-743C-454f-9C6D-692138482498} + // + { 0xaca7c06f, 0x743c, 0x454f, { 0x9c, 0x6d, 0x69, 0x21, 0x38, 0x48, 0x24, 0x98 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +EFI_USER_MANAGER_PROTOCOL gUserIdentifyManager = { + UserProfileCreate, + UserProfileDelete, + UserProfileGetNext, + UserProfileCurrent, + UserProfileIdentify, + UserProfileFind, + UserProfileNotify, + UserProfileGetInfo, + UserProfileSetInfo, + UserProfileDeleteInfo, + UserProfileGetNextInfo, +}; + + +/** + Find the specified user in the user database. + + This function searches the specified user from the beginning of the user database. + And if NextUser is TRUE, return the next User in the user database. + + @param[in, out] User On entry, points to the user profile entry to search. + On return, points to the user profile entry or NULL if not found. + @param[in] NextUser If FALSE, find the user in user profile database specifyed by User + If TRUE, find the next user in user profile database specifyed + by User. + @param[out] ProfileIndex A pointer to the index of user profile database that matches the + user specifyed by User. + + @retval EFI_NOT_FOUND User was NULL, or User was not found, or the next user was not found. + @retval EFI_SUCCESS User or the next user are found in user profile database + +**/ +EFI_STATUS +FindUserProfile ( + IN OUT USER_PROFILE_ENTRY **User, + IN BOOLEAN NextUser, + OUT UINTN *ProfileIndex OPTIONAL + ) +{ + UINTN Index; + + // + // Check parameters + // + if ((mUserProfileDb == NULL) || (User == NULL)) { + return EFI_NOT_FOUND; + } + + // + // Check whether the user profile is in the user profile database. + // + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + if (mUserProfileDb->UserProfile[Index] == *User) { + if (ProfileIndex != NULL) { + *ProfileIndex = Index; + } + break; + } + } + + if (NextUser) { + // + // Find the next user profile. + // + Index++; + if (Index < mUserProfileDb->UserProfileNum) { + *User = mUserProfileDb->UserProfile[Index]; + } else if (Index == mUserProfileDb->UserProfileNum) { + *User = NULL; + return EFI_NOT_FOUND; + } else { + if ((mUserProfileDb->UserProfileNum > 0) && (*User == NULL)) { + *User = mUserProfileDb->UserProfile[0]; + } else { + *User = NULL; + return EFI_NOT_FOUND; + } + } + } else if (Index == mUserProfileDb->UserProfileNum) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Find the specified user information record in the specified User profile. + + This function searches the specified user information record from the beginning of the user + profile. And if NextInfo is TRUE, return the next info in the user profile. + + @param[in] User Points to the user profile entry. + @param[in, out] Info On entry, points to the user information record or NULL to start + searching with the first user information record. + On return, points to the user information record or NULL if not found. + @param[in] NextInfo If FALSE, find the user information record in profile specifyed by User. + If TRUE, find the next user information record in profile specifyed + by User. + @param[out] Offset A pointer to the offset of the information record in the user profile. + + @retval EFI_INVALID_PARAMETER Info is NULL + @retval EFI_NOT_FOUND Info was not found, or the next Info was not found. + @retval EFI_SUCCESS Info or the next info are found in user profile. + +**/ +EFI_STATUS +FindUserInfo ( + IN USER_PROFILE_ENTRY * User, + IN OUT EFI_USER_INFO **Info, + IN BOOLEAN NextInfo, + OUT UINTN *Offset OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN InfoLen; + + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user profile entry + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find user information in the specified user record. + // + InfoLen = 0; + while (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (UserInfo == *Info) { + if (Offset != NULL) { + *Offset = InfoLen; + } + break; + } + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + } + + // + // Check whether to find the next user information. + // + if (NextInfo) { + if (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + if (InfoLen < User->UserProfileSize) { + *Info = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (Offset != NULL) { + *Offset = InfoLen; + } + } else if (InfoLen == User->UserProfileSize) { + *Info = NULL; + return EFI_NOT_FOUND; + } + } else { + if (*Info == NULL) { + *Info = (EFI_USER_INFO *) User->ProfileInfo; + if (Offset != NULL) { + *Offset = 0; + } + } else { + *Info = NULL; + return EFI_NOT_FOUND; + } + } + } else if (InfoLen == User->UserProfileSize) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Find a user infomation record by the information record type. + + This function searches all user information records of User. The search starts with the + user information record following Info and continues until either the information is found + or there are no more user infomation record. + A match occurs when a Info.InfoType field matches the user information record type. + + @param[in] User Points to the user profile record to search. + @param[in, out] Info On entry, points to the user information record or NULL to start + searching with the first user information record. + On return, points to the user information record or NULL if not found. + @param[in] InfoType The infomation type to be searched. + + @retval EFI_SUCCESS User information was found. Info points to the user information record. + @retval EFI_NOT_FOUND User information was not found. + @retval EFI_INVALID_PARAMETER User is NULL or Info is NULL. + +**/ +EFI_STATUS +FindUserInfoByType ( + IN USER_PROFILE_ENTRY *User, + IN OUT EFI_USER_INFO **Info, + IN UINT8 InfoType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN InfoLen; + + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the user has the specified user information. + // + InfoLen = 0; + if (*Info == NULL) { + Status = FindUserProfile (&User, FALSE, NULL); + } else { + Status = FindUserInfo (User, Info, TRUE, &InfoLen); + } + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + while (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (UserInfo->InfoType == InfoType) { + if (UserInfo != *Info) { + *Info = UserInfo; + return EFI_SUCCESS; + } + } + + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + } + + *Info = NULL; + return EFI_NOT_FOUND; +} + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. The + search starts with the user information record handle following UserInfo and continues + until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record type and the + user information record data matches the portion of Info passed the EFI_USER_INFO header. + + @param[in, out] User On entry, points to the previously returned user profile record, + or NULL to start searching with the first user profile. + On return, points to the user profile entry, or NULL if not found. + @param[in, out] UserInfo On entry, points to the previously returned user information record, + or NULL to start searching with the first. + On return, points to the user information record, or NULL if not found. + @param[in] Info Points to the buffer containing the user information to be compared + to the user information record. + @param[in] InfoSize The size of Info, in bytes. Same as Info->InfoSize. + + @retval EFI_SUCCESS User information was found. User points to the user profile record, + and UserInfo points to the user information record. + @retval EFI_NOT_FOUND User information was not found. + @retval EFI_INVALID_PARAMETER User is NULL; Info is NULL; or, InfoSize is too small. + +**/ +EFI_STATUS +FindUserProfileByInfo ( + IN OUT USER_PROFILE_ENTRY **User, + IN OUT EFI_USER_INFO **UserInfo, OPTIONAL + IN EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *InfoEntry; + + + if ((User == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize < sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + + if (UserInfo != NULL) { + InfoEntry = *UserInfo; + } else { + InfoEntry = NULL; + } + // + // Find user profile according to information. + // + if (*User == NULL) { + *User = mUserProfileDb->UserProfile[0]; + } + + // + // Check user profile handle. + // + Status = FindUserProfile (User, FALSE, NULL); + + while (!EFI_ERROR (Status)) { + // + // Find the user information in a user profile. + // + while (TRUE) { + Status = FindUserInfoByType (*User, &InfoEntry, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + + if (InfoSize == Info->InfoSize) { + if (CompareMem ((UINT8 *) (InfoEntry + 1), (UINT8 *) (Info + 1), InfoSize - sizeof (EFI_USER_INFO)) == 0) { + // + // Found the infomation record. + // + if (UserInfo != NULL) { + *UserInfo = InfoEntry; + } + return EFI_SUCCESS; + } + } + } + + // + // Get next user profile. + // + InfoEntry = NULL; + Status = FindUserProfile (User, TRUE, NULL); + } + + return EFI_NOT_FOUND; +} + +/** + Find the credential provider in the specified identity policy. + + @param[in] FindIdentity Point to the user identity policy. + @param[in] IdentifyInfo Point to the user information to be searched. + + @retval TRUE The credential provider was found in the identity policy. + @retval FALSE The credential provider was not found. +**/ +BOOLEAN +FindProvider ( + IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity, + IN CONST EFI_USER_INFO *IdentifyInfo + ) +{ + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Found the credential provider. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if ((Identity->Type == FindIdentity->Type) && + (Identity->Length == FindIdentity->Length) && + CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1)) + ) { + return TRUE; + } + + TotalLen += Identity->Length; + } + + return FALSE; +} + + +/** + Check whether the access policy is valid. + + @param[in] PolicyInfo Point to the access policy. + @param[in] InfoLen The policy length. + + @retval TRUE The policy is a valid access policy. + @retval FALSE The access policy is not a valid access policy. + +**/ +BOOLEAN +CheckAccessPolicy ( + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + UINTN TotalLen; + UINTN ValueLen; + UINTN OffSet; + EFI_USER_INFO_ACCESS_CONTROL Access; + EFI_DEVICE_PATH_PROTOCOL *Path; + UINTN PathSize; + + TotalLen = 0; + while (TotalLen < InfoLen) { + // + // Check access policy according to type. + // + CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access)); + ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL); + switch (Access.Type) { + case EFI_USER_INFO_ACCESS_FORBID_LOAD: + case EFI_USER_INFO_ACCESS_PERMIT_LOAD: + case EFI_USER_INFO_ACCESS_FORBID_CONNECT: + case EFI_USER_INFO_ACCESS_PERMIT_CONNECT: + OffSet = 0; + while (OffSet < ValueLen) { + Path = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet); + PathSize = GetDevicePathSize (Path); + OffSet += PathSize; + } + if (OffSet != ValueLen) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_SETUP: + if (ValueLen % sizeof (EFI_GUID) != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_BOOT_ORDER: + if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_ENROLL_SELF: + case EFI_USER_INFO_ACCESS_ENROLL_OTHERS: + case EFI_USER_INFO_ACCESS_MANAGE: + if (ValueLen != 0) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + TotalLen += Access.Size; + } + + if (TotalLen != InfoLen) { + return FALSE; + } + + return TRUE; +} + + +/** + Check whether the identity policy is valid. + + @param[in] PolicyInfo Point to the identity policy. + @param[in] InfoLen The policy length. + + @retval TRUE The policy is a valid identity policy. + @retval FALSE The access policy is not a valid identity policy. + +**/ +BOOLEAN +CheckIdentityPolicy ( + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + TotalLen = 0; + + // + // Check each part of policy expression. + // + while (TotalLen < InfoLen) { + // + // Check access polisy according to type. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + switch (Identity->Type) { + // + // Check False option. + // + case EFI_USER_INFO_IDENTITY_FALSE: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check True option. + // + case EFI_USER_INFO_IDENTITY_TRUE: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check negative operation. + // + case EFI_USER_INFO_IDENTITY_NOT: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check and operation. + // + case EFI_USER_INFO_IDENTITY_AND: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check or operation. + // + case EFI_USER_INFO_IDENTITY_OR: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check credential provider by type. + // + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + if (ValueLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + // + // Check credential provider by ID. + // + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + if (ValueLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + TotalLen += Identity->Length; + } + + if (TotalLen != InfoLen) { + return FALSE; + } + + return TRUE; +} + + +/** + Check whether the user information is a valid user information record. + + @param[in] Info points to the user information. + + @retval TRUE The info is a valid user information record. + @retval FALSE The info is not a valid user information record. + +**/ +BOOLEAN +CheckUserInfo ( + IN CONST EFI_USER_INFO *Info + ) +{ + UINTN InfoLen; + + if (Info == NULL) { + return FALSE; + } + // + // Check user information according to information type. + // + InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO); + switch (Info->InfoType) { + case EFI_USER_INFO_EMPTY_RECORD: + if (InfoLen != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_NAME_RECORD: + case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD: + case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD: + break; + + case EFI_USER_INFO_CREATE_DATE_RECORD: + case EFI_USER_INFO_USAGE_DATE_RECORD: + if (InfoLen != sizeof (EFI_TIME)) { + return FALSE; + } + break; + + case EFI_USER_INFO_USAGE_COUNT_RECORD: + if (InfoLen != sizeof (UINT64)) { + return FALSE; + } + break; + + case EFI_USER_INFO_IDENTIFIER_RECORD: + if (InfoLen != 16) { + return FALSE; + } + break; + + case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD: + case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD: + case EFI_USER_INFO_GUID_RECORD: + if (InfoLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + case EFI_USER_INFO_PKCS11_RECORD: + case EFI_USER_INFO_CBEFF_RECORD: + break; + + case EFI_USER_INFO_FAR_RECORD: + case EFI_USER_INFO_RETRY_RECORD: + if (InfoLen != 1) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_POLICY_RECORD: + if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) { + return FALSE; + } + break; + + case EFI_USER_INFO_IDENTITY_POLICY_RECORD: + if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + return TRUE; +} + + +/** + Check the user profile data format to be added. + + @param[in] UserProfileInfo Points to the user profile data. + @param[in] UserProfileSize The length of user profile data. + + @retval TRUE It is a valid user profile. + @retval FALSE It is not a valid user profile. + +**/ +BOOLEAN +CheckProfileInfo ( + IN UINT8 *UserProfileInfo, + IN UINTN UserProfileSize + ) +{ + UINTN ChkLen; + EFI_USER_INFO *Info; + + if (UserProfileInfo == NULL) { + return FALSE; + } + + // + // Check user profile information length. + // + ChkLen = 0; + while (ChkLen < UserProfileSize) { + Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen); + // + // Check user information format. + // + if (!CheckUserInfo (Info)) { + return FALSE; + } + + ChkLen += ALIGN_VARIABLE (Info->InfoSize); + } + + if (ChkLen != UserProfileSize) { + return FALSE; + } + + return TRUE; +} + + +/** + Find the specified RightType in current user profile. + + @param[in] RightType Could be EFI_USER_INFO_ACCESS_MANAGE, + EFI_USER_INFO_ACCESS_ENROLL_OTHERS or + EFI_USER_INFO_ACCESS_ENROLL_SELF. + + @retval TRUE Find the specified RightType in current user profile. + @retval FALSE Can't find the right in the profile. + +**/ +BOOLEAN +CheckCurrentUserAccessRight ( + IN UINT32 RightType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + UINTN TotalLen; + UINTN CheckLen; + EFI_USER_INFO_ACCESS_CONTROL Access; + + // + // Get user access right information. + // + Info = NULL; + Status = FindUserInfoByType ( + (USER_PROFILE_ENTRY *) mCurrentUser, + &Info, + EFI_USER_INFO_ACCESS_POLICY_RECORD + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + ASSERT (Info != NULL); + TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO); + CheckLen = 0; + while (CheckLen < TotalLen) { + // + // Check right according to access type. + // + CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access)); + if (Access.Type == RightType) { + return TRUE;; + } + + CheckLen += Access.Size; + } + + return FALSE; +} + + +/** + Create a unique user identifier. + + @param[out] Identifier This points to the identifier. + +**/ +VOID +GenerateIdentifier ( + OUT UINT8 *Identifier + ) +{ + EFI_TIME Time; + UINT64 MonotonicCount; + UINT32 *MonotonicPointer; + UINTN Index; + + // + // Create a unique user identifier. + // + gRT->GetTime (&Time, NULL); + CopyMem (Identifier, &Time, sizeof (EFI_TIME)); + // + // Remove zeros. + // + for (Index = 0; Index < sizeof (EFI_TIME); Index++) { + if (Identifier[Index] == 0) { + Identifier[Index] = 0x5a; + } + } + + MonotonicPointer = (UINT32 *) Identifier; + gBS->GetNextMonotonicCount (&MonotonicCount); + MonotonicPointer[0] += (UINT32) MonotonicCount; + MonotonicPointer[1] += (UINT32) MonotonicCount; + MonotonicPointer[2] += (UINT32) MonotonicCount; + MonotonicPointer[3] += (UINT32) MonotonicCount; +} + + +/** + Generate unique user ID. + + @param[out] UserId Points to the user identifer. + +**/ +VOID +GenerateUserId ( + OUT UINT8 *UserId + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *UserProfile; + EFI_USER_INFO *UserInfo; + UINTN Index; + + // + // Generate unique user ID + // + while (TRUE) { + GenerateIdentifier (UserId); + // + // Check whether it's unique in user profile database. + // + if (mUserProfileDb == NULL) { + return ; + } + + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]); + UserInfo = NULL; + Status = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + if (EFI_ERROR (Status)) { + continue; + } + + if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + break; + } + } + + if (Index == mUserProfileDb->UserProfileNum) { + return ; + } + } +} + + +/** + Expand user profile database. + + @retval TRUE Success to expand user profile database. + @retval FALSE Fail to expand user profile database. + +**/ +BOOLEAN +ExpandUsermUserProfileDb ( + VOID + ) +{ + UINTN MaxNum; + USER_PROFILE_DB *NewDataBase; + + // + // Create new user profile database. + // + if (mUserProfileDb == NULL) { + MaxNum = USER_NUMBER_INC; + } else { + MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC; + } + + NewDataBase = AllocateZeroPool ( + sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) + + MaxNum * sizeof (EFI_USER_PROFILE_HANDLE) + ); + if (NewDataBase == NULL) { + return FALSE; + } + + NewDataBase->MaxProfileNum = MaxNum; + + // + // Copy old user profile database value + // + if (mUserProfileDb == NULL) { + NewDataBase->UserProfileNum = 0; + } else { + NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum; + CopyMem ( + NewDataBase->UserProfile, + mUserProfileDb->UserProfile, + NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE) + ); + FreePool (mUserProfileDb); + } + + mUserProfileDb = NewDataBase; + return TRUE; +} + + +/** + Expand user profile + + @param[in] User Points to user profile. + @param[in] ExpandSize The size of user profile. + + @retval TRUE Success to expand user profile size. + @retval FALSE Fail to expand user profile size. + +**/ +BOOLEAN +ExpandUserProfile ( + IN USER_PROFILE_ENTRY *User, + IN UINTN ExpandSize + ) +{ + UINT8 *Info; + UINTN InfoSizeInc; + + // + // Allocate new memory. + // + InfoSizeInc = 128; + User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc; + Info = AllocateZeroPool (User->MaxProfileSize); + if (Info == NULL) { + return FALSE; + } + + // + // Copy exist information. + // + if (User->UserProfileSize > 0) { + CopyMem (Info, User->ProfileInfo, User->UserProfileSize); + FreePool (User->ProfileInfo); + } + + User->ProfileInfo = Info; + return TRUE; +} + + +/** + Add or delete the user's credential record in the provider. + + @param[in] ProviderGuid Point to credential provider guid or class guid. + @param[in] ByType If TRUE, Provider is credential class guid. + If FALSE, Provider is provider guid. + @param[in] User Points to user profile. + + @retval EFI_SUCCESS Add or delete record successfully. + @retval Others Fail to add or delete record. + +**/ +EFI_STATUS +ModifyProviderCredential ( + IN EFI_GUID *Provider, + IN BOOLEAN ByType, + IN USER_PROFILE_ENTRY *User + ) +{ + UINTN Index; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + + if (Provider == NULL) { + return EFI_INVALID_PARAMETER; + } + + + // + // Find the specified credential provider. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + // + // Check credential provider ID. + // + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, Provider)) { + return UserCredential->Enroll (UserCredential, User); + } + } + + return EFI_NOT_FOUND; +} + + +/** + Modify user's credential record in the providers. + + Found the providers information in PolicyInfo, and then add or delete the user's credential + record in the providers. + + @param User Points to user profile. + @param PolicyInfo Point to identification policy to be modified. + @param InfoLen The length of PolicyInfo. + + @retval EFI_SUCCESS Modify PolicyInfo successfully. + @retval Others Fail to modify PolicyInfo. + +**/ +EFI_STATUS +ModifyCredentialInfo ( + IN USER_PROFILE_ENTRY *User, + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + EFI_STATUS Status; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Modify user's credential. + // + TotalLen = 0; + while (TotalLen < InfoLen) { + // + // Check identification policy according to type. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen); + switch (Identity->Type) { + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), TRUE, User); + if (EFI_ERROR (Status)) { + return Status; + } + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), FALSE, User); + if (EFI_ERROR (Status)) { + return Status; + } + break; + + default: + break; + } + + TotalLen += Identity->Length; + } + + return EFI_SUCCESS; +} + + +/** + Save the user profile to non-volatile memory, or delete it from non-volatile memory. + + @param[in] User Point to the user profile + @param[in] Delete If TRUE, delete the found user profile. + If FALSE, save the user profile. + @retval EFI_SUCCESS Save or delete user profile successfully. + @retval Others Fail to change the profile. + +**/ +EFI_STATUS +SaveNvUserProfile ( + IN USER_PROFILE_ENTRY *User, + IN BOOLEAN Delete + ) +{ + EFI_STATUS Status; + + // + // Check user profile entry. + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Save the user profile to non-volatile memory. + // + Status = gRT->SetVariable ( + User->UserVarName, + &mUserManagerGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + Delete ? 0 : User->UserProfileSize, + User->ProfileInfo + ); + return Status; +} + + +/** + Replace the old identity info with NewInfo in NV Flash. + + This function only replace the identity record in the user profile. Don't update + the the information on the credential provider. + + @param[in] User Point to the user profile. + @param[in] NewInfo Point to the new identity policy info. + @param[out] UserInfo Point to the new added identity info. + + @retval EFI_SUCCESS Replace user identity successfully. + @retval Others Fail to Replace user identity. + +**/ +EFI_STATUS +SaveUserIpInfo ( + IN USER_PROFILE_ENTRY * User, + IN CONST EFI_USER_INFO * NewInfo, + OUT EFI_USER_INFO **UserInfo OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *OldIpInfo; + UINTN Offset; + UINTN NextOffset; + + if ((NewInfo == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get user old identify policy information. + // + OldIpInfo = NULL; + Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the old identity policy offset. + // + Status = FindUserInfo (User, &OldIpInfo, FALSE, &Offset); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Delete the old identity policy information. + // + NextOffset = ALIGN_VARIABLE (OldIpInfo->InfoSize) + Offset; + User->UserProfileSize -= ALIGN_VARIABLE (OldIpInfo->InfoSize); + if (Offset < User->UserProfileSize) { + CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset); + } + + // + // Add new user information. + // + if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (NewInfo->InfoSize)) { + if (!ExpandUserProfile (User, ALIGN_VARIABLE (NewInfo->InfoSize))) { + return EFI_OUT_OF_RESOURCES; + } + } + + CopyMem (User->ProfileInfo + User->UserProfileSize, (VOID *) NewInfo, NewInfo->InfoSize); + if (UserInfo != NULL) { + *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize); + } + + User->UserProfileSize += ALIGN_VARIABLE (NewInfo->InfoSize); + + // + // Save user profile information. + // + Status = SaveNvUserProfile (User, FALSE); + return Status; +} + + +/** + Remove the provider in FindIdentity from the user identification information record. + + @param[in, out] NewInfo On entry, points to the user information to remove provider. + On return, points to the user information the provider is removed. + @param[in] FindIdentity Point to the user identity policy. + + @retval TRUE The provider is removed successfully. + @retval FALSE Fail to remove the provider. + +**/ +BOOLEAN +RemoveProvider ( + IN OUT EFI_USER_INFO **NewInfo, + IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity + ) +{ + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_USER_INFO *IdentifyInfo; + UINT8 *Buffer; + + IdentifyInfo = *NewInfo; + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + if (TotalLen == FindIdentity->Length) { + // + // Only one credential provider in the identification policy. + // Set the new policy to be TRUE after removed the provider. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentifyInfo + 1); + Identity->Type = EFI_USER_INFO_IDENTITY_TRUE; + Identity->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + IdentifyInfo->InfoSize = sizeof (EFI_USER_INFO) + Identity->Length; + return TRUE; + } + + // + // Found the credential provider. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if ((Identity->Type == FindIdentity->Type) && + (Identity->Length == FindIdentity->Length) && + CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1)) + ) { + // + // Found the credential provider to delete + // + if (Identity == (EFI_USER_INFO_IDENTITY_POLICY *)(IdentifyInfo + 1)) { + // + // It is the first item in the identification policy, delete it and the connector after it. + // + Buffer = (UINT8 *) Identity + Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + CopyMem (Identity, Buffer, TotalLen); + } else { + // + // It is not the first item in the identification policy, delete it and the connector before it. + // + Buffer = (UINT8 *) Identity + Identity->Length; + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + TotalLen -= (Buffer - (UINT8 *)(IdentifyInfo + 1)); + IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + CopyMem ((UINT8 *) (Identity - 1), Buffer, TotalLen); + } + return TRUE; + } + + TotalLen += Identity->Length; + } + return FALSE; +} + + +/** + This function replaces the old identity policy with a new identity policy. + + This function changes user identity policy information. + If enroll new credential failed, recover the old identity policy. + + For new policy: + a. For each credential, if it is newly added, try to enroll it. + If enroll failed, try to delete the newly added ones. + + b. For each credential, if it exists in the old policy, delete old one, + and enroll new one. If failed to enroll the new one, removed it from new + identification policy. + + For old policy: + a. For each credential, if it does not exist in new one, delete it. + + @param[in] User Point to the user profile. + @param[in] Info Points to the user identity information. + @param[in] InfoSize The size of Info (Not used in this function). + @param[out] IpInfo The new identification info after modify. + + @retval EFI_SUCCESS Modify user identity policy successfully. + @retval Others Fail to modify user identity policy. + +**/ +EFI_STATUS +ModifyUserIpInfo ( + IN USER_PROFILE_ENTRY *User, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize, + OUT EFI_USER_INFO **IpInfo + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *OldIpInfo; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + UINT32 CredentialCount; + EFI_USER_INFO *NewIpInfo; + + // + // Get user old identify policy information. + // + OldIpInfo = NULL; + Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (OldIpInfo != NULL); + + // + // Enroll new added credential provider. + // + CredentialCount = 0; + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, OldIpInfo)) { + // + // The credential is NOT found in the old identity policy; add it. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + break; + } + CredentialCount++; + } + } + + TotalLen += Identity->Length; + } + + if (EFI_ERROR (Status)) { + // + // Enroll new credential failed. Delete the newly enrolled credential, and return. + // + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, OldIpInfo)) { + // + // The credential is NOT found in the old identity policy. Delete it. + // + if (CredentialCount == 0) { + break; + } + + ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + CredentialCount--; + } + } + TotalLen += Identity->Length; + } + + return EFI_DEVICE_ERROR; + } + + // + // Backup new identification policy + // + NewIpInfo = AllocateCopyPool (Info->InfoSize, Info); + ASSERT (NewIpInfo != NULL); + + // + // Enroll the credential that existed in the old identity policy. + // + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (FindProvider (Identity, OldIpInfo)) { + // + // The credential is found in the old identity policy, so delete the old credential first. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + // + // Failed to delete old credential. + // + FreePool (NewIpInfo); + return EFI_DEVICE_ERROR; + } + + // + // Add the new credential. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + // + // Failed to enroll the user by new identification policy. + // So removed the credential provider from the identification policy + // + RemoveProvider (&NewIpInfo, Identity); + } + } + } + TotalLen += Identity->Length; + } + + // + // Delete old credential that didn't exist in the new identity policy. + // + TotalLen = 0; + while (TotalLen < OldIpInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (OldIpInfo + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, Info)) { + // + // The credential is NOT found in the new identity policy. Delete the old credential. + // + ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + } + } + TotalLen += Identity->Length; + } + + *IpInfo = NewIpInfo; + return EFI_SUCCESS; +} + + +/** + Add one new user info into the user's profile. + + @param[in] User point to the user profile + @param[in] Info Points to the user information payload. + @param[in] InfoSize The size of the user information payload, in bytes. + @param[out] UserInfo Point to the new info in user profile + @param[in] Save If TRUE, save the profile to NV flash. + If FALSE, don't need to save the profile to NV flash. + + @retval EFI_SUCCESS Add user info to user profile successfully. + @retval Others Fail to add user info to user profile. + +**/ +EFI_STATUS +AddUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN UINT8 *Info, + IN UINTN InfoSize, + OUT EFI_USER_INFO **UserInfo, OPTIONAL + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + + if ((Info == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user profile handle. + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check user information memory size. + // + if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) { + if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) { + return EFI_OUT_OF_RESOURCES; + } + } + + // + // Add credential. + // + if (((EFI_USER_INFO *) Info)->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + Status = ModifyCredentialInfo ( + User, + (UINT8 *) ((EFI_USER_INFO *) Info + 1), + InfoSize - sizeof (EFI_USER_INFO) + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Add new user information. + // + CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize); + if (UserInfo != NULL) { + *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize); + } + User->UserProfileSize += ALIGN_VARIABLE (InfoSize); + + // + // Save user profile information. + // + if (Save) { + Status = SaveNvUserProfile (User, FALSE); + } + + return Status; +} + + +/** + Get the user info from the specified user info handle. + + @param[in] User Point to the user profile. + @param[in] UserInfo Point to the user information record to get. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. + On exit, holds the user information. + @param[in, out] InfoSize On entry, points to the size of Info. + On return, points to the size of the user information. + @param[in] ChkRight If TRUE, check the user info attribute. + If FALSE, don't check the user info attribute. + + + @retval EFI_ACCESS_DENIED The information cannot be accessed by the current user. + @retval EFI_INVALID_PARAMETER InfoSize is NULL or UserInfo is NULL. + @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the + returned data. The actual size required is returned in *InfoSize. + @retval EFI_SUCCESS Information returned successfully. + +**/ +EFI_STATUS +GetUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN EFI_USER_INFO *UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize, + IN BOOLEAN ChkRight + ) +{ + EFI_STATUS Status; + + if ((InfoSize == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((*InfoSize != 0) && (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the user information to get. + // + Status = FindUserInfo (User, &UserInfo, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check information attributes. + // + if (ChkRight) { + switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) { + case EFI_USER_INFO_PRIVATE: + case EFI_USER_INFO_PROTECTED: + if (User != mCurrentUser) { + return EFI_ACCESS_DENIED; + } + break; + + case EFI_USER_INFO_PUBLIC: + break; + + default: + return EFI_INVALID_PARAMETER; + break; + } + } + + // + // Get user information. + // + if (UserInfo->InfoSize > *InfoSize) { + *InfoSize = UserInfo->InfoSize; + return EFI_BUFFER_TOO_SMALL; + } + + *InfoSize = UserInfo->InfoSize; + if (Info != NULL) { + CopyMem (Info, UserInfo, *InfoSize); + } + + return EFI_SUCCESS; +} + + +/** + Delete the specified user information from user profile. + + @param[in] User Point to the user profile. + @param[in] Info Point to the user information record to delete. + @param[in] Save If TRUE, save the profile to NV flash. + If FALSE, don't need to save the profile to NV flash. + + @retval EFI_SUCCESS Delete user info from user profile successfully. + @retval Others Fail to delete user info from user profile. + +**/ +EFI_STATUS +DelUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN EFI_USER_INFO *Info, + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINTN NextOffset; + + // + // Check user information handle. + // + Status = FindUserInfo (User, &Info, FALSE, &Offset); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) { + return EFI_ACCESS_DENIED; + } else if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + Status = ModifyCredentialInfo (User, (UINT8 *) (Info + 1), Info->InfoSize - sizeof (EFI_USER_INFO)); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Delete the specified user information. + // + NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize); + User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize); + if (Offset < User->UserProfileSize) { + CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset); + } + + if (Save) { + Status = SaveNvUserProfile (User, FALSE); + } + + return Status; +} + + +/** + Add or update user information. + + @param[in] User Point to the user profile. + @param[in, out] UserInfo On entry, points to the user information to modify, + or NULL to add a new UserInfo. + On return, points to the modified user information. + @param[in] Info Points to the new user information. + @param[in] InfoSize The size of Info,in bytes. + + @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SUCCESS User information was successfully changed/added. + +**/ +EFI_STATUS +ModifyUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN OUT EFI_USER_INFO **UserInfo, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + UINTN PayloadLen; + EFI_USER_INFO *OldInfo; + EFI_USER_INFO *IpInfo; + + if ((UserInfo == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user information. + // + if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) { + return EFI_ACCESS_DENIED; + } + + if (!CheckUserInfo (Info)) { + return EFI_INVALID_PARAMETER; + } + + + if (*UserInfo == NULL) { + // + // Add new user information. + // + OldInfo = NULL; + do { + Status = FindUserInfoByType (User, &OldInfo, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + ASSERT (OldInfo != NULL); + + if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) || + ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) { + // + // Same type can not co-exist for exclusive information. + // + return EFI_ACCESS_DENIED; + } + + // + // Check whether it exists in DB. + // + if (Info->InfoSize != OldInfo->InfoSize) { + continue; + } + + if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) { + continue; + } + + PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO); + if (PayloadLen == 0) { + continue; + } + + if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) { + continue; + } + + // + // Yes. The new info is as same as the one in profile. + // + return EFI_SUCCESS; + } while (!EFI_ERROR (Status)); + + Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE); + return Status; + } + + // + // Modify existing user information. + // + OldInfo = *UserInfo; + if (OldInfo->InfoType != Info->InfoType) { + return EFI_INVALID_PARAMETER; + } + + if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) && + (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) { + // + // Try to add exclusive attrib in new info. + // Check whether there is another information with the same type in profile. + // + OldInfo = NULL; + do { + Status = FindUserInfoByType (User, &OldInfo, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + if (OldInfo != *UserInfo) { + // + // There is another information with the same type in profile. + // Therefore, can't modify existing user information to add exclusive attribute. + // + return EFI_ACCESS_DENIED; + } + } while (TRUE); + } + + if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + // + // For user identification policy, need to update the info in credential provider. + // + IpInfo = NULL; + Status = ModifyUserIpInfo (User, Info, InfoSize, &IpInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (IpInfo != NULL); + Status = SaveUserIpInfo (User, IpInfo, UserInfo); + if (IpInfo->InfoSize != Info->InfoSize) { + Status = EFI_DEVICE_ERROR; + } + FreePool (IpInfo); + return Status; + } + + Status = DelUserInfo (User, *UserInfo, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE); +} + + +/** + Delete the user profile from non-volatile memory and database. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS Delete user from the user profile successfully. + @retval Others Fail to delete user from user profile + +**/ +EFI_STATUS +DelUserProfile ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_USER_INFO *UserInfo; + + // + // Check whether it is in the user profile database. + // + Status = FindUserProfile (&User, FALSE, &Index); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether it is the current user. + // + if (User == mCurrentUser) { + return EFI_ACCESS_DENIED; + } + + // + // Delete user credential information. + // + UserInfo = NULL; + Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (Status == EFI_SUCCESS) { + Status = DelUserInfo (User, UserInfo, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Delete user profile from the non-volatile memory. + // + Status = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + mUserProfileDb->UserProfileNum--; + + // + // Modify user profile database. + // + if (Index != mUserProfileDb->UserProfileNum) { + mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum]; + CopyMem ( + ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName, + User->UserVarName, + sizeof (User->UserVarName) + ); + Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Delete user profile information. + // + if (User->ProfileInfo != NULL) { + FreePool (User->ProfileInfo); + } + + FreePool (User); + return EFI_SUCCESS; +} + + +/** + Add user profile to user profile database. + + @param[out] UserProfile Point to the newly added user profile. + @param[in] ProfileSize The size of the user profile. + @param[in] ProfileInfo Point to the user profie data. + @param[in] Save If TRUE, save the new added profile to NV flash. + If FALSE, don't save the profile to NV flash. + + @retval EFI_SUCCESS Add user profile to user profile database successfully. + @retval Others Fail to add user profile to user profile database. + +**/ +EFI_STATUS +AddUserProfile ( + OUT USER_PROFILE_ENTRY **UserProfile, OPTIONAL + IN UINTN ProfileSize, + IN UINT8 *ProfileInfo, + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + + // + // Check the data format to be added. + // + if (!CheckProfileInfo (ProfileInfo, ProfileSize)) { + return EFI_SECURITY_VIOLATION; + } + + // + // Create user profile entry. + // + User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY)); + if (User == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Add the entry to the user profile database. + // + if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) { + if (!ExpandUsermUserProfileDb ()) { + FreePool (User); + return EFI_OUT_OF_RESOURCES; + } + } + + UnicodeSPrint ( + User->UserVarName, + sizeof (User->UserVarName), + L"User%04x", + mUserProfileDb->UserProfileNum + ); + User->UserProfileSize = 0; + User->MaxProfileSize = 0; + User->ProfileInfo = NULL; + mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User; + mUserProfileDb->UserProfileNum++; + + // + // Add user profile information. + // + Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save); + if (EFI_ERROR (Status)) { + DelUserProfile (User); + return Status; + } + // + // Set new user profile handle. + // + if (UserProfile != NULL) { + *UserProfile = User; + } + + return EFI_SUCCESS; +} + + +/** + This function creates a new user profile with only a new user identifier + attached and returns its handle. The user profile is non-volatile, but the + handle User can change across reboots. + + @param[out] User Handle of a new user profile. + + @retval EFI_SUCCESS User profile was successfully created. + @retval Others Fail to create user profile + +**/ +EFI_STATUS +CreateUserProfile ( + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + + if (User == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Generate user id information. + // + UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER)); + if (UserInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UserInfo->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD; + UserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER); + UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + GenerateUserId ((UINT8 *) (UserInfo + 1)); + + // + // Add user profile to the user profile database. + // + Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE); + FreePool (UserInfo); + return Status; +} + + +/** + Add a default user profile to user profile database. + + @retval EFI_SUCCESS A default user profile is added successfully. + @retval Others Fail to add a default user profile + +**/ +EFI_STATUS +AddDefaultUserProfile ( + VOID + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + EFI_USER_INFO *Info; + EFI_USER_INFO *NewInfo; + EFI_USER_INFO_CREATE_DATE CreateDate; + EFI_USER_INFO_USAGE_COUNT UsageCount; + EFI_USER_INFO_ACCESS_CONTROL *Access; + EFI_USER_INFO_IDENTITY_POLICY *Policy; + + // + // Create a user profile. + // + Status = CreateUserProfile (&User); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate a buffer to add all default user information. + // + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Add user name. + // + Info->InfoType = EFI_USER_INFO_NAME_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (mUserName); + CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user profile create date record. + // + Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE); + Status = gRT->GetTime (&CreateDate, NULL); + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user profile usage count record. + // + Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT); + UsageCount = 0; + CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user access right. + // + Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Access = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1); + Access->Type = EFI_USER_INFO_ACCESS_MANAGE; + Access->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL); + Info->InfoSize = sizeof (EFI_USER_INFO) + Access->Size; + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user identity policy. + // + Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE; + Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1); + Policy->Type = EFI_USER_INFO_IDENTITY_TRUE; + Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + Info->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length; + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + +Done: + FreePool (Info); + return Status; +} + + +/** + Publish current user information into EFI System Configuration Table. + + By UEFI spec, the User Identity Manager will publish the current user profile + into the EFI System Configuration Table. Currently, only the user identifier and user + name are published. + + @retval EFI_SUCCESS Current user information is published successfully. + @retval Others Fail to publish current user information + +**/ +EFI_STATUS +PublishUserTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_CONFIGURATION_TABLE *EfiConfigurationTable; + EFI_USER_INFO_TABLE *UserInfoTable; + EFI_USER_INFO *IdInfo; + EFI_USER_INFO *NameInfo; + + Status = EfiGetSystemConfigurationTable ( + &gEfiUserManagerProtocolGuid, + (VOID **) &EfiConfigurationTable + ); + if (!EFI_ERROR (Status)) { + // + // The table existed! + // + return EFI_SUCCESS; + } + + // + // Get user ID information. + // + IdInfo = NULL; + Status = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + if (EFI_ERROR (Status)) { + return Status; + + } + // + // Get user name information. + // + NameInfo = NULL; + Status = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate a buffer for user information table. + // + UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool ( + sizeof (EFI_USER_INFO_TABLE) + + IdInfo->InfoSize + + NameInfo->InfoSize + ); + if (UserInfoTable == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + + UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE); + + // + // Append the user information to the user info table + // + CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize); + UserInfoTable->Size += IdInfo->InfoSize; + + CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize); + UserInfoTable->Size += NameInfo->InfoSize; + + Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable); + return Status; +} + + +/** + Get the user's identity type. + + The identify manager only supports the identity policy in which the credential + provider handles are connected by the operator 'AND' or 'OR'. + + + @param[in] User Handle of a user profile. + @param[out] PolicyType Point to the identity type. + + @retval EFI_SUCCESS Get user's identity type successfully. + @retval Others Fail to get user's identity type. + +**/ +EFI_STATUS +GetIdentifyType ( + IN EFI_USER_PROFILE_HANDLE User, + OUT UINT8 *PolicyType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Search the user identify policy according to type. + // + TotalLen = 0; + *PolicyType = EFI_USER_INFO_IDENTITY_FALSE; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) { + *PolicyType = EFI_USER_INFO_IDENTITY_AND; + break; + } + + if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) { + *PolicyType = EFI_USER_INFO_IDENTITY_OR; + break; + } + TotalLen += Identity->Length; + } + return EFI_SUCCESS; +} + + +/** + Identify the User by the specfied provider. + + @param[in] User Handle of a user profile. + @param[in] Provider Points to the identifir of credential provider. + + @retval EFI_INVALID_PARAMETER Provider is NULL. + @retval EFI_NOT_FOUND Fail to identify the specified user. + @retval EFI_SUCCESS User is identified successfully. + +**/ +EFI_STATUS +IdentifyByProviderId ( + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_GUID *Provider + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_IDENTIFIER UserId; + UINTN Index; + EFI_CREDENTIAL_LOGON_FLAGS AutoLogon; + EFI_HII_HANDLE HiiHandle; + EFI_GUID FormSetId; + EFI_FORM_ID FormId; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + EFI_USER_INFO *IdInfo; + + if (Provider == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the user ID identified by the specified credential provider. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + // + // Check credential provider class. + // + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, Provider)) { + Status = UserCredential->Select (UserCredential, &AutoLogon); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) { + // + // Get credential provider form. + // + Status = UserCredential->Form ( + UserCredential, + &HiiHandle, + &FormSetId, + &FormId + ); + if (!EFI_ERROR (Status)) { + // + // Send form to get user input. + // + Status = mCallbackInfo->FormBrowser2->SendForm ( + mCallbackInfo->FormBrowser2, + &HiiHandle, + 1, + &FormSetId, + FormId, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + Status = UserCredential->User (UserCredential, User, &UserId); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = UserCredential->Deselect (UserCredential); + if (EFI_ERROR (Status)) { + return Status; + } + + if (User == NULL) { + return EFI_SUCCESS; + } + + // + // Get user ID information. + // + IdInfo = NULL; + Status = FindUserInfoByType (User, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + ASSERT (IdInfo != NULL); + + if (CompareMem ((UINT8 *) (IdInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) != 0) { + // + // One user name is selected, but the other's credential is given. Here no user passed. + // + break; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Update user information when user is logon on successfully. + + @param[in] User Points to user profile. + + @retval EFI_SUCCESS Update user information successfully. + @retval Others Fail to update user information. + +**/ +EFI_STATUS +UpdateUserInfo ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + EFI_USER_INFO *NewInfo; + EFI_USER_INFO_CREATE_DATE Date; + EFI_USER_INFO_USAGE_COUNT UsageCount; + UINTN InfoLen; + + // + // Allocate a buffer to update user's date record and usage record. + // + InfoLen = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT)); + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Check create date record. + // + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD); + if (Status == EFI_NOT_FOUND) { + Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE); + Status = gRT->GetTime (&Date, NULL); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + // + // Update usage date record. + // + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD); + if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) { + Info->InfoType = EFI_USER_INFO_USAGE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE); + Status = gRT->GetTime (&Date, NULL); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE)); + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + // + // Update usage count record. + // + UsageCount = 0; + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD); + // + // Get usage count. + // + if (Status == EFI_SUCCESS) { + CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT)); + } + + UsageCount++; + if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) { + Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT); + CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT)); + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + FreePool (Info); + return EFI_SUCCESS; +} + + +/** + Add a credenetial provider item in form. + + @param[in] ProviderGuid Points to the identifir of credential provider. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + +**/ +VOID +AddProviderSelection ( + IN EFI_GUID *ProviderGuid, + IN VOID *OpCodeHandle + ) +{ + EFI_HII_HANDLE HiiHandle; + EFI_STRING_ID ProvID; + CHAR16 *ProvStr; + UINTN Index; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + + for (Index = 0; Index < mProviderDb->Count; Index++) { + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) { + // + // Add credential provider selection. + // + UserCredential->Title (UserCredential, &HiiHandle, &ProvID); + ProvStr = HiiGetString (HiiHandle, ProvID, NULL); + if (ProvStr == NULL) { + continue ; + } + ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL); + FreePool (ProvStr); + HiiCreateActionOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index), // Question ID + ProvID, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + 0 // Action String ID + ); + break; + } + } +} + + +/** + Add a username item in form. + + @param[in] Index The index of the user in the user name list. + @param[in] User Points to the user profile whose username is added. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + + @retval EFI_SUCCESS Add a username successfully. + @retval Others Fail to add a username. + +**/ +EFI_STATUS +AddUserSelection ( + IN UINT16 Index, + IN USER_PROFILE_ENTRY *User, + IN VOID *OpCodeHandle + ) +{ + EFI_STRING_ID UserName; + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + + UserInfo = NULL; + Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add user name selection. + // + UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL); + if (UserName == 0) { + return EFI_OUT_OF_RESOURCES; + } + + HiiCreateGotoOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + FORMID_PROVIDER_FORM, // Target Form ID + UserName, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + (UINT16) Index // Question ID + ); + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identity policy does not contain the operator 'OR'. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS The specified user is identified successfully. + @retval Others Fail to identify the user. + +**/ +EFI_STATUS +IdentifyAndTypeUser ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + BOOLEAN Success; + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Check each part of identification policy expression. + // + Success = FALSE; + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + switch (Identity->Type) { + + case EFI_USER_INFO_IDENTITY_FALSE: + // + // Check False option. + // + Success = FALSE; + break; + + case EFI_USER_INFO_IDENTITY_TRUE: + // + // Check True option. + // + Success = TRUE; + break; + + case EFI_USER_INFO_IDENTITY_NOT: + // + // Check negative operation. + // + break; + + case EFI_USER_INFO_IDENTITY_AND: + // + // Check and operation. + // + if (!Success) { + return EFI_NOT_READY; + } + + Success = FALSE; + break; + + case EFI_USER_INFO_IDENTITY_OR: + // + // Check or operation. + // + if (Success) { + return EFI_SUCCESS; + } + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + // + // Check credential provider by type. + // + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + // + // Check credential provider by ID. + // + if (ValueLen != sizeof (EFI_GUID)) { + return EFI_INVALID_PARAMETER; + } + + Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1)); + if (EFI_ERROR (Status)) { + return Status; + } + + Success = TRUE; + break; + + default: + return EFI_INVALID_PARAMETER; + break; + } + + TotalLen += Identity->Length; + } + + if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + + if (!Success) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identity policy does not contain the operator 'AND'. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS The specified user is identified successfully. + @retval Others Fail to identify the user. + +**/ +EFI_STATUS +IdentifyOrTypeUser ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_PROVIDER_NAME; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add the providers that exists in the user's policy. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle); + } + + TotalLen += Identity->Length; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserManagerGuid, // Formset GUID + FORMID_PROVIDER_FORM, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; +} + + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval Others Fail to handle the action. + +**/ +EFI_STATUS +EFIAPI +UserIdentifyManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + UINT8 PolicyType; + UINT16 Index; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + Status = EFI_SUCCESS; + + switch (Action) { + case EFI_BROWSER_ACTION_FORM_OPEN: + { + // + // Update user Form when user Form is opened. + // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form. + // + if (QuestionId != FORM_OPEN_QUESTION_ID) { + return EFI_SUCCESS; + } + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_NAME; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add all the user profile in the user profile database. + // + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index]; + AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle); + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserManagerGuid, // Formset GUID + FORMID_USER_FORM, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; + } + break; + + case EFI_BROWSER_ACTION_FORM_CLOSE: + Status = EFI_SUCCESS; + break; + + case EFI_BROWSER_ACTION_CHANGING: + { + if (QuestionId >= LABEL_PROVIDER_NAME) { + // + // QuestionId comes from the second Form (Select a Credential Provider if identity + // policy is OR type). Identify the user by the selected provider. + // + Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier); + if (Status == EFI_SUCCESS) { + mIdentified = TRUE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + return EFI_SUCCESS; + } + + // + // QuestionId comes from the first Form (Select a user to identify). + // + User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF]; + Status = GetIdentifyType (User, &PolicyType); + if (EFI_ERROR (Status)) { + return Status; + } + + if (PolicyType == EFI_USER_INFO_IDENTITY_OR) { + // + // Identify the user by "OR" logical. + // + Status = IdentifyOrTypeUser (User); + if (EFI_ERROR (Status)) { + return Status; + } + + mCurrentUser = (EFI_USER_PROFILE_HANDLE) User; + } else { + // + // Identify the user by "AND" logical. + // + Status = IdentifyAndTypeUser (User); + if (EFI_ERROR (Status)) { + return Status; + } + + mCurrentUser = (EFI_USER_PROFILE_HANDLE) User; + mIdentified = TRUE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + } + break; + + default: + // + // All other action return unsupported. + // + Status = EFI_UNSUPPORTED; + break; + } + + + return Status; +} + + +/** + This function construct user profile database from user data saved in the Flash. + If no user is found in Flash, add one default user "administrator" in the user + profile database. + + @retval EFI_SUCCESS Init user profile database successfully. + @retval Others Fail to init user profile database. + +**/ +EFI_STATUS +InitUserProfileDb ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 *VarData; + UINTN VarSize; + UINTN CurVarSize; + CHAR16 VarName[10]; + UINTN Index; + UINT32 VarAttr; + + if (mUserProfileDb != NULL) { + // + // The user profiles had been already initialized. + // + return EFI_SUCCESS; + } + + // + // Init user profile database structure. + // + if (!ExpandUsermUserProfileDb ()) { + return EFI_OUT_OF_RESOURCES; + } + + CurVarSize = DEFAULT_PROFILE_SIZE; + VarData = AllocateZeroPool (CurVarSize); + if (VarData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all user proifle entries. + // + Index = 0; + while (TRUE) { + // + // Get variable name. + // + UnicodeSPrint ( + VarName, + sizeof (VarName), + L"User%04x", + Index + ); + Index++; + + // + // Get variable value. + // + VarSize = CurVarSize; + Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (VarData); + VarData = AllocatePool (VarSize); + if (VarData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + CurVarSize = VarSize; + Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData); + } + + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + } + break; + } + + // + // Check variable attributes. + // + if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) { + Status = gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + continue; + } + + // + // Add user profile to the user profile database. + // + Status = AddUserProfile (NULL, VarSize, VarData, FALSE); + if (EFI_ERROR (Status)) { + if (Status == EFI_SECURITY_VIOLATION) { + // + // Delete invalid user profile + // + gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + } else if (Status == EFI_OUT_OF_RESOURCES) { + break; + } + } else { + // + // Delete and save the profile again if some invalid profiles are deleted. + // + if (mUserProfileDb->UserProfileNum < Index) { + gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE); + } + } + } + + if (VarData != NULL) { + FreePool (VarData); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check whether the user profile database is empty. + // + if (mUserProfileDb->UserProfileNum == 0) { + Status = AddDefaultUserProfile (); + } + + return Status; +} + + +/** + This function collects all the credential providers and saves to mProviderDb. + + @retval EFI_SUCCESS Collect credential providers successfully. + @retval Others Fail to collect credential providers. + +**/ +EFI_STATUS +InitProviderInfo ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + + if (mProviderDb != NULL) { + // + // The credential providers had been collected before. + // + return EFI_SUCCESS; + } + + // + // Try to find all the user credential provider driver. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUserCredentialProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get provider infomation. + // + mProviderDb = AllocateZeroPool ( + sizeof (CREDENTIAL_PROVIDER_INFO) - + sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + + HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + ); + if (mProviderDb == NULL) { + FreePool (HandleBuf); + return EFI_OUT_OF_RESOURCES; + } + + mProviderDb->Count = HandleCount; + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuf[Index], + &gEfiUserCredentialProtocolGuid, + (VOID **) &mProviderDb->Provider[Index] + ); + if (EFI_ERROR (Status)) { + FreePool (HandleBuf); + FreePool (mProviderDb); + mProviderDb = NULL; + return Status; + } + } + + FreePool (HandleBuf); + return EFI_SUCCESS; +} + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + + +/** + This function initialize the data mainly used in form browser. + + @retval EFI_SUCCESS Initialize form data successfully. + @retval Others Fail to Initialize form data. + +**/ +EFI_STATUS +InitFormBrowser ( + VOID + ) +{ + EFI_STATUS Status; + USER_MANAGER_CALLBACK_INFO *CallbackInfo; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + // + // Initialize driver private data. + // + CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO)); + if (CallbackInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CallbackInfo->Signature = USER_MANAGER_SIGNATURE; + CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig; + CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig; + CallbackInfo->ConfigAccess.Callback = UserIdentifyManagerCallback; + + // + // Locate Hii Database protocol. + // + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase); + if (EFI_ERROR (Status)) { + return Status; + } + CallbackInfo->HiiDatabase = HiiDatabase; + + // + // Locate HiiString protocol. + // + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); + if (EFI_ERROR (Status)) { + return Status; + } + CallbackInfo->HiiString = HiiString; + + // + // Locate Formbrowser2 protocol. + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + CallbackInfo->FormBrowser2 = FormBrowser2; + CallbackInfo->DriverHandle = NULL; + + // + // Install Device Path Protocol and Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &CallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &CallbackInfo->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish HII data. + // + CallbackInfo->HiiHandle = HiiAddPackages ( + &mUserManagerGuid, + CallbackInfo->DriverHandle, + UserIdentifyManagerStrings, + UserIdentifyManagerVfrBin, + NULL + ); + if (CallbackInfo->HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mCallbackInfo = CallbackInfo; + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identification policy supports auto logon. + + @param[in] ProviderIndex The provider index in the provider list. + @param[out] User Points to user user profile if a user is identified successfully. + + @retval EFI_SUCCESS Identify a user with the specified provider successfully. + @retval Others Fail to identify a user. + +**/ +EFI_STATUS +IdentifyAutoLogonUser ( + IN UINTN ProviderIndex, + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + UINT8 PolicyType; + + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER)); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Info->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER); + + // + // Identify the specified credential provider's auto logon user. + // + Status = mProviderDb->Provider[ProviderIndex]->User ( + mProviderDb->Provider[ProviderIndex], + NULL, + (EFI_USER_INFO_IDENTIFIER *) (Info + 1) + ); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + // + // Find user with the specified user ID. + // + *User = NULL; + Status = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize); + FreePool (Info); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType); + if (PolicyType == EFI_USER_INFO_IDENTITY_AND) { + // + // The identified user need also identified by other credential provider. + // This can handle through select user. + // + return EFI_NOT_READY; + } + + return Status; +} + + +/** + Check whether the given console is ready. + + @param[in] ProtocolGuid Points to the protocol guid of sonsole . + + @retval TRUE The given console is ready. + @retval FALSE The given console is not ready. + +**/ +BOOLEAN +CheckConsole ( + EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Try to find all the handle driver. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + ProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + for (Index = 0; Index < HandleCount; Index++) { + DevicePath = DevicePathFromHandle (HandleBuf[Index]); + if (DevicePath != NULL) { + FreePool (HandleBuf); + return TRUE; + } + } + FreePool (HandleBuf); + return FALSE; +} + + +/** + Check whether the console is ready. + + @retval TRUE The console is ready. + @retval FALSE The console is not ready. + +**/ +BOOLEAN +IsConsoleReady ( + VOID + ) +{ + if (!CheckConsole (&gEfiSimpleTextOutProtocolGuid)) { + return FALSE; + } + + if (!CheckConsole (&gEfiSimpleTextInProtocolGuid)) { + if (!CheckConsole (&gEfiSimpleTextInputExProtocolGuid)) { + return FALSE; + } + } + + return TRUE; +} + + +/** + Identify a user to logon. + + @param[out] User Points to user user profile if a user is identified successfully. + + @retval EFI_SUCCESS Identify a user successfully. + +**/ +EFI_STATUS +IdentifyUser ( + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_CREDENTIAL_LOGON_FLAGS AutoLogon; + EFI_USER_INFO *IdentifyInfo; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + USER_PROFILE_ENTRY *UserEntry; + + // + // Initialize credential providers. + // + InitProviderInfo (); + + // + // Initialize user profile database. + // + InitUserProfileDb (); + + // + // If only one user in system, and its identify policy is TRUE, then auto logon. + // + if (mUserProfileDb->UserProfileNum == 1) { + UserEntry = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[0]; + IdentifyInfo = NULL; + Status = FindUserInfoByType (UserEntry, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1)); + if (Identity->Type == EFI_USER_INFO_IDENTITY_TRUE) { + mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry; + UpdateUserInfo (UserEntry); + *User = UserEntry; + return EFI_SUCCESS; + } + } + + // + // Find and login the default & AutoLogon user. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + UserCredential = mProviderDb->Provider[Index]; + Status = UserCredential->Default (UserCredential, &AutoLogon); + if (EFI_ERROR (Status)) { + continue; + } + + if ((AutoLogon & (EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO)) != 0) { + Status = IdentifyAutoLogonUser (Index, &UserEntry); + if (Status == EFI_SUCCESS) { + mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry; + UpdateUserInfo (UserEntry); + *User = UserEntry; + return EFI_SUCCESS; + } + } + } + + if (!IsConsoleReady ()) { + // + // The console is still not ready for user selection. + // + return EFI_ACCESS_DENIED; + } + + // + // Select a user and identify it. + // + mCallbackInfo->FormBrowser2->SendForm ( + mCallbackInfo->FormBrowser2, + &mCallbackInfo->HiiHandle, + 1, + &mUserManagerGuid, + 0, + NULL, + NULL + ); + + if (mIdentified) { + *User = (USER_PROFILE_ENTRY *) mCurrentUser; + UpdateUserInfo (*User); + return EFI_SUCCESS; + } + + return EFI_ACCESS_DENIED; +} + + +/** + An empty function to pass error checking of CreateEventEx (). + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +InternalEmptyFuntion ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + + +/** + Create, Signal, and Close the User Profile Changed event. + +**/ +VOID +SignalEventUserProfileChanged ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InternalEmptyFuntion, + NULL, + &gEfiEventUserProfileChangedGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + gBS->SignalEvent (Event); + gBS->CloseEvent (Event); +} + + +/** + Create a new user profile. + + This function creates a new user profile with only a new user identifier attached and returns + its handle. The user profile is non-volatile, but the handle User can change across reboots. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the new user profile handle. + The user profile handle is unique only during this boot. + + @retval EFI_SUCCESS User profile was successfully created. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to create a + user profile. + @retval EFI_UNSUPPORTED Creation of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCreate ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) { + return EFI_ACCESS_DENIED; + } + } + + // + // Create new user profile + // + Status = CreateUserProfile ((USER_PROFILE_ENTRY **) User); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Delete an existing user profile. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User User profile handle. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to delete a user + profile or there is only one user profile. + @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile. + +**/ +EFI_STATUS +EFIAPI +UserProfileDelete ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + return EFI_ACCESS_DENIED; + } + + // + // Delete user profile. + // + Status = DelUserProfile (User); + if (EFI_ERROR (Status)) { + if (Status != EFI_INVALID_PARAMETER) { + return EFI_ACCESS_DENIED; + } + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +/** + Enumerate all of the enrolled users on the platform. + + This function returns the next enrolled user profile. To retrieve the first user profile handle, + point User at a NULL. Each subsequent call will retrieve another user profile handle until there + are no more, at which point User will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previous user profile handle or NULL to + start enumeration. On exit, points to the next user profile handle + or NULL if there are no more user profiles. + + @retval EFI_SUCCESS Next enrolled user profile successfully returned. + @retval EFI_ACCESS_DENIED Next enrolled user profile was not successfully returned. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. +**/ +EFI_STATUS +EFIAPI +UserProfileGetNext ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = FindUserProfile ((USER_PROFILE_ENTRY **) User, TRUE, NULL); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Return the current user profile handle. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] CurrentUser On return, points to the current user profile handle. + + @retval EFI_SUCCESS Current user profile handle returned successfully. + @retval EFI_INVALID_PARAMETER The CurrentUser parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCurrent ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *CurrentUser + ) +{ + // + // Get current user profile. + // + if ((This == NULL) || (CurrentUser == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *CurrentUser = mCurrentUser; + return EFI_SUCCESS; +} + + +/** + Identify a user. + + Identify the user and, if authenticated, returns the user handle and changes the current + user profile. All user information marked as private in a previously selected profile + is no longer available for inspection. + Whenever the current user profile is changed then the an event with the GUID + EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the user profile handle for the current + user profile. + + @retval EFI_SUCCESS User was successfully identified. + @retval EFI_ACCESS_DENIED User was not successfully identified. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileIdentify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (mCurrentUser != NULL) { + *User = mCurrentUser; + return EFI_SUCCESS; + } + + // + // Identify user + // + Status = IdentifyUser ((USER_PROFILE_ENTRY **) User); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + + // + // Publish the user info into the EFI system configuration table. + // + PublishUserTable (); + + // + // Signal User Profile Changed event. + // + SignalEventUserProfileChanged (); + return EFI_SUCCESS; +} + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. + The search starts with the user information record handle following UserInfo and + continues until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record + type and the user information record data matches the portion of Info. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previously returned user profile + handle, or NULL to start searching with the first user profile. + On return, points to the user profile handle, or NULL if not + found. + @param[in, out] UserInfo On entry, points to the previously returned user information + handle, or NULL to start searching with the first. On return, + points to the user information handle of the user information + record, or NULL if not found. Can be NULL, in which case only + one user information record per user can be returned. + @param[in] Info Points to the buffer containing the user information to be + compared to the user information record. If the user information + record data is empty, then only the user information record type + is compared. If InfoSize is 0, then the user information record + must be empty. + + @param[in] InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User information was found. User points to the user profile + handle, and UserInfo points to the user information handle. + @retval EFI_NOT_FOUND User information was not found. User points to NULL, and + UserInfo points to NULL. + @retval EFI_INVALID_PARAMETER User is NULL. Or Info is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileFind ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo OPTIONAL, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + UINTN Size; + + if ((This == NULL) || (User == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize == 0) { + // + // If InfoSize is 0, then the user information record must be empty. + // + if (Info->InfoSize != sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + } else { + if (InfoSize != Info->InfoSize) { + return EFI_INVALID_PARAMETER; + } + } + Size = Info->InfoSize; + + // + // Find user profile accdoring to user information. + // + Status = FindUserProfileByInfo ( + (USER_PROFILE_ENTRY **) User, + (EFI_USER_INFO **) UserInfo, + (EFI_USER_INFO *) Info, + Size + ); + if (EFI_ERROR (Status)) { + *User = NULL; + if (UserInfo != NULL) { + *UserInfo = NULL; + } + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + Return information attached to the user. + + This function returns user information. The format of the information is described in User + Information. The function may return EFI_ACCESS_DENIED if the information is marked private + and the handle specified by User is not the current user profile. The function may return + EFI_ACCESS_DENIED if the information is marked protected and the information is associated + with a credential provider for which the user has not been authenticated. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, + holds the user information. If the buffer is too small to hold the + information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is + updated to contain the number of bytes actually required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the size + of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The information about the specified user cannot be accessed by the + current user. + @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the + returned data. The actual size required is returned in *InfoSize. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not refer + to a valid user info handle. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (InfoSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((*InfoSize != 0) && (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((User == NULL) || (UserInfo == NULL)) { + return EFI_NOT_FOUND; + } + + Status = GetUserInfo (User, UserInfo, Info, InfoSize, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + return EFI_BUFFER_TOO_SMALL; + } + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Add or update user information. + + This function changes user information. If NULL is pointed to by UserInfo, then a new user + information record is created and its handle is returned in UserInfo. Otherwise, the existing + one is replaced. + If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same + type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and UserInfo + will point to the handle of the existing record. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in, out] UserInfo Handle of the user information data record. + @param[in] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, + holds the user information. If the buffer is too small to hold the + information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is + updated to contain the number of bytes actually required. + @param[in] InfoSize On entry, points to the size of Info. On return, points to the size + of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SECURITY_VIOLATION The current user does not have permission to change the specified + user profile or user information record. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not + refer to a valid user info handle. + @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL. +**/ +EFI_STATUS +EFIAPI +UserProfileSetInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL) || (UserInfo == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (User != mCurrentUser) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + if (*UserInfo != NULL) { + // + // Can't update info in other profiles without MANAGE right. + // + return EFI_SECURITY_VIOLATION; + } + + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) { + // + // Can't add info into other profiles. + // + return EFI_SECURITY_VIOLATION; + } + } + } + + if (User == mCurrentUser) { + if (CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_SELF)) { + // + // Only identify policy can be added/updated. + // + if (Info->InfoType != EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + return EFI_SECURITY_VIOLATION; + } + } + } + + // + // Modify user information. + // + Status = ModifyUserInfo (User, (EFI_USER_INFO **) UserInfo, Info, InfoSize); + if (EFI_ERROR (Status)) { + if (Status == EFI_ACCESS_DENIED) { + return EFI_ACCESS_DENIED; + } + return EFI_SECURITY_VIOLATION; + } + return EFI_SUCCESS; +} + + +/** + Called by credential provider to notify of information change. + + This function allows the credential provider to notify the User Identity Manager when user status + has changed while deselected. + If the User Identity Manager doesn't support asynchronous changes in credentials, then this function + should return EFI_UNSUPPORTED. + If the User Identity Manager supports this, it will call User() to get the user identifier and then + GetNextInfo() and GetInfo() in the User Credential Protocol to get all of the information from the + credential and add it. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] Changed Handle on which is installed an instance of the EFI_USER_CREDENTIAL_PROTOCOL + where the user has changed. + + @retval EFI_SUCCESS The User Identity Manager has handled the notification. + @retval EFI_NOT_READY The function was called while the specified credential provider was not selected. + @retval EFI_UNSUPPORTED The User Identity Manager doesn't support asynchronous notifications. + +**/ +EFI_STATUS +EFIAPI +UserProfileNotify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_HANDLE Changed + ) +{ + EFI_STATUS Status; + EFI_USER_CREDENTIAL_PROTOCOL *Provider; + EFI_USER_INFO_IDENTIFIER UserId; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO_HANDLE UserInfo2; + UINTN InfoSize; + EFI_USER_INFO *Info; + USER_PROFILE_ENTRY *User; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->HandleProtocol ( + Changed, + &gEfiUserCredentialProtocolGuid, + (VOID **) &Provider + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Provider->User (Provider, NULL, &UserId); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + // + // Find user with the UserId. + // + User = NULL; + while (TRUE) { + // + // Find next user profile. + // + Status = FindUserProfile (&User, TRUE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find the user information. + // + Info = NULL; + FindUserInfoByType (User, &Info, EFI_USER_INFO_IDENTIFIER_RECORD); + if (CompareMem ((UINT8 *) (Info + 1), UserId, sizeof (UserId)) == 0) { + // + // Found the infomation record. + // + break; + } + } + + UserInfo = NULL; + do { + // + // Get user info handle. + // + Status = Provider->GetNextInfo(Provider, &UserInfo); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Get the user information from the user info handle. + // + InfoSize = 0; + Status = Provider->GetInfo(Provider, UserInfo, NULL, &InfoSize); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + Info = AllocateZeroPool (InfoSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = Provider->GetInfo(Provider, UserInfo, Info, &InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + break; + } + + // + // Save the user information. + // + UserInfo2 = NULL; + Status = UserProfileSetInfo (&gUserIdentifyManager, (EFI_USER_PROFILE_HANDLE)User, &UserInfo2, Info, InfoSize); + FreePool (Info); + if (EFI_ERROR (Status)) { + break; + } + } while (TRUE); + + return Status; +} + + +/** + Delete user information. + + Delete the user information attached to the user profile specified by the UserInfo. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information deleted successfully. + @retval EFI_NOT_FOUND User information record UserInfo does not exist in the user profile. + @retval EFI_ACCESS_DENIED The current user does not have permission to delete this user information. + +**/ +EFI_STATUS +EFIAPI +UserProfileDeleteInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo + ) +{ + EFI_STATUS Status; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (User != mCurrentUser) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + return EFI_ACCESS_DENIED; + } + } + + // + // Delete user information. + // + Status = DelUserInfo (User, UserInfo, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + return EFI_NOT_FOUND; + } + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Enumerate user information of all the enrolled users on the platform. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in, out] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNextInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ) +{ + if ((This == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // Get next user information entry. + // + return FindUserInfo (User, (EFI_USER_INFO **) UserInfo, TRUE, NULL); +} + + +/** + Main entry for this driver. + + @param[in] ImageHandle Image handle this driver. + @param[in] SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +UserIdentifyManagerInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + + // + // Initiate form browser. + // + InitFormBrowser (); + + // + // Install protocol interfaces for the User Identity Manager. + // + Status = gBS->InstallProtocolInterface ( + &mCallbackInfo->DriverHandle, + &gEfiUserManagerProtocolGuid, + EFI_NATIVE_INTERFACE, + &gUserIdentifyManager + ); + ASSERT_EFI_ERROR (Status); + + LoadDeferredImageInit (ImageHandle); + return EFI_SUCCESS; +} + + diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h new file mode 100644 index 0000000000..b1e078a03e --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h @@ -0,0 +1,413 @@ +/** @file + The header file for User identify Manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USER_IDENTIFY_MANAGER_H_ +#define _USER_IDENTIFY_MANAGER_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UserIdentifyManagerData.h" + +// +// This is the generated IFR binary data for each formset defined in VFR. +// This data array is ready to be used as input of HiiAddPackages() to +// create a packagelist. +// +extern UINT8 UserIdentifyManagerVfrBin[]; + +// +// This is the generated String package data for all .UNI files. +// This data array is ready to be used as input of HiiAddPackages() to +// create a packagelist. +// +extern UINT8 UserIdentifyManagerStrings[]; + +#define USER_NUMBER_INC 32 +#define DEFAULT_PROFILE_SIZE 512 +#define INFO_PAYLOAD_SIZE 64 + +// +// Credential Provider Information. +// +typedef struct { + UINTN Count; + EFI_USER_CREDENTIAL_PROTOCOL *Provider[1]; +} CREDENTIAL_PROVIDER_INFO; + +// +// Internal user profile entry. +// +typedef struct { + UINTN MaxProfileSize; + UINTN UserProfileSize; + CHAR16 UserVarName[9]; + UINT8 *ProfileInfo; +} USER_PROFILE_ENTRY; + +// +// Internal user profile database. +// +typedef struct { + UINTN UserProfileNum; + UINTN MaxProfileNum; + EFI_USER_PROFILE_HANDLE UserProfile[1]; +} USER_PROFILE_DB; + +#define USER_MANAGER_SIGNATURE SIGNATURE_32 ('U', 'I', 'M', 'S') + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + + // + // Consumed protocol. + // + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + // + // Produced protocol. + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} USER_MANAGER_CALLBACK_INFO; + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +/** + Register an event notification function for the user profile changed. + + @param[in] ImageHandle Image handle this driver. + +**/ +VOID +LoadDeferredImageInit ( + IN EFI_HANDLE ImageHandle + ); + + +/** + This function creates a new user profile with only + a new user identifier attached and returns its handle. + The user profile is non-volatile, but the handle User + can change across reboots. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param[out] User Handle of a new user profile. + + @retval EFI_SUCCESS User profile was successfully created. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions + to create a user profile. + @retval EFI_UNSUPPORTED Creation of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCreate ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + Delete an existing user profile. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User User profile handle. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions + to delete a user profile or there is only one + user profile. + @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile. + +**/ +EFI_STATUS +EFIAPI +UserProfileDelete ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + + +/** + Get next user profile from the user profile database. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param[in, out] User User profile handle. + + @retval EFI_SUCCESS Next enrolled user profile successfully returned. + @retval EFI_INVALID_PARAMETER User is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNext ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + This function returns the current user profile handle. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param[out] CurrentUser User profile handle. + + @retval EFI_SUCCESS Current user profile handle returned successfully. + @retval EFI_INVALID_PARAMETER CurrentUser is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCurrent ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *CurrentUser + ); + + +/** + Identify the user and, if authenticated, returns the user handle and changes + the current user profile. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param CurrentUser User profile handle. + + @retval EFI_SUCCESS User was successfully identified. + @retval EFI_INVALID_PARAMETER User is NULL. + @retval EFI_ACCESS_DENIED User was not successfully identified. + +**/ +EFI_STATUS +EFIAPI +UserProfileIdentify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. + The search starts with the user information record handle following UserInfo and + continues until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record + type and the user information record data matches the portion of Info passed the + EFI_USER_INFO header. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previously returned user profile + handle, or NULL to start searching with the first user profile. + On return, points to the user profile handle, or NULL if not + found. + @param[in, out] UserInfo On entry, points to the previously returned user information + handle, or NULL to start searching with the first. On return, + points to the user information handle of the user information + record, or NULL if not found. Can be NULL, in which case only + one user information record per user can be returned. + @param[in] Info Points to the buffer containing the user information to be + compared to the user information record. If NULL, then only + the user information record type is compared. If InfoSize is 0, + then the user information record must be empty. + + @param[in] InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User information was found. User points to the user profile handle, + and UserInfo points to the user information handle. + @retval EFI_NOT_FOUND User information was not found. User points to NULL and UserInfo + points to NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileFind ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo OPTIONAL, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ); + + +/** + This function returns user information. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User Handle of the user whose profile will be + retrieved. + @param UserInfo Handle of the user information data record. + @param Info On entry, points to a buffer of at least + *InfoSize bytes. On exit, holds the user + information. + @param InfoSize On entry, points to the size of Info. On return, + points to the size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The information about the specified user cannot + be accessed by the current user. + EFI_BUFFER_TOO_SMALL- The number of bytes + specified by *InfoSize is too small to hold the + returned data. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + + +/** + This function changes user information. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User Handle of the user whose profile will be + retrieved. + @param UserInfo Handle of the user information data record. + @param Info Points to the user information. + @param InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User profile information was successfully + changed/added. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SECURITY_VIOLATION The current user does not have permission to + change the specified user profile or user + information record. + +**/ +EFI_STATUS +EFIAPI +UserProfileSetInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ); + + +/** + This function allows the credential provider to notify the User Identity Manager + when user status has changed while deselected. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param Changed Points to the instance of the + EFI_USER_CREDENTIAL_PROTOCOL where the user has + changed. + + @retval EFI_SUCCESS The User Identity Manager has handled the + notification. + @retval EFI_NOT_READY The function was called while the specified + credential provider was not selected. + @retval EFI_UNSUPPORTED The User Identity Manager doesn't support + asynchronous notifications. + +**/ +EFI_STATUS +EFIAPI +UserProfileNotify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_HANDLE Changed + ); + + +/** + Delete the user information attached to the user profile specified by the UserInfo. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param User Handle of the user whose profile will be retrieved. + @param UserInfo Handle of the user information data record. + + @retval EFI_SUCCESS User information deleted successfully. + @retval EFI_ACCESS_DENIED The current user does not have permission to + delete this user in-formation. + @retval EFI_NOT_FOUND User information record UserInfo does not exist + in the user pro-file. + +**/ +EFI_STATUS +EFIAPI +UserProfileDeleteInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo + ); + + +/** + This function returns the next user information record. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param User Handle of the user whose profile will be retrieved. + @param UserInfo Handle of the user information data record. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNextInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +#endif diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h new file mode 100644 index 0000000000..d91de101f7 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h @@ -0,0 +1,42 @@ +/** @file + Data structure used by the user identify manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USER_IDENTIFY_MANAGER_DATA_H_ +#define _USER_IDENTIFY_MANAGER_DATA_H_ + +#include "UserIdentifyManagerStrDefs.h" + +// +// Guid used in user profile saving and in form browser. +// +#define USER_IDENTIFY_MANAGER_GUID \ + { \ + 0x3ccd3dd8, 0x8d45, 0x4fed, { 0x96, 0x2d, 0x2b, 0x38, 0xcd, 0x82, 0xb3, 0xc4 } \ + } + +// +// Forms definition. +// +#define FORMID_USER_FORM 1 +#define FORMID_PROVIDER_FORM 2 + +// +// Labels definition. +// +#define LABEL_USER_NAME 0x1000 +#define LABEL_PROVIDER_NAME 0x3000 +#define LABEL_END 0xffff +#define FORM_OPEN_QUESTION_ID 0xfffe + +#endif diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf new file mode 100644 index 0000000000..d5fccea342 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf @@ -0,0 +1,62 @@ +## @file +# Component description file for user identify manager driver. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = UserIdentifyManager + FILE_GUID = C5D3191B-27D5-4873-8DF2-628136991A21 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = UserIdentifyManagerInit + +[sources] + UserIdentifyManager.c + LoadDeferredImage.c + UserIdentifyManager.h + UserIdentifyManagerData.h + UserIdentifyManagerStrings.uni + UserIdentifyManagerVfr.Vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + DebugLib + HiiLib + UefiLib + +[Guids] + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiEventUserProfileChangedGuid ## CONSUMES ## Guid + +[Protocols] + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiHiiDatabaseProtocolGuid ## CONSUMES + gEfiUserCredentialProtocolGuid ## CONSUMES + gEfiDeferredImageLoadProtocolGuid ## CONSUMES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiUserManagerProtocolGuid ## PRODUCES + gEfiSimpleTextOutProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextInputExProtocolGuid + +[Depex] + gEfiHiiDatabaseProtocolGuid AND + gEfiHiiStringProtocolGuid AND + gEfiFormBrowser2ProtocolGuid diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni new file mode 100644 index 0000000000..8ae4489715 Binary files /dev/null and b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni differ diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr new file mode 100644 index 0000000000..ebe8195c73 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr @@ -0,0 +1,44 @@ +/** @file + User identify manager formset. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManagerData.h" + +formset + guid = USER_IDENTIFY_MANAGER_GUID, + title = STRING_TOKEN(STR_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = USER_IDENTIFY_MANAGER_GUID, + + form formid = FORMID_USER_FORM, + title = STRING_TOKEN(STR_USER_SELECT); + + suppressif TRUE; + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = FORM_OPEN_QUESTION_ID; + endif; + + label LABEL_USER_NAME; + label LABEL_END; + endform; + + form formid = FORMID_PROVIDER_FORM, + title = STRING_TOKEN(STR_PROVIDER_SELECT); + label LABEL_PROVIDER_NAME; + label LABEL_END; + endform; +endformset; \ No newline at end of file -- cgit v1.2.3