Home | History | Annotate | Download | only in PwdCredentialProviderDxe
      1 /** @file
      2   Password Credential Provider driver implementation.
      3 
      4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PwdCredentialProvider.h"
     16 
     17 CREDENTIAL_TABLE            *mPwdTable      = NULL;
     18 PWD_PROVIDER_CALLBACK_INFO  *mCallbackInfo  = NULL;
     19 PASSWORD_CREDENTIAL_INFO    *mPwdInfoHandle = NULL;
     20 
     21 HII_VENDOR_DEVICE_PATH      mHiiVendorDevicePath = {
     22   {
     23     {
     24       HARDWARE_DEVICE_PATH,
     25       HW_VENDOR_DP,
     26       {
     27         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     28         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     29       }
     30     },
     31     PWD_CREDENTIAL_PROVIDER_GUID
     32   },
     33   {
     34     END_DEVICE_PATH_TYPE,
     35     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     36     {
     37       (UINT8) (END_DEVICE_PATH_LENGTH),
     38       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     39     }
     40   }
     41 };
     42 
     43 EFI_USER_CREDENTIAL2_PROTOCOL  gPwdCredentialProviderDriver = {
     44   PWD_CREDENTIAL_PROVIDER_GUID,
     45   EFI_USER_CREDENTIAL_CLASS_PASSWORD,
     46   CredentialEnroll,
     47   CredentialForm,
     48   CredentialTile,
     49   CredentialTitle,
     50   CredentialUser,
     51   CredentialSelect,
     52   CredentialDeselect,
     53   CredentialDefault,
     54   CredentialGetInfo,
     55   CredentialGetNextInfo,
     56   EFI_CREDENTIAL_CAPABILITIES_ENROLL,
     57   CredentialDelete
     58 };
     59 
     60 
     61 /**
     62   Get string by string id from HII Interface.
     63 
     64 
     65   @param[in] Id      String ID to get the string from.
     66 
     67   @retval  CHAR16 *  String from ID.
     68   @retval  NULL      If error occurs.
     69 
     70 **/
     71 CHAR16 *
     72 GetStringById (
     73   IN EFI_STRING_ID             Id
     74   )
     75 {
     76   //
     77   // Get the current string for the current Language.
     78   //
     79   return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL);
     80 }
     81 
     82 
     83 /**
     84   Expand password table size.
     85 
     86 **/
     87 VOID
     88 ExpandTableSize (
     89   VOID
     90   )
     91 {
     92   CREDENTIAL_TABLE  *NewTable;
     93   UINTN             Count;
     94 
     95   Count = mPwdTable->MaxCount + PASSWORD_TABLE_INC;
     96   //
     97   // Create new credential table.
     98   //
     99   NewTable = (CREDENTIAL_TABLE *) AllocateZeroPool (
    100                                     sizeof (CREDENTIAL_TABLE) +
    101                                     (Count - 1) * sizeof (PASSWORD_INFO)
    102                                     );
    103   ASSERT (NewTable != NULL);
    104 
    105   NewTable->MaxCount    = Count;
    106   NewTable->Count       = mPwdTable->Count;
    107   NewTable->ValidIndex  = mPwdTable->ValidIndex;
    108   //
    109   // Copy old entries
    110   //
    111   CopyMem (
    112     &NewTable->UserInfo,
    113     &mPwdTable->UserInfo,
    114     mPwdTable->Count * sizeof (PASSWORD_INFO)
    115     );
    116   FreePool (mPwdTable);
    117   mPwdTable = NewTable;
    118 }
    119 
    120 
    121 /**
    122   Add, update or delete info in table, and sync with NV variable.
    123 
    124   @param[in]  Index     The index of the password in table. If index is found in
    125                         table, update the info, else add the into to table.
    126   @param[in]  Info      The new password info to add into table.If Info is NULL,
    127                         delete the info by Index.
    128 
    129   @retval EFI_INVALID_PARAMETER  Info is NULL when save the info.
    130   @retval EFI_SUCCESS            Modify the table successfully.
    131   @retval Others                 Failed to modify the table.
    132 
    133 **/
    134 EFI_STATUS
    135 ModifyTable (
    136   IN  UINTN                                     Index,
    137   IN  PASSWORD_INFO                             * Info OPTIONAL
    138   )
    139 {
    140   EFI_STATUS       Status;
    141   PASSWORD_INFO    *NewPasswordInfo;
    142 
    143   NewPasswordInfo = NULL;
    144 
    145   if (Index < mPwdTable->Count) {
    146     if (Info == NULL) {
    147       //
    148       // Delete the specified entry.
    149       //
    150       mPwdTable->Count--;
    151       if (Index != mPwdTable->Count) {
    152         NewPasswordInfo = &mPwdTable->UserInfo[mPwdTable->Count];
    153       }
    154     } else {
    155       //
    156       // Update the specified entry.
    157       //
    158       NewPasswordInfo = Info;
    159     }
    160   } else {
    161     //
    162     // Add a new password info.
    163     //
    164     if (Info == NULL) {
    165       return EFI_INVALID_PARAMETER;
    166     }
    167 
    168     if (mPwdTable->Count >= mPwdTable->MaxCount) {
    169       ExpandTableSize ();
    170     }
    171 
    172     NewPasswordInfo = Info;
    173     mPwdTable->Count++;
    174   }
    175 
    176   if (NewPasswordInfo != NULL) {
    177     CopyMem (&mPwdTable->UserInfo[Index], NewPasswordInfo, sizeof (PASSWORD_INFO));
    178   }
    179 
    180   //
    181   // Save the credential table.
    182   //
    183   Status = gRT->SetVariable (
    184                   L"PwdCredential",
    185                   &gPwdCredentialProviderGuid,
    186                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    187                   mPwdTable->Count * sizeof (PASSWORD_INFO),
    188                   &mPwdTable->UserInfo
    189                   );
    190   return Status;
    191 }
    192 
    193 
    194 /**
    195   Create a password table.
    196 
    197   @retval EFI_SUCCESS      Create a password table successfully.
    198   @retval Others           Failed to create a password.
    199 
    200 **/
    201 EFI_STATUS
    202 InitCredentialTable (
    203   VOID
    204   )
    205 {
    206   EFI_STATUS  Status;
    207   UINT8       *Var;
    208   UINTN       VarSize;
    209 
    210   //
    211   // Get Password credential data from NV variable.
    212   //
    213   VarSize = 0;
    214   Var     = NULL;
    215   Status  = gRT->GetVariable (
    216                    L"PwdCredential",
    217                    &gPwdCredentialProviderGuid,
    218                    NULL,
    219                    &VarSize,
    220                    Var
    221                    );
    222   if (Status == EFI_BUFFER_TOO_SMALL) {
    223     Var = AllocateZeroPool (VarSize);
    224     if (Var == NULL) {
    225       return EFI_OUT_OF_RESOURCES;
    226     }
    227     Status = gRT->GetVariable (
    228                     L"PwdCredential",
    229                     &gPwdCredentialProviderGuid,
    230                     NULL,
    231                     &VarSize,
    232                     Var
    233                     );
    234   }
    235   if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
    236     return Status;
    237   }
    238 
    239   //
    240   // Create the password credential table.
    241   //
    242   mPwdTable = AllocateZeroPool (
    243                 sizeof (CREDENTIAL_TABLE) - sizeof (PASSWORD_INFO) +
    244                 PASSWORD_TABLE_INC * sizeof (PASSWORD_INFO) +
    245                 VarSize
    246                 );
    247   if (mPwdTable == NULL) {
    248     FreePool (Var);
    249     return EFI_OUT_OF_RESOURCES;
    250   }
    251 
    252   mPwdTable->Count      = VarSize / sizeof (PASSWORD_INFO);
    253   mPwdTable->MaxCount   = mPwdTable->Count + PASSWORD_TABLE_INC;
    254   mPwdTable->ValidIndex = 0;
    255   if (Var != NULL) {
    256     CopyMem (mPwdTable->UserInfo, Var, VarSize);
    257     FreePool (Var);
    258   }
    259   return EFI_SUCCESS;
    260 }
    261 
    262 
    263 /**
    264   Hash the password to get credential.
    265 
    266   @param[in]   Password       Points to the input password.
    267   @param[in]   PasswordSize   The size of password, in bytes.
    268   @param[out]  Credential     Points to the hashed result.
    269 
    270   @retval      TRUE           Hash the password successfully.
    271   @retval      FALSE          Failed to hash the password.
    272 
    273 **/
    274 BOOLEAN
    275 GenerateCredential (
    276   IN      CHAR16                              *Password,
    277   IN      UINTN                               PasswordSize,
    278      OUT  UINT8                               *Credential
    279   )
    280 {
    281   BOOLEAN           Status;
    282   UINTN             HashSize;
    283   VOID              *Hash;
    284 
    285   HashSize = Sha1GetContextSize ();
    286   Hash     = AllocatePool (HashSize);
    287   ASSERT (Hash != NULL);
    288 
    289   Status = Sha1Init (Hash);
    290   if (!Status) {
    291     goto Done;
    292   }
    293 
    294   Status = Sha1Update (Hash, Password, PasswordSize);
    295   if (!Status) {
    296     goto Done;
    297   }
    298 
    299   Status = Sha1Final (Hash, Credential);
    300 
    301 Done:
    302   FreePool (Hash);
    303   return Status;
    304 }
    305 
    306 
    307 /**
    308   Get password from user input.
    309 
    310   @param[in]   FirstPwd       If True, prompt to input the first password.
    311                               If False, prompt to input password again.
    312   @param[out]  Credential     Points to the input password.
    313 
    314 **/
    315 VOID
    316 GetPassword (
    317   IN  BOOLEAN                               FirstPwd,
    318   OUT CHAR8                                 *Credential
    319   )
    320 {
    321   EFI_INPUT_KEY Key;
    322   CHAR16        PasswordMask[CREDENTIAL_LEN + 1];
    323   CHAR16        Password[CREDENTIAL_LEN];
    324   UINTN         PasswordLen;
    325   CHAR16        *QuestionStr;
    326   CHAR16        *LineStr;
    327 
    328   PasswordLen = 0;
    329   while (TRUE) {
    330     PasswordMask[PasswordLen]     = L'_';
    331     PasswordMask[PasswordLen + 1] = L'\0';
    332     LineStr = GetStringById (STRING_TOKEN (STR_DRAW_A_LINE));
    333     if (FirstPwd) {
    334       QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD));
    335     } else {
    336       QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN));
    337     }
    338     CreatePopUp (
    339       EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
    340       &Key,
    341       QuestionStr,
    342       LineStr,
    343       PasswordMask,
    344       NULL
    345       );
    346     FreePool (QuestionStr);
    347     FreePool (LineStr);
    348 
    349     //
    350     // Check key stroke
    351     //
    352     if (Key.ScanCode == SCAN_NULL) {
    353       if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
    354         break;
    355       } else if (Key.UnicodeChar == CHAR_BACKSPACE) {
    356         if (PasswordLen > 0) {
    357           PasswordLen--;
    358         }
    359       } else if ((Key.UnicodeChar == CHAR_NULL) ||
    360                  (Key.UnicodeChar == CHAR_TAB) ||
    361                  (Key.UnicodeChar == CHAR_LINEFEED)) {
    362         continue;
    363       } else {
    364         Password[PasswordLen] = Key.UnicodeChar;
    365         PasswordMask[PasswordLen] = L'*';
    366         PasswordLen++;
    367         if (PasswordLen == CREDENTIAL_LEN) {
    368           break;
    369         }
    370       }
    371     }
    372   }
    373 
    374   PasswordLen = PasswordLen * sizeof (CHAR16);
    375   GenerateCredential (Password, PasswordLen, (UINT8 *)Credential);
    376 }
    377 
    378 /**
    379   Check whether the password can be found on this provider.
    380 
    381   @param[in]  Password           The password to be found.
    382 
    383   @retval EFI_SUCCESS            Found password sucessfully.
    384   @retval EFI_NOT_FOUND          Fail to find the password.
    385 
    386 **/
    387 EFI_STATUS
    388 CheckPassword (
    389   IN CHAR8                                      *Password
    390   )
    391 {
    392   UINTN      Index;
    393   CHAR8      *Pwd;
    394 
    395   //
    396   // Check password credential.
    397   //
    398   mPwdTable->ValidIndex = 0;
    399   for (Index = 0; Index < mPwdTable->Count; Index++) {
    400     Pwd = mPwdTable->UserInfo[Index].Password;
    401     if (CompareMem (Pwd, Password, CREDENTIAL_LEN) == 0) {
    402       mPwdTable->ValidIndex = Index + 1;
    403       return EFI_SUCCESS;
    404     }
    405   }
    406 
    407   return EFI_NOT_FOUND;
    408 }
    409 
    410 
    411 /**
    412   Find a user infomation record by the information record type.
    413 
    414   This function searches all user information records of User from beginning
    415   until either the information is found, or there are no more user infomation
    416   records. A match occurs when a Info.InfoType field matches the user information
    417   record type.
    418 
    419   @param[in]     User      Points to the user profile record to search.
    420   @param[in]     InfoType  The infomation type to be searched.
    421   @param[out]    Info      Points to the user info found, the caller is responsible
    422                            to free.
    423 
    424   @retval EFI_SUCCESS      Find the user information successfully.
    425   @retval Others           Fail to find the user information.
    426 
    427 **/
    428 EFI_STATUS
    429 FindUserInfoByType (
    430   IN      EFI_USER_PROFILE_HANDLE               User,
    431   IN      UINT8                                 InfoType,
    432   OUT     EFI_USER_INFO                         **Info
    433   )
    434 {
    435   EFI_STATUS                 Status;
    436   EFI_USER_INFO              *UserInfo;
    437   UINTN                      UserInfoSize;
    438   EFI_USER_INFO_HANDLE       UserInfoHandle;
    439   EFI_USER_MANAGER_PROTOCOL  *UserManager;
    440 
    441   //
    442   // Find user information by information type.
    443   //
    444   if (Info == NULL) {
    445     return EFI_INVALID_PARAMETER;
    446   }
    447 
    448   Status = gBS->LocateProtocol (
    449                   &gEfiUserManagerProtocolGuid,
    450                   NULL,
    451                   (VOID **) &UserManager
    452                   );
    453   if (EFI_ERROR (Status)) {
    454     return EFI_NOT_FOUND;
    455   }
    456 
    457   //
    458   // Get each user information.
    459   //
    460 
    461   UserInfoHandle = NULL;
    462   UserInfo       = NULL;
    463   UserInfoSize   = 0;
    464   while (TRUE) {
    465     Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle);
    466     if (EFI_ERROR (Status)) {
    467       break;
    468     }
    469     //
    470     // Get information.
    471     //
    472     Status = UserManager->GetInfo (
    473                             UserManager,
    474                             User,
    475                             UserInfoHandle,
    476                             UserInfo,
    477                             &UserInfoSize
    478                             );
    479     if (Status == EFI_BUFFER_TOO_SMALL) {
    480       if (UserInfo != NULL) {
    481         FreePool (UserInfo);
    482       }
    483       UserInfo = AllocateZeroPool (UserInfoSize);
    484       if (UserInfo == NULL) {
    485         return EFI_OUT_OF_RESOURCES;
    486       }
    487       Status = UserManager->GetInfo (
    488                               UserManager,
    489                               User,
    490                               UserInfoHandle,
    491                               UserInfo,
    492                               &UserInfoSize
    493                               );
    494     }
    495     if (EFI_ERROR (Status)) {
    496       break;
    497     }
    498 
    499     ASSERT (UserInfo != NULL);
    500     if (UserInfo->InfoType == InfoType) {
    501       *Info = UserInfo;
    502       return EFI_SUCCESS;
    503     }
    504   }
    505 
    506   if (UserInfo != NULL) {
    507     FreePool (UserInfo);
    508   }
    509   return Status;
    510 }
    511 
    512 
    513 /**
    514   This function processes the results of changes in configuration.
    515 
    516   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    517   @param  Action                 Specifies the type of action taken by the browser.
    518   @param  QuestionId             A unique value which is sent to the original
    519                                  exporting driver so that it can identify the type
    520                                  of data to expect.
    521   @param  Type                   The type of value for the question.
    522   @param  Value                  A pointer to the data being sent to the original
    523                                  exporting driver.
    524   @param  ActionRequest          On return, points to the action requested by the
    525                                  callback function.
    526 
    527   @retval EFI_SUCCESS            The callback successfully handled the action.
    528   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
    529                                  variable and its data.
    530   @retval EFI_DEVICE_ERROR       The variable could not be saved.
    531   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
    532                                  callback.
    533 
    534 **/
    535 EFI_STATUS
    536 EFIAPI
    537 CredentialDriverCallback (
    538   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
    539   IN  EFI_BROWSER_ACTION                     Action,
    540   IN  EFI_QUESTION_ID                        QuestionId,
    541   IN  UINT8                                  Type,
    542   IN  EFI_IFR_TYPE_VALUE                     *Value,
    543   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
    544   )
    545 {
    546   EFI_STATUS    Status;
    547   EFI_INPUT_KEY Key;
    548   CHAR8         Password[CREDENTIAL_LEN];
    549   CHAR16        *PromptStr;
    550 
    551   if (Action == EFI_BROWSER_ACTION_CHANGED) {
    552     if (QuestionId == KEY_GET_PASSWORD) {
    553       //
    554       // Get and check password.
    555       //
    556       GetPassword (TRUE, Password);
    557       Status = CheckPassword (Password);
    558       if (EFI_ERROR (Status)) {
    559         PromptStr = GetStringById (STRING_TOKEN (STR_PASSWORD_INCORRECT));
    560         CreatePopUp (
    561           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
    562           &Key,
    563           L"",
    564           PromptStr,
    565           L"",
    566           NULL
    567           );
    568         FreePool (PromptStr);
    569         return Status;
    570       }
    571       *ActionRequest  = EFI_BROWSER_ACTION_REQUEST_EXIT;
    572     }
    573     return EFI_SUCCESS;
    574   }
    575 
    576   //
    577   // All other action return unsupported.
    578   //
    579   return EFI_UNSUPPORTED;
    580 }
    581 
    582 
    583 /**
    584   This function allows a caller to extract the current configuration for one
    585   or more named elements from the target driver.
    586 
    587 
    588   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    589   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
    590   @param Progress        On return, points to a character in the Request string.
    591                          Points to the string's null terminator if request was successful.
    592                          Points to the most recent '&' before the first failing name/value
    593                          pair (or the beginning of the string if the failure is in the
    594                          first name/value pair) if the request was not successful.
    595   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
    596                          has all values filled in for the names in the Request string.
    597                          String to be allocated by the called function.
    598 
    599   @retval  EFI_SUCCESS            The Results is filled with the requested values.
    600   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
    601   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
    602   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
    603 
    604 **/
    605 EFI_STATUS
    606 EFIAPI
    607 FakeExtractConfig (
    608   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
    609   IN  CONST EFI_STRING                       Request,
    610   OUT EFI_STRING                             *Progress,
    611   OUT EFI_STRING                             *Results
    612   )
    613 {
    614   if (Progress == NULL || Results == NULL) {
    615     return EFI_INVALID_PARAMETER;
    616   }
    617   *Progress = Request;
    618   return EFI_NOT_FOUND;
    619 }
    620 
    621 /**
    622   This function processes the results of changes in configuration.
    623 
    624 
    625   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    626   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
    627   @param Progress        A pointer to a string filled in with the offset of the most
    628                          recent '&' before the first failing name/value pair (or the
    629                          beginning of the string if the failure is in the first
    630                          name/value pair) or the terminating NULL if all was successful.
    631 
    632   @retval  EFI_SUCCESS            The Results is processed successfully.
    633   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
    634   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
    635 
    636 **/
    637 EFI_STATUS
    638 EFIAPI
    639 FakeRouteConfig (
    640   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
    641   IN  CONST EFI_STRING                       Configuration,
    642   OUT EFI_STRING                             *Progress
    643   )
    644 {
    645   if (Configuration == NULL || Progress == NULL) {
    646     return EFI_INVALID_PARAMETER;
    647   }
    648 
    649   return EFI_NOT_FOUND;
    650 }
    651 
    652 /**
    653   This function initialize the data mainly used in form browser.
    654 
    655   @retval EFI_SUCCESS          Initialize form data successfully.
    656   @retval Others               Fail to Initialize form data.
    657 
    658 **/
    659 EFI_STATUS
    660 InitFormBrowser (
    661   VOID
    662   )
    663 {
    664   EFI_STATUS                  Status;
    665   PWD_PROVIDER_CALLBACK_INFO  *CallbackInfo;
    666 
    667   //
    668   // Initialize driver private data.
    669   //
    670   CallbackInfo = AllocateZeroPool (sizeof (PWD_PROVIDER_CALLBACK_INFO));
    671   if (CallbackInfo == NULL) {
    672     return EFI_OUT_OF_RESOURCES;
    673   }
    674 
    675   CallbackInfo->Signature                   = PWD_PROVIDER_SIGNATURE;
    676   CallbackInfo->ConfigAccess.ExtractConfig  = FakeExtractConfig;
    677   CallbackInfo->ConfigAccess.RouteConfig    = FakeRouteConfig;
    678   CallbackInfo->ConfigAccess.Callback       = CredentialDriverCallback;
    679   CallbackInfo->DriverHandle  = NULL;
    680 
    681   //
    682   // Install Device Path Protocol and Config Access protocol to driver handle.
    683   //
    684   Status = gBS->InstallMultipleProtocolInterfaces (
    685                   &CallbackInfo->DriverHandle,
    686                   &gEfiDevicePathProtocolGuid,
    687                   &mHiiVendorDevicePath,
    688                   &gEfiHiiConfigAccessProtocolGuid,
    689                   &CallbackInfo->ConfigAccess,
    690                   NULL
    691                   );
    692   ASSERT_EFI_ERROR (Status);
    693 
    694   //
    695   // Publish HII data.
    696   //
    697   CallbackInfo->HiiHandle = HiiAddPackages (
    698                               &gPwdCredentialProviderGuid,
    699                               CallbackInfo->DriverHandle,
    700                               PwdCredentialProviderStrings,
    701                               PwdCredentialProviderVfrBin,
    702                               NULL
    703                               );
    704   if (CallbackInfo->HiiHandle == NULL) {
    705     return EFI_OUT_OF_RESOURCES;
    706   }
    707   mCallbackInfo = CallbackInfo;
    708 
    709   return Status;
    710 }
    711 
    712 
    713 /**
    714   Enroll a user on a credential provider.
    715 
    716   This function enrolls a user on this credential provider. If the user exists on
    717   this credential provider, update the user information on this credential provider;
    718   otherwise add the user information on credential provider.
    719 
    720   @param[in] This                Points to this instance of EFI_USER_CREDENTIAL2_PROTOCOL.
    721   @param[in] User                The user profile to enroll.
    722 
    723   @retval EFI_SUCCESS            User profile was successfully enrolled.
    724   @retval EFI_ACCESS_DENIED      Current user profile does not permit enrollment on the
    725                                  user profile handle. Either the user profile cannot enroll
    726                                  on any user profile or cannot enroll on a user profile
    727                                  other than the current user profile.
    728   @retval EFI_UNSUPPORTED        This credential provider does not support enrollment in
    729                                  the pre-OS.
    730   @retval EFI_DEVICE_ERROR       The new credential could not be created because of a device
    731                                  error.
    732   @retval EFI_INVALID_PARAMETER  User does not refer to a valid user profile handle.
    733 
    734 **/
    735 EFI_STATUS
    736 EFIAPI
    737 CredentialEnroll (
    738   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
    739   IN        EFI_USER_PROFILE_HANDLE             User
    740   )
    741 {
    742   EFI_STATUS                Status;
    743   UINTN                     Index;
    744   PASSWORD_INFO             PwdInfo;
    745   EFI_USER_INFO             *UserInfo;
    746   CHAR8                     Password[CREDENTIAL_LEN];
    747   EFI_INPUT_KEY             Key;
    748   UINT8                     *UserId;
    749   CHAR16                    *QuestionStr;
    750   CHAR16                    *PromptStr;
    751 
    752   if ((This == NULL) || (User == NULL)) {
    753     return EFI_INVALID_PARAMETER;
    754   }
    755 
    756   //
    757   // Get User Identifier.
    758   //
    759   UserInfo = NULL;
    760   Status = FindUserInfoByType (
    761              User,
    762              EFI_USER_INFO_IDENTIFIER_RECORD,
    763              &UserInfo
    764              );
    765   if (EFI_ERROR (Status)) {
    766     return EFI_INVALID_PARAMETER;
    767   }
    768 
    769   CopyMem (PwdInfo.UserId, (UINT8 *) (UserInfo + 1), sizeof (EFI_USER_INFO_IDENTIFIER));
    770   FreePool (UserInfo);
    771 
    772   //
    773   // Get password from user.
    774   //
    775   while (TRUE) {
    776     //
    777     // Input password.
    778     //
    779     GetPassword (TRUE, PwdInfo.Password);
    780 
    781     //
    782     // Input password again.
    783     //
    784     GetPassword (FALSE, Password);
    785 
    786     //
    787     // Compare the two password consistency.
    788     //
    789     if (CompareMem (PwdInfo.Password, Password, CREDENTIAL_LEN) == 0) {
    790       break;
    791     }
    792 
    793     QuestionStr = GetStringById (STRING_TOKEN (STR_PASSWORD_MISMATCH));
    794     PromptStr   = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN));
    795     CreatePopUp (
    796       EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
    797       &Key,
    798       QuestionStr,
    799       L"",
    800       PromptStr,
    801       NULL
    802       );
    803     FreePool (QuestionStr);
    804     FreePool (PromptStr);
    805   }
    806 
    807   //
    808   // Check whether User is ever enrolled in the provider.
    809   //
    810   for (Index = 0; Index < mPwdTable->Count; Index++) {
    811     UserId = (UINT8 *) &mPwdTable->UserInfo[Index].UserId;
    812     if (CompareMem (UserId, (UINT8 *) &PwdInfo.UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
    813       //
    814       // User already exists, update the password.
    815       //
    816       break;
    817     }
    818   }
    819 
    820   //
    821   // Enroll the User to the provider.
    822   //
    823   Status = ModifyTable (Index, &PwdInfo);
    824   if (EFI_ERROR (Status)) {
    825     return Status;
    826   }
    827 
    828   return EFI_SUCCESS;
    829 }
    830 
    831 
    832 /**
    833   Returns the user interface information used during user identification.
    834 
    835   This function returns information about the form used when interacting with the
    836   user during user identification. The form is the first enabled form in the form-set
    837   class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
    838   the user credential provider does not require a form to identify the user, then this
    839   function should return EFI_NOT_FOUND.
    840 
    841   @param[in]  This       Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
    842   @param[out] Hii        On return, holds the HII database handle.
    843   @param[out] FormSetId  On return, holds the identifier of the form set which contains
    844                          the form used during user identification.
    845   @param[out] FormId     On return, holds the identifier of the form used during user
    846                          identification.
    847 
    848   @retval EFI_SUCCESS            Form returned successfully.
    849   @retval EFI_NOT_FOUND          Form not returned.
    850   @retval EFI_INVALID_PARAMETER  Hii is NULL or FormSetId is NULL or FormId is NULL.
    851 
    852 **/
    853 EFI_STATUS
    854 EFIAPI
    855 CredentialForm (
    856   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
    857   OUT       EFI_HII_HANDLE                      *Hii,
    858   OUT       EFI_GUID                            *FormSetId,
    859   OUT       EFI_FORM_ID                         *FormId
    860   )
    861 {
    862   if ((This == NULL) || (Hii == NULL) ||
    863       (FormSetId == NULL) || (FormId == NULL)) {
    864     return EFI_INVALID_PARAMETER;
    865   }
    866 
    867   *Hii       = mCallbackInfo->HiiHandle;
    868   *FormId    = FORMID_GET_PASSWORD_FORM;
    869   CopyGuid (FormSetId, &gPwdCredentialProviderGuid);
    870 
    871   return EFI_SUCCESS;
    872 }
    873 
    874 
    875 /**
    876   Returns bitmap used to describe the credential provider type.
    877 
    878   This optional function returns a bitmap that is less than or equal to the number
    879   of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
    880   is returned.
    881 
    882   @param[in]      This    Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
    883   @param[in, out] Width   On entry, points to the desired bitmap width. If NULL then no
    884                           bitmap information will be returned. On exit, points to the
    885                           width of the bitmap returned.
    886   @param[in, out] Height  On entry, points to the desired bitmap height. If NULL then no
    887                           bitmap information will be returned. On exit, points to the
    888                           height of the bitmap returned
    889   @param[out]     Hii     On return, holds the HII database handle.
    890   @param[out]     Image   On return, holds the HII image identifier.
    891 
    892   @retval EFI_SUCCESS            Image identifier returned successfully.
    893   @retval EFI_NOT_FOUND          Image identifier not returned.
    894   @retval EFI_INVALID_PARAMETER  Hii is NULL or Image is NULL.
    895 
    896 **/
    897 EFI_STATUS
    898 EFIAPI
    899 CredentialTile (
    900   IN  CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
    901   IN  OUT    UINTN                               *Width,
    902   IN  OUT    UINTN                               *Height,
    903       OUT    EFI_HII_HANDLE                      *Hii,
    904       OUT    EFI_IMAGE_ID                        *Image
    905   )
    906 {
    907   if ((This == NULL) || (Hii == NULL) || (Image == NULL)) {
    908     return EFI_INVALID_PARAMETER;
    909   }
    910   return EFI_NOT_FOUND;
    911 }
    912 
    913 
    914 /**
    915   Returns string used to describe the credential provider type.
    916 
    917   This function returns a string which describes the credential provider. If no
    918   such string exists, then EFI_NOT_FOUND is returned.
    919 
    920   @param[in]  This       Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
    921   @param[out] Hii        On return, holds the HII database handle.
    922   @param[out] String     On return, holds the HII string identifier.
    923 
    924   @retval EFI_SUCCESS            String identifier returned successfully.
    925   @retval EFI_NOT_FOUND          String identifier not returned.
    926   @retval EFI_INVALID_PARAMETER  Hii is NULL or String is NULL.
    927 
    928 **/
    929 EFI_STATUS
    930 EFIAPI
    931 CredentialTitle (
    932   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
    933   OUT       EFI_HII_HANDLE                      *Hii,
    934   OUT       EFI_STRING_ID                       *String
    935   )
    936 {
    937   if ((This == NULL) || (Hii == NULL) || (String == NULL)) {
    938     return EFI_INVALID_PARAMETER;
    939   }
    940 
    941   //
    942   // Set Hii handle and String ID.
    943   //
    944   *Hii    = mCallbackInfo->HiiHandle;
    945   *String = STRING_TOKEN (STR_CREDENTIAL_TITLE);
    946 
    947   return EFI_SUCCESS;
    948 }
    949 
    950 
    951 /**
    952   Return the user identifier associated with the currently authenticated user.
    953 
    954   This function returns the user identifier of the user authenticated by this credential
    955   provider. This function is called after the credential-related information has been
    956   submitted on a form, OR after a call to Default() has returned that this credential is
    957   ready to log on.
    958 
    959   @param[in]  This           Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
    960   @param[in]  User           The user profile handle of the user profile currently being
    961                              considered by the user identity manager. If NULL, then no user
    962                              profile is currently under consideration.
    963   @param[out] Identifier     On return, points to the user identifier.
    964 
    965   @retval EFI_SUCCESS            User identifier returned successfully.
    966   @retval EFI_NOT_READY          No user identifier can be returned.
    967   @retval EFI_ACCESS_DENIED      The user has been locked out of this user credential.
    968   @retval EFI_INVALID_PARAMETER  This is NULL, or Identifier is NULL.
    969   @retval EFI_NOT_FOUND          User is not NULL, and the specified user handle can't be
    970                                  found in user profile database
    971 
    972 **/
    973 EFI_STATUS
    974 EFIAPI
    975 CredentialUser (
    976   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
    977   IN        EFI_USER_PROFILE_HANDLE             User,
    978   OUT       EFI_USER_INFO_IDENTIFIER            *Identifier
    979   )
    980 {
    981   EFI_STATUS    Status;
    982   UINTN         Index;
    983   EFI_USER_INFO *UserInfo;
    984   UINT8         *UserId;
    985   UINT8         *NewUserId;
    986   CHAR8         *Pwd;
    987   CHAR8         *NewPwd;
    988 
    989   if ((This == NULL) || (Identifier == NULL)) {
    990     return EFI_INVALID_PARAMETER;
    991   }
    992 
    993   if (mPwdTable->ValidIndex == 0) {
    994     //
    995     // No password input, or the input password doesn't match
    996     // anyone in PwdTable.
    997     //
    998     return EFI_NOT_READY;
    999   }
   1000 
   1001   if (User == NULL) {
   1002     //
   1003     // Return the user ID whose password matches the input password.
   1004     //
   1005     CopyMem (
   1006       Identifier,
   1007       &mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].UserId,
   1008       sizeof (EFI_USER_INFO_IDENTIFIER)
   1009       );
   1010     return EFI_SUCCESS;
   1011   }
   1012 
   1013   //
   1014   // Get the User's ID.
   1015   //
   1016   Status = FindUserInfoByType (
   1017              User,
   1018              EFI_USER_INFO_IDENTIFIER_RECORD,
   1019              &UserInfo
   1020              );
   1021   if (EFI_ERROR (Status)) {
   1022     return EFI_NOT_FOUND;
   1023   }
   1024 
   1025   //
   1026   // Check whether the input password matches one in PwdTable.
   1027   //
   1028   for (Index = 0; Index < mPwdTable->Count; Index++) {
   1029     UserId    = (UINT8 *) &mPwdTable->UserInfo[Index].UserId;
   1030     NewUserId = (UINT8 *) (UserInfo + 1);
   1031     if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
   1032       Pwd    = mPwdTable->UserInfo[Index].Password;
   1033       NewPwd = mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].Password;
   1034       if (CompareMem (Pwd, NewPwd, CREDENTIAL_LEN) == 0) {
   1035         CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
   1036         FreePool (UserInfo);
   1037         return EFI_SUCCESS;
   1038       }
   1039     }
   1040   }
   1041 
   1042   FreePool (UserInfo);
   1043   return EFI_NOT_READY;
   1044 }
   1045 
   1046 
   1047 /**
   1048   Indicate that user interface interaction has begun for the specified credential.
   1049 
   1050   This function is called when a credential provider is selected by the user. If
   1051   AutoLogon returns FALSE, then the user interface will be constructed by the User
   1052   Identity Manager.
   1053 
   1054   @param[in]  This       Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1055   @param[out] AutoLogon  On return, points to the credential provider's capabilities
   1056                          after the credential provider has been selected by the user.
   1057 
   1058   @retval EFI_SUCCESS            Credential provider successfully selected.
   1059   @retval EFI_INVALID_PARAMETER  AutoLogon is NULL.
   1060 
   1061 **/
   1062 EFI_STATUS
   1063 EFIAPI
   1064 CredentialSelect (
   1065   IN  CONST  EFI_USER_CREDENTIAL2_PROTOCOL   *This,
   1066   OUT        EFI_CREDENTIAL_LOGON_FLAGS      *AutoLogon
   1067   )
   1068 {
   1069   if ((This == NULL) || (AutoLogon == NULL)) {
   1070     return EFI_INVALID_PARAMETER;
   1071   }
   1072   *AutoLogon = 0;
   1073 
   1074   return EFI_SUCCESS;
   1075 }
   1076 
   1077 
   1078 /**
   1079   Indicate that user interface interaction has ended for the specified credential.
   1080 
   1081   This function is called when a credential provider is deselected by the user.
   1082 
   1083   @param[in] This        Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1084 
   1085   @retval EFI_SUCCESS    Credential provider successfully deselected.
   1086 
   1087 **/
   1088 EFI_STATUS
   1089 EFIAPI
   1090 CredentialDeselect (
   1091   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This
   1092   )
   1093 {
   1094   if (This == NULL) {
   1095     return EFI_INVALID_PARAMETER;
   1096   }
   1097   return EFI_SUCCESS;
   1098 }
   1099 
   1100 
   1101 /**
   1102   Return the default logon behavior for this user credential.
   1103 
   1104   This function reports the default login behavior regarding this credential provider.
   1105 
   1106   @param[in]  This       Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1107   @param[out] AutoLogon  On return, holds whether the credential provider should be used
   1108                          by default to automatically log on the user.
   1109 
   1110   @retval EFI_SUCCESS            Default information successfully returned.
   1111   @retval EFI_INVALID_PARAMETER  AutoLogon is NULL.
   1112 
   1113 **/
   1114 EFI_STATUS
   1115 EFIAPI
   1116 CredentialDefault (
   1117   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
   1118   OUT       EFI_CREDENTIAL_LOGON_FLAGS          *AutoLogon
   1119   )
   1120 {
   1121   if ((This == NULL) || (AutoLogon == NULL)) {
   1122     return EFI_INVALID_PARAMETER;
   1123   }
   1124   *AutoLogon = 0;
   1125 
   1126   return EFI_SUCCESS;
   1127 }
   1128 
   1129 
   1130 /**
   1131   Return information attached to the credential provider.
   1132 
   1133   This function returns user information.
   1134 
   1135   @param[in]      This          Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1136   @param[in]      UserInfo      Handle of the user information data record.
   1137   @param[out]     Info          On entry, points to a buffer of at least *InfoSize bytes. On
   1138                                 exit, holds the user information. If the buffer is too small
   1139                                 to hold the information, then EFI_BUFFER_TOO_SMALL is returned
   1140                                 and InfoSize is updated to contain the number of bytes actually
   1141                                 required.
   1142   @param[in, out] InfoSize      On entry, points to the size of Info. On return, points to the
   1143                                 size of the user information.
   1144 
   1145   @retval EFI_SUCCESS           Information returned successfully.
   1146   @retval EFI_BUFFER_TOO_SMALL  The size specified by InfoSize is too small to hold all of the
   1147                                 user information. The size required is returned in *InfoSize.
   1148   @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
   1149   @retval EFI_NOT_FOUND         The specified UserInfo does not refer to a valid user info handle.
   1150 
   1151 **/
   1152 EFI_STATUS
   1153 EFIAPI
   1154 CredentialGetInfo (
   1155   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
   1156   IN        EFI_USER_INFO_HANDLE                UserInfo,
   1157   OUT       EFI_USER_INFO                       *Info,
   1158   IN OUT    UINTN                               *InfoSize
   1159   )
   1160 {
   1161   EFI_USER_INFO            *CredentialInfo;
   1162   UINTN                    Index;
   1163 
   1164   if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) {
   1165     return EFI_INVALID_PARAMETER;
   1166   }
   1167 
   1168   if ((UserInfo == NULL) || (mPwdInfoHandle == NULL)) {
   1169     return EFI_NOT_FOUND;
   1170   }
   1171 
   1172   //
   1173   // Find information handle in credential info table.
   1174   //
   1175   for (Index = 0; Index < mPwdInfoHandle->Count; Index++) {
   1176     CredentialInfo = mPwdInfoHandle->Info[Index];
   1177     if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) {
   1178       //
   1179       // The handle is found, copy the user info.
   1180       //
   1181       if (CredentialInfo->InfoSize > *InfoSize) {
   1182         *InfoSize = CredentialInfo->InfoSize;
   1183         return EFI_BUFFER_TOO_SMALL;
   1184       }
   1185       CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize);
   1186       return EFI_SUCCESS;
   1187     }
   1188   }
   1189 
   1190   return EFI_NOT_FOUND;
   1191 }
   1192 
   1193 
   1194 /**
   1195   Enumerate all of the user informations on the credential provider.
   1196 
   1197   This function returns the next user information record. To retrieve the first user
   1198   information record handle, point UserInfo at a NULL. Each subsequent call will retrieve
   1199   another user information record handle until there are no more, at which point UserInfo
   1200   will point to NULL.
   1201 
   1202   @param[in]      This     Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1203   @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
   1204                            to start enumeration. On exit, points to the next user information
   1205                            handle or NULL if there is no more user information.
   1206 
   1207   @retval EFI_SUCCESS            User information returned.
   1208   @retval EFI_NOT_FOUND          No more user information found.
   1209   @retval EFI_INVALID_PARAMETER  UserInfo is NULL.
   1210 
   1211 **/
   1212 EFI_STATUS
   1213 EFIAPI
   1214 CredentialGetNextInfo (
   1215   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
   1216   IN OUT    EFI_USER_INFO_HANDLE                *UserInfo
   1217   )
   1218 {
   1219   EFI_USER_INFO            *Info;
   1220   CHAR16                   *ProvNameStr;
   1221   UINTN                    InfoLen;
   1222   UINTN                    Index;
   1223   UINTN                    ProvStrLen;
   1224 
   1225   if ((This == NULL) || (UserInfo == NULL)) {
   1226     return EFI_INVALID_PARAMETER;
   1227   }
   1228 
   1229   if (mPwdInfoHandle == NULL) {
   1230     //
   1231     // Initilized user info table. There are 4 user info records in the table.
   1232     //
   1233     InfoLen  = sizeof (PASSWORD_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *);
   1234     mPwdInfoHandle = AllocateZeroPool (InfoLen);
   1235     if (mPwdInfoHandle == NULL) {
   1236       *UserInfo = NULL;
   1237       return EFI_NOT_FOUND;
   1238     }
   1239 
   1240     //
   1241     // The first information, Credential Provider info.
   1242     //
   1243     InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
   1244     Info    = AllocateZeroPool (InfoLen);
   1245     ASSERT (Info != NULL);
   1246 
   1247     Info->InfoType    = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD;
   1248     Info->InfoSize    = (UINT32) InfoLen;
   1249     Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
   1250     CopyGuid (&Info->Credential, &gPwdCredentialProviderGuid);
   1251     CopyGuid ((EFI_GUID *)(Info + 1), &gPwdCredentialProviderGuid);
   1252 
   1253     mPwdInfoHandle->Info[0] = Info;
   1254     mPwdInfoHandle->Count++;
   1255 
   1256     //
   1257     // The second information, Credential Provider name info.
   1258     //
   1259     ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME));
   1260     ProvStrLen  = StrSize (ProvNameStr);
   1261     InfoLen     = sizeof (EFI_USER_INFO) + ProvStrLen;
   1262     Info        = AllocateZeroPool (InfoLen);
   1263     ASSERT (Info != NULL);
   1264 
   1265     Info->InfoType    = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
   1266     Info->InfoSize    = (UINT32) InfoLen;
   1267     Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
   1268     CopyGuid (&Info->Credential, &gPwdCredentialProviderGuid);
   1269     CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
   1270     FreePool (ProvNameStr);
   1271 
   1272     mPwdInfoHandle->Info[1] = Info;
   1273     mPwdInfoHandle->Count++;
   1274 
   1275     //
   1276     // The third information, Credential Provider type info.
   1277     //
   1278     InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
   1279     Info    = AllocateZeroPool (InfoLen);
   1280     ASSERT (Info != NULL);
   1281 
   1282     Info->InfoType    = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD;
   1283     Info->InfoSize    = (UINT32) InfoLen;
   1284     Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
   1285     CopyGuid (&Info->Credential, &gPwdCredentialProviderGuid);
   1286     CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassPasswordGuid);
   1287 
   1288     mPwdInfoHandle->Info[2] = Info;
   1289     mPwdInfoHandle->Count++;
   1290 
   1291     //
   1292     // The fourth information, Credential Provider type name info.
   1293     //
   1294     ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME));
   1295     ProvStrLen  = StrSize (ProvNameStr);
   1296     InfoLen     = sizeof (EFI_USER_INFO) + ProvStrLen;
   1297     Info        = AllocateZeroPool (InfoLen);
   1298     ASSERT (Info != NULL);
   1299 
   1300     Info->InfoType    = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
   1301     Info->InfoSize    = (UINT32) InfoLen;
   1302     Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
   1303     CopyGuid (&Info->Credential, &gPwdCredentialProviderGuid);
   1304     CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
   1305     FreePool (ProvNameStr);
   1306 
   1307     mPwdInfoHandle->Info[3] = Info;
   1308     mPwdInfoHandle->Count++;
   1309   }
   1310 
   1311   if (*UserInfo == NULL) {
   1312     //
   1313     // Return the first info handle.
   1314     //
   1315     *UserInfo = (EFI_USER_INFO_HANDLE) mPwdInfoHandle->Info[0];
   1316     return EFI_SUCCESS;
   1317   }
   1318 
   1319   //
   1320   // Find information handle in credential info table.
   1321   //
   1322   for (Index = 0; Index < mPwdInfoHandle->Count; Index++) {
   1323     Info = mPwdInfoHandle->Info[Index];
   1324     if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) {
   1325       //
   1326       // The handle is found, get the next one.
   1327       //
   1328       if (Index == mPwdInfoHandle->Count - 1) {
   1329         //
   1330         // Already last one.
   1331         //
   1332         *UserInfo = NULL;
   1333         return EFI_NOT_FOUND;
   1334       }
   1335 
   1336       Index++;
   1337       *UserInfo = (EFI_USER_INFO_HANDLE)mPwdInfoHandle->Info[Index];
   1338       return EFI_SUCCESS;
   1339     }
   1340   }
   1341 
   1342   *UserInfo = NULL;
   1343   return EFI_NOT_FOUND;
   1344 }
   1345 
   1346 /**
   1347   Delete a user on this credential provider.
   1348 
   1349   This function deletes a user on this credential provider.
   1350 
   1351   @param[in]     This            Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL.
   1352   @param[in]     User            The user profile handle to delete.
   1353 
   1354   @retval EFI_SUCCESS            User profile was successfully deleted.
   1355   @retval EFI_ACCESS_DENIED      Current user profile does not permit deletion on the user profile handle.
   1356                                  Either the user profile cannot delete on any user profile or cannot delete
   1357                                  on a user profile other than the current user profile.
   1358   @retval EFI_UNSUPPORTED        This credential provider does not support deletion in the pre-OS.
   1359   @retval EFI_DEVICE_ERROR       The new credential could not be deleted because of a device error.
   1360   @retval EFI_INVALID_PARAMETER  User does not refer to a valid user profile handle.
   1361 **/
   1362 EFI_STATUS
   1363 EFIAPI
   1364 CredentialDelete (
   1365   IN CONST  EFI_USER_CREDENTIAL2_PROTOCOL       *This,
   1366   IN        EFI_USER_PROFILE_HANDLE             User
   1367   )
   1368 {
   1369   EFI_STATUS                Status;
   1370   EFI_USER_INFO             *UserInfo;
   1371   UINT8                     *UserId;
   1372   UINT8                     *NewUserId;
   1373   UINTN                     Index;
   1374 
   1375   if ((This == NULL) || (User == NULL)) {
   1376     return EFI_INVALID_PARAMETER;
   1377   }
   1378 
   1379   //
   1380   // Get User Identifier.
   1381   //
   1382   UserInfo = NULL;
   1383   Status = FindUserInfoByType (
   1384              User,
   1385              EFI_USER_INFO_IDENTIFIER_RECORD,
   1386              &UserInfo
   1387              );
   1388   if (EFI_ERROR (Status)) {
   1389     return EFI_INVALID_PARAMETER;
   1390   }
   1391 
   1392   //
   1393   // Find the user by user identifier in mPwdTable.
   1394   //
   1395   for (Index = 0; Index < mPwdTable->Count; Index++) {
   1396     UserId    = (UINT8 *) &mPwdTable->UserInfo[Index].UserId;
   1397     NewUserId = (UINT8 *) (UserInfo + 1);
   1398     if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
   1399       //
   1400       // Found the user, delete it.
   1401       //
   1402       ModifyTable (Index, NULL);
   1403       break;
   1404     }
   1405   }
   1406 
   1407   FreePool (UserInfo);
   1408   return EFI_SUCCESS;
   1409 }
   1410 
   1411 
   1412 /**
   1413   Main entry for this driver.
   1414 
   1415   @param ImageHandle     Image handle this driver.
   1416   @param SystemTable     Pointer to SystemTable.
   1417 
   1418   @retval EFI_SUCESS     This function always complete successfully.
   1419 
   1420 **/
   1421 EFI_STATUS
   1422 EFIAPI
   1423 PasswordProviderInit (
   1424   IN EFI_HANDLE        ImageHandle,
   1425   IN EFI_SYSTEM_TABLE  *SystemTable
   1426   )
   1427 {
   1428   EFI_STATUS  Status;
   1429 
   1430   //
   1431   // It is NOT robust enough to be included in production.
   1432   //
   1433   #error "This implementation is just a sample, please comment this line if you really want to use this driver."
   1434 
   1435   //
   1436   // Init credential table.
   1437   //
   1438   Status = InitCredentialTable ();
   1439   if (EFI_ERROR (Status)) {
   1440     return Status;
   1441   }
   1442 
   1443   //
   1444   // Init Form Browser.
   1445   //
   1446   Status = InitFormBrowser ();
   1447   if (EFI_ERROR (Status)) {
   1448     return Status;
   1449   }
   1450 
   1451   //
   1452   // Install protocol interfaces for the password credential provider.
   1453   //
   1454   Status = gBS->InstallProtocolInterface (
   1455                   &mCallbackInfo->DriverHandle,
   1456                   &gEfiUserCredential2ProtocolGuid,
   1457                   EFI_NATIVE_INTERFACE,
   1458                   &gPwdCredentialProviderDriver
   1459                   );
   1460   return Status;
   1461 }
   1462