summaryrefslogtreecommitdiff
path: root/SecurityPkg/UserIdentification
diff options
context:
space:
mode:
authorgdong1 <gdong1@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-02 07:49:32 +0000
committergdong1 <gdong1@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-02 07:49:32 +0000
commit0c18794ea4289f03fefc7117b56740414cc0536c (patch)
tree4e51c5cc23c69a67cead8c58464da870daa4c029 /SecurityPkg/UserIdentification
parent986d1dfb0813d6a7623531e85c2e2a7e1f956cf8 (diff)
downloadedk2-platforms-0c18794ea4289f03fefc7117b56740414cc0536c.tar.xz
Add security package to repository.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'SecurityPkg/UserIdentification')
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c1422
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h354
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h33
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf53
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.unibin0 -> 5128 bytes
-rw-r--r--SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr35
-rw-r--r--SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c1407
-rw-r--r--SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h354
-rw-r--r--SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf58
-rw-r--r--SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.unibin0 -> 3556 bytes
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c148
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c4381
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h413
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h42
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf62
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.unibin0 -> 2696 bytes
-rw-r--r--SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr44
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c372
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c314
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c806
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h387
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h161
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf60
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.unibin0 -> 21532 bytes
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr247
-rw-r--r--SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c2511
26 files changed, 13664 insertions, 0 deletions
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c
new file mode 100644
index 0000000000..ad1521040c
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c
@@ -0,0 +1,1422 @@
+/** @file
+ Password Credential Provider driver implementation.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+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 "PwdCredentialProvider.h"
+
+CREDENTIAL_TABLE *mPwdTable = NULL;
+PWD_PROVIDER_CALLBACK_INFO *mCallbackInfo = NULL;
+PASSWORD_CREDENTIAL_INFO *mPwdInfoHandle = NULL;
+
+//
+// Used for save password credential and form browser.
+// Also used as provider identifier.
+//
+EFI_GUID mPwdCredentialGuid = PWD_CREDENTIAL_PROVIDER_GUID;
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ { 0xeba7fc2b, 0xa465, 0x4d96, { 0x85, 0xa9, 0xd2, 0xf6, 0x64, 0xdf, 0x9b, 0x45 } }
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+EFI_USER_CREDENTIAL_PROTOCOL gPwdCredentialProviderDriver = {
+ PWD_CREDENTIAL_PROVIDER_GUID,
+ EFI_USER_CREDENTIAL_CLASS_PASSWORD,
+ CredentialEnroll,
+ CredentialForm,
+ CredentialTile,
+ CredentialTitle,
+ CredentialUser,
+ CredentialSelect,
+ CredentialDeselect,
+ CredentialDefault,
+ CredentialGetInfo,
+ CredentialGetNextInfo
+};
+
+
+/**
+ Get string by string id from HII Interface.
+
+
+ @param[in] Id String ID to get the string from.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ //
+ // Get the current string for the current Language.
+ //
+ return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL);
+}
+
+
+/**
+ Expand password table size.
+
+**/
+VOID
+ExpandTableSize (
+ VOID
+ )
+{
+ CREDENTIAL_TABLE *NewTable;
+ UINTN Count;
+
+ Count = mPwdTable->MaxCount + PASSWORD_TABLE_INC;
+ //
+ // Create new credential table.
+ //
+ NewTable = (CREDENTIAL_TABLE *) AllocateZeroPool (
+ sizeof (CREDENTIAL_TABLE) +
+ (Count - 1) * sizeof (PASSWORD_INFO)
+ );
+ ASSERT (NewTable != NULL);
+
+ NewTable->MaxCount = Count;
+ NewTable->Count = mPwdTable->Count;
+ NewTable->ValidIndex = mPwdTable->ValidIndex;
+ //
+ // Copy old entries
+ //
+ CopyMem (
+ &NewTable->UserInfo,
+ &mPwdTable->UserInfo,
+ mPwdTable->Count * sizeof (PASSWORD_INFO)
+ );
+ FreePool (mPwdTable);
+ mPwdTable = NewTable;
+}
+
+
+/**
+ Add or delete info in table, and sync with NV variable.
+
+ @param[in] Index The index of the password in table. The index begin from 1.
+ If index is found in table, delete the info, else add the
+ into to table.
+ @param[in] Info The new password info to add into table.
+
+ @retval EFI_INVALID_PARAMETER Info is NULL when save the info.
+ @retval EFI_SUCCESS Modify the table successfully.
+ @retval Others Failed to modify the table.
+
+**/
+EFI_STATUS
+ModifyTable (
+ IN UINTN Index,
+ IN PASSWORD_INFO * Info OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (Index < mPwdTable->Count) {
+ //
+ // Delete the specified entry.
+ //
+ mPwdTable->Count--;
+ if (Index != mPwdTable->Count) {
+ CopyMem (
+ &mPwdTable->UserInfo[Index],
+ &mPwdTable->UserInfo[mPwdTable->Count],
+ sizeof (PASSWORD_INFO)
+ );
+ }
+ } else {
+ //
+ // Add a new entry.
+ //
+ if (Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mPwdTable->Count >= mPwdTable->MaxCount) {
+ ExpandTableSize ();
+ }
+
+ CopyMem (
+ &mPwdTable->UserInfo[mPwdTable->Count],
+ Info,
+ sizeof (PASSWORD_INFO)
+ );
+ mPwdTable->Count++;
+ }
+
+ //
+ // Save the credential table.
+ //
+ Status = gRT->SetVariable (
+ L"PwdCredential",
+ &mPwdCredentialGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ mPwdTable->Count * sizeof (PASSWORD_INFO),
+ &mPwdTable->UserInfo
+ );
+ return Status;
+}
+
+
+/**
+ Create a password table.
+
+ @retval EFI_SUCCESS Create a password table successfully.
+ @retval Others Failed to create a password.
+
+**/
+EFI_STATUS
+InitCredentialTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Var;
+ UINTN VarSize;
+
+ //
+ // Get Password credential data from NV variable.
+ //
+ VarSize = 0;
+ Var = NULL;
+ Status = gRT->GetVariable (
+ L"PwdCredential",
+ &mPwdCredentialGuid,
+ NULL,
+ &VarSize,
+ Var
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Var = AllocateZeroPool (VarSize);
+ if (Var == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gRT->GetVariable (
+ L"PwdCredential",
+ &mPwdCredentialGuid,
+ NULL,
+ &VarSize,
+ Var
+ );
+ }
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ return Status;
+ }
+
+ //
+ // Create the password credential table.
+ //
+ mPwdTable = AllocateZeroPool (
+ sizeof (CREDENTIAL_TABLE) - sizeof (PASSWORD_INFO) +
+ PASSWORD_TABLE_INC * sizeof (PASSWORD_INFO) +
+ VarSize
+ );
+ if (mPwdTable == NULL) {
+ FreePool (Var);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPwdTable->Count = VarSize / sizeof (PASSWORD_INFO);
+ mPwdTable->MaxCount = mPwdTable->Count + PASSWORD_TABLE_INC;
+ mPwdTable->ValidIndex = 0;
+ if (Var != NULL) {
+ CopyMem (mPwdTable->UserInfo, Var, VarSize);
+ FreePool (Var);
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Hash the password to get credential.
+
+ @param[in] Password Points to the input password.
+ @param[in] PasswordSize The size of password, in bytes.
+ @param[out] Credential Points to the hashed result.
+
+ @retval TRUE Hash the password successfully.
+ @retval FALSE Failed to hash the password.
+
+**/
+BOOLEAN
+GenerateCredential (
+ IN CHAR16 *Password,
+ IN UINTN PasswordSize,
+ OUT UINT8 *Credential
+ )
+{
+ BOOLEAN Status;
+ UINTN HashSize;
+ VOID *Hash;
+
+ HashSize = Sha1GetContextSize ();
+ Hash = AllocatePool (HashSize);
+ ASSERT (Hash != NULL);
+
+ Status = Sha1Init (Hash);
+ if (!Status) {
+ goto Done;
+ }
+
+ Status = Sha1Update (Hash, Password, PasswordSize);
+ if (!Status) {
+ goto Done;
+ }
+
+ Status = Sha1Final (Hash, Credential);
+
+Done:
+ FreePool (Hash);
+ return Status;
+}
+
+
+/**
+ Get password from user input.
+
+ @param[in] FirstPwd If True, prompt to input the first password.
+ If False, prompt to input password again.
+ @param[out] Credential Points to the input password.
+
+**/
+VOID
+GetPassword (
+ IN BOOLEAN FirstPwd,
+ OUT CHAR8 *Credential
+ )
+{
+ EFI_INPUT_KEY Key;
+ CHAR16 PasswordMask[CREDENTIAL_LEN + 1];
+ CHAR16 Password[CREDENTIAL_LEN];
+ UINTN PasswordLen;
+ CHAR16 *QuestionStr;
+ CHAR16 *LineStr;
+
+ PasswordLen = 0;
+ while (TRUE) {
+ PasswordMask[PasswordLen] = L'_';
+ PasswordMask[PasswordLen + 1] = L'\0';
+ LineStr = GetStringById (STRING_TOKEN (STR_DRAW_A_LINE));
+ if (FirstPwd) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD));
+ } else {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN));
+ }
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ LineStr,
+ PasswordMask,
+ NULL
+ );
+ FreePool (QuestionStr);
+ FreePool (LineStr);
+
+ //
+ // Check key stroke
+ //
+ if (Key.ScanCode == SCAN_NULL) {
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ break;
+ } else if (Key.UnicodeChar == CHAR_BACKSPACE) {
+ if (PasswordLen > 0) {
+ PasswordLen--;
+ }
+ } else if ((Key.UnicodeChar == CHAR_NULL) ||
+ (Key.UnicodeChar == CHAR_TAB) ||
+ (Key.UnicodeChar == CHAR_LINEFEED)) {
+ continue;
+ } else {
+ Password[PasswordLen] = Key.UnicodeChar;
+ PasswordMask[PasswordLen] = L'*';
+ PasswordLen++;
+ if (PasswordLen == CREDENTIAL_LEN) {
+ break;
+ }
+ }
+ }
+ }
+
+ PasswordLen = PasswordLen * sizeof (CHAR16);
+ GenerateCredential (Password, PasswordLen, (UINT8 *)Credential);
+}
+
+/**
+ Check whether the password can be found on this provider.
+
+ @param[in] Password The password to be found.
+
+ @retval EFI_SUCCESS Found password sucessfully.
+ @retval EFI_NOT_FOUND Fail to find the password.
+
+**/
+EFI_STATUS
+CheckPassword (
+ IN CHAR8 *Password
+ )
+{
+ UINTN Index;
+ CHAR8 *Pwd;
+
+ //
+ // Check password credential.
+ //
+ mPwdTable->ValidIndex = 0;
+ for (Index = 0; Index < mPwdTable->Count; Index++) {
+ Pwd = mPwdTable->UserInfo[Index].Password;
+ if (CompareMem (Pwd, Password, CREDENTIAL_LEN) == 0) {
+ mPwdTable->ValidIndex = Index + 1;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Find a user infomation record by the information record type.
+
+ This function searches all user information records of User from beginning
+ until either the information is found, or there are no more user infomation
+ records. 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] InfoType The infomation type to be searched.
+ @param[out] Info Points to the user info found, the caller is responsible
+ to free.
+
+ @retval EFI_SUCCESS Find the user information successfully.
+ @retval Others Fail to find the user information.
+
+**/
+EFI_STATUS
+FindUserInfoByType (
+ IN EFI_USER_PROFILE_HANDLE User,
+ IN UINT8 InfoType,
+ OUT EFI_USER_INFO **Info
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO *UserInfo;
+ UINTN UserInfoSize;
+ EFI_USER_INFO_HANDLE UserInfoHandle;
+ EFI_USER_MANAGER_PROTOCOL *UserManager;
+
+ //
+ // Find user information by information type.
+ //
+ if (Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &UserManager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get each user information.
+ //
+
+ UserInfoHandle = NULL;
+ UserInfo = NULL;
+ UserInfoSize = 0;
+ while (TRUE) {
+ Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Get information.
+ //
+ Status = UserManager->GetInfo (
+ UserManager,
+ User,
+ UserInfoHandle,
+ UserInfo,
+ &UserInfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (UserInfo != NULL) {
+ FreePool (UserInfo);
+ }
+ UserInfo = AllocateZeroPool (UserInfoSize);
+ if (UserInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = UserManager->GetInfo (
+ UserManager,
+ User,
+ UserInfoHandle,
+ UserInfo,
+ &UserInfoSize
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ ASSERT (UserInfo != NULL);
+ if (UserInfo->InfoType == InfoType) {
+ *Info = UserInfo;
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (UserInfo != NULL) {
+ FreePool (UserInfo);
+ }
+ return Status;
+}
+
+
+/**
+ 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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDriverCallback (
+ 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;
+ EFI_INPUT_KEY Key;
+ CHAR8 Password[CREDENTIAL_LEN];
+ CHAR16 *PromptStr;
+
+ if (Action == EFI_BROWSER_ACTION_CHANGING) {
+ if (QuestionId == KEY_GET_PASSWORD) {
+ //
+ // Get and check password.
+ //
+ GetPassword (TRUE, Password);
+ Status = CheckPassword (Password);
+ if (EFI_ERROR (Status)) {
+ PromptStr = GetStringById (STRING_TOKEN (STR_PASSWORD_INCORRECT));
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"",
+ PromptStr,
+ L"",
+ NULL
+ );
+ FreePool (PromptStr);
+ return Status;
+ }
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ // All other action return unsupported.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ 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 <ConfigRequest> 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 <ConfigAltResp> 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 <ConfigResp> 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;
+ PWD_PROVIDER_CALLBACK_INFO *CallbackInfo;
+
+ //
+ // Initialize driver private data.
+ //
+ CallbackInfo = AllocateZeroPool (sizeof (PWD_PROVIDER_CALLBACK_INFO));
+ if (CallbackInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CallbackInfo->Signature = PWD_PROVIDER_SIGNATURE;
+ CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig;
+ CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig;
+ CallbackInfo->ConfigAccess.Callback = CredentialDriverCallback;
+ 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 (
+ &mPwdCredentialGuid,
+ CallbackInfo->DriverHandle,
+ PwdCredentialProviderStrings,
+ PwdCredentialProviderVfrBin,
+ NULL
+ );
+ if (CallbackInfo->HiiHandle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ mCallbackInfo = CallbackInfo;
+
+ return Status;
+}
+
+
+/**
+ Enroll a user on a credential provider.
+
+ This function enrolls and deletes a user profile using this credential provider.
+ If a user profile is successfully enrolled, it calls the User Manager Protocol
+ function Notify() to notify the user manager driver that credential information
+ has changed. If an enrolled user does exist, delete the user on the credential
+ provider.
+
+ @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile to enroll.
+
+ @retval EFI_SUCCESS User profile was successfully enrolled.
+ @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the
+ user profile handle. Either the user profile cannot enroll
+ on any user profile or cannot enroll on a user profile
+ other than the current user profile.
+ @retval EFI_UNSUPPORTED This credential provider does not support enrollment in
+ the pre-OS.
+ @retval EFI_DEVICE_ERROR The new credential could not be created because of a device
+ error.
+ @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialEnroll (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ PASSWORD_INFO PwdInfo;
+ EFI_USER_INFO *UserInfo;
+ CHAR8 Password[CREDENTIAL_LEN];
+ EFI_INPUT_KEY Key;
+ EFI_USER_MANAGER_PROTOCOL *UserManager;
+ UINT8 *UserId;
+ UINT8 *NewUserId;
+ CHAR16 *QuestionStr;
+ CHAR16 *PromptStr;
+
+ if ((This == NULL) || (User == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &UserManager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get User Identifier.
+ //
+ UserInfo = NULL;
+ Status = FindUserInfoByType (
+ User,
+ EFI_USER_INFO_IDENTIFIER_RECORD,
+ &UserInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If User exists in mPwdTable, delete User.
+ //
+ for (Index = 0; Index < mPwdTable->Count; Index++) {
+ UserId = (UINT8 *) &mPwdTable->UserInfo[Index].UserId;
+ NewUserId = (UINT8 *) (UserInfo + 1);
+ if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
+ //
+ // Delete the existing password.
+ //
+ FreePool (UserInfo);
+ return ModifyTable (Index, NULL);
+ }
+ }
+
+ //
+ // The User doesn't exist in mPwdTable; Enroll the new User.
+ //
+ while (TRUE) {
+ //
+ // Input password.
+ //
+ GetPassword (TRUE, PwdInfo.Password);
+
+ //
+ // Input password again.
+ //
+ GetPassword (FALSE, Password);
+
+ //
+ // Compare the two password consistency.
+ //
+ if (CompareMem (PwdInfo.Password, Password, CREDENTIAL_LEN) == 0) {
+ break;
+ }
+
+ QuestionStr = GetStringById (STRING_TOKEN (STR_PASSWORD_MISMATCH));
+ PromptStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN));
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+ }
+
+ CopyMem (
+ PwdInfo.UserId,
+ (UINT8 *) (UserInfo + 1),
+ sizeof (EFI_USER_INFO_IDENTIFIER)
+ );
+ FreePool (UserInfo);
+
+ //
+ // Save the new added entry.
+ //
+ Status = ModifyTable (mPwdTable->Count, &PwdInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the user manager driver that credential information has changed.
+ //
+ UserManager->Notify (UserManager, mCallbackInfo->DriverHandle);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the user interface information used during user identification.
+
+ This function returns information about the form used when interacting with the
+ user during user identification. The form is the first enabled form in the form-set
+ class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
+ the user credential provider does not require a form to identify the user, then this
+ function should return EFI_NOT_FOUND.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] FormSetId On return, holds the identifier of the form set which contains
+ the form used during user identification.
+ @param[out] FormId On return, holds the identifier of the form used during user
+ identification.
+
+ @retval EFI_SUCCESS Form returned successfully.
+ @retval EFI_NOT_FOUND Form not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialForm (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_GUID *FormSetId,
+ OUT EFI_FORM_ID *FormId
+ )
+{
+ if ((This == NULL) || (Hii == NULL) ||
+ (FormSetId == NULL) || (FormId == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Hii = mCallbackInfo->HiiHandle;
+ *FormId = FORMID_GET_PASSWORD_FORM;
+ CopyGuid (FormSetId, &mPwdCredentialGuid);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns bitmap used to describe the credential provider type.
+
+ This optional function returns a bitmap that is less than or equal to the number
+ of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
+ is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ width of the bitmap returned.
+ @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ height of the bitmap returned
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] Image On return, holds the HII image identifier.
+
+ @retval EFI_SUCCESS Image identifier returned successfully.
+ @retval EFI_NOT_FOUND Image identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTile (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT UINTN *Width,
+ IN OUT UINTN *Height,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_IMAGE_ID *Image
+ )
+{
+ if ((This == NULL) || (Hii == NULL) || (Image == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Returns string used to describe the credential provider type.
+
+ This function returns a string which describes the credential provider. If no
+ such string exists, then EFI_NOT_FOUND is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] String On return, holds the HII string identifier.
+
+ @retval EFI_SUCCESS String identifier returned successfully.
+ @retval EFI_NOT_FOUND String identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTitle (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_STRING_ID *String
+ )
+{
+ if ((This == NULL) || (Hii == NULL) || (String == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set Hii handle and String ID.
+ //
+ *Hii = mCallbackInfo->HiiHandle;
+ *String = STRING_TOKEN (STR_CREDENTIAL_TITLE);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the user identifier associated with the currently authenticated user.
+
+ This function returns the user identifier of the user authenticated by this credential
+ provider. This function is called after the credential-related information has been
+ submitted on a form, OR after a call to Default() has returned that this credential is
+ ready to log on.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile handle of the user profile currently being
+ considered by the user identity manager. If NULL, then no user
+ profile is currently under consideration.
+ @param[out] Identifier On return, points to the user identifier.
+
+ @retval EFI_SUCCESS User identifier returned successfully.
+ @retval EFI_NOT_READY No user identifier can be returned.
+ @retval EFI_ACCESS_DENIED The user has been locked out of this user credential.
+ @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL.
+ @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be
+ found in user profile database
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialUser (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User,
+ OUT EFI_USER_INFO_IDENTIFIER *Identifier
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_USER_INFO *UserInfo;
+ UINT8 *UserId;
+ UINT8 *NewUserId;
+ CHAR8 *Pwd;
+ CHAR8 *NewPwd;
+
+ if ((This == NULL) || (Identifier == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mPwdTable->ValidIndex == 0) {
+ //
+ // No password input, or the input password doesn't match
+ // anyone in PwdTable.
+ //
+ return EFI_NOT_READY;
+ }
+
+ if (User == NULL) {
+ //
+ // Return the user ID whose password matches the input password.
+ //
+ CopyMem (
+ Identifier,
+ &mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].UserId,
+ sizeof (EFI_USER_INFO_IDENTIFIER)
+ );
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the User's ID.
+ //
+ Status = FindUserInfoByType (
+ User,
+ EFI_USER_INFO_IDENTIFIER_RECORD,
+ &UserInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check whether the input password matches one in PwdTable.
+ //
+ for (Index = 0; Index < mPwdTable->Count; Index++) {
+ UserId = (UINT8 *) &mPwdTable->UserInfo[Index].UserId;
+ NewUserId = (UINT8 *) (UserInfo + 1);
+ if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
+ Pwd = mPwdTable->UserInfo[Index].Password;
+ NewPwd = mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].Password;
+ if (CompareMem (Pwd, NewPwd, CREDENTIAL_LEN) == 0) {
+ CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
+ FreePool (UserInfo);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // The User's password doesn't match the input password.
+ // Return the user ID whose password matches the input password.
+ //
+ CopyMem (
+ Identifier,
+ &mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].UserId,
+ sizeof (EFI_USER_INFO_IDENTIFIER)
+ );
+ FreePool (UserInfo);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Indicate that user interface interaction has begun for the specified credential.
+
+ This function is called when a credential provider is selected by the user. If
+ AutoLogon returns FALSE, then the user interface will be constructed by the User
+ Identity Manager.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, points to the credential provider's capabilities
+ after the credential provider has been selected by the user.
+
+ @retval EFI_SUCCESS Credential provider successfully selected.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialSelect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ )
+{
+ if ((This == NULL) || (AutoLogon == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *AutoLogon = 0;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Indicate that user interface interaction has ended for the specified credential.
+
+ This function is called when a credential provider is deselected by the user.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+
+ @retval EFI_SUCCESS Credential provider successfully deselected.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDeselect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This
+ )
+{
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the default logon behavior for this user credential.
+
+ This function reports the default login behavior regarding this credential provider.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, holds whether the credential provider should be used
+ by default to automatically log on the user.
+
+ @retval EFI_SUCCESS Default information successfully returned.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDefault (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ )
+{
+ if ((This == NULL) || (AutoLogon == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *AutoLogon = 0;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return information attached to the credential provider.
+
+ This function returns user information.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @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_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the
+ user information. The size required is returned in *InfoSize.
+ @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
+ @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialGetInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_INFO_HANDLE UserInfo,
+ OUT EFI_USER_INFO *Info,
+ IN OUT UINTN *InfoSize
+ )
+{
+ EFI_USER_INFO *CredentialInfo;
+ UINTN Index;
+
+ if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UserInfo == NULL) || (mPwdInfoHandle == NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find information handle in credential info table.
+ //
+ for (Index = 0; Index < mPwdInfoHandle->Count; Index++) {
+ CredentialInfo = mPwdInfoHandle->Info[Index];
+ if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) {
+ //
+ // The handle is found, copy the user info.
+ //
+ if (CredentialInfo->InfoSize > *InfoSize) {
+ *InfoSize = CredentialInfo->InfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Enumerate all of the user informations on the credential provider.
+
+ 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_CREDENTIAL_PROTOCOL.
+ @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
+ to start enumeration. On exit, points to the next user information
+ handle or NULL if there is no more user information.
+
+ @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
+CredentialGetNextInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT EFI_USER_INFO_HANDLE *UserInfo
+ )
+{
+ EFI_USER_INFO *Info;
+ CHAR16 *ProvNameStr;
+ UINTN InfoLen;
+ UINTN Index;
+ UINTN ProvStrLen;
+
+ if ((This == NULL) || (UserInfo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mPwdInfoHandle == NULL) {
+ //
+ // Initilized user info table. There are 4 user info records in the table.
+ //
+ InfoLen = sizeof (PASSWORD_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *);
+ mPwdInfoHandle = AllocateZeroPool (InfoLen);
+ if (mPwdInfoHandle == NULL) {
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The first information, Credential Provider info.
+ //
+ InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mPwdCredentialGuid);
+ CopyGuid ((EFI_GUID *)(Info + 1), &mPwdCredentialGuid);
+
+ mPwdInfoHandle->Info[0] = Info;
+ mPwdInfoHandle->Count++;
+
+ //
+ // The second information, Credential Provider name info.
+ //
+ ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME));
+ ProvStrLen = StrSize (ProvNameStr);
+ InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mPwdCredentialGuid);
+ CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
+ FreePool (ProvNameStr);
+
+ mPwdInfoHandle->Info[1] = Info;
+ mPwdInfoHandle->Count++;
+
+ //
+ // The third information, Credential Provider type info.
+ //
+ InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mPwdCredentialGuid);
+ CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassPasswordGuid);
+
+ mPwdInfoHandle->Info[2] = Info;
+ mPwdInfoHandle->Count++;
+
+ //
+ // The fourth information, Credential Provider type name info.
+ //
+ ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME));
+ ProvStrLen = StrSize (ProvNameStr);
+ InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mPwdCredentialGuid);
+ CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
+ FreePool (ProvNameStr);
+
+ mPwdInfoHandle->Info[3] = Info;
+ mPwdInfoHandle->Count++;
+ }
+
+ if (*UserInfo == NULL) {
+ //
+ // Return the first info handle.
+ //
+ *UserInfo = (EFI_USER_INFO_HANDLE) mPwdInfoHandle->Info[0];
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Find information handle in credential info table.
+ //
+ for (Index = 0; Index < mPwdInfoHandle->Count; Index++) {
+ Info = mPwdInfoHandle->Info[Index];
+ if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) {
+ //
+ // The handle is found, get the next one.
+ //
+ if (Index == mPwdInfoHandle->Count - 1) {
+ //
+ // Already last one.
+ //
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ Index++;
+ *UserInfo = (EFI_USER_INFO_HANDLE)mPwdInfoHandle->Info[Index];
+ return EFI_SUCCESS;
+ }
+ }
+
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PasswordProviderInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init credential table.
+ //
+ Status = InitCredentialTable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Init Form Browser.
+ //
+ Status = InitFormBrowser ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install protocol interfaces for the password credential provider.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mCallbackInfo->DriverHandle,
+ &gEfiUserCredentialProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gPwdCredentialProviderDriver
+ );
+ return Status;
+}
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h
new file mode 100644
index 0000000000..9b5e7768ba
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h
@@ -0,0 +1,354 @@
+/** @file
+ Password Credential Provider driver header file.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _PASSWORD_CREDENTIAL_PROVIDER_H_
+#define _PASSWORD_CREDENTIAL_PROVIDER_H_
+
+#include <Uefi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/MdeModuleHii.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/UserCredential.h>
+#include <Protocol/UserManager.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/BaseCryptLib.h>
+
+#include "PwdCredentialProviderData.h"
+
+extern UINT8 PwdCredentialProviderStrings[];
+extern UINT8 PwdCredentialProviderVfrBin[];
+
+#define PASSWORD_TABLE_INC 16
+#define CREDENTIAL_LEN 20
+
+//
+// Password credential information.
+//
+typedef struct {
+ EFI_USER_INFO_IDENTIFIER UserId;
+ CHAR8 Password[CREDENTIAL_LEN];
+} PASSWORD_INFO;
+
+//
+// Password credential table.
+//
+typedef struct {
+ UINTN Count;
+ UINTN MaxCount;
+ UINTN ValidIndex;
+ PASSWORD_INFO UserInfo[1];
+} CREDENTIAL_TABLE;
+
+//
+// The user information on the password provider.
+//
+typedef struct {
+ UINTN Count;
+ EFI_USER_INFO *Info[1];
+} PASSWORD_CREDENTIAL_INFO;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#define PWD_PROVIDER_SIGNATURE SIGNATURE_32 ('P', 'W', 'D', 'P')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ //
+ // Produced protocol.
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} PWD_PROVIDER_CALLBACK_INFO;
+
+
+/**
+ Enroll a user on a credential provider.
+
+ This function enrolls and deletes a user profile using this credential provider.
+ If a user profile is successfully enrolled, it calls the User Manager Protocol
+ function Notify() to notify the user manager driver that credential information
+ has changed. If an enrolled user does exist, delete the user on the credential
+ provider.
+
+ @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile to enroll.
+
+ @retval EFI_SUCCESS User profile was successfully enrolled.
+ @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the
+ user profile handle. Either the user profile cannot enroll
+ on any user profile or cannot enroll on a user profile
+ other than the current user profile.
+ @retval EFI_UNSUPPORTED This credential provider does not support enrollment in
+ the pre-OS.
+ @retval EFI_DEVICE_ERROR The new credential could not be created because of a device
+ error.
+ @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialEnroll (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User
+ );
+
+/**
+ Returns the user interface information used during user identification.
+
+ This function returns information about the form used when interacting with the
+ user during user identification. The form is the first enabled form in the form-set
+ class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
+ the user credential provider does not require a form to identify the user, then this
+ function should return EFI_NOT_FOUND.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] FormSetId On return, holds the identifier of the form set which contains
+ the form used during user identification.
+ @param[out] FormId On return, holds the identifier of the form used during user
+ identification.
+
+ @retval EFI_SUCCESS Form returned successfully.
+ @retval EFI_NOT_FOUND Form not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialForm (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_GUID *FormSetId,
+ OUT EFI_FORM_ID *FormId
+ );
+
+/**
+ Returns bitmap used to describe the credential provider type.
+
+ This optional function returns a bitmap which is less than or equal to the number
+ of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
+ is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ width of the bitmap returned.
+ @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ height of the bitmap returned
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] Image On return, holds the HII image identifier.
+
+ @retval EFI_SUCCESS Image identifier returned successfully.
+ @retval EFI_NOT_FOUND Image identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTile (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT UINTN *Width,
+ IN OUT UINTN *Height,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_IMAGE_ID *Image
+ );
+
+/**
+ Returns string used to describe the credential provider type.
+
+ This function returns a string which describes the credential provider. If no
+ such string exists, then EFI_NOT_FOUND is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] String On return, holds the HII string identifier.
+
+ @retval EFI_SUCCESS String identifier returned successfully.
+ @retval EFI_NOT_FOUND String identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTitle (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_STRING_ID *String
+ );
+
+/**
+ Return the user identifier associated with the currently authenticated user.
+
+ This function returns the user identifier of the user authenticated by this credential
+ provider. This function is called after the credential-related information has been
+ submitted on a form OR after a call to Default() has returned that this credential is
+ ready to log on.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile handle of the user profile currently being
+ considered by the user identity manager. If NULL, then no user
+ profile is currently under consideration.
+ @param[out] Identifier On return, points to the user identifier.
+
+ @retval EFI_SUCCESS User identifier returned successfully.
+ @retval EFI_NOT_READY No user identifier can be returned.
+ @retval EFI_ACCESS_DENIED The user has been locked out of this user credential.
+ @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL.
+ @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be
+ found in user profile database
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialUser (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User,
+ OUT EFI_USER_INFO_IDENTIFIER *Identifier
+ );
+
+/**
+ Indicate that user interface interaction has begun for the specified credential.
+
+ This function is called when a credential provider is selected by the user. If
+ AutoLogon returns FALSE, then the user interface will be constructed by the User
+ Identity Manager.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, points to the credential provider's capabilities
+ after the credential provider has been selected by the user.
+
+ @retval EFI_SUCCESS Credential provider successfully selected.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialSelect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ );
+
+/**
+ Indicate that user interface interaction has ended for the specified credential.
+
+ This function is called when a credential provider is deselected by the user.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+
+ @retval EFI_SUCCESS Credential provider successfully deselected.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDeselect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This
+ );
+
+/**
+ Return the default logon behavior for this user credential.
+
+ This function reports the default login behavior regarding this credential provider.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, holds whether the credential provider should be used
+ by default to automatically log on the user.
+
+ @retval EFI_SUCCESS Default information successfully returned.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDefault (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ );
+
+/**
+ Return information attached to the credential provider.
+
+ This function returns user information.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @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_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the
+ user information. The size required is returned in *InfoSize.
+ @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
+ @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialGetInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_INFO_HANDLE UserInfo,
+ OUT EFI_USER_INFO *Info,
+ IN OUT UINTN *InfoSize
+ );
+
+
+/**
+ Enumerate all of the user informations on the credential provider.
+
+ 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_CREDENTIAL_PROTOCOL.
+ @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
+ to start enumeration. On exit, points to the next user information
+ handle or NULL if there is no more user information.
+
+ @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
+CredentialGetNextInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT EFI_USER_INFO_HANDLE *UserInfo
+ );
+
+#endif
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h
new file mode 100644
index 0000000000..ffe0adea20
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h
@@ -0,0 +1,33 @@
+/** @file
+ Data structure used by the Password Credential Provider driver.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _PWD_CREDENTIAL_PROVIDER_DATA_H_
+#define _PWD_CREDENTIAL_PROVIDER_DATA_H_
+
+#define PWD_CREDENTIAL_PROVIDER_GUID \
+ { \
+ 0x78b9ec8b, 0xc000, 0x46c5, { 0xac, 0x93, 0x24, 0xa0, 0xc1, 0xbb, 0x0, 0xce } \
+ }
+
+//
+// Forms definition
+//
+#define FORMID_GET_PASSWORD_FORM 1
+
+//
+// Key defination
+//
+#define KEY_GET_PASSWORD 0x1000
+
+#endif
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf
new file mode 100644
index 0000000000..0ffc24e076
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf
@@ -0,0 +1,53 @@
+## @file
+# Component description file for Password Credential Provider.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+# 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 = PwdCredentialProvider
+ FILE_GUID = D6C589EA-DD29-49ef-97F6-1A9FE19A04E0
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PasswordProviderInit
+
+[Sources]
+ PwdCredentialProvider.c
+ PwdCredentialProvider.h
+ PwdCredentialProviderData.h
+ PwdCredentialProviderVfr.Vfr
+ PwdCredentialProviderStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ BaseMemoryLib
+ DebugLib
+ HiiLib
+ UefiLib
+ BaseCryptLib
+
+[Guids]
+ gEfiIfrTianoGuid ## CONSUMES ## Guid
+ gEfiUserCredentialClassPasswordGuid ## CONSUMES ## Guid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiUserCredentialProtocolGuid
+ gEfiUserManagerProtocolGuid \ No newline at end of file
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni
new file mode 100644
index 0000000000..48573b6e8e
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni
Binary files differ
diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr
new file mode 100644
index 0000000000..69f4be8c23
--- /dev/null
+++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr
@@ -0,0 +1,35 @@
+/** @file
+ Password Credential Provider formset.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "PwdCredentialProviderData.h"
+
+formset
+ guid = PWD_CREDENTIAL_PROVIDER_GUID,
+ title = STRING_TOKEN(STR_CREDENTIAL_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ classguid = PWD_CREDENTIAL_PROVIDER_GUID,
+
+ form formid = FORMID_GET_PASSWORD_FORM,
+ title = STRING_TOKEN(STR_FORM_TITLE);
+
+ text
+ help = STRING_TOKEN(STR_NULL_STRING),
+ text = STRING_TOKEN(STR_INPUT_PASSWORD),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_GET_PASSWORD;
+
+ endform;
+
+endformset; \ No newline at end of file
diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c
new file mode 100644
index 0000000000..6c22bfb2bb
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c
@@ -0,0 +1,1407 @@
+/** @file
+ Usb Credential Provider driver implemenetation.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "UsbCredentialProvider.h"
+
+CREDENTIAL_TABLE *mUsbTable = NULL;
+USB_PROVIDER_CALLBACK_INFO *mCallbackInfo = NULL;
+USB_CREDENTIAL_INFO *mUsbInfoHandle = NULL;
+
+//
+// Used for save password credential and form browser
+// And used as provider identifier
+//
+EFI_GUID mUsbCredentialGuid = USB_CREDENTIAL_PROVIDER_GUID;
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ { 0x9463f883, 0x48f6, 0x4a7a, { 0x97, 0x2d, 0x9f, 0x8f, 0x38, 0xf2, 0xdd, 0x91 } }
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+EFI_USER_CREDENTIAL_PROTOCOL gUsbCredentialProviderDriver = {
+ USB_CREDENTIAL_PROVIDER_GUID,
+ EFI_USER_CREDENTIAL_CLASS_SECURE_CARD,
+ CredentialEnroll,
+ CredentialForm,
+ CredentialTile,
+ CredentialTitle,
+ CredentialUser,
+ CredentialSelect,
+ CredentialDeselect,
+ CredentialDefault,
+ CredentialGetInfo,
+ CredentialGetNextInfo
+};
+
+
+/**
+ Get string by string id from HII Interface.
+
+
+ @param[in] Id String ID to get the string from.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ //
+ // Get the current string for the current Language
+ //
+ return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL);
+}
+
+
+/**
+ Expand password table size.
+
+**/
+VOID
+ExpandTableSize (
+ VOID
+ )
+{
+ CREDENTIAL_TABLE *NewTable;
+ UINTN Count;
+
+ Count = mUsbTable->MaxCount + USB_TABLE_INC;
+ //
+ // Create new credential table.
+ //
+ NewTable = AllocateZeroPool (
+ sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) +
+ Count * sizeof (USB_INFO)
+ );
+ ASSERT (NewTable != NULL);
+
+ NewTable->MaxCount = Count;
+ NewTable->Count = mUsbTable->Count;
+
+ //
+ // Copy old entries.
+ //
+ CopyMem (
+ &NewTable->UserInfo,
+ &mUsbTable->UserInfo,
+ mUsbTable->Count * sizeof (USB_INFO)
+ );
+ FreePool (mUsbTable);
+ mUsbTable = NewTable;
+}
+
+
+/**
+ Add or delete info in table, and sync with NV variable.
+
+ @param[in] Index The index of the password in table. The index begin from 1.
+ If index is found in table, delete the info, else add the
+ into to table.
+ @param[in] Info The new password info to add into table.
+
+ @retval EFI_INVALID_PARAMETER Info is NULL when save the info.
+ @retval EFI_SUCCESS Modify the table successfully.
+ @retval Others Failed to modify the table.
+
+**/
+EFI_STATUS
+ModifyTable (
+ IN UINTN Index,
+ IN USB_INFO * Info OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (Index < mUsbTable->Count) {
+ //
+ // Delete the specified entry
+ //
+ mUsbTable->Count--;
+ if (Index != mUsbTable->Count) {
+ CopyMem (
+ &mUsbTable->UserInfo[Index],
+ &mUsbTable->UserInfo[mUsbTable->Count],
+ sizeof (USB_INFO)
+ );
+ }
+ } else {
+ //
+ // Add a new entry
+ //
+ if (Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mUsbTable->Count >= mUsbTable->MaxCount) {
+ ExpandTableSize ();
+ }
+
+ CopyMem (
+ &mUsbTable->UserInfo[mUsbTable->Count],
+ Info,
+ sizeof (USB_INFO)
+ );
+ mUsbTable->Count++;
+ }
+
+ //
+ // Save the credential table.
+ //
+ Status = gRT->SetVariable (
+ L"UsbCredential",
+ &mUsbCredentialGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ mUsbTable->Count * sizeof (USB_INFO),
+ &mUsbTable->UserInfo
+ );
+ return Status;
+}
+
+
+/**
+ Create a credential table
+
+ @retval EFI_SUCCESS Create a credential table successfully.
+ @retval Others Failed to create a password.
+
+**/
+EFI_STATUS
+InitCredentialTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Var;
+ UINTN VarSize;
+
+ //
+ // Get Usb credential data from NV variable.
+ //
+ VarSize = 0;
+ Var = NULL;
+ Status = gRT->GetVariable (
+ L"UsbCredential",
+ &mUsbCredentialGuid,
+ NULL,
+ &VarSize,
+ Var
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Var = AllocateZeroPool (VarSize);
+ if (Var == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gRT->GetVariable (
+ L"UsbCredential",
+ &mUsbCredentialGuid,
+ NULL,
+ &VarSize,
+ Var
+ );
+ }
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ return Status;
+ }
+
+ //
+ // Init Usb credential table.
+ //
+ mUsbTable = AllocateZeroPool (
+ sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) +
+ USB_TABLE_INC * sizeof (USB_INFO) +
+ VarSize
+ );
+ if (mUsbTable == NULL) {
+ FreePool (Var);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mUsbTable->Count = VarSize / sizeof (USB_INFO);
+ mUsbTable->MaxCount = mUsbTable->Count + USB_TABLE_INC;
+ if (Var != NULL) {
+ CopyMem (mUsbTable->UserInfo, Var, VarSize);
+ FreePool (Var);
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read the specified file by FileName in the Usb key and return the file size in BufferSize
+ and file content in Buffer.
+ Note: the caller is responsible to free the buffer memory.
+
+ @param FileName File to read.
+ @param Buffer Returned with data read from the file.
+ @param BufferSize Size of the data buffer.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Resource allocation failed.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_DEVICE_ERROR Device I/O error.
+
+**/
+EFI_STATUS
+GetFileData (
+ IN CHAR16 *FileName,
+ OUT VOID **Buffer,
+ OUT UINTN *BufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN HandleCount;
+ UINTN ScratchBufferSize;
+ EFI_HANDLE *HandleBuffer;
+ EFI_FILE *RootFs;
+ EFI_FILE *FileHandle;
+ EFI_FILE_INFO *FileInfo;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+
+ FileInfo = NULL;
+ FileHandle = NULL;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Can not Locate SimpleFileSystemProtocol\n"));
+ goto Done;
+ }
+
+ //
+ // Find and open the file in removable media disk.
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (BlkIo->Media->RemovableMedia) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **) &SimpleFileSystem
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = SimpleFileSystem->OpenVolume (
+ SimpleFileSystem,
+ &RootFs
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = RootFs->Open (
+ RootFs,
+ &FileHandle,
+ FileName,
+ EFI_FILE_MODE_READ,
+ 0
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+
+ if (Index >= HandleCount) {
+ DEBUG ((DEBUG_ERROR, "Can not found the token file!\n"));
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Figure out how big the file is.
+ //
+ ScratchBufferSize = 0;
+ Status = FileHandle->GetInfo (
+ FileHandle,
+ &gEfiFileInfoGuid,
+ &ScratchBufferSize,
+ NULL
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ DEBUG ((DEBUG_ERROR, "Can not obtain file size info!\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ FileInfo = AllocateZeroPool (ScratchBufferSize);
+ if (FileInfo == NULL) {
+ DEBUG ((DEBUG_ERROR, "Can not allocate enough memory for the token file!\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = FileHandle->GetInfo (
+ FileHandle,
+ &gEfiFileInfoGuid,
+ &ScratchBufferSize,
+ FileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Can not obtain file info from the token file!\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Allocate a buffer for the file.
+ //
+ *BufferSize = (UINT32) FileInfo->FileSize;
+ *Buffer = AllocateZeroPool (*BufferSize);
+ if (*Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "Can not allocate a buffer for the file!\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Load file into the allocated memory.
+ //
+ Status = FileHandle->Read (FileHandle, BufferSize, *Buffer);
+ if (EFI_ERROR (Status)) {
+ FreePool (*Buffer);
+ DEBUG ((DEBUG_ERROR, "Can not read the token file!\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Close file.
+ //
+ Status = FileHandle->Close (FileHandle);
+ if (EFI_ERROR (Status)) {
+ FreePool (*Buffer);
+ DEBUG ((DEBUG_ERROR, "Can not close the token file !\n"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+Done:
+
+ if (FileInfo != NULL) {
+ FreePool (FileInfo);
+ }
+
+ return Status;
+}
+
+
+/**
+ Hash the data to get credential.
+
+ @param[in] Buffer Points to the data buffer
+ @param[in] BufferSize The size of data in buffer, in bytes.
+ @param[out] Credential Points to the hashed result
+
+ @retval TRUE Hash the data successfully.
+ @retval FALSE Failed to hash the data.
+
+**/
+BOOLEAN
+GenerateCredential (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ OUT UINT8 *Credential
+ )
+{
+ BOOLEAN Status;
+ UINTN HashSize;
+ VOID *Hash;
+
+ HashSize = Sha1GetContextSize ();
+ Hash = AllocatePool (HashSize);
+ ASSERT (Hash != NULL);
+
+ Status = Sha1Init (Hash);
+ if (!Status) {
+ goto Done;
+ }
+
+ Status = Sha1Update (Hash, Buffer, BufferSize);
+ if (!Status) {
+ goto Done;
+ }
+
+ Status = Sha1Final (Hash, Credential);
+
+Done:
+ FreePool (Hash);
+ return Status;
+}
+
+
+/**
+ Read the token file, and default the Token is saved at the begining of the file.
+
+ @param[out] Token Token read from a Token file.
+
+ @retval EFI_SUCCESS Read a Token successfully.
+ @retval Others Fails to read a Token.
+
+**/
+EFI_STATUS
+GetToken (
+ OUT UINT8 *Token
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN BufSize;
+ CHAR16 *TokenFile;
+
+ BufSize = 0;
+ Buffer = NULL;
+ TokenFile = FixedPcdGetPtr (PcdFixedUsbCredentialProviderTokenFileName);
+ Status = GetFileData (TokenFile, (VOID *)&Buffer, &BufSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Read file %s from USB error! Status=(%r)\n", TokenFile, Status));
+ return Status;
+ }
+
+ if (!GenerateCredential (Buffer, BufSize, Token)) {
+ DEBUG ((DEBUG_ERROR, "Generate credential from read data failed!\n"));
+ FreePool (Buffer);
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find a user infomation record by the information record type.
+
+ This function searches all user information records of User from beginning
+ 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] InfoType The infomation type to be searched.
+ @param[out] Info Points to the user info found, the caller is responsible
+ to free.
+
+ @retval EFI_SUCCESS Find the user information successfully.
+ @retval Others Fail to find the user information.
+
+**/
+EFI_STATUS
+FindUserInfoByType (
+ IN EFI_USER_PROFILE_HANDLE User,
+ IN UINT8 InfoType,
+ OUT EFI_USER_INFO **Info
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO *UserInfo;
+ UINTN UserInfoSize;
+ EFI_USER_INFO_HANDLE UserInfoHandle;
+ EFI_USER_MANAGER_PROTOCOL *UserManager;
+
+ //
+ // Find user information by information type.
+ //
+ if (Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &UserManager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get each user information.
+ //
+
+ UserInfoHandle = NULL;
+ UserInfo = NULL;
+ UserInfoSize = 0;
+ while (TRUE) {
+ Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Get information.
+ //
+ Status = UserManager->GetInfo (
+ UserManager,
+ User,
+ UserInfoHandle,
+ UserInfo,
+ &UserInfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (UserInfo != NULL) {
+ FreePool (UserInfo);
+ }
+ UserInfo = AllocateZeroPool (UserInfoSize);
+ if (UserInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = UserManager->GetInfo (
+ UserManager,
+ User,
+ UserInfoHandle,
+ UserInfo,
+ &UserInfoSize
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ ASSERT (UserInfo != NULL);
+ if (UserInfo->InfoType == InfoType) {
+ *Info = UserInfo;
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (UserInfo != NULL) {
+ FreePool (UserInfo);
+ }
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+ USB_PROVIDER_CALLBACK_INFO *CallbackInfo;
+
+ //
+ // Initialize driver private data.
+ //
+ CallbackInfo = AllocateZeroPool (sizeof (USB_PROVIDER_CALLBACK_INFO));
+ if (CallbackInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CallbackInfo->DriverHandle = NULL;
+
+ //
+ // Publish HII data.
+ //
+ CallbackInfo->HiiHandle = HiiAddPackages (
+ &mUsbCredentialGuid,
+ CallbackInfo->DriverHandle,
+ UsbCredentialProviderStrings,
+ NULL
+ );
+ if (CallbackInfo->HiiHandle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ mCallbackInfo = CallbackInfo;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enroll a user on a credential provider.
+
+ This function enrolls and deletes a user profile using this credential provider.
+ If a user profile is successfully enrolled, it calls the User Manager Protocol
+ function Notify() to notify the user manager driver that credential information
+ has changed. If an enrolled user does exist, delete the user on the credential
+ provider.
+
+ @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile to enroll.
+
+ @retval EFI_SUCCESS User profile was successfully enrolled.
+ @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the
+ user profile handle. Either the user profile cannot enroll
+ on any user profile or cannot enroll on a user profile
+ other than the current user profile.
+ @retval EFI_UNSUPPORTED This credential provider does not support enrollment in
+ the pre-OS.
+ @retval EFI_DEVICE_ERROR The new credential could not be created because of a device
+ error.
+ @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialEnroll (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ USB_INFO UsbInfo;
+ EFI_USER_INFO *UserInfo;
+ EFI_INPUT_KEY Key;
+ EFI_USER_MANAGER_PROTOCOL *UserManager;
+ UINT8 *UserId;
+ UINT8 *NewUserId;
+ EFI_TPL OldTpl;
+ CHAR16 *QuestionStr;
+ CHAR16 *PromptStr;
+
+ if ((This == NULL) || (User == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &UserManager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get User Identifier
+ //
+ UserInfo = NULL;
+ Status = FindUserInfoByType (
+ User,
+ EFI_USER_INFO_IDENTIFIER_RECORD,
+ &UserInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If User exists in mUsbTable, delete User.
+ //
+ for (Index = 0; Index < mUsbTable->Count; Index++) {
+ UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
+ NewUserId = (UINT8 *) (UserInfo + 1);
+ if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
+ //
+ // Delete the exist Token.
+ //
+ FreePool (UserInfo);
+ return ModifyTable (Index, NULL);
+ }
+ }
+
+ //
+ // Get Token and User ID to UsbInfo.
+ //
+ Status = GetToken (UsbInfo.Token);
+ if (EFI_ERROR (Status)) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR));
+ PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN));
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (TPL_APPLICATION);
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ gBS->RaiseTPL (OldTpl);
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+ FreePool (UserInfo);
+ return Status;
+ }
+ CopyMem (
+ UsbInfo.UserId,
+ (UINT8 *) (UserInfo + 1),
+ sizeof (EFI_USER_INFO_IDENTIFIER)
+ );
+ FreePool (UserInfo);
+
+ //
+ // Save the new added entry.
+ //
+ Status = ModifyTable (mUsbTable->Count, &UsbInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the user manager driver that credential information has changed.
+ //
+ UserManager->Notify (UserManager, mCallbackInfo->DriverHandle);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the user interface information used during user identification.
+
+ This function returns information about the form used when interacting with the
+ user during user identification. The form is the first enabled form in the form-set
+ class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
+ the user credential provider does not require a form to identify the user, then this
+ function should return EFI_NOT_FOUND.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] FormSetId On return, holds the identifier of the form set which contains
+ the form used during user identification.
+ @param[out] FormId On return, holds the identifier of the form used during user
+ identification.
+
+ @retval EFI_SUCCESS Form returned successfully.
+ @retval EFI_NOT_FOUND Form not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialForm (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_GUID *FormSetId,
+ OUT EFI_FORM_ID *FormId
+ )
+{
+ if ((This == NULL) || (Hii == NULL) ||
+ (FormSetId == NULL) || (FormId == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Returns bitmap used to describe the credential provider type.
+
+ This optional function returns a bitmap which is less than or equal to the number
+ of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
+ is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ width of the bitmap returned.
+ @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ height of the bitmap returned.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] Image On return, holds the HII image identifier.
+
+ @retval EFI_SUCCESS Image identifier returned successfully.
+ @retval EFI_NOT_FOUND Image identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTile (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT UINTN *Width,
+ IN OUT UINTN *Height,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_IMAGE_ID *Image
+ )
+{
+ if ((This == NULL) || (Hii == NULL) || (Image == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Returns string used to describe the credential provider type.
+
+ This function returns a string which describes the credential provider. If no
+ such string exists, then EFI_NOT_FOUND is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] String On return, holds the HII string identifier.
+
+ @retval EFI_SUCCESS String identifier returned successfully.
+ @retval EFI_NOT_FOUND String identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTitle (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_STRING_ID *String
+ )
+{
+ if ((This == NULL) || (Hii == NULL) || (String == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Set Hii handle and String ID.
+ //
+ *Hii = mCallbackInfo->HiiHandle;
+ *String = STRING_TOKEN (STR_CREDENTIAL_TITLE);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the user identifier associated with the currently authenticated user.
+
+ This function returns the user identifier of the user authenticated by this credential
+ provider. This function is called after the credential-related information has been
+ submitted on a form OR after a call to Default() has returned that this credential is
+ ready to log on.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile handle of the user profile currently being
+ considered by the user identity manager. If NULL, then no user
+ profile is currently under consideration.
+ @param[out] Identifier On return, points to the user identifier.
+
+ @retval EFI_SUCCESS User identifier returned successfully.
+ @retval EFI_NOT_READY No user identifier can be returned.
+ @retval EFI_ACCESS_DENIED The user has been locked out of this user credential.
+ @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL.
+ @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be
+ found in user profile database.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialUser (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User,
+ OUT EFI_USER_INFO_IDENTIFIER *Identifier
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_USER_INFO *UserInfo;
+ UINT8 *UserId;
+ UINT8 *NewUserId;
+ UINT8 *UserToken;
+ UINT8 ReadToken[HASHED_CREDENTIAL_LEN];
+ EFI_INPUT_KEY Key;
+ EFI_TPL OldTpl;
+ CHAR16 *QuestionStr;
+ CHAR16 *PromptStr;
+
+ if ((This == NULL) || (Identifier == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (User == NULL) {
+ //
+ // Verify the auto logon user, get user id by matched token.
+ //
+ if (mUsbTable->Count == 0) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // No user selected, get token first and verify the user existed in user database.
+ //
+ Status = GetToken (ReadToken);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_READY;
+ }
+
+ for (Index = 0; Index < mUsbTable->Count; Index++) {
+ //
+ // find the specified credential in the Usb credential database.
+ //
+ UserToken = mUsbTable->UserInfo[Index].Token;
+ if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) {
+ UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
+ CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+ }
+
+ //
+ // User is not NULL here. Read a token, and check whether the token matches with
+ // the selected user's Token. If not, try to find a token in token DB to matches
+ // with read token.
+ //
+
+ Status = GetToken (ReadToken);
+ if (EFI_ERROR (Status)) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR));
+ PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN));
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (TPL_APPLICATION);
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ gBS->RaiseTPL (OldTpl);
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the selected user's identifier.
+ //
+ Status = FindUserInfoByType (User, EFI_USER_INFO_IDENTIFIER_RECORD, &UserInfo);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check the selected user's Token with the read token.
+ //
+ for (Index = 0; Index < mUsbTable->Count; Index++) {
+ UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
+ NewUserId = (UINT8 *) (UserInfo + 1);
+ if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
+ //
+ // The user's ID is found in the UsbTable.
+ //
+ UserToken = mUsbTable->UserInfo[Index].Token;
+ if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) {
+ //
+ // The read token matches with the one in UsbTable.
+ //
+ CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
+ FreePool (UserInfo);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ FreePool (UserInfo);
+
+ //
+ // The read token mismatch with the User's Token.
+ // Only check token.
+ //
+ for (Index = 0; Index < mUsbTable->Count; Index++) {
+ UserToken = mUsbTable->UserInfo[Index].Token;
+ if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) {
+ //
+ // The read token matches with the one in UsbTable.
+ //
+ UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
+ CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Indicate that user interface interaction has begun for the specified credential.
+
+ This function is called when a credential provider is selected by the user. If
+ AutoLogon returns FALSE, then the user interface will be constructed by the User
+ Identity Manager.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, points to the credential provider's capabilities
+ after the credential provider has been selected by the user.
+
+ @retval EFI_SUCCESS Credential provider successfully selected.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialSelect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ )
+{
+ if ((This == NULL) || (AutoLogon == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Indicate that user interface interaction has ended for the specified credential.
+
+ This function is called when a credential provider is deselected by the user.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+
+ @retval EFI_SUCCESS Credential provider successfully deselected.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDeselect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This
+ )
+{
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the default logon behavior for this user credential.
+
+ This function reports the default login behavior regarding this credential provider.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, holds whether the credential provider should be used
+ by default to automatically log on the user.
+
+ @retval EFI_SUCCESS Default information successfully returned.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDefault (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ )
+{
+ if ((This == NULL) || (AutoLogon == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return information attached to the credential provider.
+
+ This function returns user information.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @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_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the
+ user information. The size required is returned in *InfoSize.
+ @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
+ @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialGetInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_INFO_HANDLE UserInfo,
+ OUT EFI_USER_INFO *Info,
+ IN OUT UINTN *InfoSize
+ )
+{
+ EFI_USER_INFO *CredentialInfo;
+ UINTN Index;
+
+ if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UserInfo == NULL) || (mUsbInfoHandle == NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find information handle in credential info table.
+ //
+ for (Index = 0; Index < mUsbInfoHandle->Count; Index++) {
+ CredentialInfo = mUsbInfoHandle->Info[Index];
+ if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) {
+ //
+ // The handle is found, copy the user info.
+ //
+ if (CredentialInfo->InfoSize > *InfoSize) {
+ *InfoSize = CredentialInfo->InfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Enumerate all of the user informations on the credential provider.
+
+ 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_CREDENTIAL_PROTOCOL.
+ @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
+ to start enumeration. On exit, points to the next user information
+ handle or NULL if there is no more user information.
+
+ @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
+CredentialGetNextInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT EFI_USER_INFO_HANDLE *UserInfo
+ )
+{
+ EFI_USER_INFO *Info;
+ CHAR16 *ProvNameStr;
+ UINTN InfoLen;
+ UINTN Index;
+ UINTN ProvStrLen;
+
+ if ((This == NULL) || (UserInfo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mUsbInfoHandle == NULL) {
+ //
+ // Initilized user info table. There are 4 user info records in the table.
+ //
+ InfoLen = sizeof (USB_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *);
+ mUsbInfoHandle = AllocateZeroPool (InfoLen);
+ if (mUsbInfoHandle == NULL) {
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The first information, Credential Provider info.
+ //
+ InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mUsbCredentialGuid);
+ CopyGuid ((EFI_GUID *)(Info + 1), &mUsbCredentialGuid);
+
+ mUsbInfoHandle->Info[0] = Info;
+ mUsbInfoHandle->Count++;
+
+ //
+ // The second information, Credential Provider name info.
+ //
+ ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME));
+ ProvStrLen = StrSize (ProvNameStr);
+ InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mUsbCredentialGuid);
+ CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
+ FreePool (ProvNameStr);
+
+ mUsbInfoHandle->Info[1] = Info;
+ mUsbInfoHandle->Count++;
+
+ //
+ // The third information, Credential Provider type info.
+ //
+ InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mUsbCredentialGuid);
+ CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassSecureCardGuid);
+
+ mUsbInfoHandle->Info[2] = Info;
+ mUsbInfoHandle->Count++;
+
+ //
+ // The fourth information, Credential Provider type name info.
+ //
+ ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME));
+ ProvStrLen = StrSize (ProvNameStr);
+ InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
+ Info = AllocateZeroPool (InfoLen);
+ ASSERT (Info != NULL);
+
+ Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
+ Info->InfoSize = (UINT32) InfoLen;
+ Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
+ CopyGuid (&Info->Credential, &mUsbCredentialGuid);
+ CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
+ FreePool (ProvNameStr);
+
+ mUsbInfoHandle->Info[3] = Info;
+ mUsbInfoHandle->Count++;
+ }
+
+ if (*UserInfo == NULL) {
+ //
+ // Return the first info handle.
+ //
+ *UserInfo = (EFI_USER_INFO_HANDLE) mUsbInfoHandle->Info[0];
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Find information handle in credential info table.
+ //
+ for (Index = 0; Index < mUsbInfoHandle->Count; Index++) {
+ Info = mUsbInfoHandle->Info[Index];
+ if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) {
+ //
+ // The handle is found, get the next one.
+ //
+ if (Index == mUsbInfoHandle->Count - 1) {
+ //
+ // Already last one.
+ //
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+ }
+ Index++;
+ *UserInfo = (EFI_USER_INFO_HANDLE)mUsbInfoHandle->Info[Index];
+ return EFI_SUCCESS;
+ }
+ }
+
+ *UserInfo = NULL;
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbProviderInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init credential table.
+ //
+ Status = InitCredentialTable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Init Form Browser
+ //
+ Status = InitFormBrowser ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install protocol interfaces for the Usb Credential Provider.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mCallbackInfo->DriverHandle,
+ &gEfiUserCredentialProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gUsbCredentialProviderDriver
+ );
+ return Status;
+}
diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h
new file mode 100644
index 0000000000..1d43e9ac99
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h
@@ -0,0 +1,354 @@
+/** @file
+ Usb Credential Provider driver header file.
+
+Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+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 _USB_CREDENTIAL_PROVIDER_H_
+#define _USB_CREDENTIAL_PROVIDER_H_
+
+#include <Uefi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/FileInfo.h>
+#include <Guid/SecurityPkgTokenSpace.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/UserCredential.h>
+#include <Protocol/UserManager.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+
+extern UINT8 UsbCredentialProviderStrings[];
+extern UINT8 UsbCredentialProviderVfrBin[];
+
+#define USB_TABLE_INC 16
+#define HASHED_CREDENTIAL_LEN 20
+
+#define USB_CREDENTIAL_PROVIDER_GUID \
+ { \
+ 0xd0849ed1, 0xa88c, 0x4ba6, { 0xb1, 0xd6, 0xab, 0x50, 0xe2, 0x80, 0xb7, 0xa9 }\
+ }
+
+//
+// Save the enroll user credential Information.
+//
+typedef struct {
+ EFI_USER_INFO_IDENTIFIER UserId;
+ UINT8 Token[HASHED_CREDENTIAL_LEN];
+} USB_INFO;
+
+//
+// USB Credential Table.
+//
+typedef struct {
+ UINTN Count;
+ UINTN MaxCount;
+ USB_INFO UserInfo[1];
+} CREDENTIAL_TABLE;
+
+//
+// The user information on the USB provider.
+//
+typedef struct {
+ UINTN Count;
+ EFI_USER_INFO *Info[1];
+} USB_CREDENTIAL_INFO;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#define USB_PROVIDER_SIGNATURE SIGNATURE_32 ('U', 'S', 'B', 'P')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+} USB_PROVIDER_CALLBACK_INFO;
+
+/**
+ Enroll a user on a credential provider.
+
+ This function enrolls and deletes a user profile using this credential provider.
+ If a user profile is successfully enrolled, it calls the User Manager Protocol
+ function Notify() to notify the user manager driver that credential information
+ has changed. If an enrolled user does exist, delete the user on the credential
+ provider.
+
+ @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile to enroll.
+
+ @retval EFI_SUCCESS User profile was successfully enrolled.
+ @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the
+ user profile handle. Either the user profile cannot enroll
+ on any user profile or cannot enroll on a user profile
+ other than the current user profile.
+ @retval EFI_UNSUPPORTED This credential provider does not support enrollment in
+ the pre-OS.
+ @retval EFI_DEVICE_ERROR The new credential could not be created because of a device
+ error.
+ @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialEnroll (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User
+ );
+
+/**
+ Returns the user interface information used during user identification.
+
+ This function returns information about the form used when interacting with the
+ user during user identification. The form is the first enabled form in the form-set
+ class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
+ the user credential provider does not require a form to identify the user, then this
+ function should return EFI_NOT_FOUND.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] FormSetId On return, holds the identifier of the form set which contains
+ the form used during user identification.
+ @param[out] FormId On return, holds the identifier of the form used during user
+ identification.
+
+ @retval EFI_SUCCESS Form returned successfully.
+ @retval EFI_NOT_FOUND Form not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialForm (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_GUID *FormSetId,
+ OUT EFI_FORM_ID *FormId
+ );
+
+/**
+ Returns bitmap used to describe the credential provider type.
+
+ This optional function returns a bitmap which is less than or equal to the number
+ of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
+ is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ width of the bitmap returned.
+ @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no
+ bitmap information will be returned. On exit, points to the
+ height of the bitmap returned.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] Image On return, holds the HII image identifier.
+
+ @retval EFI_SUCCESS Image identifier returned successfully.
+ @retval EFI_NOT_FOUND Image identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTile (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT UINTN *Width,
+ IN OUT UINTN *Height,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_IMAGE_ID *Image
+ );
+
+/**
+ Returns string used to describe the credential provider type.
+
+ This function returns a string which describes the credential provider. If no
+ such string exists, then EFI_NOT_FOUND is returned.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] Hii On return, holds the HII database handle.
+ @param[out] String On return, holds the HII string identifier.
+
+ @retval EFI_SUCCESS String identifier returned successfully.
+ @retval EFI_NOT_FOUND String identifier not returned.
+ @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialTitle (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_HII_HANDLE *Hii,
+ OUT EFI_STRING_ID *String
+ );
+
+/**
+ Return the user identifier associated with the currently authenticated user.
+
+ This function returns the user identifier of the user authenticated by this credential
+ provider. This function is called after the credential-related information has been
+ submitted on a form OR after a call to Default() has returned that this credential is
+ ready to log on.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[in] User The user profile handle of the user profile currently being
+ considered by the user identity manager. If NULL, then no user
+ profile is currently under consideration.
+ @param[out] Identifier On return, points to the user identifier.
+
+ @retval EFI_SUCCESS User identifier returned successfully.
+ @retval EFI_NOT_READY No user identifier can be returned.
+ @retval EFI_ACCESS_DENIED The user has been locked out of this user credential.
+ @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL.
+ @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be
+ found in user profile database.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialUser (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_PROFILE_HANDLE User,
+ OUT EFI_USER_INFO_IDENTIFIER *Identifier
+ );
+
+/**
+ Indicate that user interface interaction has begun for the specified credential.
+
+ This function is called when a credential provider is selected by the user. If
+ AutoLogon returns FALSE, then the user interface will be constructed by the User
+ Identity Manager.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, points to the credential provider's capabilities
+ after the credential provider has been selected by the user.
+
+ @retval EFI_SUCCESS Credential provider successfully selected.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialSelect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ );
+
+/**
+ Indicate that user interface interaction has ended for the specified credential.
+
+ This function is called when a credential provider is deselected by the user.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+
+ @retval EFI_SUCCESS Credential provider successfully deselected.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDeselect (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This
+ );
+
+/**
+ Return the default logon behavior for this user credential.
+
+ This function reports the default login behavior regarding this credential provider.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @param[out] AutoLogon On return, holds whether the credential provider should be used
+ by default to automatically log on the user.
+
+ @retval EFI_SUCCESS Default information successfully returned.
+ @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialDefault (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
+ );
+
+/**
+ Return information attached to the credential provider.
+
+ This function returns user information.
+
+ @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
+ @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_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the
+ user information. The size required is returned in *InfoSize.
+ @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
+ @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CredentialGetInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN EFI_USER_INFO_HANDLE UserInfo,
+ OUT EFI_USER_INFO *Info,
+ IN OUT UINTN *InfoSize
+ );
+
+/**
+ Enumerate all of the user informations on the credential provider.
+
+ 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_CREDENTIAL_PROTOCOL.
+ @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
+ to start enumeration. On exit, points to the next user information
+ handle or NULL if there is no more user information.
+
+ @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
+CredentialGetNextInfo (
+ IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
+ IN OUT EFI_USER_INFO_HANDLE *UserInfo
+ );
+
+#endif
diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf
new file mode 100644
index 0000000000..2a45763566
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for USB Credential Provider.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+# 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 = UsbCredentialProvider
+ FILE_GUID = 672A0C68-2BF0-46f9-93C3-C4E7DC0FA555
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UsbProviderInit
+
+[Sources]
+ UsbCredentialProvider.c
+ UsbCredentialProvider.h
+ UsbCredentialProviderStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CryptoPkg/CryptoPkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ BaseMemoryLib
+ DebugLib
+ HiiLib
+ UefiLib
+ BaseCryptLib
+
+[Guids]
+ gEfiIfrTianoGuid ## CONSUMES ## Guid
+ gEfiFileInfoGuid ## CONSUMES ## Guid
+ gEfiUserCredentialClassSecureCardGuid ## CONSUMES ## Guid
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedUsbCredentialProviderTokenFileName
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiUserCredentialProtocolGuid
+ gEfiUserManagerProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ \ No newline at end of file
diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni
new file mode 100644
index 0000000000..7c531f4230
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni
Binary files differ
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.<BR>
+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.<BR>
+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 <ConfigRequest> 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 <ConfigAltResp> 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 <ConfigResp> 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.<BR>
+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 <Uefi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/MdeModuleHii.h>
+
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/UserCredential.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/DeferredImageLoad.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+
+#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.<BR>
+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.<BR>
+# 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
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni
Binary files 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.<BR>
+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
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c
new file mode 100644
index 0000000000..eb96c8edf6
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c
@@ -0,0 +1,372 @@
+/** @file
+ The functions to add a user profile.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "UserProfileManager.h"
+
+
+/**
+ Get user name from the popup windows.
+
+ @param[in, out] UserNameLen On entry, point to UserName buffer lengh, in bytes.
+ On exit, point to input user name length, in bytes.
+ @param[out] UserName The buffer to hold the input user name.
+
+ @retval EFI_ABORTED It is given up by pressing 'ESC' key.
+ @retval EFI_NOT_READY Not a valid input at all.
+ @retval EFI_SUCCESS Get a user name successfully.
+
+**/
+EFI_STATUS
+GetUserNameInput (
+ IN OUT UINTN *UserNameLen,
+ OUT CHAR16 *UserName
+ )
+{
+ EFI_INPUT_KEY Key;
+ UINTN NameLen;
+ CHAR16 Name[USER_NAME_LENGTH];
+
+ NameLen = 0;
+ while (TRUE) {
+ Name[NameLen] = L'_';
+ Name[NameLen + 1] = L'\0';
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Input User Name",
+ L"---------------------",
+ Name,
+ NULL
+ );
+ //
+ // Check key.
+ //
+ if (Key.ScanCode == SCAN_NULL) {
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // Add the null terminator.
+ //
+ Name[NameLen] = 0;
+ NameLen++;
+ break;
+ } else if ((Key.UnicodeChar == CHAR_NULL) ||
+ (Key.UnicodeChar == CHAR_TAB) ||
+ (Key.UnicodeChar == CHAR_LINEFEED)
+ ) {
+ continue;
+ } else {
+ if (Key.UnicodeChar == CHAR_BACKSPACE) {
+ if (NameLen > 0) {
+ NameLen--;
+ }
+ } else {
+ Name[NameLen] = Key.UnicodeChar;
+ NameLen++;
+ if (NameLen + 1 == USER_NAME_LENGTH) {
+ //
+ // Add the null terminator.
+ //
+ Name[NameLen] = 0;
+ NameLen++;
+ break;
+ }
+ }
+ }
+ }
+
+ if (Key.ScanCode == SCAN_ESC) {
+ return EFI_ABORTED;
+ }
+ }
+
+ if (NameLen <= 1) {
+ return EFI_NOT_READY;
+ }
+
+ if (*UserNameLen < NameLen * sizeof (CHAR16)) {
+ return EFI_NOT_READY;
+ }
+
+ *UserNameLen = NameLen * sizeof (CHAR16);
+ CopyMem (UserName, Name, *UserNameLen);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set a user's username.
+
+ @param[in] User Handle of a user profile .
+ @param[in] UserNameLen The lengh of UserName.
+ @param[in] UserName Point to the buffer of user name.
+
+ @retval EFI_NOT_READY The usernme in mAddUserName had been used.
+ @retval EFI_SUCCESS Change the user's username successfully with
+ username in mAddUserName.
+
+**/
+EFI_STATUS
+SetUserName (
+ IN EFI_USER_PROFILE_HANDLE User,
+ IN UINTN UserNameLen,
+ IN CHAR16 *UserName
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_PROFILE_HANDLE TempUser;
+ EFI_USER_INFO *NewUserInfo;
+
+ NewUserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + UserNameLen);
+ ASSERT (NewUserInfo != NULL);
+
+ NewUserInfo->InfoType = EFI_USER_INFO_NAME_RECORD;
+ NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PUBLIC |
+ EFI_USER_INFO_EXCLUSIVE;
+ NewUserInfo->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + UserNameLen);
+ CopyMem ((UINT8 *) (NewUserInfo + 1), UserName, UserNameLen);
+ TempUser = NULL;
+ Status = mUserManager->Find (
+ mUserManager,
+ &TempUser,
+ NULL,
+ NewUserInfo,
+ NewUserInfo->InfoSize
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The user name had been used, return error.
+ //
+ FreePool (NewUserInfo);
+ return EFI_NOT_READY;
+ }
+
+ UserInfo = NULL;
+ mUserManager->SetInfo (
+ mUserManager,
+ User,
+ &UserInfo,
+ NewUserInfo,
+ NewUserInfo->InfoSize
+ );
+ FreePool (NewUserInfo);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set create date of the specified user.
+
+ @param[in] User Handle of a user profile.
+
+**/
+VOID
+SetCreateDate (
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO_CREATE_DATE Date;
+ EFI_USER_INFO *NewUserInfo;
+
+ NewUserInfo = AllocateZeroPool (
+ sizeof (EFI_USER_INFO) +
+ sizeof (EFI_USER_INFO_CREATE_DATE)
+ );
+ ASSERT (NewUserInfo != NULL);
+
+ NewUserInfo->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;
+ NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PUBLIC |
+ EFI_USER_INFO_EXCLUSIVE;
+ NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
+ Status = gRT->GetTime (&Date, NULL);
+ if (EFI_ERROR (Status)) {
+ FreePool (NewUserInfo);
+ return ;
+ }
+
+ CopyMem ((UINT8 *) (NewUserInfo + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));
+ UserInfo = NULL;
+ mUserManager->SetInfo (
+ mUserManager,
+ User,
+ &UserInfo,
+ NewUserInfo,
+ NewUserInfo->InfoSize
+ );
+ FreePool (NewUserInfo);
+}
+
+
+/**
+ Set the default identity policy of the specified user.
+
+ @param[in] User Handle of a user profile.
+
+**/
+VOID
+SetIdentityPolicy (
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_USER_INFO_IDENTITY_POLICY *Policy;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *NewUserInfo;
+
+ NewUserInfo = AllocateZeroPool (
+ sizeof (EFI_USER_INFO) +
+ sizeof (EFI_USER_INFO_IDENTITY_POLICY)
+ );
+ ASSERT (NewUserInfo != NULL);
+
+ Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewUserInfo + 1);
+ Policy->Type = EFI_USER_INFO_IDENTITY_TRUE;
+ Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
+
+ NewUserInfo->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
+ NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PRIVATE |
+ EFI_USER_INFO_EXCLUSIVE;
+ NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length;
+ UserInfo = NULL;
+ mUserManager->SetInfo (
+ mUserManager,
+ User,
+ &UserInfo,
+ NewUserInfo,
+ NewUserInfo->InfoSize
+ );
+ FreePool (NewUserInfo);
+}
+
+
+/**
+ Set the default access policy of the specified user.
+
+ @param[in] User Handle of a user profile.
+
+**/
+VOID
+SetAccessPolicy (
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_USER_INFO_ACCESS_CONTROL *Control;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *NewUserInfo;
+
+ NewUserInfo = AllocateZeroPool (
+ sizeof (EFI_USER_INFO) +
+ sizeof (EFI_USER_INFO_ACCESS_CONTROL)
+ );
+ ASSERT (NewUserInfo != NULL);
+
+ Control = (EFI_USER_INFO_ACCESS_CONTROL *) (NewUserInfo + 1);
+ Control->Type = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ Control->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL);
+
+ NewUserInfo->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD;
+ NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PUBLIC |
+ EFI_USER_INFO_EXCLUSIVE;
+ NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + Control->Size;
+ UserInfo = NULL;
+ mUserManager->SetInfo (
+ mUserManager,
+ User,
+ &UserInfo,
+ NewUserInfo,
+ NewUserInfo->InfoSize
+ );
+ FreePool (NewUserInfo);
+}
+
+
+/**
+ Add a new user profile into the user profile database.
+
+**/
+VOID
+CallAddUser (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ EFI_USER_PROFILE_HANDLE User;
+ UINTN UserNameLen;
+ CHAR16 UserName[USER_NAME_LENGTH];
+ CHAR16 *QuestionStr;
+ CHAR16 *PromptStr;
+
+ QuestionStr = NULL;
+ PromptStr = NULL;
+
+ //
+ // Get user name to add.
+ //
+ UserNameLen = sizeof (UserName);
+ Status = GetUserNameInput (&UserNameLen, UserName);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ABORTED) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_GET_USERNAME_FAILED));
+ PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE));
+ goto Done;
+ }
+ return ;
+ }
+
+ //
+ // Create a new user profile.
+ //
+ User = NULL;
+ Status = mUserManager->Create (mUserManager, &User);
+ if (EFI_ERROR (Status)) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_FAILED));
+ PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE));
+ } else {
+ //
+ // Add default user information.
+ //
+ Status = SetUserName (User, UserNameLen, UserName);
+ if (EFI_ERROR (Status)) {
+ QuestionStr = GetStringById (STRING_TOKEN (STR_USER_ALREADY_EXISTED));
+ PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE));
+ goto Done;
+ }
+
+ SetCreateDate (User);
+ SetIdentityPolicy (User);
+ SetAccessPolicy (User);
+
+ QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_SUCCESS));
+ PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE));
+ }
+
+Done:
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+}
+
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c
new file mode 100644
index 0000000000..d0295b731b
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c
@@ -0,0 +1,314 @@
+/** @file
+ The functions to delete a user profile.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "UserProfileManager.h"
+
+/**
+ Get the username from the specified user.
+
+ @param[in] User Handle of a user profile.
+
+ @retval EFI_STRING_ID The String Id of the user's username.
+
+**/
+EFI_STRING_ID
+GetUserName (
+ IN EFI_USER_PROFILE_HANDLE User
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+ UINTN InfoSize;
+ UINTN MemSize;
+ UINTN NameLen;
+ CHAR16 UserName[USER_NAME_LENGTH];
+ EFI_STRING_ID UserId;
+
+ //
+ // Allocate user information memory.
+ //
+ MemSize = sizeof (EFI_USER_INFO) + 63;
+ Info = AllocateZeroPool (MemSize);
+ ASSERT (Info != NULL);
+
+ //
+ // Get user name information.
+ //
+ UserInfo = NULL;
+ while (TRUE) {
+ InfoSize = MemSize;
+ //
+ // Get next user information.
+ //
+ Status = mUserManager->GetNextInfo (
+ mUserManager,
+ User,
+ &UserInfo
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ User,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MemSize = InfoSize;
+ FreePool (Info);
+ Info = AllocateZeroPool (MemSize);
+ ASSERT (Info != NULL);
+
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ User,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ }
+ //
+ // Check user information.
+ //
+ if (Status == EFI_SUCCESS) {
+ if (Info->InfoType == EFI_USER_INFO_NAME_RECORD) {
+ NameLen = Info->InfoSize - sizeof (EFI_USER_INFO);
+ if (NameLen > USER_NAME_LENGTH * sizeof (CHAR16)) {
+ NameLen = USER_NAME_LENGTH * sizeof (CHAR16);
+ }
+ ASSERT (NameLen >= sizeof (CHAR16));
+ CopyMem (UserName, (UINT8 *) (Info + 1), NameLen);
+ UserName[NameLen / sizeof (CHAR16) - 1] = 0;
+ UserId = HiiSetString (
+ mCallbackInfo->HiiHandle,
+ 0,
+ UserName,
+ NULL
+ );
+ if (UserId != 0) {
+ FreePool (Info);
+ return UserId;
+ }
+ }
+ }
+ }
+
+ FreePool (Info);
+ return 0;
+}
+
+
+/**
+ Add a username item in form.
+
+ @param[in] User Points to the user profile whose username is added.
+ @param[in] Index The index of the user in the user name list
+ @param[in] OpCodeHandle Points to container for dynamic created opcodes.
+
+**/
+VOID
+AddUserToForm (
+ IN EFI_USER_PROFILE_HANDLE User,
+ IN UINT16 Index,
+ IN VOID *OpCodeHandle
+ )
+{
+ EFI_STRING_ID NameId;
+
+ //
+ // Get user name
+ //
+ NameId = GetUserName (User);
+ if (NameId == 0) {
+ return ;
+ }
+
+ //
+ // Create user name option.
+ //
+ switch (Index & KEY_FIRST_FORM_MASK) {
+ case KEY_MODIFY_USER:
+ HiiCreateGotoOpCode (
+ OpCodeHandle, // Container for dynamic created opcodes
+ FORMID_USER_INFO, // Target Form ID
+ NameId, // Prompt text
+ STRING_TOKEN (STR_NULL_STRING), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ Index // Question ID
+ );
+ break;
+
+ case KEY_DEL_USER:
+ HiiCreateActionOpCode (
+ OpCodeHandle, // Container for dynamic created opcodes
+ Index, // Question ID
+ NameId, // Prompt text
+ STRING_TOKEN (STR_NULL_STRING), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ 0 // Action String ID
+ );
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ Delete the user specified by UserIndex in user profile database.
+
+ @param[in] UserIndex The index of user in the user name list
+ to be deleted.
+
+**/
+VOID
+DeleteUser (
+ IN UINT8 UserIndex
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_PROFILE_HANDLE User;
+ EFI_INPUT_KEY Key;
+
+ //
+ // Find specified user profile and delete it.
+ //
+ User = NULL;
+ Status = mUserManager->GetNext (mUserManager, &User);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ while (UserIndex > 1) {
+ Status = mUserManager->GetNext (mUserManager, &User);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ UserIndex--;
+ }
+
+ if (UserIndex == 1) {
+ Status = mUserManager->Delete (mUserManager, User);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Delete User Succeed!",
+ L"",
+ L"Please Press Any Key to Continue ...",
+ NULL
+ );
+ return ;
+ }
+
+Done:
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Delete User Failed!",
+ L"",
+ L"Please Press Any Key to Continue ...",
+ NULL
+ );
+}
+
+
+/**
+ Display user select form, cab select a user to delete.
+
+**/
+VOID
+SelectUserToDelete (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_USER_PROFILE_HANDLE User;
+ EFI_USER_PROFILE_HANDLE CurrentUser;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // 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_DEL_FUNC;
+
+ 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 each user can be deleted.
+ //
+ User = NULL;
+ Index = 1;
+ mUserManager->Current (mUserManager, &CurrentUser);
+ while (TRUE) {
+ Status = mUserManager->GetNext (mUserManager, &User);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (User != CurrentUser) {
+ AddUserToForm (
+ User,
+ (UINT16)(KEY_DEL_USER | KEY_SELECT_USER | Index),
+ StartOpCodeHandle
+ );
+ }
+ Index++;
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_DEL_USER, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c
new file mode 100644
index 0000000000..74c979d58e
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c
@@ -0,0 +1,806 @@
+/** @file
+ This driver is a configuration tool for adding, deleting or modifying user
+ profiles, including gathering the necessary information to ascertain their
+ identity in the future, updating user access policy and identification
+ policy, etc.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+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 "UserProfileManager.h"
+
+EFI_GUID mUserProfileManagerGuid = USER_PROFILE_MANAGER_GUID;
+EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
+CREDENTIAL_PROVIDER_INFO *mProviderInfo = NULL;
+UINT8 mProviderChoice;
+UINT8 mConncetLogical;
+USER_INFO_ACCESS mAccessInfo;
+USER_INFO mUserInfo;
+USER_PROFILE_MANAGER_CALLBACK_INFO *mCallbackInfo;
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ {0xad2e3474, 0x93e6, 0x488b, {0x93, 0x19, 0x64, 0x88, 0xfc, 0x68, 0x1f, 0x16}}
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+
+/**
+ Get string by string id from HII Interface.
+
+
+ @param[in] Id String ID to get the string from.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ //
+ // Get the current string for the current Language.
+ //
+ return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL);
+}
+
+
+/**
+ This function gets all the credential providers in the system and saved them
+ to mProviderInfo.
+
+ @retval EFI_SUCESS Init credential provider database successfully.
+ @retval Others Fail to init credential provider database.
+
+**/
+EFI_STATUS
+InitProviderInfo (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuf;
+ UINTN Index;
+
+ //
+ // 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.
+ //
+ if (mProviderInfo != NULL) {
+ FreePool (mProviderInfo);
+ }
+ mProviderInfo = AllocateZeroPool (
+ sizeof (CREDENTIAL_PROVIDER_INFO) -
+ sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) +
+ HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *)
+ );
+ if (mProviderInfo == NULL) {
+ FreePool (HandleBuf);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mProviderInfo->Count = HandleCount;
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuf[Index],
+ &gEfiUserCredentialProtocolGuid,
+ (VOID **) &mProviderInfo->Provider[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (HandleBuf);
+ FreePool (mProviderInfo);
+ mProviderInfo = NULL;
+ return Status;
+ }
+ }
+
+ FreePool (HandleBuf);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function processes changes in user profile 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
+UserProfileManagerCallback (
+ 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;
+ EFI_INPUT_KEY Key;
+ UINT32 CurrentAccessRight;
+ CHAR16 *QuestionStr;
+ CHAR16 *PromptStr;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ EFI_USER_PROFILE_HANDLE CurrentUser;
+
+ Status = EFI_SUCCESS;
+
+ switch (Action) {
+ case EFI_BROWSER_ACTION_FORM_OPEN:
+ {
+ //
+ // Update user manage Form when user manage Form is opened.
+ // This will be done only in FORM_OPEN CallBack of question with QUESTIONID_USER_MANAGE from user manage Form.
+ //
+ if (QuestionId != QUESTIONID_USER_MANAGE) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get current user
+ //
+ CurrentUser = NULL;
+ mUserManager->Current (mUserManager, &CurrentUser);
+ if (CurrentUser == NULL) {
+ DEBUG ((DEBUG_ERROR, "Error: current user does not exist!\n"));
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Get current user's right information.
+ //
+ Status = GetAccessRight (&CurrentAccessRight);
+ if (EFI_ERROR (Status)) {
+ CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ }
+
+ //
+ // Init credential provider information.
+ //
+ Status = InitProviderInfo ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // 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_MANAGE_FUNC;
+
+ 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 user profile option.
+ //
+ if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) ||
+ (CurrentAccessRight == EFI_USER_INFO_ACCESS_ENROLL_OTHERS)
+ ) {
+ HiiCreateActionOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_ADD_USER, // Question ID
+ STRING_TOKEN (STR_ADD_USER_TITLE), // Prompt text
+ STRING_TOKEN (STR_ADD_USER_HELP), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ 0 // Action String ID
+ );
+ }
+
+ //
+ // Add modify user profile option.
+ //
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ FORMID_MODIFY_USER, // Target Form ID
+ STRING_TOKEN (STR_MODIFY_USER_TITLE), // Prompt text
+ STRING_TOKEN (STR_MODIFY_USER_HELP), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ KEY_MODIFY_USER // Question ID
+ );
+
+ //
+ // Add delete user profile option
+ //
+ if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) {
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ FORMID_DEL_USER, // Target Form ID
+ STRING_TOKEN (STR_DELETE_USER_TITLE), // Prompt text
+ STRING_TOKEN (STR_DELETE_USER_HELP), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ KEY_DEL_USER // Question ID
+ );
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_USER_MANAGE, // 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:
+ {
+ //
+ // Handle the request from form.
+ //
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Judge first 2 bits.
+ //
+ switch (QuestionId & KEY_FIRST_FORM_MASK) {
+ //
+ // Add user profile operation.
+ //
+ case KEY_ADD_USER:
+ CallAddUser ();
+ break;
+
+ //
+ // Delete user profile operation.
+ //
+ case KEY_DEL_USER:
+ //
+ // Judge next 2 bits.
+ //
+ switch (QuestionId & KEY_SECOND_FORM_MASK) {
+ //
+ // Enter delete user profile form.
+ //
+ case KEY_ENTER_NEXT_FORM:
+ SelectUserToDelete ();
+ break;
+
+ //
+ // Delete specified user profile.
+ //
+ case KEY_SELECT_USER:
+ DeleteUser ((UINT8) QuestionId);
+ //
+ // Update select user form after delete a user.
+ //
+ SelectUserToDelete ();
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Modify user profile operation.
+ //
+ case KEY_MODIFY_USER:
+ //
+ // Judge next 2 bits.
+ //
+ switch (QuestionId & KEY_SECOND_FORM_MASK) {
+ //
+ // Enter modify user profile form.
+ //
+ case KEY_ENTER_NEXT_FORM:
+ SelectUserToModify ();
+ break;
+
+ //
+ // Enter user profile information form.
+ //
+ case KEY_SELECT_USER:
+ //
+ // Judge next 3 bits.
+ //
+ switch (QuestionId & KEY_MODIFY_INFO_MASK) {
+ //
+ // Display user information form.
+ //
+ case KEY_ENTER_NEXT_FORM:
+ ModifyUserInfo ((UINT8) QuestionId);
+ break;
+
+ //
+ // Modify user name.
+ //
+ case KEY_MODIFY_NAME:
+ ModifyUserName ();
+ //
+ // Update username in parent form.
+ //
+ SelectUserToModify ();
+ break;
+
+ //
+ // Modify identity policy.
+ //
+ case KEY_MODIFY_IP:
+ //
+ // Judge next 3 bits
+ //
+ switch (QuestionId & KEY_MODIFY_IP_MASK) {
+ //
+ // Display identity policy modify form.
+ //
+ case KEY_ENTER_NEXT_FORM:
+ ModifyIdentityPolicy ();
+ break;
+
+ //
+ // Change credential provider option.
+ //
+ case KEY_MODIFY_PROV:
+ mProviderChoice = Value->u8;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ //
+ // Change logical connector.
+ //
+ case KEY_MODIFY_CONN:
+ mConncetLogical = Value->u8;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ //
+ // Save option.
+ //
+ case KEY_ADD_IP_OP:
+ AddIdentityPolicyItem ();
+ break;
+
+ //
+ // Return to user profile information form.
+ //
+ case KEY_IP_RETURN_UIF:
+ SaveIdentityPolicy ();
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Modify access policy.
+ //
+ case KEY_MODIFY_AP:
+ //
+ // Judge next 3 bits.
+ //
+ switch (QuestionId & KEY_MODIFY_AP_MASK) {
+ //
+ // Display access policy modify form.
+ //
+ case KEY_ENTER_NEXT_FORM:
+ ModidyAccessPolicy ();
+ break;
+
+ //
+ // Change access right choice.
+ //
+ case KEY_MODIFY_RIGHT:
+ mAccessInfo.AccessRight = Value->u8;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ //
+ // Change setup choice.
+ //
+ case KEY_MODIFY_SETUP:
+ mAccessInfo.AccessSetup= Value->u8;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ //
+ // Change boot order choice.
+ //
+ case KEY_MODIFY_BOOT:
+ mAccessInfo.AccessBootOrder = Value->u32;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ //
+ // Load device path form.
+ //
+ case KEY_MODIFY_LOAD:
+ //
+ // Judge next 2 bits.
+ //
+ switch (QuestionId & KEY_DISPLAY_DP_MASK) {
+ //
+ // Permit load device path.
+ //
+ case KEY_PERMIT_MODIFY:
+ DisplayLoadPermit ();
+ break;
+
+ //
+ // Forbid load device path.
+ //
+ case KEY_FORBID_MODIFY:
+ DisplayLoadForbid ();
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Connect device path form.
+ //
+ case KEY_MODIFY_CONNECT:
+ //
+ // Judge next 2 bits.
+ //
+ switch (QuestionId & KEY_DISPLAY_DP_MASK) {
+ //
+ // Permit connect device path.
+ //
+ case KEY_PERMIT_MODIFY:
+ DisplayConnectPermit ();
+ break;
+
+ //
+ // Forbid connect device path.
+ //
+ case KEY_FORBID_MODIFY:
+ DisplayConnectForbid ();
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Return to user profile information form.
+ //
+ case KEY_AP_RETURN_UIF:
+ SaveAccessPolicy ();
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Access policy device path modified.
+ //
+ case KEY_MODIFY_AP_DP:
+ //
+ // Judge next 2 bits.
+ //
+ switch (QuestionId & KEY_MODIFY_DP_MASK) {
+ //
+ // Load permit device path modified.
+ //
+ case KEY_LOAD_PERMIT_MODIFY:
+ QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_FORBID_LIST));
+ PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE));
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+ if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) {
+ break;
+ }
+
+ AddToForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1)));
+ DisplayLoadPermit ();
+ break;
+
+ //
+ // Load forbid device path modified.
+ //
+ case KEY_LOAD_FORBID_MODIFY:
+ QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_PERMIT_LIST));
+ PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE));
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ QuestionStr,
+ L"",
+ PromptStr,
+ NULL
+ );
+ FreePool (QuestionStr);
+ FreePool (PromptStr);
+ if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) {
+ break;
+ }
+
+ DeleteFromForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1)));
+ DisplayLoadForbid ();
+ break;
+
+ //
+ // Connect permit device path modified.
+ //
+ case KEY_CONNECT_PERMIT_MODIFY:
+ break;
+
+ //
+ // Connect forbid device path modified.
+ //
+ case KEY_CONNECT_FORBID_MODIFY:
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ //
+ // All other action return unsupported.
+ //
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+
+ return Status;
+}
+
+
+/**
+ 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 <ConfigRequest> 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 <ConfigAltResp> 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 <ConfigResp> 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;
+}
+
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+UserProfileManagerInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ USER_PROFILE_MANAGER_CALLBACK_INFO *CallbackInfo;
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &mUserManager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Initialize driver private data.
+ //
+ ZeroMem (&mUserInfo, sizeof (mUserInfo));
+ ZeroMem (&mAccessInfo, sizeof (mAccessInfo));
+
+ CallbackInfo = AllocateZeroPool (sizeof (USER_PROFILE_MANAGER_CALLBACK_INFO));
+ ASSERT (CallbackInfo != NULL);
+
+ CallbackInfo->Signature = USER_PROFILE_MANAGER_SIGNATURE;
+ CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig;
+ CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig;
+ CallbackInfo->ConfigAccess.Callback = UserProfileManagerCallback;
+ 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 (
+ &mUserProfileManagerGuid,
+ CallbackInfo->DriverHandle,
+ UserProfileManagerStrings,
+ UserProfileManagerVfrBin,
+ NULL
+ );
+ ASSERT (CallbackInfo->HiiHandle != NULL);
+ mCallbackInfo = CallbackInfo;
+
+ return Status;
+}
+
+
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h
new file mode 100644
index 0000000000..b7098dc7b6
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h
@@ -0,0 +1,387 @@
+/** @file
+ The header file for user profile manager driver.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 __EFI_USER_PROFILE_MANAGER_H__
+#define __EFI_USER_PROFILE_MANAGER_H__
+
+#include <Uefi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/MdeModuleHii.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/UserCredential.h>
+#include <Protocol/UserManager.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+
+#include "UserProfileManagerData.h"
+
+#define USER_NAME_LENGTH 17
+
+//
+// Credential Provider Information.
+//
+typedef struct {
+ UINTN Count;
+ EFI_USER_CREDENTIAL_PROTOCOL *Provider[1];
+} CREDENTIAL_PROVIDER_INFO;
+
+//
+// User profile information structure.
+//
+typedef struct {
+ UINT64 UsageCount;
+ EFI_TIME CreateDate;
+ EFI_TIME UsageDate;
+ UINTN AccessPolicyLen;
+ UINTN IdentityPolicyLen;
+ UINTN NewIdentityPolicyLen;
+ UINT8 *AccessPolicy;
+ UINT8 *IdentityPolicy;
+ UINT8 *NewIdentityPolicy;
+ CHAR16 UserName[USER_NAME_LENGTH];
+ BOOLEAN CreateDateExist;
+ BOOLEAN UsageDateExist;
+ BOOLEAN AccessPolicyModified;
+ BOOLEAN IdentityPolicyModified;
+ BOOLEAN NewIdentityPolicyModified;
+} USER_INFO;
+
+//
+// User access information structure.
+//
+typedef struct {
+ UINTN LoadPermitLen;
+ UINTN LoadForbidLen;
+ UINTN ConnectPermitLen;
+ UINTN ConnectForbidLen;
+ UINT8 *LoadPermit;
+ UINT8 *LoadForbid;
+ UINT8 *ConnectPermit;
+ UINT8 *ConnectForbid;
+ UINT32 AccessBootOrder;
+ UINT8 AccessRight;
+ UINT8 AccessSetup;
+} USER_INFO_ACCESS;
+
+#define USER_PROFILE_MANAGER_SIGNATURE SIGNATURE_32 ('U', 'P', 'M', 'S')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} USER_PROFILE_MANAGER_CALLBACK_INFO;
+
+//
+// HII specific Vendor Device Path definition.
+//
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+//
+extern UINT8 UserProfileManagerVfrBin[];
+
+//
+// This is the generated String package data for .UNI file.
+//
+extern UINT8 UserProfileManagerStrings[];
+
+//
+// Guid used in the form browse.
+//
+extern EFI_GUID mUserProfileManagerGuid;
+
+//
+// The user manager protocol, used in several function.
+//
+extern EFI_USER_MANAGER_PROTOCOL *mUserManager;
+
+//
+// The credential providers database in system.
+//
+extern CREDENTIAL_PROVIDER_INFO *mProviderInfo;
+
+//
+// The variables used to update identity policy.
+//
+extern UINT8 mProviderChoice;
+extern UINT8 mConncetLogical;
+
+//
+// The variables used to update access policy.
+//
+extern USER_INFO_ACCESS mAccessInfo;
+
+//
+// The user information used to record all data in UI.
+//
+extern USER_INFO mUserInfo;
+
+extern USER_PROFILE_MANAGER_CALLBACK_INFO *mCallbackInfo;
+
+
+/**
+ Get string by string id from HII Interface.
+
+
+ @param[in] Id String ID to get the string from.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ );
+
+/**
+ Add a new user profile into the user profile database.
+
+**/
+VOID
+CallAddUser (
+ VOID
+ );
+
+/**
+ Display user select form; can select a user to modify.
+
+**/
+VOID
+SelectUserToModify (
+ VOID
+ );
+
+/**
+ Display user select form, cab select a user to delete.
+
+**/
+VOID
+SelectUserToDelete (
+ VOID
+ );
+
+/**
+ Delete the user specified by UserIndex in user profile database.
+
+ @param[in] UserIndex The index of user in the user name list to be deleted.
+
+**/
+VOID
+DeleteUser (
+ IN UINT8 UserIndex
+ );
+
+/**
+ Add a username item in form.
+
+ @param[in] User Points to the user profile whose username is added.
+ @param[in] Index The index of the user in the user name list.
+ @param[in] OpCodeHandle Points to container for dynamic created opcodes.
+
+**/
+VOID
+AddUserToForm (
+ IN EFI_USER_PROFILE_HANDLE User,
+ IN UINT16 Index,
+ IN VOID *OpCodeHandle
+ );
+
+/**
+ Display modify user information form
+
+ In this form, username, create Date, usage date, usage count, identity policy,
+ and access policy are displayed.
+
+ @param[in] UserIndex The index of the user in display list to modify.
+
+**/
+VOID
+ModifyUserInfo (
+ IN UINT8 UserIndex
+ );
+
+/**
+ Get the username from user input and update username string in Hii
+ database with it.
+
+**/
+VOID
+ModifyUserName (
+ VOID
+ );
+
+/**
+ Display the form of modifying user identity policy.
+
+**/
+VOID
+ModifyIdentityPolicy (
+ VOID
+ );
+
+/**
+ Update the mUserInfo.NewIdentityPolicy and UI when 'add option' is pressed.
+
+**/
+VOID
+AddIdentityPolicyItem (
+ VOID
+ );
+
+/**
+ Save the identity policy and update UI with it.
+
+ This funciton will verify the new identity policy, in current implementation,
+ the identity policy can be: T, P & P & P & ..., P | P | P | ...
+ Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or".
+ Other identity policies are not supported.
+
+**/
+VOID
+SaveIdentityPolicy (
+ VOID
+ );
+
+/**
+ Display modify user access policy form
+
+ In this form, access right, access setu,p and access boot order are dynamically
+ added. Load devicepath and connect devicepath are displayed too.
+
+**/
+VOID
+ModidyAccessPolicy (
+ VOID
+ );
+
+/**
+ Collect all the access policy data to mUserInfo.AccessPolicy,
+ and save it to user profile.
+
+**/
+VOID
+SaveAccessPolicy (
+ VOID
+ );
+
+/**
+ Get current user's access rights.
+
+ @param[out] AccessRight Points to the buffer used for user's access rights.
+
+ @retval EFI_SUCCESS Get current user access rights successfully.
+ @retval others Fail to get current user access rights.
+
+**/
+EFI_STATUS
+GetAccessRight (
+ OUT UINT32 *AccessRight
+ );
+
+/**
+ Display the permit load device path in the loadable device path list.
+
+**/
+VOID
+DisplayLoadPermit(
+ VOID
+ );
+
+/**
+ Display the forbid load device path list (mAccessInfo.LoadForbid).
+
+**/
+VOID
+DisplayLoadForbid (
+ VOID
+ );
+
+/**
+ Display the permit connect device path.
+
+**/
+VOID
+DisplayConnectPermit (
+ VOID
+ );
+
+/**
+ Display the forbid connect device path list.
+
+**/
+VOID
+DisplayConnectForbid (
+ VOID
+ );
+
+/**
+ Delete the specified device path by DriverIndex from the forbid device path
+ list (mAccessInfo.LoadForbid).
+
+ @param[in] DriverIndex The index of driver in a forbidden device path list.
+
+**/
+VOID
+DeleteFromForbidLoad (
+ IN UINT16 DriverIndex
+ );
+
+/**
+ Add the specified device path by DriverIndex to the forbid device path
+ list (mAccessInfo.LoadForbid).
+
+ @param[in] DriverIndex The index of driver saved in driver options.
+
+**/
+VOID
+AddToForbidLoad (
+ IN UINT16 DriverIndex
+ );
+
+/**
+ Get user name from the popup windows.
+
+ @param[in, out] UserNameLen On entry, point to the buffer lengh of UserName.
+ On exit, point to the input user name length.
+ @param[out] UserName The buffer to hold the input user name.
+
+ @retval EFI_ABORTED It is given up by pressing 'ESC' key.
+ @retval EFI_NOT_READY Not a valid input at all.
+ @retval EFI_SUCCESS Get a user name successfully.
+
+**/
+EFI_STATUS
+GetUserNameInput (
+ IN OUT UINTN *UserNameLen,
+ OUT CHAR16 *UserName
+ );
+
+#endif
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h
new file mode 100644
index 0000000000..58b6cb8c1e
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h
@@ -0,0 +1,161 @@
+/** @file
+ The form data for user profile manager driver.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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_PROFILE_MANAGER_DATA_H__
+#define __USER_PROFILE_MANAGER_DATA_H__
+
+#define USER_PROFILE_MANAGER_GUID \
+ { \
+ 0xc35f272c, 0x97c2, 0x465a, { 0xa2, 0x16, 0x69, 0x6b, 0x66, 0x8a, 0x8c, 0xfe } \
+ }
+
+//
+// Form ID
+//
+#define FORMID_USER_MANAGE 0x0001
+#define FORMID_MODIFY_USER 0x0002
+#define FORMID_DEL_USER 0x0003
+#define FORMID_USER_INFO 0x0004
+#define FORMID_MODIFY_IP 0x0005
+#define FORMID_MODIFY_AP 0x0006
+#define FORMID_LOAD_DP 0x0007
+#define FORMID_CONNECT_DP 0x0008
+#define FORMID_PERMIT_LOAD_DP 0x0009
+#define FORMID_FORBID_LOAD_DP 0x000A
+#define FORMID_PERMIT_CONNECT_DP 0x000B
+#define FORMID_FORBID_CONNECT_DP 0x000C
+
+//
+// Label ID
+//
+#define LABEL_USER_MANAGE_FUNC 0x0010
+#define LABEL_USER_DEL_FUNC 0x0020
+#define LABEL_USER_MOD_FUNC 0x0030
+#define LABEL_USER_INFO_FUNC 0x0040
+#define LABEL_IP_MOD_FUNC 0x0050
+#define LABEL_AP_MOD_FUNC 0x0060
+#define LABEL_PERMIT_LOAD_FUNC 0x0070
+#define LABLE_FORBID_LOAD_FUNC 0x0080
+#define LABEL_END 0x00F0
+
+//
+// First form key (Add/modify/del user profile).
+// First 2 bits (bit 16~15).
+//
+#define KEY_MODIFY_USER 0x4000
+#define KEY_DEL_USER 0x8000
+#define KEY_ADD_USER 0xC000
+#define KEY_FIRST_FORM_MASK 0xC000
+
+//
+// Second form key (Display new form /Select user / modify device path in access policy).
+// Next 2 bits (bit 14~13).
+//
+#define KEY_ENTER_NEXT_FORM 0x0000
+#define KEY_SELECT_USER 0x1000
+#define KEY_MODIFY_AP_DP 0x2000
+#define KEY_OPEN_CLOSE_FORM_ACTION 0x3000
+#define KEY_SECOND_FORM_MASK 0x3000
+
+//
+// User profile information form key.
+// Next 3 bits (bit 12~10).
+//
+#define KEY_MODIFY_NAME 0x0200
+#define KEY_MODIFY_IP 0x0400
+#define KEY_MODIFY_AP 0x0600
+#define KEY_MODIFY_INFO_MASK 0x0E00
+
+//
+// Specified key, used in VFR (KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_NAME).
+//
+#define KEY_MODIFY_USER_NAME 0x5200
+
+//
+// Modify identity policy form key.
+// Next 3 bits (bit 9~7).
+//
+#define KEY_MODIFY_PROV 0x0040
+#define KEY_MODIFY_MTYPE 0x0080
+#define KEY_MODIFY_CONN 0x00C0
+#define KEY_ADD_IP_OP 0x0100
+#define KEY_IP_RETURN_UIF 0x0140
+#define KEY_MODIFY_IP_MASK 0x01C0
+
+//
+// Specified key.
+//
+#define KEY_ADD_LOGICAL_OP 0x5500
+#define KEY_IP_RETURN 0x5540
+
+//
+// Modify access policy form key.
+// Next 3 bits (bit 9~7).
+//
+#define KEY_MODIFY_RIGHT 0x0040
+#define KEY_MODIFY_SETUP 0x0080
+#define KEY_MODIFY_BOOT 0x00C0
+#define KEY_MODIFY_LOAD 0x0100
+#define KEY_MODIFY_CONNECT 0x0140
+#define KEY_AP_RETURN_UIF 0x0180
+#define KEY_MODIFY_AP_MASK 0x01C0
+
+//
+// Specified key.
+//
+#define KEY_LOAD_DP 0x5700
+#define KEY_CONN_DP 0x5740
+#define KEY_AP_RETURN 0x5780
+
+//
+// Device path form key.
+// Next 2 bits (bit 6~5).
+//
+#define KEY_PERMIT_MODIFY 0x0010
+#define KEY_FORBID_MODIFY 0x0020
+#define KEY_DISPLAY_DP_MASK 0x0030
+
+//
+// Specified key.
+//
+#define KEY_LOAD_PERMIT 0x5710
+#define KEY_LOAD_FORBID 0x5720
+#define KEY_CONNECT_PERMIT 0x5750
+#define KEY_CONNECT_FORBID 0x5760
+
+//
+// Device path modify key.
+// 2 bits (bit 12~11).
+//
+#define KEY_LOAD_PERMIT_MODIFY 0x0000
+#define KEY_LOAD_FORBID_MODIFY 0x0400
+#define KEY_CONNECT_PERMIT_MODIFY 0x0800
+#define KEY_CONNECT_FORBID_MODIFY 0x0C00
+#define KEY_MODIFY_DP_MASK 0x0C00
+
+
+//
+// The permissions usable when configuring the platform.
+//
+#define ACCESS_SETUP_RESTRICTED 1
+#define ACCESS_SETUP_NORMAL 2
+#define ACCESS_SETUP_ADMIN 3
+
+//
+// Question ID for the question used in each form (KEY_OPEN_CLOSE_FORM_ACTION | FORMID_FORM_USER_MANAGE)
+// This ID is used in FORM OPEN/CLOSE CallBack action.
+//
+#define QUESTIONID_USER_MANAGE 0x3001
+
+#endif
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf
new file mode 100644
index 0000000000..27b3464dcf
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf
@@ -0,0 +1,60 @@
+## @file
+# Component description file for user profile manager driver.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+# 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 = UserProfileManager
+ FILE_GUID = E38CB52D-A74D-45db-A8D0-290C9B21BBF2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UserProfileManagerInit
+
+[Sources]
+ UserProfileManager.c
+ UserProfileManager.h
+ UserProfileAdd.c
+ UserProfileDelete.c
+ UserProfileModify.c
+ UserProfileManagerData.h
+ UserProfileManagerStrings.uni
+ UserProfileManagerVfr.Vfr
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ BaseMemoryLib
+ DebugLib
+ HiiLib
+ UefiLib
+
+ [Guids]
+ gEfiIfrTianoGuid ## CONSUMES ## Guid
+ gEfiUserInfoAccessSetupAdminGuid ## CONSUMES ## Guid
+ gEfiUserInfoAccessSetupNormalGuid ## CONSUMES ## Guid
+ gEfiUserInfoAccessSetupRestrictedGuid ## CONSUMES ## Guid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiUserCredentialProtocolGuid
+ gEfiUserManagerProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
+
+[Depex]
+ gEfiUserManagerProtocolGuid \ No newline at end of file
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni
new file mode 100644
index 0000000000..64631bb921
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni
Binary files differ
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr
new file mode 100644
index 0000000000..d094d78a76
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr
@@ -0,0 +1,247 @@
+/** @file
+ User Profile Manager formset.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "UserProfileManagerData.h"
+
+#define USER_MANAGER_CLASS 0x00
+#define USER_MANAGER_SUBCLASS 0x04
+
+formset
+ guid = USER_PROFILE_MANAGER_GUID,
+ title = STRING_TOKEN(STR_FORMSET_TITLE),
+ help = STRING_TOKEN(STR_TITLE_HELP),
+ class = USER_MANAGER_CLASS,
+ subclass = USER_MANAGER_SUBCLASS,
+
+ // User manager form
+ form formid = FORMID_USER_MANAGE,
+ title = STRING_TOKEN(STR_USERMAN_TITLE);
+
+ label LABEL_USER_MANAGE_FUNC;
+ label LABEL_END;
+
+ suppressif TRUE;
+ text
+ help = STRING_TOKEN(STR_NULL_STRING),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = QUESTIONID_USER_MANAGE;
+ endif;
+
+ endform;
+
+ // Modify user profile form
+ form formid = FORMID_MODIFY_USER,
+ title = STRING_TOKEN(STR_MODIFY_USER_TITLE);
+
+ label LABEL_USER_MOD_FUNC;
+ label LABEL_END;
+
+ endform;
+
+ // Delete user profile form
+ form formid = FORMID_DEL_USER,
+ title = STRING_TOKEN(STR_DELETE_USER_TITLE);
+
+ label LABEL_USER_DEL_FUNC;
+ label LABEL_END;
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+ endform;
+
+ //
+ // User profile information form
+ //
+ form formid = FORMID_USER_INFO,
+ title = STRING_TOKEN(STR_USER_INFO);
+
+ text
+ help = STRING_TOKEN(STR_USER_NAME_VAL),
+ text = STRING_TOKEN(STR_USER_NAME),
+ flags = INTERACTIVE,
+ key = KEY_MODIFY_USER_NAME;
+
+ text
+ help = STRING_TOKEN(STR_CREATE_DATE_VAL),
+ text = STRING_TOKEN(STR_CREATE_DATE);
+
+ text
+ help = STRING_TOKEN(STR_USAGE_DATE_VAL),
+ text = STRING_TOKEN(STR_USAGE_DATE);
+
+ text
+ help = STRING_TOKEN(STR_USAGE_COUNT_VAL),
+ text = STRING_TOKEN(STR_USAGE_COUNT);
+
+ label LABEL_USER_INFO_FUNC;
+ label LABEL_END;
+
+ endform;
+
+ //
+ // Identify policy modify form
+ //
+ form formid = FORMID_MODIFY_IP,
+ title = STRING_TOKEN(STR_IDENTIFY_POLICY);
+
+ text
+ help = STRING_TOKEN(STR_IDENTIFY_POLICY_HELP),
+ text = STRING_TOKEN(STR_IDENTIFY_POLICY),
+ text = STRING_TOKEN(STR_IDENTIFY_POLICY_VALUE);
+
+ label LABEL_IP_MOD_FUNC;
+ label LABEL_END;
+
+ text
+ help = STRING_TOKEN(STR_ADD_OPTION_HELP),
+ text = STRING_TOKEN(STR_ADD_OPTION),
+ flags = INTERACTIVE,
+ key = KEY_ADD_LOGICAL_OP;
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORMID_USER_INFO,
+ prompt = STRING_TOKEN(STR_SAVE),
+ help = STRING_TOKEN(STR_IDENTIFY_SAVE_HELP),
+ flags = INTERACTIVE,
+ key = KEY_IP_RETURN;
+
+ endform;
+
+ //
+ // Access policy modify form
+ //
+ form formid = FORMID_MODIFY_AP,
+ title = STRING_TOKEN(STR_ACCESS_POLICY);
+
+ label LABEL_AP_MOD_FUNC;
+ label LABEL_END;
+
+ goto FORMID_LOAD_DP,
+ prompt = STRING_TOKEN(STR_LOAD),
+ help = STRING_TOKEN(STR_LOAD_HELP),
+ flags = INTERACTIVE,
+ key = KEY_LOAD_DP;
+
+ goto FORMID_CONNECT_DP,
+ prompt = STRING_TOKEN(STR_CONNECT),
+ help = STRING_TOKEN(STR_CONNECT_HELP),
+ flags = INTERACTIVE,
+ key = KEY_CONN_DP;
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORMID_USER_INFO,
+ prompt = STRING_TOKEN(STR_SAVE),
+ help = STRING_TOKEN(STR_ACCESS_SAVE_HELP),
+ flags = INTERACTIVE,
+ key = KEY_AP_RETURN;
+
+ endform;
+
+ //
+ // Load device path form
+ //
+ form formid = FORMID_LOAD_DP,
+ title = STRING_TOKEN(STR_LOAD);
+
+ goto FORMID_PERMIT_LOAD_DP,
+ prompt = STRING_TOKEN(STR_LOAD_PERMIT),
+ help = STRING_TOKEN(STR_LOAD_PERMIT_HELP),
+ flags = INTERACTIVE,
+ key = KEY_LOAD_PERMIT;
+
+ goto FORMID_FORBID_LOAD_DP,
+ prompt = STRING_TOKEN(STR_LOAD_FORBID),
+ help = STRING_TOKEN(STR_LOAD_FORBID_HELP),
+ flags = INTERACTIVE,
+ key = KEY_LOAD_FORBID;
+
+ endform;
+
+ //
+ // Permit load device path form
+ //
+ form formid = FORMID_PERMIT_LOAD_DP,
+ title = STRING_TOKEN(STR_LOAD_PERMIT);
+
+ label LABEL_PERMIT_LOAD_FUNC;
+ label LABEL_END;
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ endform;
+
+ //
+ // Forbid load device path form
+ //
+ form formid = FORMID_FORBID_LOAD_DP,
+ title = STRING_TOKEN(STR_LOAD_FORBID);
+
+ label LABLE_FORBID_LOAD_FUNC;
+ label LABEL_END;
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ endform;
+
+ //
+ // Connect device path form
+ //
+ form formid = FORMID_CONNECT_DP,
+ title = STRING_TOKEN(STR_CONNECT);
+
+ goto FORMID_PERMIT_CONNECT_DP,
+ prompt = STRING_TOKEN(STR_CONNECT_PERMIT),
+ help = STRING_TOKEN(STR_CONNECT_PERMIT_HELP),
+ flags = INTERACTIVE,
+ key = KEY_CONNECT_PERMIT;
+
+ goto FORMID_FORBID_CONNECT_DP,
+ prompt = STRING_TOKEN(STR_CONNECT_FORBID),
+ help = STRING_TOKEN(STR_CONNECT_FORBID_HELP),
+ flags = INTERACTIVE,
+ key = KEY_CONNECT_FORBID;
+
+ endform;
+
+ //
+ // Permit connect device path form
+ //
+ form formid = FORMID_PERMIT_CONNECT_DP,
+ title = STRING_TOKEN(STR_CONNECT_PERMIT);
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ endform;
+
+ //
+ // Forbid connect device path form
+ //
+ form formid = FORMID_FORBID_CONNECT_DP,
+ title = STRING_TOKEN(STR_CONNECT_FORBID);
+
+ subtitle
+ text = STRING_TOKEN(STR_NULL_STRING);
+
+ endform;
+
+endformset;
diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
new file mode 100644
index 0000000000..156c155c2c
--- /dev/null
+++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
@@ -0,0 +1,2511 @@
+/** @file
+ The functions to modify a user profile.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "UserProfileManager.h"
+
+EFI_USER_PROFILE_HANDLE mModifyUser = NULL;
+
+/**
+ Display user select form, cab select a user to modify.
+
+**/
+VOID
+SelectUserToModify (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_USER_PROFILE_HANDLE User;
+ EFI_USER_PROFILE_HANDLE CurrentUser;
+ UINT32 CurrentAccessRight;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // 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_MOD_FUNC;
+
+ 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 each user can be modified.
+ //
+ User = NULL;
+ Index = 1;
+ mUserManager->Current (mUserManager, &CurrentUser);
+ while (TRUE) {
+ Status = mUserManager->GetNext (mUserManager, &User);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = GetAccessRight (&CurrentAccessRight);
+ if (EFI_ERROR (Status)) {
+ CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ }
+
+ if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) || (User == CurrentUser)) {
+ AddUserToForm (User, (UINT16)(KEY_MODIFY_USER | KEY_SELECT_USER | Index), StartOpCodeHandle);
+ }
+ Index++;
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_MODIFY_USER, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+ Get all the user info from mModifyUser in the user manager, and save on the
+ global variable.
+
+**/
+VOID
+GetAllUserInfo (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+ UINTN InfoSize;
+ UINTN MemSize;
+ UINTN DataLen;
+
+ //
+ // Init variable to default value.
+ //
+ mProviderChoice = 0;
+ mConncetLogical = 0;
+
+ mUserInfo.CreateDateExist = FALSE;
+ mUserInfo.UsageDateExist = FALSE;
+ mUserInfo.UsageCount = 0;
+
+ mUserInfo.AccessPolicyLen = 0;
+ mUserInfo.AccessPolicyModified = FALSE;
+ if (mUserInfo.AccessPolicy != NULL) {
+ FreePool (mUserInfo.AccessPolicy);
+ mUserInfo.AccessPolicy = NULL;
+ }
+ mUserInfo.IdentityPolicyLen = 0;
+ mUserInfo.IdentityPolicyModified = FALSE;
+ if (mUserInfo.IdentityPolicy != NULL) {
+ FreePool (mUserInfo.IdentityPolicy);
+ mUserInfo.IdentityPolicy = NULL;
+ }
+
+ //
+ // Allocate user information memory.
+ //
+ MemSize = sizeof (EFI_USER_INFO) + 63;
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return ;
+ }
+
+ //
+ // Get each user information.
+ //
+ UserInfo = NULL;
+ while (TRUE) {
+ Status = mUserManager->GetNextInfo (mUserManager, mModifyUser, &UserInfo);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Get information.
+ //
+ InfoSize = MemSize;
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MemSize = InfoSize;
+ FreePool (Info);
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return ;
+ }
+
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ }
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Deal with each information according to informaiton type.
+ //
+ DataLen = Info->InfoSize - sizeof (EFI_USER_INFO);
+ switch (Info->InfoType) {
+ case EFI_USER_INFO_NAME_RECORD:
+ CopyMem (&mUserInfo.UserName, (UINT8 *) (Info + 1), DataLen);
+ break;
+
+ case EFI_USER_INFO_CREATE_DATE_RECORD:
+ CopyMem (&mUserInfo.CreateDate, (UINT8 *) (Info + 1), DataLen);
+ mUserInfo.CreateDateExist = TRUE;
+ break;
+
+ case EFI_USER_INFO_USAGE_DATE_RECORD:
+ CopyMem (&mUserInfo.UsageDate, (UINT8 *) (Info + 1), DataLen);
+ mUserInfo.UsageDateExist = TRUE;
+ break;
+
+ case EFI_USER_INFO_USAGE_COUNT_RECORD:
+ CopyMem (&mUserInfo.UsageCount, (UINT8 *) (Info + 1), DataLen);
+ break;
+
+ case EFI_USER_INFO_ACCESS_POLICY_RECORD:
+ mUserInfo.AccessPolicy = AllocateZeroPool (DataLen);
+ if (mUserInfo.AccessPolicy == NULL) {
+ break;
+ }
+
+ CopyMem (mUserInfo.AccessPolicy, (UINT8 *) (Info + 1), DataLen);
+ mUserInfo.AccessPolicyLen = DataLen;
+ break;
+
+ case EFI_USER_INFO_IDENTITY_POLICY_RECORD:
+ mUserInfo.IdentityPolicy = AllocateZeroPool (DataLen);
+ if (mUserInfo.IdentityPolicy == NULL) {
+ break;
+ }
+
+ CopyMem (mUserInfo.IdentityPolicy, (UINT8 *) (Info + 1), DataLen);
+ mUserInfo.IdentityPolicyLen = DataLen;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ FreePool (Info);
+}
+
+
+/**
+ Convert the Date to a string, and update the Hii database DateID string with it.
+
+ @param[in] Date Points to the date to be converted.
+ @param[in] DateId String ID in the HII database to be replaced.
+
+**/
+VOID
+ResolveDate (
+ IN EFI_TIME *Date,
+ IN EFI_STRING_ID DateId
+ )
+{
+ CHAR16 *Str;
+ UINTN DateBufLen;
+
+ //
+ // Convert date to string.
+ //
+ DateBufLen = 64;
+ Str = AllocateZeroPool (DateBufLen);
+ if (Str == NULL) {
+ return ;
+ }
+
+ UnicodeSPrint (
+ Str,
+ DateBufLen,
+ L"%4d-%2d-%2d ",
+ Date->Year,
+ Date->Month,
+ Date->Day
+ );
+
+ //
+ // Convert time to string.
+ //
+ DateBufLen -= StrLen (Str);
+ UnicodeSPrint (
+ Str + StrLen (Str),
+ DateBufLen,
+ L"%2d:%2d:%2d",
+ Date->Hour,
+ Date->Minute,
+ Date->Second
+ );
+
+ HiiSetString (mCallbackInfo->HiiHandle, DateId, Str, NULL);
+ FreePool (Str);
+}
+
+
+/**
+ Convert the CountVal to a string, and update the Hii database CountId string
+ with it.
+
+ @param[in] CountVal The hex value to convert.
+ @param[in] CountId String ID in the HII database to be replaced.
+
+**/
+VOID
+ResolveCount (
+ IN UINT32 CountVal,
+ IN EFI_STRING_ID CountId
+ )
+{
+ CHAR16 Count[10];
+
+ UnicodeSPrint (Count, 20, L"%d", CountVal);
+ HiiSetString (mCallbackInfo->HiiHandle, CountId, Count, NULL);
+}
+
+
+/**
+ Concatenates one Null-terminated Unicode string to another Null-terminated
+ Unicode string.
+
+ @param[in, out] Source1 On entry, point to a Null-terminated Unicode string.
+ On exit, point to a new concatenated Unicode string
+ @param[in] Source2 Pointer to a Null-terminated Unicode string.
+
+**/
+VOID
+AddStr (
+ IN OUT CHAR16 **Source1,
+ IN CONST CHAR16 *Source2
+ )
+{
+ CHAR16 *TmpStr;
+ UINTN StrLength;
+
+ ASSERT (Source1 != NULL);
+ ASSERT (Source2 != NULL);
+
+ if (*Source1 == NULL) {
+ StrLength = StrSize (Source2);
+ } else {
+ StrLength = StrSize (*Source1);
+ StrLength += StrSize (Source2) -1;
+ }
+
+ TmpStr = AllocateZeroPool (StrLength);
+ ASSERT (TmpStr != NULL);
+
+ if (*Source1 == NULL) {
+ StrCpy (TmpStr, Source2);;
+ } else {
+ StrCpy (TmpStr, *Source1);
+ FreePool (*Source1);
+ StrCat (TmpStr, Source2);
+ }
+
+ *Source1 = TmpStr;
+}
+
+
+/**
+ Convert the identity policy to a unicode string and update the Hii database
+ IpStringId string with it.
+
+ @param[in] Ip Points to identity policy.
+ @param[in] IpLen The identity policy length.
+ @param[in] IpStringId String ID in the HII database to be replaced.
+
+**/
+VOID
+ResolveIdentityPolicy (
+ IN UINT8 *Ip,
+ IN UINTN IpLen,
+ IN EFI_STRING_ID IpStringId
+ )
+{
+ CHAR16 *TmpStr;
+ UINTN ChkLen;
+ EFI_USER_INFO_IDENTITY_POLICY *Identity;
+ UINT16 Index;
+ CHAR16 *ProvStr;
+ EFI_STRING_ID ProvId;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
+
+ TmpStr = NULL;
+
+ //
+ // Resolve each policy.
+ //
+ ChkLen = 0;
+ while (ChkLen < IpLen) {
+ Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (Ip + ChkLen);
+ switch (Identity->Type) {
+ case EFI_USER_INFO_IDENTITY_FALSE:
+ AddStr (&TmpStr, L"False");
+ break;
+
+ case EFI_USER_INFO_IDENTITY_TRUE:
+ AddStr (&TmpStr, L"None");
+ break;
+
+ case EFI_USER_INFO_IDENTITY_NOT:
+ AddStr (&TmpStr, L"! ");
+ break;
+
+ case EFI_USER_INFO_IDENTITY_AND:
+ AddStr (&TmpStr, L" && ");
+ break;
+
+ case EFI_USER_INFO_IDENTITY_OR:
+ AddStr (&TmpStr, L" || ");
+ break;
+
+ case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
+ for (Index = 0; Index < mProviderInfo->Count; Index++) {
+ UserCredential = mProviderInfo->Provider[Index];
+ if (CompareGuid ((EFI_GUID *) (Identity + 1), &UserCredential->Type)) {
+ UserCredential->Title (
+ UserCredential,
+ &HiiHandle,
+ &ProvId
+ );
+ ProvStr = HiiGetString (HiiHandle, ProvId, NULL);
+ if (ProvStr != NULL) {
+ AddStr (&TmpStr, ProvStr);
+ FreePool (ProvStr);
+ }
+ break;
+ }
+ }
+ break;
+
+ case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
+ for (Index = 0; Index < mProviderInfo->Count; Index++) {
+ UserCredential = mProviderInfo->Provider[Index];
+ if (CompareGuid ((EFI_GUID *) (Identity + 1), &UserCredential->Identifier)) {
+ UserCredential->Title (
+ UserCredential,
+ &HiiHandle,
+ &ProvId
+ );
+ ProvStr = HiiGetString (HiiHandle, ProvId, NULL);
+ if (ProvStr != NULL) {
+ AddStr (&TmpStr, ProvStr);
+ FreePool (ProvStr);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ ChkLen += Identity->Length;
+ }
+
+ if (TmpStr != NULL) {
+ HiiSetString (mCallbackInfo->HiiHandle, IpStringId, TmpStr, NULL);
+ FreePool (TmpStr);
+ }
+}
+
+
+/**
+ Display modify user information form.
+
+ This form displays, username, create Date, usage date, usage count, identity policy,
+ and access policy.
+
+ @param[in] UserIndex The index of the user in display list to modify.
+
+**/
+VOID
+ModifyUserInfo (
+ IN UINT8 UserIndex
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_PROFILE_HANDLE CurrentUser;
+ UINT32 CurrentAccessRight;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // 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_INFO_FUNC;
+
+ 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;
+
+ //
+ // Find the user profile to be modified.
+ //
+ mModifyUser = NULL;
+ Status = mUserManager->GetNext (mUserManager, &mModifyUser);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ while (UserIndex > 1) {
+ Status = mUserManager->GetNext (mUserManager, &mModifyUser);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ UserIndex--;
+ }
+
+ //
+ // Get user profile information.
+ //
+ GetAllUserInfo ();
+
+ //
+ // Update user name.
+ HiiSetString (
+ mCallbackInfo->HiiHandle,
+ STRING_TOKEN (STR_USER_NAME_VAL),
+ mUserInfo.UserName,
+ NULL
+ );
+
+ //
+ // Update create date.
+ //
+ if (mUserInfo.CreateDateExist) {
+ ResolveDate (&mUserInfo.CreateDate, STRING_TOKEN (STR_CREATE_DATE_VAL));
+ } else {
+ HiiSetString (
+ mCallbackInfo->HiiHandle,
+ STRING_TOKEN (STR_CREATE_DATE_VAL),
+ L"",
+ NULL
+ );
+ }
+
+ //
+ // Add usage date.
+ //
+ if (mUserInfo.UsageDateExist) {
+ ResolveDate (&mUserInfo.UsageDate, STRING_TOKEN (STR_USAGE_DATE_VAL));
+ } else {
+ HiiSetString (
+ mCallbackInfo->HiiHandle,
+ STRING_TOKEN (STR_USAGE_DATE_VAL),
+ L"",
+ NULL
+ );
+ }
+
+ //
+ // Add usage count.
+ //
+ ResolveCount ((UINT32) mUserInfo.UsageCount, STRING_TOKEN (STR_USAGE_COUNT_VAL));
+
+ //
+ // Add identity policy.
+ //
+ mUserManager->Current (mUserManager, &CurrentUser);
+ if (mModifyUser == CurrentUser) {
+ ResolveIdentityPolicy (
+ mUserInfo.IdentityPolicy,
+ mUserInfo.IdentityPolicyLen,
+ STRING_TOKEN (STR_IDENTIFY_POLICY_VAL)
+ );
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for opcodes
+ FORMID_MODIFY_IP, // Target Form ID
+ STRING_TOKEN (STR_IDENTIFY_POLICY), // Prompt text
+ STRING_TOKEN (STR_IDENTIFY_POLICY_VAL), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP // Question ID
+ );
+ }
+
+ //
+ // Add access policy.
+ //
+ Status = GetAccessRight (&CurrentAccessRight);
+ if (EFI_ERROR (Status)) {
+ CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ }
+
+ if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) {
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for opcodes
+ FORMID_MODIFY_AP, // Target Form ID
+ STRING_TOKEN (STR_ACCESS_POLICY), // Prompt text
+ STRING_TOKEN (STR_NULL_STRING), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP // Question ID
+ );
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_USER_INFO, // Form ID
+ StartOpCodeHandle, // Label
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+ Get all the access policy info from current user info, and save in the global
+ variable.
+
+**/
+VOID
+ResolveAccessPolicy (
+ VOID
+ )
+{
+ UINTN OffSet;
+ EFI_USER_INFO_ACCESS_CONTROL Control;
+ UINTN ValLen;
+ UINT8 *AccessData;
+
+ //
+ // Set default value
+ //
+ mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ mAccessInfo.AccessSetup = ACCESS_SETUP_RESTRICTED;
+ mAccessInfo.AccessBootOrder = EFI_USER_INFO_ACCESS_BOOT_ORDER_INSERT;
+
+ mAccessInfo.LoadPermitLen = 0;
+ mAccessInfo.LoadForbidLen = 0;
+ mAccessInfo.ConnectPermitLen = 0;
+ mAccessInfo.ConnectForbidLen = 0;
+
+ //
+ // Get each user access policy.
+ //
+ OffSet = 0;
+ while (OffSet < mUserInfo.AccessPolicyLen) {
+ CopyMem (&Control, mUserInfo.AccessPolicy + OffSet, sizeof (Control));
+ ValLen = Control.Size - sizeof (Control);
+ switch (Control.Type) {
+ case EFI_USER_INFO_ACCESS_ENROLL_SELF:
+ mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF;
+ break;
+
+ case EFI_USER_INFO_ACCESS_ENROLL_OTHERS:
+ mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_OTHERS;
+ break;
+
+ case EFI_USER_INFO_ACCESS_MANAGE:
+ mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_MANAGE;
+ break;
+
+ case EFI_USER_INFO_ACCESS_SETUP:
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupNormalGuid)) {
+ mAccessInfo.AccessSetup = ACCESS_SETUP_NORMAL;
+ } else if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupRestrictedGuid)) {
+ mAccessInfo.AccessSetup = ACCESS_SETUP_RESTRICTED;
+ } else if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupAdminGuid)) {
+ mAccessInfo.AccessSetup = ACCESS_SETUP_ADMIN;
+ }
+ break;
+
+ case EFI_USER_INFO_ACCESS_BOOT_ORDER:
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ CopyMem (&mAccessInfo.AccessBootOrder, AccessData, sizeof (UINT32));
+ break;
+
+ case EFI_USER_INFO_ACCESS_FORBID_LOAD:
+ if (mAccessInfo.LoadForbid != NULL) {
+ FreePool (mAccessInfo.LoadForbid);
+ }
+
+ mAccessInfo.LoadForbid = AllocateZeroPool (ValLen);
+ if (mAccessInfo.LoadForbid != NULL) {
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ CopyMem (mAccessInfo.LoadForbid, AccessData, ValLen);
+ mAccessInfo.LoadForbidLen = ValLen;
+ }
+ break;
+
+ case EFI_USER_INFO_ACCESS_PERMIT_LOAD:
+ if (mAccessInfo.LoadPermit != NULL) {
+ FreePool (mAccessInfo.LoadPermit);
+ }
+
+ mAccessInfo.LoadPermit = AllocateZeroPool (ValLen);
+ if (mAccessInfo.LoadPermit != NULL) {
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ CopyMem (mAccessInfo.LoadPermit, AccessData, ValLen);
+ mAccessInfo.LoadPermitLen = ValLen;
+ }
+ break;
+
+ case EFI_USER_INFO_ACCESS_FORBID_CONNECT:
+ if (mAccessInfo.ConnectForbid != NULL) {
+ FreePool (mAccessInfo.ConnectForbid);
+ }
+
+ mAccessInfo.ConnectForbid = AllocateZeroPool (ValLen);
+ if (mAccessInfo.ConnectForbid != NULL) {
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ CopyMem (mAccessInfo.ConnectForbid, AccessData, ValLen);
+ mAccessInfo.ConnectForbidLen = ValLen;
+ }
+ break;
+
+ case EFI_USER_INFO_ACCESS_PERMIT_CONNECT:
+ if (mAccessInfo.ConnectPermit != NULL) {
+ FreePool (mAccessInfo.ConnectPermit);
+ }
+
+ mAccessInfo.ConnectPermit = AllocateZeroPool (ValLen);
+ if (mAccessInfo.ConnectPermit != NULL) {
+ AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control);
+ CopyMem (mAccessInfo.ConnectPermit, AccessData, ValLen);
+ mAccessInfo.ConnectPermitLen = ValLen;
+ }
+ break;
+ }
+
+ OffSet += Control.Size;
+ }
+}
+
+
+/**
+ Find the specified info in profile mModifyUser by the InfoType.
+
+ @param[in] InfoType The user information type to find.
+ @param[out] UserInfo Points to user information handle found.
+
+ @retval EFI_SUCCESS Find the user information successfully.
+ @retval Others Fail to find the user information.
+
+**/
+EFI_STATUS
+FindInfoByType (
+ IN UINT8 InfoType,
+ OUT EFI_USER_INFO_HANDLE *UserInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO *Info;
+ UINTN InfoSize;
+ UINTN MemSize;
+
+ if (UserInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *UserInfo = NULL;
+ //
+ // Allocate user information memory.
+ //
+ MemSize = sizeof (EFI_USER_INFO) + 63;
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get each user information.
+ //
+ while (TRUE) {
+ Status = mUserManager->GetNextInfo (mUserManager, mModifyUser, UserInfo);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Get information.
+ //
+ InfoSize = MemSize;
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ *UserInfo,
+ Info,
+ &InfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MemSize = InfoSize;
+ FreePool (Info);
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ *UserInfo,
+ Info,
+ &InfoSize
+ );
+ }
+ if (Status == EFI_SUCCESS) {
+ if (Info->InfoType == InfoType) {
+ break;
+ }
+ }
+ }
+
+ FreePool (Info);
+ return Status;
+}
+
+
+/**
+ Display modify user access policy form.
+
+ In this form, access right, access setup and access boot order are dynamically
+ added. Load devicepath and connect devicepath are displayed too.
+
+**/
+VOID
+ModidyAccessPolicy (
+ VOID
+ )
+{
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ VOID *OptionsOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ VOID *DefaultOpCodeHandle;
+
+ //
+ // 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_AP_MOD_FUNC;
+
+ 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;
+
+
+ //
+ // Resolve access policy information.
+ //
+ ResolveAccessPolicy ();
+
+ //
+ // Add access right one-of-code.
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+ DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (DefaultOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_NORMAL),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ EFI_USER_INFO_ACCESS_ENROLL_SELF
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_ENROLL),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ EFI_USER_INFO_ACCESS_ENROLL_OTHERS
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MANAGE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ EFI_USER_INFO_ACCESS_MANAGE
+ );
+
+ HiiCreateDefaultOpCode (
+ DefaultOpCodeHandle,
+ EFI_HII_DEFAULT_CLASS_STANDARD,
+ EFI_IFR_NUMERIC_SIZE_1,
+ mAccessInfo.AccessRight
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_RIGHT, // Question ID
+ 0, // VarStore ID
+ 0, // Offset in Buffer Storage
+ STRING_TOKEN (STR_ACCESS_RIGHT), // Question prompt text
+ STRING_TOKEN (STR_ACCESS_RIGHT_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ DefaultOpCodeHandle // Default Opcode
+ );
+ HiiFreeOpCodeHandle (DefaultOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+
+ //
+ // Add setup type one-of-code.
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+ DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (DefaultOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_RESTRICTED),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ ACCESS_SETUP_RESTRICTED
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_NORMAL),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ ACCESS_SETUP_NORMAL
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_ADMIN),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ ACCESS_SETUP_ADMIN
+ );
+
+ HiiCreateDefaultOpCode (
+ DefaultOpCodeHandle,
+ EFI_HII_DEFAULT_CLASS_STANDARD,
+ EFI_IFR_NUMERIC_SIZE_1,
+ mAccessInfo.AccessSetup
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_SETUP, // Question ID
+ 0, // VarStore ID
+ 0, // Offset in Buffer Storage
+ STRING_TOKEN (STR_ACCESS_SETUP), // Question prompt text
+ STRING_TOKEN (STR_ACCESS_SETUP_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ DefaultOpCodeHandle // Default Opcode
+ );
+ HiiFreeOpCodeHandle (DefaultOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ //
+ // Add boot order one-of-code.
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+ DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (DefaultOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_INSERT),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ EFI_USER_INFO_ACCESS_BOOT_ORDER_INSERT
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_APPEND),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ EFI_USER_INFO_ACCESS_BOOT_ORDER_APPEND
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_REPLACE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ EFI_USER_INFO_ACCESS_BOOT_ORDER_REPLACE
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_NODEFAULT),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ EFI_USER_INFO_ACCESS_BOOT_ORDER_NODEFAULT
+ );
+
+ HiiCreateDefaultOpCode (
+ DefaultOpCodeHandle,
+ EFI_HII_DEFAULT_CLASS_STANDARD,
+ EFI_IFR_NUMERIC_SIZE_4,
+ mAccessInfo.AccessBootOrder
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_BOOT, // Question ID
+ 0, // VarStore ID
+ 0, // Offset in Buffer Storage
+ STRING_TOKEN (STR_BOOR_ORDER), // Question prompt text
+ STRING_TOKEN (STR_BOOT_ORDER_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ DefaultOpCodeHandle // Default Opcode
+ );
+ HiiFreeOpCodeHandle (DefaultOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ //
+ // Update Form.
+ //
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_MODIFY_AP, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+ Expand access policy memory size.
+
+ @param[in] ValidLen The valid access policy length.
+ @param[in] ExpandLen The length that is needed to expand.
+
+**/
+VOID
+ExpandMemory (
+ IN UINTN ValidLen,
+ IN UINTN ExpandLen
+ )
+{
+ UINT8 *Mem;
+ UINTN Len;
+
+ //
+ // Expand memory.
+ //
+ Len = mUserInfo.AccessPolicyLen + (ExpandLen / 64 + 1) * 64;
+ Mem = AllocateZeroPool (Len);
+ ASSERT (Mem != NULL);
+
+ if (mUserInfo.AccessPolicy != NULL) {
+ CopyMem (Mem, mUserInfo.AccessPolicy, ValidLen);
+ FreePool (mUserInfo.AccessPolicy);
+ }
+
+ mUserInfo.AccessPolicy = Mem;
+ mUserInfo.AccessPolicyLen = Len;
+}
+
+
+/**
+ Collect all the access policy data to mUserInfo.AccessPolicy,
+ and save it to user profile.
+
+**/
+VOID
+SaveAccessPolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN OffSet;
+ UINTN Size;
+ EFI_USER_INFO_ACCESS_CONTROL Control;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+
+ if (mUserInfo.AccessPolicy != NULL) {
+ FreePool (mUserInfo.AccessPolicy);
+ }
+ mUserInfo.AccessPolicy = NULL;
+ mUserInfo.AccessPolicyLen = 0;
+ mUserInfo.AccessPolicyModified = TRUE;
+ OffSet = 0;
+
+ //
+ // Save access right.
+ //
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL);
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = mAccessInfo.AccessRight;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ //
+ // Save access setup.
+ //
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (EFI_GUID);
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_SETUP;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ if (mAccessInfo.AccessSetup == ACCESS_SETUP_NORMAL) {
+ CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupNormalGuid);
+ } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_RESTRICTED) {
+ CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupRestrictedGuid);
+ } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_ADMIN) {
+ CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupAdminGuid);
+ }
+ OffSet += sizeof (EFI_GUID);
+
+ //
+ // Save access of boot order.
+ //
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (UINT32);
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_BOOT_ORDER;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ CopyMem ((UINT8 *) (mUserInfo.AccessPolicy + OffSet), &mAccessInfo.AccessBootOrder, sizeof (UINT32));
+ OffSet += sizeof (UINT32);
+
+ //
+ // Save permit load.
+ //
+ if (mAccessInfo.LoadPermitLen > 0) {
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadPermitLen;
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_PERMIT_LOAD;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadPermit, mAccessInfo.LoadPermitLen);
+ OffSet += mAccessInfo.LoadPermitLen;
+ }
+
+ //
+ // Save forbid load.
+ //
+ if (mAccessInfo.LoadForbidLen > 0) {
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadForbidLen;
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_FORBID_LOAD;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen);
+ OffSet += mAccessInfo.LoadForbidLen;
+ }
+
+ //
+ // Save permit connect.
+ //
+ if (mAccessInfo.ConnectPermitLen > 0) {
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectPermitLen;
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_PERMIT_CONNECT;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectPermit, mAccessInfo.ConnectPermitLen);
+ OffSet += mAccessInfo.ConnectPermitLen;
+ }
+
+ //
+ // Save forbid connect.
+ //
+ if (mAccessInfo.ConnectForbidLen > 0) {
+ Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectForbidLen;
+ if (mUserInfo.AccessPolicyLen - OffSet < Size) {
+ ExpandMemory (OffSet, Size);
+ }
+
+ Control.Type = EFI_USER_INFO_ACCESS_FORBID_CONNECT;
+ Control.Size = (UINT32) Size;
+ CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control));
+ OffSet += sizeof (Control);
+
+ CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectForbid, mAccessInfo.ConnectForbidLen);
+ OffSet += mAccessInfo.ConnectForbidLen;
+ }
+
+ mUserInfo.AccessPolicyLen = OffSet;
+
+ //
+ // Save access policy.
+ //
+ if (mUserInfo.AccessPolicyModified && (mUserInfo.AccessPolicyLen > 0)) {
+ Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen);
+ if (Info == NULL) {
+ return ;
+ }
+
+ Status = FindInfoByType (EFI_USER_INFO_ACCESS_POLICY_RECORD, &UserInfo);
+ if (!EFI_ERROR (Status)) {
+ Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD;
+ Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PUBLIC |
+ EFI_USER_INFO_EXCLUSIVE;
+ Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen);
+ CopyMem ((UINT8 *) (Info + 1), mUserInfo.AccessPolicy, mUserInfo.AccessPolicyLen);
+ Status = mUserManager->SetInfo (
+ mUserManager,
+ mModifyUser,
+ &UserInfo,
+ Info,
+ Info->InfoSize
+ );
+ mUserInfo.AccessPolicyModified = FALSE;
+ }
+ FreePool (Info);
+ }
+
+ if (mAccessInfo.ConnectForbid != NULL) {
+ FreePool (mAccessInfo.ConnectForbid);
+ mAccessInfo.ConnectForbid = NULL;
+ }
+
+ if (mAccessInfo.ConnectPermit != NULL) {
+ FreePool (mAccessInfo.ConnectPermit);
+ mAccessInfo.ConnectPermit = NULL;
+ }
+
+ if (mAccessInfo.LoadForbid != NULL) {
+ FreePool (mAccessInfo.LoadForbid);
+ mAccessInfo.LoadForbid = NULL;
+ }
+
+ if (mAccessInfo.LoadPermit != NULL) {
+ FreePool (mAccessInfo.LoadPermit);
+ mAccessInfo.LoadPermit = NULL;
+ }
+}
+
+
+/**
+ Get the username from user input, and update username string in the Hii
+ database with it.
+
+**/
+VOID
+ModifyUserName (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 UserName[USER_NAME_LENGTH];
+ UINTN Len;
+ EFI_INPUT_KEY Key;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+ EFI_USER_PROFILE_HANDLE TempUser;
+
+ //
+ // Get the new user name.
+ //
+ Len = sizeof (UserName);
+ Status = GetUserNameInput (&Len, UserName);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ABORTED) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Failed To Get User Name.",
+ L"",
+ L"Please Press Any Key to Continue ...",
+ NULL
+ );
+ }
+ return ;
+ }
+
+ //
+ // Check whether the username had been used or not.
+ //
+ Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + Len);
+ if (Info == NULL) {
+ return ;
+ }
+
+ 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 = (UINT32) (sizeof (EFI_USER_INFO) + Len);
+ CopyMem ((UINT8 *) (Info + 1), UserName, Len);
+
+ TempUser = NULL;
+ Status = mUserManager->Find (
+ mUserManager,
+ &TempUser,
+ NULL,
+ Info,
+ Info->InfoSize
+ );
+ if (!EFI_ERROR (Status)) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"The User Name Had Been Used.",
+ L"",
+ L"Please Use Other User Name",
+ NULL
+ );
+ FreePool (Info);
+ return ;
+ }
+
+ //
+ // Update username display in the form.
+ //
+ CopyMem (mUserInfo.UserName, UserName, Len);
+ HiiSetString (
+ mCallbackInfo->HiiHandle,
+ STRING_TOKEN (STR_USER_NAME_VAL),
+ mUserInfo.UserName,
+ NULL
+ );
+
+ //
+ // Save the user name.
+ //
+ Status = FindInfoByType (EFI_USER_INFO_NAME_RECORD, &UserInfo);
+ if (!EFI_ERROR (Status)) {
+ mUserManager->SetInfo (
+ mUserManager,
+ mModifyUser,
+ &UserInfo,
+ Info,
+ Info->InfoSize
+ );
+ }
+ FreePool (Info);
+}
+
+
+/**
+ Display the form of the modifying user identity policy.
+
+**/
+VOID
+ModifyIdentityPolicy (
+ VOID
+ )
+{
+ UINTN Index;
+ CHAR16 *ProvStr;
+ EFI_STRING_ID ProvID;
+ EFI_HII_HANDLE HiiHandle;
+ VOID *OptionsOpCodeHandle;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // 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_IP_MOD_FUNC;
+
+ 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 credential providers
+ //.
+ if (mProviderInfo->Count > 0) {
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ //
+ // Add credential provider Option OpCode.
+ //
+ for (Index = 0; Index < mProviderInfo->Count; Index++) {
+ mProviderInfo->Provider[Index]->Title (
+ mProviderInfo->Provider[Index],
+ &HiiHandle,
+ &ProvID
+ );
+ ProvStr = HiiGetString (HiiHandle, ProvID, NULL);
+ ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);
+ FreePool (ProvStr);
+ if (ProvID == 0) {
+ return ;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ ProvID,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ (UINT8) Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP | KEY_MODIFY_PROV, // Question ID
+ 0, // VarStore ID
+ 0, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PROVIDER), // Question prompt text
+ STRING_TOKEN (STR_PROVIDER_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ }
+
+ //
+ // Add logical connector Option OpCode.
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_AND_CON),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_OR_CON),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP | KEY_MODIFY_CONN, // Question ID
+ 0, // VarStore ID
+ 0, // Offset in Buffer Storage
+ STRING_TOKEN (STR_CONNECTOR), // Question prompt text
+ STRING_TOKEN (STR_CONNECTOR_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ //
+ // Update identity policy in the form.
+ //
+ ResolveIdentityPolicy (
+ mUserInfo.IdentityPolicy,
+ mUserInfo.IdentityPolicyLen,
+ STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE)
+ );
+
+ if (mUserInfo.NewIdentityPolicy != NULL) {
+ FreePool (mUserInfo.NewIdentityPolicy);
+ mUserInfo.NewIdentityPolicy = NULL;
+ mUserInfo.NewIdentityPolicyLen = 0;
+ mUserInfo.NewIdentityPolicyModified = FALSE;
+ }
+ mProviderChoice = 0;
+ mConncetLogical = 0;
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_MODIFY_IP, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+ Save the identity policy and update UI with it.
+
+ This funciton will verify the new identity policy, in current implementation,
+ the identity policy can be: T, P & P & P & ..., P | P | P | ...
+ Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or".
+ Other identity policies are not supported.
+
+**/
+VOID
+SaveIdentityPolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_IDENTITY_POLICY *Identity;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+ EFI_INPUT_KEY Key;
+ UINTN Offset;
+ UINT32 OpCode;
+ UINTN InfoSize;
+
+ if (!mUserInfo.NewIdentityPolicyModified || (mUserInfo.NewIdentityPolicyLen == 0)) {
+ return;
+ }
+
+ //
+ // Check policy expression.
+ //
+ OpCode = EFI_USER_INFO_IDENTITY_FALSE;
+ Offset = 0;
+ while (Offset < mUserInfo.NewIdentityPolicyLen) {
+ //
+ // Check access policy according to type
+ //
+ Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset);
+ switch (Identity->Type) {
+
+ case EFI_USER_INFO_IDENTITY_TRUE:
+ break;
+
+ case EFI_USER_INFO_IDENTITY_OR:
+ if (OpCode == EFI_USER_INFO_IDENTITY_AND) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Invalid Identity Policy, Mixed Connector Unsupport!",
+ L"",
+ L"Press Any Key to Continue ...",
+ NULL
+ );
+ return ;
+ }
+
+ OpCode = EFI_USER_INFO_IDENTITY_OR;
+ break;
+
+ case EFI_USER_INFO_IDENTITY_AND:
+ if (OpCode == EFI_USER_INFO_IDENTITY_OR) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Invalid Identity Policy, Mixed Connector Unsupport!",
+ L"",
+ L"Press Any Key to Continue ...",
+ NULL
+ );
+ return ;
+ }
+
+ OpCode = EFI_USER_INFO_IDENTITY_AND;
+ break;
+
+ case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
+ break;
+
+ default:
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Unsupport parameter",
+ L"",
+ L"Press Any Key to Continue ...",
+ NULL
+ );
+ return ;
+ }
+ Offset += Identity->Length;
+ }
+
+ //
+ // Save identity policy.
+ //
+ Info = AllocateZeroPool (
+ sizeof (EFI_USER_INFO) +
+ mUserInfo.NewIdentityPolicyLen
+ );
+ if (Info == NULL) {
+ return ;
+ }
+
+ Status = FindInfoByType (EFI_USER_INFO_IDENTITY_POLICY_RECORD, &UserInfo);
+ if (EFI_ERROR (Status)) {
+ FreePool (Info);
+ return ;
+ }
+
+ Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
+ Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV |
+ EFI_USER_INFO_PRIVATE |
+ EFI_USER_INFO_EXCLUSIVE;
+ Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen);
+ CopyMem ((UINT8 *) (Info + 1), mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);
+ Status = mUserManager->SetInfo (
+ mUserManager,
+ mModifyUser,
+ &UserInfo,
+ Info,
+ Info->InfoSize
+ );
+ FreePool (Info);
+ if (EFI_ERROR (Status)) {
+ //
+ // Get the user information again, it may be changed during saving it.
+ //
+ InfoSize = 0;
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Info = AllocateZeroPool (InfoSize);
+ ASSERT (Info != NULL);
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ mModifyUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Save current identification policy to mUserInfo.IdentityPolicy.
+ //
+ ASSERT (Info != NULL);
+ if (mUserInfo.IdentityPolicy != NULL) {
+ FreePool (mUserInfo.IdentityPolicy);
+ }
+
+ mUserInfo.IdentityPolicyLen = Info->InfoSize - sizeof (EFI_USER_INFO);
+ mUserInfo.IdentityPolicy = AllocateCopyPool (mUserInfo.IdentityPolicyLen, Info + 1);
+ ASSERT (mUserInfo.IdentityPolicy != NULL);
+
+ //
+ // Free the memory
+ //
+ FreePool (Info);
+ FreePool (mUserInfo.NewIdentityPolicy);
+ } else {
+ //
+ // Update the mUserInfo.IdentityPolicy by mUserInfo.NewIdentityPolicy
+ //
+ if (mUserInfo.IdentityPolicy != NULL) {
+ FreePool (mUserInfo.IdentityPolicy);
+ }
+ mUserInfo.IdentityPolicy = mUserInfo.NewIdentityPolicy;
+ mUserInfo.IdentityPolicyLen = mUserInfo.NewIdentityPolicyLen;
+ }
+
+ mUserInfo.NewIdentityPolicy = NULL;
+ mUserInfo.NewIdentityPolicyLen = 0;
+ mUserInfo.NewIdentityPolicyModified = FALSE;
+
+ //
+ // Update identity policy choice.
+ //
+ ResolveIdentityPolicy (
+ mUserInfo.IdentityPolicy,
+ mUserInfo.IdentityPolicyLen,
+ STRING_TOKEN (STR_IDENTIFY_POLICY_VAL)
+ );
+}
+
+
+/**
+ Verify the new identity policy in the current implementation. The same credential
+ provider can't appear twice in one identity policy.
+
+ @param[in] NewGuid Points to the credential provider guid.
+
+ @retval TRUE The NewGuid was found in the identity policy.
+ @retval FALSE The NewGuid was not found.
+
+**/
+BOOLEAN
+CheckIdentityPolicy (
+ IN EFI_GUID *NewGuid
+ )
+{
+ UINTN Offset;
+ EFI_USER_INFO_IDENTITY_POLICY *Identity;
+ EFI_INPUT_KEY Key;
+
+ Offset = 0;
+ while (Offset < mUserInfo.NewIdentityPolicyLen) {
+ //
+ // Check access policy according to type.
+ //
+ Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset);
+ switch (Identity->Type) {
+
+ case EFI_USER_INFO_IDENTITY_TRUE:
+ case EFI_USER_INFO_IDENTITY_OR:
+ case EFI_USER_INFO_IDENTITY_AND:
+ break;
+
+ case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
+ if (CompareGuid (NewGuid, (EFI_GUID *) (Identity + 1))) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"This Credential Provider Are Already Used!",
+ L"",
+ L"Press Any Key to Continue ...",
+ NULL
+ );
+ return FALSE;
+ }
+ break;
+
+ default:
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Unsupport parameter",
+ L"",
+ L"Press Any Key to Continue ...",
+ NULL
+ );
+ return FALSE;
+ }
+
+ Offset += Identity->Length;
+ }
+ return TRUE;
+}
+
+
+/**
+ Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed.
+
+**/
+VOID
+AddIdentityPolicyItem (
+ VOID
+ )
+{
+ UINT8 *NewInfo;
+ EFI_USER_INFO_IDENTITY_POLICY *Policy;
+
+ if (mProviderInfo->Count == 0) {
+ return ;
+ }
+
+ if (!mUserInfo.NewIdentityPolicyModified && (mUserInfo.NewIdentityPolicyLen > 0)) {
+ FreePool (mUserInfo.NewIdentityPolicy);
+ mUserInfo.NewIdentityPolicy = NULL;
+ mUserInfo.NewIdentityPolicyLen = 0;
+ }
+ //
+ // Expand the identity policy memory for the newly added policy info.
+ //
+ if (mUserInfo.NewIdentityPolicyLen > 0) {
+ //
+ // The new policy is not empty, expand space for connetor and provider.
+ //
+ if (!CheckIdentityPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier)) {
+ return ;
+ }
+ NewInfo = AllocateZeroPool (
+ mUserInfo.NewIdentityPolicyLen +
+ sizeof (EFI_USER_INFO_IDENTITY_POLICY) * 2 +
+ sizeof (EFI_GUID)
+ );
+ } else {
+ //
+ // The new policy is empty, only expand space for provider.
+ //
+ NewInfo = AllocateZeroPool (
+ mUserInfo.NewIdentityPolicyLen +
+ sizeof (EFI_USER_INFO_IDENTITY_POLICY) +
+ sizeof (EFI_GUID)
+ );
+ }
+
+ if (NewInfo == NULL) {
+ return ;
+ }
+
+ if (mUserInfo.NewIdentityPolicyLen > 0) {
+ CopyMem (NewInfo, mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);
+ FreePool (mUserInfo.NewIdentityPolicy);
+ }
+ mUserInfo.NewIdentityPolicy = NewInfo;
+
+ //
+ // Save logical connector.
+ //
+ if (mUserInfo.NewIdentityPolicyLen > 0) {
+ Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy +
+ mUserInfo.NewIdentityPolicyLen);
+ if (mConncetLogical == 0) {
+ Policy->Type = EFI_USER_INFO_IDENTITY_AND;
+ } else {
+ Policy->Type = EFI_USER_INFO_IDENTITY_OR;
+ }
+
+ Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
+ mUserInfo.NewIdentityPolicyLen += Policy->Length;
+ }
+
+ //
+ // Save credential provider.
+ //
+ Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy +
+ mUserInfo.NewIdentityPolicyLen);
+ Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID);
+ Policy->Type = EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER;
+ CopyGuid ((EFI_GUID *) (Policy + 1), &mProviderInfo->Provider[mProviderChoice]->Identifier);
+ mUserInfo.NewIdentityPolicyLen += Policy->Length;
+
+ //
+ // Update identity policy choice.
+ //
+ mUserInfo.NewIdentityPolicyModified = TRUE;
+ ResolveIdentityPolicy (
+ mUserInfo.NewIdentityPolicy,
+ mUserInfo.NewIdentityPolicyLen,
+ STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE)
+ );
+}
+
+
+/**
+ Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle.
+
+ @param[in] QuestionID The question ID.
+ @param[in] DevicePath Points to device path.
+ @param[in] OpCodeHandle Points to container for dynamic created opcodes.
+
+**/
+VOID
+AddDevicePath (
+ IN UINTN QuestionID,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN VOID *OpCodeHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ EFI_STRING_ID NameID;
+ EFI_STRING DriverName;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText;
+
+ //
+ // Locate device path to text protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevicePathText
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ //
+ // Get driver file name node.
+ //
+ Next = DevicePath;
+ while (!IsDevicePathEnd (Next)) {
+ DevicePath = Next;
+ Next = NextDevicePathNode (Next);
+ }
+
+ //
+ // Display the device path in form.
+ //
+ DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL);
+ FreePool (DriverName);
+ if (NameID == 0) {
+ return ;
+ }
+
+ HiiCreateActionOpCode (
+ OpCodeHandle, // Container for dynamic created opcodes
+ (UINT16) QuestionID, // Question ID
+ NameID, // Prompt text
+ STRING_TOKEN (STR_NULL_STRING), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ 0 // Action String ID
+ );
+}
+
+
+/**
+ Check whether the DevicePath is in the device path forbid list
+ (mAccessInfo.LoadForbid).
+
+ @param[in] DevicePath Points to device path.
+
+ @retval TRUE The DevicePath is in the device path forbid list.
+ @retval FALSE The DevicePath is not in the device path forbid list.
+
+**/
+BOOLEAN
+IsLoadForbidden (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ UINTN OffSet;
+ UINTN DPSize;
+ UINTN Size;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+
+ OffSet = 0;
+ Size = GetDevicePathSize (DevicePath);
+ //
+ // Check each device path.
+ //
+ while (OffSet < mAccessInfo.LoadForbidLen) {
+ Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet);
+ DPSize = GetDevicePathSize (Dp);
+ //
+ // Compare device path.
+ //
+ if ((DPSize == Size) && (CompareMem (DevicePath, Dp, Size) == 0)) {
+ return TRUE;
+ }
+ OffSet += DPSize;
+ }
+ return FALSE;
+}
+
+
+/**
+ Display the permit load device path in the loadable device path list.
+
+**/
+VOID
+DisplayLoadPermit(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Order;
+ UINTN OrderSize;
+ UINTN ListCount;
+ UINTN Index;
+ UINT8 *Var;
+ UINT8 *VarPtr;
+ CHAR16 VarName[12];
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // Get DriverOrder.
+ //
+ OrderSize = 0;
+ Status = gRT->GetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &OrderSize,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return ;
+ }
+
+ Order = AllocateZeroPool (OrderSize);
+ if (Order == NULL) {
+ return ;
+ }
+
+ Status = gRT->GetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &OrderSize,
+ Order
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ //
+ // 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_PERMIT_LOAD_FUNC;
+
+ 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 each driver option.
+ //
+ Var = NULL;
+ ListCount = OrderSize / sizeof (UINT16);
+ for (Index = 0; Index < ListCount; Index++) {
+ //
+ // Get driver device path.
+ //
+ UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", Order[Index]);
+ Var = GetEfiGlobalVariable (VarName);
+ if (Var == NULL) {
+ continue;
+ }
+
+ //
+ // Check whether the driver is already forbidden.
+ //
+
+ VarPtr = Var;
+ //
+ // Skip attribute.
+ //
+ VarPtr += sizeof (UINT32);
+
+ //
+ // Skip device path lenth.
+ //
+ VarPtr += sizeof (UINT16);
+
+ //
+ // Skip descript string.
+ //
+ VarPtr += StrSize ((UINT16 *) VarPtr);
+
+ if (IsLoadForbidden ((EFI_DEVICE_PATH_PROTOCOL *) VarPtr)) {
+ FreePool (Var);
+ Var = NULL;
+ continue;
+ }
+
+ AddDevicePath (
+ KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_PERMIT_MODIFY | Order[Index],
+ (EFI_DEVICE_PATH_PROTOCOL *) VarPtr,
+ StartOpCodeHandle
+ );
+ FreePool (Var);
+ Var = NULL;
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_PERMIT_LOAD_DP, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ //
+ // Clear Environment.
+ //
+ if (Var != NULL) {
+ FreePool (Var);
+ }
+ FreePool (Order);
+}
+
+
+/**
+ Display the forbid load device path list (mAccessInfo.LoadForbid).
+
+**/
+VOID
+DisplayLoadForbid (
+ VOID
+ )
+{
+ UINTN Offset;
+ UINTN DPSize;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // 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 = LABLE_FORBID_LOAD_FUNC;
+
+ 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 each forbid load drivers.
+ //
+ Offset = 0;
+ Index = 0;
+ while (Offset < mAccessInfo.LoadForbidLen) {
+ Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + Offset);
+ DPSize = GetDevicePathSize (Dp);
+ AddDevicePath (
+ KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_FORBID_MODIFY | Index,
+ Dp,
+ StartOpCodeHandle
+ );
+ Index++;
+ Offset += DPSize;
+ }
+
+ HiiUpdateForm (
+ mCallbackInfo->HiiHandle, // HII handle
+ &mUserProfileManagerGuid, // Formset GUID
+ FORMID_FORBID_LOAD_DP, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Replace data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+ Display the permit connect device path.
+
+**/
+VOID
+DisplayConnectPermit (
+ VOID
+ )
+{
+ //
+ // Note:
+ // As no architect protocol/interface to be called in ConnectController()
+ // to verify the device path, just add a place holder for permitted connect
+ // device path.
+ //
+}
+
+
+/**
+ Display the forbid connect device path list.
+
+**/
+VOID
+DisplayConnectForbid (
+ VOID
+ )
+{
+ //
+ // Note:
+ // As no architect protocol/interface to be called in ConnectController()
+ // to verify the device path, just add a place holder for forbidden connect
+ // device path.
+ //
+}
+
+
+/**
+ Delete the specified device path by DriverIndex from the forbid device path
+ list (mAccessInfo.LoadForbid).
+
+ @param[in] DriverIndex The index of driver in forbidden device path list.
+
+**/
+VOID
+DeleteFromForbidLoad (
+ IN UINT16 DriverIndex
+ )
+{
+ UINTN OffSet;
+ UINTN DPSize;
+ UINTN OffLen;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+
+ OffSet = 0;
+ //
+ // Find the specified device path.
+ //
+ while ((OffSet < mAccessInfo.LoadForbidLen) && (DriverIndex > 0)) {
+ Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet);
+ DPSize = GetDevicePathSize (Dp);
+ OffSet += DPSize;
+ DriverIndex--;
+ }
+
+ //
+ // Specified device path found.
+ //
+ if (DriverIndex == 0) {
+ Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet);
+ DPSize = GetDevicePathSize (Dp);
+ OffLen = mAccessInfo.LoadForbidLen - OffSet - DPSize;
+ if (OffLen > 0) {
+ CopyMem (
+ mAccessInfo.LoadForbid + OffSet,
+ mAccessInfo.LoadForbid + OffSet + DPSize,
+ OffLen
+ );
+ }
+ mAccessInfo.LoadForbidLen -= DPSize;
+ }
+}
+
+
+/**
+ Add the specified device path by DriverIndex to the forbid device path
+ list (mAccessInfo.LoadForbid).
+
+ @param[in] DriverIndex The index of driver saved in driver options.
+
+**/
+VOID
+AddToForbidLoad (
+ IN UINT16 DriverIndex
+ )
+{
+ UINTN DevicePathLen;
+ UINT8 *Var;
+ UINT8 *VarPtr;
+ UINTN NewLen;
+ UINT8 *NewFL;
+ CHAR16 VarName[13];
+
+ //
+ // Get loadable driver device path.
+ //
+ UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", DriverIndex);
+ Var = GetEfiGlobalVariable (VarName);
+ if (Var == NULL) {
+ return;
+ }
+
+ //
+ // Save forbid load driver.
+ //
+
+ VarPtr = Var;
+ //
+ // Skip attribute.
+ //
+ VarPtr += sizeof (UINT32);
+
+ DevicePathLen = *(UINT16 *) VarPtr;
+ //
+ // Skip device path length.
+ //
+ VarPtr += sizeof (UINT16);
+
+ //
+ // Skip description string.
+ //
+ VarPtr += StrSize ((UINT16 *) VarPtr);
+
+ NewLen = mAccessInfo.LoadForbidLen + DevicePathLen;
+ NewFL = AllocateZeroPool (NewLen);
+ if (NewFL == NULL) {
+ FreePool (Var);
+ return ;
+ }
+
+ if (mAccessInfo.LoadForbidLen > 0) {
+ CopyMem (NewFL, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen);
+ FreePool (mAccessInfo.LoadForbid);
+ }
+
+ CopyMem (NewFL + mAccessInfo.LoadForbidLen, VarPtr, DevicePathLen);
+ mAccessInfo.LoadForbidLen = NewLen;
+ mAccessInfo.LoadForbid = NewFL;
+ FreePool (Var);
+}
+
+
+/**
+ Get current user's access right.
+
+ @param[out] AccessRight Points to the buffer used for user's access right.
+
+ @retval EFI_SUCCESS Get current user access right successfully.
+ @retval others Fail to get current user access right.
+
+**/
+EFI_STATUS
+GetAccessRight (
+ OUT UINT32 *AccessRight
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_INFO_HANDLE UserInfo;
+ EFI_USER_INFO *Info;
+ UINTN InfoSize;
+ UINTN MemSize;
+ EFI_USER_INFO_ACCESS_CONTROL Access;
+ EFI_USER_PROFILE_HANDLE CurrentUser;
+ UINTN TotalLen;
+ UINTN CheckLen;
+
+ //
+ // Allocate user information memory.
+ //
+ MemSize = sizeof (EFI_USER_INFO) + 63;
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get user access information.
+ //
+ UserInfo = NULL;
+ mUserManager->Current (mUserManager, &CurrentUser);
+ while (TRUE) {
+ InfoSize = MemSize;
+ //
+ // Get next user information.
+ //
+ Status = mUserManager->GetNextInfo (mUserManager, CurrentUser, &UserInfo);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ CurrentUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MemSize = InfoSize;
+ FreePool (Info);
+ Info = AllocateZeroPool (MemSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = mUserManager->GetInfo (
+ mUserManager,
+ CurrentUser,
+ UserInfo,
+ Info,
+ &InfoSize
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Check user information.
+ //
+ if (Info->InfoType == EFI_USER_INFO_ACCESS_POLICY_RECORD) {
+ TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO);
+ CheckLen = 0;
+ //
+ // Get specified access information.
+ //
+ while (CheckLen < TotalLen) {
+ CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access));
+ if ((Access.Type == EFI_USER_INFO_ACCESS_ENROLL_SELF) ||
+ (Access.Type == EFI_USER_INFO_ACCESS_ENROLL_OTHERS) ||
+ (Access.Type == EFI_USER_INFO_ACCESS_MANAGE)
+ ) {
+ *AccessRight = Access.Type;
+ FreePool (Info);
+ return EFI_SUCCESS;
+ }
+ CheckLen += Access.Size;
+ }
+ }
+ }
+ FreePool (Info);
+ return EFI_NOT_FOUND;
+}
+
+
+