Home | History | Annotate | Download | only in UserIdentifyManagerDxe
      1 /** @file
      2   This driver manages user information and produces user manager protocol.
      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 "UserIdentifyManager.h"
     16 
     17 //
     18 // Default user name.
     19 //
     20 CHAR16                      mUserName[]       = L"Administrator";
     21 
     22 //
     23 // Points to the user profile database.
     24 //
     25 USER_PROFILE_DB             *mUserProfileDb   = NULL;
     26 
     27 //
     28 // Points to the credential providers found in system.
     29 //
     30 CREDENTIAL_PROVIDER_INFO    *mProviderDb      = NULL;
     31 
     32 //
     33 // Current user shared in multi function.
     34 //
     35 EFI_USER_PROFILE_HANDLE     mCurrentUser      = NULL;
     36 
     37 //
     38 // Flag indicates a user is identified.
     39 //
     40 BOOLEAN                     mIdentified       = FALSE;
     41 USER_MANAGER_CALLBACK_INFO  *mCallbackInfo    = NULL;
     42 HII_VENDOR_DEVICE_PATH      mHiiVendorDevicePath = {
     43   {
     44     {
     45       HARDWARE_DEVICE_PATH,
     46       HW_VENDOR_DP,
     47       {
     48         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     49         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     50       }
     51     },
     52     USER_IDENTIFY_MANAGER_GUID
     53   },
     54   {
     55     END_DEVICE_PATH_TYPE,
     56     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     57     {
     58       (UINT8) (END_DEVICE_PATH_LENGTH),
     59       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     60     }
     61   }
     62 };
     63 
     64 
     65 EFI_USER_MANAGER_PROTOCOL gUserIdentifyManager = {
     66   UserProfileCreate,
     67   UserProfileDelete,
     68   UserProfileGetNext,
     69   UserProfileCurrent,
     70   UserProfileIdentify,
     71   UserProfileFind,
     72   UserProfileNotify,
     73   UserProfileGetInfo,
     74   UserProfileSetInfo,
     75   UserProfileDeleteInfo,
     76   UserProfileGetNextInfo,
     77 };
     78 
     79 
     80 /**
     81   Find the specified user in the user database.
     82 
     83   This function searches the specified user from the beginning of the user database.
     84   And if NextUser is TRUE, return the next User in the user database.
     85 
     86   @param[in, out] User         On entry, points to the user profile entry to search.
     87                                On return, points to the user profile entry or NULL if not found.
     88   @param[in]      NextUser     If FALSE, find the user in user profile database specifyed by User
     89                                If TRUE, find the next user in user profile database specifyed
     90                                by User.
     91   @param[out]     ProfileIndex A pointer to the index of user profile database that matches the
     92                                user specifyed by User.
     93 
     94   @retval EFI_NOT_FOUND        User was NULL, or User was not found, or the next user was not found.
     95   @retval EFI_SUCCESS          User or the next user are found in user profile database
     96 
     97 **/
     98 EFI_STATUS
     99 FindUserProfile (
    100   IN OUT  USER_PROFILE_ENTRY                    **User,
    101   IN      BOOLEAN                               NextUser,
    102      OUT  UINTN                                 *ProfileIndex OPTIONAL
    103   )
    104 {
    105   UINTN               Index;
    106 
    107   //
    108   // Check parameters
    109   //
    110   if ((mUserProfileDb == NULL) || (User == NULL)) {
    111     return EFI_NOT_FOUND;
    112   }
    113 
    114   //
    115   // Check whether the user profile is in the user profile database.
    116   //
    117   for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
    118     if (mUserProfileDb->UserProfile[Index] == *User) {
    119       if (ProfileIndex != NULL) {
    120         *ProfileIndex = Index;
    121       }
    122       break;
    123     }
    124   }
    125 
    126   if (NextUser) {
    127     //
    128     // Find the next user profile.
    129     //
    130     Index++;
    131     if (Index < mUserProfileDb->UserProfileNum) {
    132       *User = mUserProfileDb->UserProfile[Index];
    133     } else if (Index == mUserProfileDb->UserProfileNum) {
    134       *User = NULL;
    135       return EFI_NOT_FOUND;
    136     } else {
    137       if ((mUserProfileDb->UserProfileNum > 0) && (*User == NULL)) {
    138         *User = mUserProfileDb->UserProfile[0];
    139       } else {
    140         *User = NULL;
    141         return EFI_NOT_FOUND;
    142       }
    143     }
    144   } else if (Index == mUserProfileDb->UserProfileNum) {
    145     return EFI_NOT_FOUND;
    146   }
    147 
    148   return EFI_SUCCESS;
    149 }
    150 
    151 /**
    152   Find the specified user information record in the specified User profile.
    153 
    154   This function searches the specified user information record from the beginning of the user
    155   profile. And if NextInfo is TRUE, return the next info in the user profile.
    156 
    157   @param[in]      User     Points to the user profile entry.
    158   @param[in, out] Info     On entry, points to the user information record or NULL to start
    159                            searching with the first user information record.
    160                            On return, points to the user information record or NULL if not found.
    161   @param[in]      NextInfo If FALSE, find the user information record in profile specifyed by User.
    162                            If TRUE, find the next user information record in profile specifyed
    163                            by User.
    164   @param[out]     Offset   A pointer to the offset of the information record in the user profile.
    165 
    166   @retval EFI_INVALID_PARAMETER Info is NULL
    167   @retval EFI_NOT_FOUND         Info was not found, or the next Info was not found.
    168   @retval EFI_SUCCESS           Info or the next info are found in user profile.
    169 
    170 **/
    171 EFI_STATUS
    172 FindUserInfo (
    173   IN     USER_PROFILE_ENTRY                    * User,
    174   IN OUT EFI_USER_INFO                         **Info,
    175   IN     BOOLEAN                               NextInfo,
    176      OUT UINTN                                 *Offset OPTIONAL
    177   )
    178 {
    179   EFI_STATUS    Status;
    180   EFI_USER_INFO *UserInfo;
    181   UINTN         InfoLen;
    182 
    183   if (Info == NULL) {
    184     return EFI_INVALID_PARAMETER;
    185   }
    186 
    187   //
    188   // Check user profile entry
    189   //
    190   Status = FindUserProfile (&User, FALSE, NULL);
    191   if (EFI_ERROR (Status)) {
    192     return Status;
    193   }
    194 
    195   //
    196   // Find user information in the specified user record.
    197   //
    198   InfoLen = 0;
    199   while (InfoLen < User->UserProfileSize) {
    200     UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
    201     if (UserInfo == *Info) {
    202       if (Offset != NULL) {
    203         *Offset = InfoLen;
    204       }
    205       break;
    206     }
    207     InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
    208   }
    209 
    210   //
    211   // Check whether to find the next user information.
    212   //
    213   if (NextInfo) {
    214     if (InfoLen < User->UserProfileSize) {
    215       UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
    216       InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
    217       if (InfoLen < User->UserProfileSize) {
    218         *Info = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
    219         if (Offset != NULL) {
    220           *Offset = InfoLen;
    221         }
    222       } else if (InfoLen == User->UserProfileSize) {
    223         *Info = NULL;
    224         return EFI_NOT_FOUND;
    225       }
    226     } else {
    227       if (*Info == NULL) {
    228         *Info = (EFI_USER_INFO *) User->ProfileInfo;
    229         if (Offset != NULL) {
    230           *Offset = 0;
    231         }
    232       } else {
    233         *Info = NULL;
    234         return EFI_NOT_FOUND;
    235       }
    236     }
    237   } else if (InfoLen == User->UserProfileSize) {
    238     return EFI_NOT_FOUND;
    239   }
    240 
    241   return EFI_SUCCESS;
    242 }
    243 
    244 /**
    245   Find a user infomation record by the information record type.
    246 
    247   This function searches all user information records of User. The search starts with the
    248   user information record following Info and continues until either the information is found
    249   or there are no more user infomation record.
    250   A match occurs when a Info.InfoType field matches the user information record type.
    251 
    252   @param[in]      User     Points to the user profile record to search.
    253   @param[in, out] Info     On entry, points to the user information record or NULL to start
    254                            searching with the first user information record.
    255                            On return, points to the user information record or NULL if not found.
    256   @param[in]      InfoType The infomation type to be searched.
    257 
    258   @retval EFI_SUCCESS           User information was found. Info points to the user information record.
    259   @retval EFI_NOT_FOUND         User information was not found.
    260   @retval EFI_INVALID_PARAMETER User is NULL or Info is NULL.
    261 
    262 **/
    263 EFI_STATUS
    264 FindUserInfoByType (
    265   IN      USER_PROFILE_ENTRY                    *User,
    266   IN OUT  EFI_USER_INFO                         **Info,
    267   IN      UINT8                                 InfoType
    268   )
    269 {
    270   EFI_STATUS    Status;
    271   EFI_USER_INFO *UserInfo;
    272   UINTN         InfoLen;
    273 
    274   if (Info == NULL) {
    275     return EFI_INVALID_PARAMETER;
    276   }
    277 
    278   //
    279   // Check whether the user has the specified user information.
    280   //
    281   InfoLen = 0;
    282   if (*Info == NULL) {
    283     Status = FindUserProfile (&User, FALSE, NULL);
    284   } else {
    285     Status = FindUserInfo (User, Info, TRUE, &InfoLen);
    286   }
    287 
    288   if (EFI_ERROR (Status)) {
    289     return EFI_NOT_FOUND;
    290   }
    291 
    292   while (InfoLen < User->UserProfileSize) {
    293     UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
    294     if (UserInfo->InfoType == InfoType) {
    295       if (UserInfo != *Info) {
    296         *Info = UserInfo;
    297         return EFI_SUCCESS;
    298       }
    299     }
    300 
    301     InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
    302   }
    303 
    304   *Info = NULL;
    305   return EFI_NOT_FOUND;
    306 }
    307 
    308 /**
    309   Find a user using a user information record.
    310 
    311   This function searches all user profiles for the specified user information record. The
    312   search starts with the user information record handle following UserInfo and continues
    313   until either the information is found or there are no more user profiles.
    314   A match occurs when the Info.InfoType field matches the user information record type and the
    315   user information record data matches the portion of Info passed the EFI_USER_INFO header.
    316 
    317   @param[in, out] User     On entry, points to the previously returned user profile record,
    318                            or NULL to start searching with the first user profile.
    319                            On return, points to the user profile entry, or NULL if not found.
    320   @param[in, out] UserInfo On entry, points to the previously returned user information record,
    321                            or NULL to start searching with the first.
    322                            On return, points to the user information record, or NULL if not found.
    323   @param[in]      Info     Points to the buffer containing the user information to be compared
    324                            to the user information record.
    325   @param[in]      InfoSize The size of Info, in bytes. Same as Info->InfoSize.
    326 
    327   @retval EFI_SUCCESS           User information was found. User points to the user profile record,
    328                                 and UserInfo points to the user information record.
    329   @retval EFI_NOT_FOUND         User information was not found.
    330   @retval EFI_INVALID_PARAMETER User is NULL; Info is NULL; or, InfoSize is too small.
    331 
    332 **/
    333 EFI_STATUS
    334 FindUserProfileByInfo (
    335   IN OUT  USER_PROFILE_ENTRY                    **User,
    336   IN OUT  EFI_USER_INFO                         **UserInfo, OPTIONAL
    337   IN      EFI_USER_INFO                         *Info,
    338   IN      UINTN                                 InfoSize
    339   )
    340 {
    341   EFI_STATUS    Status;
    342   EFI_USER_INFO *InfoEntry;
    343 
    344 
    345   if ((User == NULL) || (Info == NULL)) {
    346     return EFI_INVALID_PARAMETER;
    347   }
    348 
    349   if (InfoSize < sizeof (EFI_USER_INFO)) {
    350     return EFI_INVALID_PARAMETER;
    351   }
    352 
    353   if (UserInfo != NULL) {
    354     InfoEntry = *UserInfo;
    355   } else {
    356     InfoEntry = NULL;
    357   }
    358   //
    359   // Find user profile according to information.
    360   //
    361   if (*User == NULL) {
    362     *User = mUserProfileDb->UserProfile[0];
    363   }
    364 
    365   //
    366   // Check user profile handle.
    367   //
    368   Status = FindUserProfile (User, FALSE, NULL);
    369 
    370   while (!EFI_ERROR (Status)) {
    371     //
    372     // Find the user information in a user profile.
    373     //
    374     while (TRUE) {
    375       Status = FindUserInfoByType (*User, &InfoEntry, Info->InfoType);
    376       if (EFI_ERROR (Status)) {
    377         break;
    378       }
    379 
    380       if (InfoSize == Info->InfoSize) {
    381         if (CompareMem ((UINT8 *) (InfoEntry + 1), (UINT8 *) (Info + 1), InfoSize - sizeof (EFI_USER_INFO)) == 0) {
    382           //
    383           // Found the infomation record.
    384           //
    385           if (UserInfo != NULL) {
    386             *UserInfo = InfoEntry;
    387           }
    388           return EFI_SUCCESS;
    389         }
    390       }
    391     }
    392 
    393     //
    394     // Get next user profile.
    395     //
    396     InfoEntry = NULL;
    397     Status    = FindUserProfile (User, TRUE, NULL);
    398   }
    399 
    400   return EFI_NOT_FOUND;
    401 }
    402 
    403 
    404 /**
    405   Check whether the access policy is valid.
    406 
    407   @param[in]  PolicyInfo          Point to the access policy.
    408   @param[in]  InfoLen             The policy length.
    409 
    410   @retval TRUE     The policy is a valid access policy.
    411   @retval FALSE    The access policy is not a valid access policy.
    412 
    413 **/
    414 BOOLEAN
    415 CheckAccessPolicy (
    416   IN  UINT8                                     *PolicyInfo,
    417   IN  UINTN                                     InfoLen
    418   )
    419 {
    420   UINTN                         TotalLen;
    421   UINTN                         ValueLen;
    422   UINTN                         OffSet;
    423   EFI_USER_INFO_ACCESS_CONTROL  Access;
    424   EFI_DEVICE_PATH_PROTOCOL      *Path;
    425   UINTN                         PathSize;
    426 
    427   TotalLen = 0;
    428   while (TotalLen < InfoLen) {
    429     //
    430     // Check access policy according to type.
    431     //
    432     CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access));
    433     ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
    434     switch (Access.Type) {
    435     case EFI_USER_INFO_ACCESS_FORBID_LOAD:
    436     case EFI_USER_INFO_ACCESS_PERMIT_LOAD:
    437     case EFI_USER_INFO_ACCESS_FORBID_CONNECT:
    438     case EFI_USER_INFO_ACCESS_PERMIT_CONNECT:
    439       OffSet = 0;
    440       while (OffSet < ValueLen) {
    441         Path      = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet);
    442         PathSize  = GetDevicePathSize (Path);
    443         OffSet += PathSize;
    444       }
    445       if (OffSet != ValueLen) {
    446         return FALSE;
    447       }
    448       break;
    449 
    450     case EFI_USER_INFO_ACCESS_SETUP:
    451       if (ValueLen % sizeof (EFI_GUID) != 0) {
    452         return FALSE;
    453       }
    454       break;
    455 
    456     case EFI_USER_INFO_ACCESS_BOOT_ORDER:
    457       if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) {
    458         return FALSE;
    459       }
    460       break;
    461 
    462     case EFI_USER_INFO_ACCESS_ENROLL_SELF:
    463     case EFI_USER_INFO_ACCESS_ENROLL_OTHERS:
    464     case EFI_USER_INFO_ACCESS_MANAGE:
    465       if (ValueLen != 0) {
    466         return FALSE;
    467       }
    468       break;
    469 
    470     default:
    471       return FALSE;
    472       break;
    473     }
    474 
    475     TotalLen += Access.Size;
    476   }
    477 
    478   if (TotalLen != InfoLen) {
    479     return FALSE;
    480   }
    481 
    482   return TRUE;
    483 }
    484 
    485 
    486 /**
    487   Check whether the identity policy is valid.
    488 
    489   @param[in]  PolicyInfo          Point to the identity policy.
    490   @param[in]  InfoLen             The policy length.
    491 
    492   @retval TRUE     The policy is a valid identity policy.
    493   @retval FALSE    The access policy is not a valid identity policy.
    494 
    495 **/
    496 BOOLEAN
    497 CheckIdentityPolicy (
    498   IN  UINT8                                     *PolicyInfo,
    499   IN  UINTN                                     InfoLen
    500   )
    501 {
    502   UINTN                         TotalLen;
    503   UINTN                         ValueLen;
    504   EFI_USER_INFO_IDENTITY_POLICY *Identity;
    505 
    506   TotalLen  = 0;
    507 
    508   //
    509   // Check each part of policy expression.
    510   //
    511   while (TotalLen < InfoLen) {
    512     //
    513     // Check access polisy according to type.
    514     //
    515     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);
    516     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
    517     switch (Identity->Type) {
    518     //
    519     // Check False option.
    520     //
    521     case EFI_USER_INFO_IDENTITY_FALSE:
    522       if (ValueLen != 0) {
    523         return FALSE;
    524       }
    525       break;
    526 
    527     //
    528     // Check True option.
    529     //
    530     case EFI_USER_INFO_IDENTITY_TRUE:
    531       if (ValueLen != 0) {
    532         return FALSE;
    533       }
    534       break;
    535 
    536     //
    537     // Check negative operation.
    538     //
    539     case EFI_USER_INFO_IDENTITY_NOT:
    540       if (ValueLen != 0) {
    541         return FALSE;
    542       }
    543       break;
    544 
    545     //
    546     // Check and operation.
    547     //
    548     case EFI_USER_INFO_IDENTITY_AND:
    549       if (ValueLen != 0) {
    550         return FALSE;
    551       }
    552       break;
    553 
    554     //
    555     // Check or operation.
    556     //
    557     case EFI_USER_INFO_IDENTITY_OR:
    558       if (ValueLen != 0) {
    559         return FALSE;
    560       }
    561       break;
    562 
    563     //
    564     // Check credential provider by type.
    565     //
    566     case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
    567       if (ValueLen != sizeof (EFI_GUID)) {
    568         return FALSE;
    569       }
    570       break;
    571 
    572     //
    573     // Check credential provider by ID.
    574     //
    575     case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
    576       if (ValueLen != sizeof (EFI_GUID)) {
    577         return FALSE;
    578       }
    579       break;
    580 
    581     default:
    582       return FALSE;
    583       break;
    584     }
    585 
    586     TotalLen += Identity->Length;
    587   }
    588 
    589   if (TotalLen != InfoLen) {
    590     return FALSE;
    591   }
    592 
    593   return TRUE;
    594 }
    595 
    596 
    597 /**
    598   Check whether the user information is a valid user information record.
    599 
    600   @param[in]  Info points to the user information.
    601 
    602   @retval TRUE     The info is a valid user information record.
    603   @retval FALSE    The info is not a valid user information record.
    604 
    605 **/
    606 BOOLEAN
    607 CheckUserInfo (
    608   IN CONST  EFI_USER_INFO                       *Info
    609   )
    610 {
    611   UINTN       InfoLen;
    612 
    613   if (Info == NULL) {
    614     return FALSE;
    615   }
    616   //
    617   // Check user information according to information type.
    618   //
    619   InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO);
    620   switch (Info->InfoType) {
    621   case EFI_USER_INFO_EMPTY_RECORD:
    622     if (InfoLen != 0) {
    623       return FALSE;
    624     }
    625     break;
    626 
    627   case EFI_USER_INFO_NAME_RECORD:
    628   case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD:
    629   case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD:
    630     break;
    631 
    632   case EFI_USER_INFO_CREATE_DATE_RECORD:
    633   case EFI_USER_INFO_USAGE_DATE_RECORD:
    634     if (InfoLen != sizeof (EFI_TIME)) {
    635       return FALSE;
    636     }
    637     break;
    638 
    639   case EFI_USER_INFO_USAGE_COUNT_RECORD:
    640     if (InfoLen != sizeof (UINT64)) {
    641       return FALSE;
    642     }
    643     break;
    644 
    645   case EFI_USER_INFO_IDENTIFIER_RECORD:
    646     if (InfoLen != 16) {
    647       return FALSE;
    648     }
    649     break;
    650 
    651   case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD:
    652   case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD:
    653   case EFI_USER_INFO_GUID_RECORD:
    654     if (InfoLen != sizeof (EFI_GUID)) {
    655       return FALSE;
    656     }
    657     break;
    658 
    659   case EFI_USER_INFO_PKCS11_RECORD:
    660   case EFI_USER_INFO_CBEFF_RECORD:
    661     break;
    662 
    663   case EFI_USER_INFO_FAR_RECORD:
    664   case EFI_USER_INFO_RETRY_RECORD:
    665     if (InfoLen != 1) {
    666       return FALSE;
    667     }
    668     break;
    669 
    670   case EFI_USER_INFO_ACCESS_POLICY_RECORD:
    671     if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) {
    672       return FALSE;
    673     }
    674     break;
    675 
    676   case EFI_USER_INFO_IDENTITY_POLICY_RECORD:
    677     if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) {
    678       return FALSE;
    679     }
    680     break;
    681 
    682   default:
    683     return FALSE;
    684     break;
    685   }
    686 
    687   return TRUE;
    688 }
    689 
    690 
    691 /**
    692   Check the user profile data format to be added.
    693 
    694   @param[in]  UserProfileInfo     Points to the user profile data.
    695   @param[in]  UserProfileSize     The length of user profile data.
    696 
    697   @retval TRUE     It is a valid user profile.
    698   @retval FALSE    It is not a valid user profile.
    699 
    700 **/
    701 BOOLEAN
    702 CheckProfileInfo (
    703   IN  UINT8                                     *UserProfileInfo,
    704   IN  UINTN                                     UserProfileSize
    705   )
    706 {
    707   UINTN         ChkLen;
    708   EFI_USER_INFO *Info;
    709 
    710   if (UserProfileInfo == NULL) {
    711     return FALSE;
    712   }
    713 
    714   //
    715   // Check user profile information length.
    716   //
    717   ChkLen = 0;
    718   while (ChkLen < UserProfileSize) {
    719     Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen);
    720     //
    721     // Check user information format.
    722     //
    723     if (!CheckUserInfo (Info)) {
    724       return FALSE;
    725     }
    726 
    727     ChkLen += ALIGN_VARIABLE (Info->InfoSize);
    728   }
    729 
    730   if (ChkLen != UserProfileSize) {
    731     return FALSE;
    732   }
    733 
    734   return TRUE;
    735 }
    736 
    737 
    738 /**
    739   Find the specified RightType in current user profile.
    740 
    741   @param[in]  RightType      Could be EFI_USER_INFO_ACCESS_MANAGE,
    742                              EFI_USER_INFO_ACCESS_ENROLL_OTHERS or
    743                              EFI_USER_INFO_ACCESS_ENROLL_SELF.
    744 
    745   @retval TRUE     Find the specified RightType in current user profile.
    746   @retval FALSE    Can't find the right in the profile.
    747 
    748 **/
    749 BOOLEAN
    750 CheckCurrentUserAccessRight (
    751   IN        UINT32                              RightType
    752   )
    753 {
    754   EFI_STATUS                    Status;
    755   EFI_USER_INFO                 *Info;
    756   UINTN                         TotalLen;
    757   UINTN                         CheckLen;
    758   EFI_USER_INFO_ACCESS_CONTROL  Access;
    759 
    760   //
    761   // Get user access right information.
    762   //
    763   Info = NULL;
    764   Status = FindUserInfoByType (
    765             (USER_PROFILE_ENTRY *) mCurrentUser,
    766             &Info,
    767             EFI_USER_INFO_ACCESS_POLICY_RECORD
    768             );
    769   if (EFI_ERROR (Status)) {
    770     return FALSE;
    771   }
    772 
    773   ASSERT (Info != NULL);
    774   TotalLen  = Info->InfoSize - sizeof (EFI_USER_INFO);
    775   CheckLen  = 0;
    776   while (CheckLen < TotalLen) {
    777     //
    778     // Check right according to access type.
    779     //
    780     CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access));
    781     if (Access.Type == RightType) {
    782       return TRUE;;
    783     }
    784 
    785     CheckLen += Access.Size;
    786   }
    787 
    788   return FALSE;
    789 }
    790 
    791 
    792 /**
    793   Create a unique user identifier.
    794 
    795   @param[out]  Identifier     This points to the identifier.
    796 
    797 **/
    798 VOID
    799 GenerateIdentifier (
    800    OUT    UINT8                               *Identifier
    801   )
    802 {
    803   EFI_TIME  Time;
    804   UINT64    MonotonicCount;
    805   UINT32    *MonotonicPointer;
    806   UINTN     Index;
    807 
    808   //
    809   // Create a unique user identifier.
    810   //
    811   gRT->GetTime (&Time, NULL);
    812   CopyMem (Identifier, &Time, sizeof (EFI_TIME));
    813   //
    814   // Remove zeros.
    815   //
    816   for (Index = 0; Index < sizeof (EFI_TIME); Index++) {
    817     if (Identifier[Index] == 0) {
    818       Identifier[Index] = 0x5a;
    819     }
    820   }
    821 
    822   MonotonicPointer = (UINT32 *) Identifier;
    823   gBS->GetNextMonotonicCount (&MonotonicCount);
    824   MonotonicPointer[0] += (UINT32) MonotonicCount;
    825   MonotonicPointer[1] += (UINT32) MonotonicCount;
    826   MonotonicPointer[2] += (UINT32) MonotonicCount;
    827   MonotonicPointer[3] += (UINT32) MonotonicCount;
    828 }
    829 
    830 
    831 /**
    832   Generate unique user ID.
    833 
    834   @param[out]  UserId                 Points to the user identifer.
    835 
    836 **/
    837 VOID
    838 GenerateUserId (
    839   OUT    UINT8                               *UserId
    840   )
    841 {
    842   EFI_STATUS              Status;
    843   USER_PROFILE_ENTRY      *UserProfile;
    844   EFI_USER_INFO           *UserInfo;
    845   UINTN                   Index;
    846 
    847   //
    848   // Generate unique user ID
    849   //
    850   while (TRUE) {
    851     GenerateIdentifier (UserId);
    852     //
    853     // Check whether it's unique in user profile database.
    854     //
    855     if (mUserProfileDb == NULL) {
    856       return ;
    857     }
    858 
    859     for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
    860       UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]);
    861       UserInfo    = NULL;
    862       Status      = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
    863       if (EFI_ERROR (Status)) {
    864         continue;
    865       }
    866 
    867       if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
    868         break;
    869       }
    870     }
    871 
    872     if (Index == mUserProfileDb->UserProfileNum) {
    873       return ;
    874     }
    875   }
    876 }
    877 
    878 
    879 /**
    880   Expand user profile database.
    881 
    882   @retval TRUE     Success to expand user profile database.
    883   @retval FALSE    Fail to expand user profile database.
    884 
    885 **/
    886 BOOLEAN
    887 ExpandUsermUserProfileDb (
    888   VOID
    889   )
    890 {
    891   UINTN               MaxNum;
    892   USER_PROFILE_DB     *NewDataBase;
    893 
    894   //
    895   // Create new user profile database.
    896   //
    897   if (mUserProfileDb == NULL) {
    898     MaxNum = USER_NUMBER_INC;
    899   } else {
    900     MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC;
    901   }
    902 
    903   NewDataBase = AllocateZeroPool (
    904                   sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) +
    905                   MaxNum * sizeof (EFI_USER_PROFILE_HANDLE)
    906                   );
    907   if (NewDataBase == NULL) {
    908     return FALSE;
    909   }
    910 
    911   NewDataBase->MaxProfileNum = MaxNum;
    912 
    913   //
    914   // Copy old user profile database value
    915   //
    916   if (mUserProfileDb == NULL) {
    917     NewDataBase->UserProfileNum = 0;
    918   } else {
    919     NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum;
    920     CopyMem (
    921       NewDataBase->UserProfile,
    922       mUserProfileDb->UserProfile,
    923       NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE)
    924       );
    925     FreePool (mUserProfileDb);
    926   }
    927 
    928   mUserProfileDb = NewDataBase;
    929   return TRUE;
    930 }
    931 
    932 
    933 /**
    934   Expand user profile
    935 
    936   @param[in]  User                    Points to user profile.
    937   @param[in]  ExpandSize              The size of user profile.
    938 
    939   @retval TRUE     Success to expand user profile size.
    940   @retval FALSE    Fail to expand user profile size.
    941 
    942 **/
    943 BOOLEAN
    944 ExpandUserProfile (
    945   IN USER_PROFILE_ENTRY                         *User,
    946   IN UINTN                                      ExpandSize
    947   )
    948 {
    949   UINT8 *Info;
    950   UINTN InfoSizeInc;
    951 
    952   //
    953   // Allocate new memory.
    954   //
    955   InfoSizeInc = 128;
    956   User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc;
    957   Info = AllocateZeroPool (User->MaxProfileSize);
    958   if (Info == NULL) {
    959     return FALSE;
    960   }
    961 
    962   //
    963   // Copy exist information.
    964   //
    965   if (User->UserProfileSize > 0) {
    966     CopyMem (Info, User->ProfileInfo, User->UserProfileSize);
    967     FreePool (User->ProfileInfo);
    968   }
    969 
    970   User->ProfileInfo = Info;
    971   return TRUE;
    972 }
    973 
    974 
    975 /**
    976   Save the user profile to non-volatile memory, or delete it from non-volatile memory.
    977 
    978   @param[in]  User         Point to the user profile
    979   @param[in]  Delete       If TRUE, delete the found user profile.
    980                            If FALSE, save the user profile.
    981   @retval EFI_SUCCESS      Save or delete user profile successfully.
    982   @retval Others           Fail to change the profile.
    983 
    984 **/
    985 EFI_STATUS
    986 SaveNvUserProfile (
    987   IN  USER_PROFILE_ENTRY                        *User,
    988   IN  BOOLEAN                                   Delete
    989   )
    990 {
    991   EFI_STATUS  Status;
    992 
    993   //
    994   // Check user profile entry.
    995   //
    996   Status = FindUserProfile (&User, FALSE, NULL);
    997   if (EFI_ERROR (Status)) {
    998     return Status;
    999   }
   1000 
   1001   //
   1002   // Save the user profile to non-volatile memory.
   1003   //
   1004   Status = gRT->SetVariable (
   1005                   User->UserVarName,
   1006                   &gUserIdentifyManagerGuid,
   1007                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   1008                   Delete ? 0 : User->UserProfileSize,
   1009                   User->ProfileInfo
   1010                   );
   1011   return Status;
   1012 }
   1013 
   1014 /**
   1015   Add one new user info into the user's profile.
   1016 
   1017   @param[in]   User        point to the user profile
   1018   @param[in]   Info        Points to the user information payload.
   1019   @param[in]   InfoSize    The size of the user information payload, in bytes.
   1020   @param[out]  UserInfo    Point to the new info in user profile
   1021   @param[in]   Save        If TRUE, save the profile to NV flash.
   1022                            If FALSE, don't need to save the profile to NV flash.
   1023 
   1024   @retval EFI_SUCCESS      Add user info to user profile successfully.
   1025   @retval Others           Fail to add user info to user profile.
   1026 
   1027 **/
   1028 EFI_STATUS
   1029 AddUserInfo (
   1030   IN  USER_PROFILE_ENTRY                        *User,
   1031   IN  UINT8                                     *Info,
   1032   IN  UINTN                                     InfoSize,
   1033   OUT EFI_USER_INFO                             **UserInfo, OPTIONAL
   1034   IN  BOOLEAN                                   Save
   1035   )
   1036 {
   1037   EFI_STATUS  Status;
   1038 
   1039   if ((Info == NULL) || (User == NULL)) {
   1040     return EFI_INVALID_PARAMETER;
   1041   }
   1042 
   1043   //
   1044   // Check user profile handle.
   1045   //
   1046   Status = FindUserProfile (&User, FALSE, NULL);
   1047   if (EFI_ERROR (Status)) {
   1048     return Status;
   1049   }
   1050 
   1051   //
   1052   // Check user information memory size.
   1053   //
   1054   if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) {
   1055     if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) {
   1056       return EFI_OUT_OF_RESOURCES;
   1057     }
   1058   }
   1059 
   1060   //
   1061   // Add new user information.
   1062   //
   1063   CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize);
   1064   if (UserInfo != NULL) {
   1065     *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);
   1066   }
   1067   User->UserProfileSize += ALIGN_VARIABLE (InfoSize);
   1068 
   1069   //
   1070   // Save user profile information.
   1071   //
   1072   if (Save) {
   1073     Status = SaveNvUserProfile (User, FALSE);
   1074   }
   1075 
   1076   return Status;
   1077 }
   1078 
   1079 
   1080 /**
   1081   Get the user info from the specified user info handle.
   1082 
   1083   @param[in]      User            Point to the user profile.
   1084   @param[in]      UserInfo        Point to the user information record to get.
   1085   @param[out]     Info            On entry, points to a buffer of at least *InfoSize bytes.
   1086                                   On exit, holds the user information.
   1087   @param[in, out] InfoSize        On entry, points to the size of Info.
   1088                                   On return, points to the size of the user information.
   1089   @param[in]      ChkRight        If TRUE, check the user info attribute.
   1090                                   If FALSE, don't check the user info attribute.
   1091 
   1092 
   1093   @retval EFI_ACCESS_DENIED       The information cannot be accessed by the current user.
   1094   @retval EFI_INVALID_PARAMETER   InfoSize is NULL or UserInfo is NULL.
   1095   @retval EFI_BUFFER_TOO_SMALL    The number of bytes specified by *InfoSize is too small to hold the
   1096                                   returned data. The actual size required is returned in *InfoSize.
   1097   @retval EFI_SUCCESS             Information returned successfully.
   1098 
   1099 **/
   1100 EFI_STATUS
   1101 GetUserInfo (
   1102   IN        USER_PROFILE_ENTRY                  *User,
   1103   IN        EFI_USER_INFO                       *UserInfo,
   1104   OUT       EFI_USER_INFO                       *Info,
   1105   IN OUT    UINTN                               *InfoSize,
   1106   IN        BOOLEAN                             ChkRight
   1107   )
   1108 {
   1109   EFI_STATUS  Status;
   1110 
   1111   if ((InfoSize == NULL) || (UserInfo == NULL)) {
   1112     return EFI_INVALID_PARAMETER;
   1113   }
   1114 
   1115   if ((*InfoSize != 0) && (Info == NULL)) {
   1116     return EFI_INVALID_PARAMETER;
   1117   }
   1118 
   1119   //
   1120   // Find the user information to get.
   1121   //
   1122   Status = FindUserInfo (User, &UserInfo, FALSE, NULL);
   1123   if (EFI_ERROR (Status)) {
   1124     return Status;
   1125   }
   1126 
   1127   //
   1128   // Check information attributes.
   1129   //
   1130   if (ChkRight) {
   1131     switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) {
   1132     case EFI_USER_INFO_PRIVATE:
   1133     case EFI_USER_INFO_PROTECTED:
   1134       if (User != mCurrentUser) {
   1135         return EFI_ACCESS_DENIED;
   1136       }
   1137       break;
   1138 
   1139     case EFI_USER_INFO_PUBLIC:
   1140       break;
   1141 
   1142     default:
   1143       return EFI_INVALID_PARAMETER;
   1144       break;
   1145     }
   1146   }
   1147 
   1148   //
   1149   // Get user information.
   1150   //
   1151   if (UserInfo->InfoSize > *InfoSize) {
   1152     *InfoSize = UserInfo->InfoSize;
   1153     return EFI_BUFFER_TOO_SMALL;
   1154   }
   1155 
   1156   *InfoSize = UserInfo->InfoSize;
   1157   if (Info != NULL) {
   1158     CopyMem (Info, UserInfo, *InfoSize);
   1159   }
   1160 
   1161   return EFI_SUCCESS;
   1162 }
   1163 
   1164 
   1165 /**
   1166   Delete the specified user information from user profile.
   1167 
   1168   @param[in]  User        Point to the user profile.
   1169   @param[in]  Info        Point to the user information record to delete.
   1170   @param[in]  Save        If TRUE, save the profile to NV flash.
   1171                           If FALSE, don't need to save the profile to NV flash.
   1172 
   1173   @retval EFI_SUCCESS     Delete user info from user profile successfully.
   1174   @retval Others          Fail to delete user info from user profile.
   1175 
   1176 **/
   1177 EFI_STATUS
   1178 DelUserInfo (
   1179   IN  USER_PROFILE_ENTRY                        *User,
   1180   IN  EFI_USER_INFO                             *Info,
   1181   IN  BOOLEAN                                   Save
   1182   )
   1183 {
   1184   EFI_STATUS  Status;
   1185   UINTN       Offset;
   1186   UINTN       NextOffset;
   1187 
   1188   //
   1189   // Check user information handle.
   1190   //
   1191   Status = FindUserInfo (User, &Info, FALSE, &Offset);
   1192   if (EFI_ERROR (Status)) {
   1193     return Status;
   1194   }
   1195 
   1196   if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
   1197     return EFI_ACCESS_DENIED;
   1198   }
   1199 
   1200   //
   1201   // Delete the specified user information.
   1202   //
   1203   NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize);
   1204   User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize);
   1205   if (Offset < User->UserProfileSize) {
   1206     CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);
   1207   }
   1208 
   1209   if (Save) {
   1210     Status = SaveNvUserProfile (User, FALSE);
   1211   }
   1212 
   1213   return Status;
   1214 }
   1215 
   1216 
   1217 /**
   1218   Add or update user information.
   1219 
   1220   @param[in]      User           Point to the user profile.
   1221   @param[in, out] UserInfo       On entry, points to the user information to modify,
   1222                                  or NULL to add a new UserInfo.
   1223                                  On return, points to the modified user information.
   1224   @param[in]      Info           Points to the new user information.
   1225   @param[in]      InfoSize       The size of Info,in bytes.
   1226 
   1227   @retval EFI_INVALID_PARAMETER  UserInfo is NULL or Info is NULL.
   1228   @retval EFI_ACCESS_DENIED      The record is exclusive.
   1229   @retval EFI_SUCCESS            User information was successfully changed/added.
   1230 
   1231 **/
   1232 EFI_STATUS
   1233 ModifyUserInfo (
   1234   IN        USER_PROFILE_ENTRY                  *User,
   1235   IN OUT    EFI_USER_INFO                       **UserInfo,
   1236   IN CONST  EFI_USER_INFO                       *Info,
   1237   IN        UINTN                               InfoSize
   1238   )
   1239 {
   1240   EFI_STATUS    Status;
   1241   UINTN         PayloadLen;
   1242   EFI_USER_INFO *OldInfo;
   1243 
   1244   if ((UserInfo == NULL) || (Info == NULL)) {
   1245     return EFI_INVALID_PARAMETER;
   1246   }
   1247 
   1248   if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) {
   1249     return EFI_INVALID_PARAMETER;
   1250   }
   1251 
   1252   //
   1253   // Check user information.
   1254   //
   1255   if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
   1256     return EFI_ACCESS_DENIED;
   1257   }
   1258 
   1259   if (!CheckUserInfo (Info)) {
   1260     return EFI_INVALID_PARAMETER;
   1261   }
   1262 
   1263 
   1264   if (*UserInfo == NULL) {
   1265     //
   1266     // Add new user information.
   1267     //
   1268     OldInfo = NULL;
   1269     do {
   1270       Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
   1271       if (EFI_ERROR (Status)) {
   1272         break;
   1273       }
   1274       ASSERT (OldInfo != NULL);
   1275 
   1276       if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) ||
   1277            ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) {
   1278         //
   1279         //  Same type can not co-exist for exclusive information.
   1280         //
   1281         return EFI_ACCESS_DENIED;
   1282       }
   1283 
   1284       //
   1285       // Check whether it exists in DB.
   1286       //
   1287       if (Info->InfoSize != OldInfo->InfoSize) {
   1288         continue;
   1289       }
   1290 
   1291       if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) {
   1292         continue;
   1293       }
   1294 
   1295       PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO);
   1296       if (PayloadLen == 0) {
   1297         continue;
   1298       }
   1299 
   1300       if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) {
   1301         continue;
   1302       }
   1303 
   1304       //
   1305       // Yes. The new info is as same as the one in profile.
   1306       //
   1307       return EFI_SUCCESS;
   1308     } while (!EFI_ERROR (Status));
   1309 
   1310     Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
   1311     return Status;
   1312   }
   1313 
   1314   //
   1315   // Modify existing user information.
   1316   //
   1317   OldInfo = *UserInfo;
   1318   if (OldInfo->InfoType != Info->InfoType) {
   1319     return EFI_INVALID_PARAMETER;
   1320   }
   1321 
   1322   if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) &&
   1323        (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) {
   1324     //
   1325     // Try to add exclusive attrib in new info.
   1326     // Check whether there is another information with the same type in profile.
   1327     //
   1328     OldInfo = NULL;
   1329     do {
   1330       Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
   1331       if (EFI_ERROR (Status)) {
   1332         break;
   1333       }
   1334       if (OldInfo != *UserInfo) {
   1335         //
   1336         // There is another information with the same type in profile.
   1337         // Therefore, can't modify existing user information to add exclusive attribute.
   1338         //
   1339         return EFI_ACCESS_DENIED;
   1340       }
   1341     } while (TRUE);
   1342   }
   1343 
   1344   Status = DelUserInfo (User, *UserInfo, FALSE);
   1345   if (EFI_ERROR (Status)) {
   1346     return Status;
   1347   }
   1348 
   1349   return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
   1350 }
   1351 
   1352 
   1353 /**
   1354   Delete the user profile from non-volatile memory and database.
   1355 
   1356   @param[in]  User              Points to the user profile.
   1357 
   1358   @retval EFI_SUCCESS      Delete user from the user profile successfully.
   1359   @retval Others           Fail to delete user from user profile
   1360 
   1361 **/
   1362 EFI_STATUS
   1363 DelUserProfile (
   1364   IN  USER_PROFILE_ENTRY                        *User
   1365   )
   1366 {
   1367   EFI_STATUS          Status;
   1368   UINTN               Index;
   1369 
   1370   //
   1371   // Check whether it is in the user profile database.
   1372   //
   1373   Status = FindUserProfile (&User, FALSE, &Index);
   1374   if (EFI_ERROR (Status)) {
   1375     return EFI_INVALID_PARAMETER;
   1376   }
   1377 
   1378   //
   1379   // Check whether it is the current user.
   1380   //
   1381   if (User == mCurrentUser) {
   1382     return EFI_ACCESS_DENIED;
   1383   }
   1384 
   1385   //
   1386   // Delete user profile from the non-volatile memory.
   1387   //
   1388   Status    = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE);
   1389   if (EFI_ERROR (Status)) {
   1390     return Status;
   1391   }
   1392   mUserProfileDb->UserProfileNum--;
   1393 
   1394   //
   1395   // Modify user profile database.
   1396   //
   1397   if (Index != mUserProfileDb->UserProfileNum) {
   1398     mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum];
   1399     CopyMem (
   1400       ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName,
   1401       User->UserVarName,
   1402       sizeof (User->UserVarName)
   1403       );
   1404     Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE);
   1405     if (EFI_ERROR (Status)) {
   1406       return Status;
   1407     }
   1408   }
   1409   //
   1410   // Delete user profile information.
   1411   //
   1412   if (User->ProfileInfo != NULL) {
   1413     FreePool (User->ProfileInfo);
   1414   }
   1415 
   1416   FreePool (User);
   1417   return EFI_SUCCESS;
   1418 }
   1419 
   1420 
   1421 /**
   1422   Add user profile to user profile database.
   1423 
   1424   @param[out]   UserProfile   Point to the newly added user profile.
   1425   @param[in]    ProfileSize   The size of the user profile.
   1426   @param[in]    ProfileInfo   Point to the user profie data.
   1427   @param[in]    Save          If TRUE, save the new added profile to NV flash.
   1428                               If FALSE, don't save the profile to NV flash.
   1429 
   1430   @retval EFI_SUCCESS         Add user profile to user profile database successfully.
   1431   @retval Others              Fail to add user profile to user profile database.
   1432 
   1433 **/
   1434 EFI_STATUS
   1435 AddUserProfile (
   1436      OUT  USER_PROFILE_ENTRY                    **UserProfile, OPTIONAL
   1437   IN      UINTN                                 ProfileSize,
   1438   IN      UINT8                                 *ProfileInfo,
   1439   IN      BOOLEAN                               Save
   1440   )
   1441 {
   1442   EFI_STATUS              Status;
   1443   USER_PROFILE_ENTRY      *User;
   1444 
   1445   //
   1446   // Check the data format to be added.
   1447   //
   1448   if (!CheckProfileInfo (ProfileInfo, ProfileSize)) {
   1449     return EFI_SECURITY_VIOLATION;
   1450   }
   1451 
   1452   //
   1453   // Create user profile entry.
   1454   //
   1455   User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY));
   1456   if (User == NULL) {
   1457     return EFI_OUT_OF_RESOURCES;
   1458   }
   1459   //
   1460   // Add the entry to the user profile database.
   1461   //
   1462   if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) {
   1463     if (!ExpandUsermUserProfileDb ()) {
   1464       FreePool (User);
   1465       return EFI_OUT_OF_RESOURCES;
   1466     }
   1467   }
   1468 
   1469   UnicodeSPrint (
   1470     User->UserVarName,
   1471     sizeof (User->UserVarName),
   1472     L"User%04x",
   1473     mUserProfileDb->UserProfileNum
   1474     );
   1475   User->UserProfileSize = 0;
   1476   User->MaxProfileSize  = 0;
   1477   User->ProfileInfo     = NULL;
   1478   mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User;
   1479   mUserProfileDb->UserProfileNum++;
   1480 
   1481   //
   1482   // Add user profile information.
   1483   //
   1484   Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save);
   1485   if (EFI_ERROR (Status)) {
   1486     DelUserProfile (User);
   1487     return Status;
   1488   }
   1489   //
   1490   // Set new user profile handle.
   1491   //
   1492   if (UserProfile != NULL) {
   1493     *UserProfile = User;
   1494   }
   1495 
   1496   return EFI_SUCCESS;
   1497 }
   1498 
   1499 
   1500 /**
   1501   This function creates a new user profile with only a new user identifier
   1502   attached and returns its handle. The user profile is non-volatile, but the
   1503   handle User can change across reboots.
   1504 
   1505   @param[out]  User               Handle of a new user profile.
   1506 
   1507   @retval EFI_SUCCESS             User profile was successfully created.
   1508   @retval Others                  Fail to create user profile
   1509 
   1510 **/
   1511 EFI_STATUS
   1512 CreateUserProfile (
   1513   OUT USER_PROFILE_ENTRY                        **User
   1514   )
   1515 {
   1516   EFI_STATUS    Status;
   1517   EFI_USER_INFO *UserInfo;
   1518 
   1519   if (User == NULL) {
   1520     return EFI_INVALID_PARAMETER;
   1521   }
   1522   //
   1523   // Generate user id information.
   1524   //
   1525   UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
   1526   if (UserInfo == NULL) {
   1527     return EFI_OUT_OF_RESOURCES;
   1528   }
   1529 
   1530   UserInfo->InfoType    = EFI_USER_INFO_IDENTIFIER_RECORD;
   1531   UserInfo->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
   1532   UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1533   GenerateUserId ((UINT8 *) (UserInfo + 1));
   1534 
   1535   //
   1536   // Add user profile to the user profile database.
   1537   //
   1538   Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE);
   1539   FreePool (UserInfo);
   1540   return Status;
   1541 }
   1542 
   1543 
   1544 /**
   1545   Add a default user profile to user profile database.
   1546 
   1547   @retval EFI_SUCCESS             A default user profile is added successfully.
   1548   @retval Others                  Fail to add a default user profile
   1549 
   1550 **/
   1551 EFI_STATUS
   1552 AddDefaultUserProfile (
   1553   VOID
   1554   )
   1555 {
   1556   EFI_STATUS                    Status;
   1557   USER_PROFILE_ENTRY            *User;
   1558   EFI_USER_INFO                 *Info;
   1559   EFI_USER_INFO                 *NewInfo;
   1560   EFI_USER_INFO_CREATE_DATE     CreateDate;
   1561   EFI_USER_INFO_USAGE_COUNT     UsageCount;
   1562   EFI_USER_INFO_ACCESS_CONTROL  *Access;
   1563   EFI_USER_INFO_IDENTITY_POLICY *Policy;
   1564 
   1565   //
   1566   // Create a user profile.
   1567   //
   1568   Status = CreateUserProfile (&User);
   1569   if (EFI_ERROR (Status)) {
   1570     return Status;
   1571   }
   1572 
   1573   //
   1574   // Allocate a buffer to add all default user information.
   1575   //
   1576   Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE);
   1577   if (Info == NULL) {
   1578     return EFI_OUT_OF_RESOURCES;
   1579   }
   1580 
   1581   //
   1582   // Add user name.
   1583   //
   1584   Info->InfoType    = EFI_USER_INFO_NAME_RECORD;
   1585   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1586   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (mUserName);
   1587   CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName));
   1588   NewInfo = NULL;
   1589   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1590   if (EFI_ERROR (Status)) {
   1591     goto Done;
   1592   }
   1593 
   1594   //
   1595   // Add user profile create date record.
   1596   //
   1597   Info->InfoType    = EFI_USER_INFO_CREATE_DATE_RECORD;
   1598   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1599   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
   1600   Status            = gRT->GetTime (&CreateDate, NULL);
   1601   if (EFI_ERROR (Status)) {
   1602     goto Done;
   1603   }
   1604 
   1605   CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE));
   1606   NewInfo = NULL;
   1607   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1608   if (EFI_ERROR (Status)) {
   1609     goto Done;
   1610   }
   1611 
   1612   //
   1613   // Add user profile usage count record.
   1614   //
   1615   Info->InfoType    = EFI_USER_INFO_USAGE_COUNT_RECORD;
   1616   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1617   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
   1618   UsageCount        = 0;
   1619   CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
   1620   NewInfo = NULL;
   1621   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1622   if (EFI_ERROR (Status)) {
   1623     goto Done;
   1624   }
   1625 
   1626   //
   1627   // Add user access right.
   1628   //
   1629   Info->InfoType    = EFI_USER_INFO_ACCESS_POLICY_RECORD;
   1630   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1631   Access            = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1);
   1632   Access->Type      = EFI_USER_INFO_ACCESS_MANAGE;
   1633   Access->Size      = sizeof (EFI_USER_INFO_ACCESS_CONTROL);
   1634   Info->InfoSize    = sizeof (EFI_USER_INFO) + Access->Size;
   1635   NewInfo = NULL;
   1636   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1637   if (EFI_ERROR (Status)) {
   1638     goto Done;
   1639   }
   1640 
   1641   //
   1642   // Add user identity policy.
   1643   //
   1644   Info->InfoType    = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
   1645   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE;
   1646   Policy            = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1);
   1647   Policy->Type      = EFI_USER_INFO_IDENTITY_TRUE;
   1648   Policy->Length    = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
   1649   Info->InfoSize    = sizeof (EFI_USER_INFO) + Policy->Length;
   1650   NewInfo = NULL;
   1651   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1652 
   1653 Done:
   1654   FreePool (Info);
   1655   return Status;
   1656 }
   1657 
   1658 
   1659 /**
   1660   Publish current user information into EFI System Configuration Table.
   1661 
   1662   By UEFI spec, the User Identity Manager will publish the current user profile
   1663   into the EFI System Configuration Table. Currently, only the user identifier and user
   1664   name are published.
   1665 
   1666   @retval EFI_SUCCESS      Current user information is published successfully.
   1667   @retval Others           Fail to publish current user information
   1668 
   1669 **/
   1670 EFI_STATUS
   1671 PublishUserTable (
   1672   VOID
   1673   )
   1674 {
   1675   EFI_STATUS              Status;
   1676   EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
   1677   EFI_USER_INFO_TABLE     *UserInfoTable;
   1678   EFI_USER_INFO           *IdInfo;
   1679   EFI_USER_INFO           *NameInfo;
   1680 
   1681   Status = EfiGetSystemConfigurationTable (
   1682              &gEfiUserManagerProtocolGuid,
   1683              (VOID **) &EfiConfigurationTable
   1684              );
   1685   if (!EFI_ERROR (Status)) {
   1686     //
   1687     // The table existed!
   1688     //
   1689     return EFI_SUCCESS;
   1690   }
   1691 
   1692   //
   1693   // Get user ID information.
   1694   //
   1695   IdInfo  = NULL;
   1696   Status  = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
   1697   if (EFI_ERROR (Status)) {
   1698     return Status;
   1699 
   1700   }
   1701   //
   1702   // Get user name information.
   1703   //
   1704   NameInfo  = NULL;
   1705   Status    = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD);
   1706   if (EFI_ERROR (Status)) {
   1707     return Status;
   1708   }
   1709 
   1710   //
   1711   // Allocate a buffer for user information table.
   1712   //
   1713   UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool (
   1714                                             sizeof (EFI_USER_INFO_TABLE) +
   1715                                             IdInfo->InfoSize +
   1716                                             NameInfo->InfoSize
   1717                                             );
   1718   if (UserInfoTable == NULL) {
   1719     Status = EFI_OUT_OF_RESOURCES;
   1720     return Status;
   1721   }
   1722 
   1723   UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE);
   1724 
   1725   //
   1726   // Append the user information to the user info table
   1727   //
   1728   CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize);
   1729   UserInfoTable->Size += IdInfo->InfoSize;
   1730 
   1731   CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize);
   1732   UserInfoTable->Size += NameInfo->InfoSize;
   1733 
   1734   Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable);
   1735   return Status;
   1736 }
   1737 
   1738 
   1739 /**
   1740   Get the user's identity type.
   1741 
   1742   The identify manager only supports the identity policy in which the credential
   1743   provider handles are connected by the operator 'AND' or 'OR'.
   1744 
   1745 
   1746   @param[in]   User              Handle of a user profile.
   1747   @param[out]  PolicyType        Point to the identity type.
   1748 
   1749   @retval EFI_SUCCESS            Get user's identity type successfully.
   1750   @retval Others                 Fail to get user's identity type.
   1751 
   1752 **/
   1753 EFI_STATUS
   1754 GetIdentifyType (
   1755   IN      EFI_USER_PROFILE_HANDLE               User,
   1756      OUT  UINT8                                 *PolicyType
   1757   )
   1758 {
   1759   EFI_STATUS                    Status;
   1760   EFI_USER_INFO                 *IdentifyInfo;
   1761   UINTN                         TotalLen;
   1762   EFI_USER_INFO_IDENTITY_POLICY *Identity;
   1763 
   1764   //
   1765   // Get user identify policy information.
   1766   //
   1767   IdentifyInfo  = NULL;
   1768   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
   1769   if (EFI_ERROR (Status)) {
   1770     return Status;
   1771   }
   1772   ASSERT (IdentifyInfo != NULL);
   1773 
   1774   //
   1775   // Search the user identify policy according to type.
   1776   //
   1777   TotalLen    = 0;
   1778   *PolicyType = EFI_USER_INFO_IDENTITY_FALSE;
   1779   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
   1780     Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
   1781     if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) {
   1782       *PolicyType = EFI_USER_INFO_IDENTITY_AND;
   1783       break;
   1784     }
   1785 
   1786     if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) {
   1787       *PolicyType = EFI_USER_INFO_IDENTITY_OR;
   1788       break;
   1789     }
   1790     TotalLen += Identity->Length;
   1791   }
   1792   return EFI_SUCCESS;
   1793 }
   1794 
   1795 
   1796 /**
   1797   Identify the User by the specfied provider.
   1798 
   1799   @param[in]  User                Handle of a user profile.
   1800   @param[in]  Provider            Points to the identifier of credential provider.
   1801 
   1802   @retval EFI_INVALID_PARAMETER   Provider is NULL.
   1803   @retval EFI_NOT_FOUND           Fail to identify the specified user.
   1804   @retval EFI_SUCCESS             User is identified successfully.
   1805 
   1806 **/
   1807 EFI_STATUS
   1808 IdentifyByProviderId (
   1809   IN  EFI_USER_PROFILE_HANDLE                   User,
   1810   IN  EFI_GUID                                  *Provider
   1811   )
   1812 {
   1813   EFI_STATUS                    Status;
   1814   EFI_USER_INFO_IDENTIFIER      UserId;
   1815   UINTN                         Index;
   1816   EFI_CREDENTIAL_LOGON_FLAGS    AutoLogon;
   1817   EFI_HII_HANDLE                HiiHandle;
   1818   EFI_GUID                      FormSetId;
   1819   EFI_FORM_ID                   FormId;
   1820   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
   1821 
   1822   if (Provider == NULL) {
   1823     return EFI_INVALID_PARAMETER;
   1824   }
   1825 
   1826   //
   1827   // Check the user ID identified by the specified credential provider.
   1828   //
   1829   for (Index = 0; Index < mProviderDb->Count; Index++) {
   1830     //
   1831     // Check credential provider class.
   1832     //
   1833     UserCredential = mProviderDb->Provider[Index];
   1834     if (CompareGuid (&UserCredential->Identifier, Provider)) {
   1835       Status = UserCredential->Select (UserCredential, &AutoLogon);
   1836       if (EFI_ERROR (Status)) {
   1837         return Status;
   1838       }
   1839 
   1840       if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) {
   1841         //
   1842         // Get credential provider form.
   1843         //
   1844         Status = UserCredential->Form (
   1845                                    UserCredential,
   1846                                    &HiiHandle,
   1847                                    &FormSetId,
   1848                                    &FormId
   1849                                    );
   1850         if (!EFI_ERROR (Status)) {
   1851           //
   1852           // Send form to get user input.
   1853           //
   1854           Status = mCallbackInfo->FormBrowser2->SendForm (
   1855                                                   mCallbackInfo->FormBrowser2,
   1856                                                   &HiiHandle,
   1857                                                   1,
   1858                                                   &FormSetId,
   1859                                                   FormId,
   1860                                                   NULL,
   1861                                                   NULL
   1862                                                   );
   1863           if (EFI_ERROR (Status)) {
   1864             return Status;
   1865           }
   1866         }
   1867       }
   1868 
   1869       Status = UserCredential->User (UserCredential, User, &UserId);
   1870       if (EFI_ERROR (Status)) {
   1871         return Status;
   1872       }
   1873 
   1874       Status = UserCredential->Deselect (UserCredential);
   1875       if (EFI_ERROR (Status)) {
   1876         return Status;
   1877       }
   1878 
   1879       return EFI_SUCCESS;
   1880     }
   1881   }
   1882 
   1883   return EFI_NOT_FOUND;
   1884 }
   1885 
   1886 
   1887 /**
   1888   Update user information when user is logon on successfully.
   1889 
   1890   @param[in]  User         Points to user profile.
   1891 
   1892   @retval EFI_SUCCESS      Update user information successfully.
   1893   @retval Others           Fail to update user information.
   1894 
   1895 **/
   1896 EFI_STATUS
   1897 UpdateUserInfo (
   1898   IN  USER_PROFILE_ENTRY                        *User
   1899   )
   1900 {
   1901   EFI_STATUS                Status;
   1902   EFI_USER_INFO             *Info;
   1903   EFI_USER_INFO             *NewInfo;
   1904   EFI_USER_INFO_CREATE_DATE Date;
   1905   EFI_USER_INFO_USAGE_COUNT UsageCount;
   1906   UINTN                     InfoLen;
   1907 
   1908   //
   1909   // Allocate a buffer to update user's date record and usage record.
   1910   //
   1911   InfoLen  = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT));
   1912   Info     = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen);
   1913   if (Info == NULL) {
   1914     return EFI_OUT_OF_RESOURCES;
   1915   }
   1916 
   1917   //
   1918   // Check create date record.
   1919   //
   1920   NewInfo = NULL;
   1921   Status  = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD);
   1922   if (Status == EFI_NOT_FOUND) {
   1923     Info->InfoType    = EFI_USER_INFO_CREATE_DATE_RECORD;
   1924     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1925     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
   1926     Status            = gRT->GetTime (&Date, NULL);
   1927     if (EFI_ERROR (Status)) {
   1928       FreePool (Info);
   1929       return Status;
   1930     }
   1931 
   1932     CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));
   1933     NewInfo = NULL;
   1934     Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1935     if (EFI_ERROR (Status)) {
   1936       FreePool (Info);
   1937       return Status;
   1938     }
   1939   }
   1940 
   1941   //
   1942   // Update usage date record.
   1943   //
   1944   NewInfo = NULL;
   1945   Status  = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD);
   1946   if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
   1947     Info->InfoType    = EFI_USER_INFO_USAGE_DATE_RECORD;
   1948     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1949     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE);
   1950     Status            = gRT->GetTime (&Date, NULL);
   1951     if (EFI_ERROR (Status)) {
   1952       FreePool (Info);
   1953       return Status;
   1954     }
   1955 
   1956     CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE));
   1957     Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1958     if (EFI_ERROR (Status)) {
   1959       FreePool (Info);
   1960       return Status;
   1961     }
   1962   }
   1963 
   1964   //
   1965   // Update usage count record.
   1966   //
   1967   UsageCount  = 0;
   1968   NewInfo     = NULL;
   1969   Status      = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD);
   1970   //
   1971   // Get usage count.
   1972   //
   1973   if (Status == EFI_SUCCESS) {
   1974     CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT));
   1975   }
   1976 
   1977   UsageCount++;
   1978   if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
   1979     Info->InfoType    = EFI_USER_INFO_USAGE_COUNT_RECORD;
   1980     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
   1981     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
   1982     CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
   1983     Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
   1984     if (EFI_ERROR (Status)) {
   1985       FreePool (Info);
   1986       return Status;
   1987     }
   1988   }
   1989 
   1990   FreePool (Info);
   1991   return EFI_SUCCESS;
   1992 }
   1993 
   1994 
   1995 /**
   1996   Add a credenetial provider item in form.
   1997 
   1998   @param[in]  ProviderGuid        Points to the identifir of credential provider.
   1999   @param[in]  OpCodeHandle        Points to container for dynamic created opcodes.
   2000 
   2001 **/
   2002 VOID
   2003 AddProviderSelection (
   2004   IN     EFI_GUID                               *ProviderGuid,
   2005   IN     VOID                                   *OpCodeHandle
   2006   )
   2007 {
   2008   EFI_HII_HANDLE                HiiHandle;
   2009   EFI_STRING_ID                 ProvID;
   2010   CHAR16                        *ProvStr;
   2011   UINTN                         Index;
   2012   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
   2013 
   2014   for (Index = 0; Index < mProviderDb->Count; Index++) {
   2015     UserCredential = mProviderDb->Provider[Index];
   2016     if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) {
   2017       //
   2018       // Add credential provider selection.
   2019       //
   2020       UserCredential->Title (UserCredential, &HiiHandle, &ProvID);
   2021       ProvStr = HiiGetString (HiiHandle, ProvID, NULL);
   2022       if (ProvStr == NULL) {
   2023         continue ;
   2024       }
   2025       ProvID  = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);
   2026       FreePool (ProvStr);
   2027       HiiCreateActionOpCode (
   2028         OpCodeHandle,                          // Container for dynamic created opcodes
   2029         (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index),  // Question ID
   2030         ProvID,                                // Prompt text
   2031         STRING_TOKEN (STR_NULL_STRING),        // Help text
   2032         EFI_IFR_FLAG_CALLBACK,                 // Question flag
   2033         0                                      // Action String ID
   2034         );
   2035       break;
   2036     }
   2037   }
   2038 }
   2039 
   2040 
   2041 /**
   2042   Add a username item in form.
   2043 
   2044   @param[in]  Index            The index of the user in the user name list.
   2045   @param[in]  User             Points to the user profile whose username is added.
   2046   @param[in]  OpCodeHandle     Points to container for dynamic created opcodes.
   2047 
   2048   @retval EFI_SUCCESS          Add a username successfully.
   2049   @retval Others               Fail to add a username.
   2050 
   2051 **/
   2052 EFI_STATUS
   2053 AddUserSelection (
   2054   IN     UINT16                                 Index,
   2055   IN     USER_PROFILE_ENTRY                     *User,
   2056   IN     VOID                                   *OpCodeHandle
   2057   )
   2058 {
   2059   EFI_STRING_ID UserName;
   2060   EFI_STATUS    Status;
   2061   EFI_USER_INFO *UserInfo;
   2062 
   2063   UserInfo  = NULL;
   2064   Status    = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD);
   2065   if (EFI_ERROR (Status)) {
   2066     return Status;
   2067   }
   2068 
   2069   //
   2070   // Add user name selection.
   2071   //
   2072   UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL);
   2073   if (UserName == 0) {
   2074     return EFI_OUT_OF_RESOURCES;
   2075   }
   2076 
   2077   HiiCreateGotoOpCode (
   2078     OpCodeHandle,                   // Container for dynamic created opcodes
   2079     FORMID_PROVIDER_FORM,           // Target Form ID
   2080     UserName,                       // Prompt text
   2081     STRING_TOKEN (STR_NULL_STRING), // Help text
   2082     EFI_IFR_FLAG_CALLBACK,          // Question flag
   2083     (UINT16) Index                  // Question ID
   2084     );
   2085 
   2086   return EFI_SUCCESS;
   2087 }
   2088 
   2089 
   2090 /**
   2091   Identify the user whose identity policy does not contain the operator 'OR'.
   2092 
   2093   @param[in]  User             Points to the user profile.
   2094 
   2095   @retval EFI_SUCCESS          The specified user is identified successfully.
   2096   @retval Others               Fail to identify the user.
   2097 
   2098 **/
   2099 EFI_STATUS
   2100 IdentifyAndTypeUser (
   2101   IN  USER_PROFILE_ENTRY                        *User
   2102   )
   2103 {
   2104   EFI_STATUS                    Status;
   2105   EFI_USER_INFO                 *IdentifyInfo;
   2106   BOOLEAN                       Success;
   2107   UINTN                         TotalLen;
   2108   UINTN                         ValueLen;
   2109   EFI_USER_INFO_IDENTITY_POLICY *Identity;
   2110 
   2111   //
   2112   // Get user identify policy information.
   2113   //
   2114   IdentifyInfo  = NULL;
   2115   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
   2116   if (EFI_ERROR (Status)) {
   2117     return Status;
   2118   }
   2119   ASSERT (IdentifyInfo != NULL);
   2120 
   2121   //
   2122   // Check each part of identification policy expression.
   2123   //
   2124   Success   = FALSE;
   2125   TotalLen  = 0;
   2126   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
   2127     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
   2128     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
   2129     switch (Identity->Type) {
   2130 
   2131     case EFI_USER_INFO_IDENTITY_FALSE:
   2132       //
   2133       // Check False option.
   2134       //
   2135       Success = FALSE;
   2136       break;
   2137 
   2138     case EFI_USER_INFO_IDENTITY_TRUE:
   2139       //
   2140       // Check True option.
   2141       //
   2142       Success = TRUE;
   2143       break;
   2144 
   2145     case EFI_USER_INFO_IDENTITY_NOT:
   2146       //
   2147       // Check negative operation.
   2148       //
   2149       break;
   2150 
   2151     case EFI_USER_INFO_IDENTITY_AND:
   2152       //
   2153       // Check and operation.
   2154       //
   2155       if (!Success) {
   2156         return EFI_NOT_READY;
   2157       }
   2158 
   2159       Success = FALSE;
   2160       break;
   2161 
   2162     case EFI_USER_INFO_IDENTITY_OR:
   2163       //
   2164       // Check or operation.
   2165       //
   2166       if (Success) {
   2167         return EFI_SUCCESS;
   2168       }
   2169       break;
   2170 
   2171     case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
   2172       //
   2173       // Check credential provider by type.
   2174       //
   2175       break;
   2176 
   2177     case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
   2178       //
   2179       // Check credential provider by ID.
   2180       //
   2181       if (ValueLen != sizeof (EFI_GUID)) {
   2182         return EFI_INVALID_PARAMETER;
   2183       }
   2184 
   2185       Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1));
   2186       if (EFI_ERROR (Status)) {
   2187         return Status;
   2188       }
   2189 
   2190       Success = TRUE;
   2191       break;
   2192 
   2193     default:
   2194       return EFI_INVALID_PARAMETER;
   2195       break;
   2196     }
   2197 
   2198     TotalLen += Identity->Length;
   2199   }
   2200 
   2201   if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
   2202     return EFI_INVALID_PARAMETER;
   2203   }
   2204 
   2205   if (!Success) {
   2206     return EFI_NOT_READY;
   2207   }
   2208 
   2209   return EFI_SUCCESS;
   2210 }
   2211 
   2212 
   2213 /**
   2214   Identify the user whose identity policy does not contain the operator 'AND'.
   2215 
   2216   @param[in]  User             Points to the user profile.
   2217 
   2218   @retval EFI_SUCCESS          The specified user is identified successfully.
   2219   @retval Others               Fail to identify the user.
   2220 
   2221 **/
   2222 EFI_STATUS
   2223 IdentifyOrTypeUser (
   2224   IN  USER_PROFILE_ENTRY                        *User
   2225   )
   2226 {
   2227   EFI_STATUS                    Status;
   2228   EFI_USER_INFO                 *IdentifyInfo;
   2229   UINTN                         TotalLen;
   2230   UINTN                         ValueLen;
   2231   EFI_USER_INFO_IDENTITY_POLICY *Identity;
   2232   VOID                          *StartOpCodeHandle;
   2233   VOID                          *EndOpCodeHandle;
   2234   EFI_IFR_GUID_LABEL            *StartLabel;
   2235   EFI_IFR_GUID_LABEL            *EndLabel;
   2236 
   2237   //
   2238   // Get user identify policy information.
   2239   //
   2240   IdentifyInfo  = NULL;
   2241   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
   2242   if (EFI_ERROR (Status)) {
   2243     return Status;
   2244   }
   2245   ASSERT (IdentifyInfo != NULL);
   2246 
   2247   //
   2248   // Initialize the container for dynamic opcodes.
   2249   //
   2250   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   2251   ASSERT (StartOpCodeHandle != NULL);
   2252 
   2253   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
   2254   ASSERT (EndOpCodeHandle != NULL);
   2255 
   2256   //
   2257   // Create Hii Extend Label OpCode.
   2258   //
   2259   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2260                                         StartOpCodeHandle,
   2261                                         &gEfiIfrTianoGuid,
   2262                                         NULL,
   2263                                         sizeof (EFI_IFR_GUID_LABEL)
   2264                                         );
   2265   StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2266   StartLabel->Number        = LABEL_PROVIDER_NAME;
   2267 
   2268   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2269                                       EndOpCodeHandle,
   2270                                       &gEfiIfrTianoGuid,
   2271                                       NULL,
   2272                                       sizeof (EFI_IFR_GUID_LABEL)
   2273                                       );
   2274   EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2275   EndLabel->Number        = LABEL_END;
   2276 
   2277   //
   2278   // Add the providers that exists in the user's policy.
   2279   //
   2280   TotalLen = 0;
   2281   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
   2282     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
   2283     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
   2284     if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
   2285       AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle);
   2286     }
   2287 
   2288     TotalLen += Identity->Length;
   2289   }
   2290 
   2291   HiiUpdateForm (
   2292     mCallbackInfo->HiiHandle, // HII handle
   2293     &gUserIdentifyManagerGuid,// Formset GUID
   2294     FORMID_PROVIDER_FORM,     // Form ID
   2295     StartOpCodeHandle,        // Label for where to insert opcodes
   2296     EndOpCodeHandle           // Replace data
   2297     );
   2298 
   2299   HiiFreeOpCodeHandle (StartOpCodeHandle);
   2300   HiiFreeOpCodeHandle (EndOpCodeHandle);
   2301 
   2302   return EFI_SUCCESS;
   2303 }
   2304 
   2305 
   2306 /**
   2307   This function processes the results of changes in configuration.
   2308 
   2309   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   2310   @param  Action                 Specifies the type of action taken by the browser.
   2311   @param  QuestionId             A unique value which is sent to the original
   2312                                  exporting driver so that it can identify the type
   2313                                  of data to expect.
   2314   @param  Type                   The type of value for the question.
   2315   @param  Value                  A pointer to the data being sent to the original
   2316                                  exporting driver.
   2317   @param  ActionRequest          On return, points to the action requested by the
   2318                                  callback function.
   2319 
   2320   @retval EFI_SUCCESS            The callback successfully handled the action.
   2321   @retval Others                 Fail to handle the action.
   2322 
   2323 **/
   2324 EFI_STATUS
   2325 EFIAPI
   2326 UserIdentifyManagerCallback (
   2327   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
   2328   IN  EFI_BROWSER_ACTION                        Action,
   2329   IN  EFI_QUESTION_ID                           QuestionId,
   2330   IN  UINT8                                     Type,
   2331   IN  EFI_IFR_TYPE_VALUE                        *Value,
   2332   OUT EFI_BROWSER_ACTION_REQUEST                *ActionRequest
   2333   )
   2334 {
   2335   EFI_STATUS              Status;
   2336   USER_PROFILE_ENTRY      *User;
   2337   UINT8                   PolicyType;
   2338   UINT16                  Index;
   2339   VOID                    *StartOpCodeHandle;
   2340   VOID                    *EndOpCodeHandle;
   2341   EFI_IFR_GUID_LABEL      *StartLabel;
   2342   EFI_IFR_GUID_LABEL      *EndLabel;
   2343 
   2344   Status = EFI_SUCCESS;
   2345 
   2346   switch (Action) {
   2347   case EFI_BROWSER_ACTION_FORM_OPEN:
   2348     {
   2349       //
   2350       // Update user Form when user Form is opened.
   2351       // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form.
   2352       //
   2353       if (QuestionId != FORM_OPEN_QUESTION_ID) {
   2354         return EFI_SUCCESS;
   2355       }
   2356 
   2357       //
   2358       // Initialize the container for dynamic opcodes.
   2359       //
   2360       StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   2361       ASSERT (StartOpCodeHandle != NULL);
   2362 
   2363       EndOpCodeHandle = HiiAllocateOpCodeHandle ();
   2364       ASSERT (EndOpCodeHandle != NULL);
   2365 
   2366       //
   2367       // Create Hii Extend Label OpCode.
   2368       //
   2369       StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2370                                             StartOpCodeHandle,
   2371                                             &gEfiIfrTianoGuid,
   2372                                             NULL,
   2373                                             sizeof (EFI_IFR_GUID_LABEL)
   2374                                             );
   2375       StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2376       StartLabel->Number        = LABEL_USER_NAME;
   2377 
   2378       EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2379                                           EndOpCodeHandle,
   2380                                           &gEfiIfrTianoGuid,
   2381                                           NULL,
   2382                                           sizeof (EFI_IFR_GUID_LABEL)
   2383                                           );
   2384       EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2385       EndLabel->Number        = LABEL_END;
   2386 
   2387       //
   2388       // Add all the user profile in the user profile database.
   2389       //
   2390       for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
   2391         User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index];
   2392         AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle);
   2393       }
   2394 
   2395       HiiUpdateForm (
   2396         mCallbackInfo->HiiHandle, // HII handle
   2397         &gUserIdentifyManagerGuid,// Formset GUID
   2398         FORMID_USER_FORM,         // Form ID
   2399         StartOpCodeHandle,        // Label for where to insert opcodes
   2400         EndOpCodeHandle           // Replace data
   2401         );
   2402 
   2403       HiiFreeOpCodeHandle (StartOpCodeHandle);
   2404       HiiFreeOpCodeHandle (EndOpCodeHandle);
   2405 
   2406       return EFI_SUCCESS;
   2407     }
   2408     break;
   2409 
   2410   case EFI_BROWSER_ACTION_FORM_CLOSE:
   2411     Status = EFI_SUCCESS;
   2412     break;
   2413 
   2414   case EFI_BROWSER_ACTION_CHANGED:
   2415     if (QuestionId >= LABEL_PROVIDER_NAME) {
   2416       //
   2417       // QuestionId comes from the second Form (Select a Credential Provider if identity
   2418       // policy is OR type). Identify the user by the selected provider.
   2419       //
   2420       Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier);
   2421       if (Status == EFI_SUCCESS) {
   2422         mIdentified     = TRUE;
   2423         *ActionRequest  = EFI_BROWSER_ACTION_REQUEST_EXIT;
   2424       }
   2425       return EFI_SUCCESS;
   2426     }
   2427     break;
   2428 
   2429   case EFI_BROWSER_ACTION_CHANGING:
   2430     //
   2431     // QuestionId comes from the first Form (Select a user to identify).
   2432     //
   2433     if (QuestionId >= LABEL_PROVIDER_NAME) {
   2434       return EFI_SUCCESS;
   2435     }
   2436 
   2437     User   = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF];
   2438     Status = GetIdentifyType (User, &PolicyType);
   2439     if (EFI_ERROR (Status)) {
   2440       return Status;
   2441     }
   2442 
   2443     if (PolicyType == EFI_USER_INFO_IDENTITY_OR) {
   2444       //
   2445       // Identify the user by "OR" logical.
   2446       //
   2447       Status = IdentifyOrTypeUser (User);
   2448       if (EFI_ERROR (Status)) {
   2449         return Status;
   2450       }
   2451 
   2452       mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
   2453     } else {
   2454       //
   2455       // Identify the user by "AND" logical.
   2456       //
   2457       Status = IdentifyAndTypeUser (User);
   2458       if (EFI_ERROR (Status)) {
   2459         return Status;
   2460       }
   2461 
   2462       mCurrentUser    = (EFI_USER_PROFILE_HANDLE) User;
   2463       mIdentified     = TRUE;
   2464       if (Type == EFI_IFR_TYPE_REF) {
   2465         Value->ref.FormId = FORMID_INVALID_FORM;
   2466       }
   2467     }
   2468   break;
   2469 
   2470   default:
   2471     //
   2472     // All other action return unsupported.
   2473     //
   2474     Status = EFI_UNSUPPORTED;
   2475     break;
   2476   }
   2477 
   2478 
   2479   return Status;
   2480 }
   2481 
   2482 
   2483 /**
   2484   This function construct user profile database from user data saved in the Flash.
   2485   If no user is found in Flash, add one default user "administrator" in the user
   2486   profile database.
   2487 
   2488   @retval EFI_SUCCESS            Init user profile database successfully.
   2489   @retval Others                 Fail to init user profile database.
   2490 
   2491 **/
   2492 EFI_STATUS
   2493 InitUserProfileDb (
   2494   VOID
   2495   )
   2496 {
   2497   EFI_STATUS  Status;
   2498   UINT8       *VarData;
   2499   UINTN       VarSize;
   2500   UINTN       CurVarSize;
   2501   CHAR16      VarName[10];
   2502   UINTN       Index;
   2503   UINT32      VarAttr;
   2504 
   2505   if (mUserProfileDb != NULL) {
   2506     //
   2507     // The user profiles had been already initialized.
   2508     //
   2509     return EFI_SUCCESS;
   2510   }
   2511 
   2512   //
   2513   // Init user profile database structure.
   2514   //
   2515   if (!ExpandUsermUserProfileDb ()) {
   2516     return EFI_OUT_OF_RESOURCES;
   2517   }
   2518 
   2519   CurVarSize = DEFAULT_PROFILE_SIZE;
   2520   VarData    = AllocateZeroPool (CurVarSize);
   2521   if (VarData == NULL) {
   2522     return EFI_OUT_OF_RESOURCES;
   2523   }
   2524 
   2525   //
   2526   // Get all user proifle entries.
   2527   //
   2528   Index = 0;
   2529   while (TRUE) {
   2530     //
   2531     // Get variable name.
   2532     //
   2533     UnicodeSPrint (
   2534       VarName,
   2535       sizeof (VarName),
   2536       L"User%04x",
   2537       Index
   2538       );
   2539     Index++;
   2540 
   2541     //
   2542     // Get variable value.
   2543     //
   2544     VarSize = CurVarSize;
   2545     Status  = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
   2546     if (Status == EFI_BUFFER_TOO_SMALL) {
   2547       FreePool (VarData);
   2548       VarData = AllocatePool (VarSize);
   2549       if (VarData == NULL) {
   2550         Status = EFI_OUT_OF_RESOURCES;
   2551         break;
   2552       }
   2553 
   2554       CurVarSize  = VarSize;
   2555       Status      = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
   2556     }
   2557 
   2558     if (EFI_ERROR (Status)) {
   2559       if (Status == EFI_NOT_FOUND) {
   2560         Status = EFI_SUCCESS;
   2561       }
   2562       break;
   2563     }
   2564 
   2565     //
   2566     // Check variable attributes.
   2567     //
   2568     if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
   2569       Status = gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
   2570       continue;
   2571     }
   2572 
   2573     //
   2574     // Add user profile to the user profile database.
   2575     //
   2576     Status = AddUserProfile (NULL, VarSize, VarData, FALSE);
   2577     if (EFI_ERROR (Status)) {
   2578       if (Status == EFI_SECURITY_VIOLATION) {
   2579         //
   2580         // Delete invalid user profile
   2581         //
   2582         gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
   2583       } else if (Status == EFI_OUT_OF_RESOURCES) {
   2584         break;
   2585       }
   2586     } else {
   2587       //
   2588       // Delete and save the profile again if some invalid profiles are deleted.
   2589       //
   2590       if (mUserProfileDb->UserProfileNum < Index) {
   2591         gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
   2592         SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE);
   2593       }
   2594     }
   2595   }
   2596 
   2597   if (VarData != NULL) {
   2598     FreePool (VarData);
   2599   }
   2600 
   2601   if (EFI_ERROR (Status)) {
   2602     return Status;
   2603   }
   2604 
   2605   //
   2606   // Check whether the user profile database is empty.
   2607   //
   2608   if (mUserProfileDb->UserProfileNum == 0) {
   2609     Status = AddDefaultUserProfile ();
   2610   }
   2611 
   2612   return Status;
   2613 }
   2614 
   2615 
   2616 /**
   2617   This function collects all the credential providers and saves to mProviderDb.
   2618 
   2619   @retval EFI_SUCCESS            Collect credential providers successfully.
   2620   @retval Others                 Fail to collect credential providers.
   2621 
   2622 **/
   2623 EFI_STATUS
   2624 InitProviderInfo (
   2625   VOID
   2626   )
   2627 {
   2628   EFI_STATUS  Status;
   2629   UINTN       HandleCount;
   2630   EFI_HANDLE  *HandleBuf;
   2631   UINTN       Index;
   2632 
   2633   if (mProviderDb != NULL) {
   2634     //
   2635     // The credential providers had been collected before.
   2636     //
   2637     return EFI_SUCCESS;
   2638   }
   2639 
   2640   //
   2641   // Try to find all the user credential provider driver.
   2642   //
   2643   HandleCount = 0;
   2644   HandleBuf   = NULL;
   2645   Status = gBS->LocateHandleBuffer (
   2646                   ByProtocol,
   2647                   &gEfiUserCredential2ProtocolGuid,
   2648                   NULL,
   2649                   &HandleCount,
   2650                   &HandleBuf
   2651                   );
   2652   if (EFI_ERROR (Status)) {
   2653     return Status;
   2654   }
   2655 
   2656   //
   2657   // Get provider infomation.
   2658   //
   2659   mProviderDb = AllocateZeroPool (
   2660                   sizeof (CREDENTIAL_PROVIDER_INFO) -
   2661                   sizeof (EFI_USER_CREDENTIAL2_PROTOCOL *) +
   2662                   HandleCount * sizeof (EFI_USER_CREDENTIAL2_PROTOCOL *)
   2663                   );
   2664   if (mProviderDb == NULL) {
   2665     FreePool (HandleBuf);
   2666     return EFI_OUT_OF_RESOURCES;
   2667   }
   2668 
   2669  mProviderDb->Count = HandleCount;
   2670   for (Index = 0; Index < HandleCount; Index++) {
   2671     Status = gBS->HandleProtocol (
   2672                     HandleBuf[Index],
   2673                     &gEfiUserCredential2ProtocolGuid,
   2674                     (VOID **) &mProviderDb->Provider[Index]
   2675                     );
   2676     if (EFI_ERROR (Status)) {
   2677       FreePool (HandleBuf);
   2678       FreePool (mProviderDb);
   2679       mProviderDb = NULL;
   2680       return Status;
   2681     }
   2682   }
   2683 
   2684   FreePool (HandleBuf);
   2685   return EFI_SUCCESS;
   2686 }
   2687 
   2688 
   2689 /**
   2690   This function allows a caller to extract the current configuration for one
   2691   or more named elements from the target driver.
   2692 
   2693 
   2694   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   2695   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
   2696   @param Progress        On return, points to a character in the Request string.
   2697                          Points to the string's null terminator if request was successful.
   2698                          Points to the most recent '&' before the first failing name/value
   2699                          pair (or the beginning of the string if the failure is in the
   2700                          first name/value pair) if the request was not successful.
   2701   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
   2702                          has all values filled in for the names in the Request string.
   2703                          String to be allocated by the called function.
   2704 
   2705   @retval  EFI_SUCCESS            The Results is filled with the requested values.
   2706   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
   2707   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
   2708   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
   2709 
   2710 **/
   2711 EFI_STATUS
   2712 EFIAPI
   2713 FakeExtractConfig (
   2714   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
   2715   IN  CONST EFI_STRING                       Request,
   2716   OUT EFI_STRING                             *Progress,
   2717   OUT EFI_STRING                             *Results
   2718   )
   2719 {
   2720   if (Progress == NULL || Results == NULL) {
   2721     return EFI_INVALID_PARAMETER;
   2722   }
   2723   *Progress = Request;
   2724   return EFI_NOT_FOUND;
   2725 }
   2726 
   2727 /**
   2728   This function processes the results of changes in configuration.
   2729 
   2730 
   2731   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   2732   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
   2733   @param Progress        A pointer to a string filled in with the offset of the most
   2734                          recent '&' before the first failing name/value pair (or the
   2735                          beginning of the string if the failure is in the first
   2736                          name/value pair) or the terminating NULL if all was successful.
   2737 
   2738   @retval  EFI_SUCCESS            The Results is processed successfully.
   2739   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
   2740   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
   2741 
   2742 **/
   2743 EFI_STATUS
   2744 EFIAPI
   2745 FakeRouteConfig (
   2746   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
   2747   IN  CONST EFI_STRING                       Configuration,
   2748   OUT EFI_STRING                             *Progress
   2749   )
   2750 {
   2751   if (Configuration == NULL || Progress == NULL) {
   2752     return EFI_INVALID_PARAMETER;
   2753   }
   2754 
   2755   return EFI_NOT_FOUND;
   2756 }
   2757 
   2758 
   2759 /**
   2760   This function initialize the data mainly used in form browser.
   2761 
   2762   @retval EFI_SUCCESS          Initialize form data successfully.
   2763   @retval Others               Fail to Initialize form data.
   2764 
   2765 **/
   2766 EFI_STATUS
   2767 InitFormBrowser (
   2768   VOID
   2769   )
   2770 {
   2771   EFI_STATUS                  Status;
   2772   USER_MANAGER_CALLBACK_INFO  *CallbackInfo;
   2773   EFI_HII_DATABASE_PROTOCOL   *HiiDatabase;
   2774   EFI_HII_STRING_PROTOCOL     *HiiString;
   2775   EFI_FORM_BROWSER2_PROTOCOL  *FormBrowser2;
   2776 
   2777   //
   2778   // Initialize driver private data.
   2779   //
   2780   CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO));
   2781   if (CallbackInfo == NULL) {
   2782     return EFI_OUT_OF_RESOURCES;
   2783   }
   2784 
   2785   CallbackInfo->Signature                   = USER_MANAGER_SIGNATURE;
   2786   CallbackInfo->ConfigAccess.ExtractConfig  = FakeExtractConfig;
   2787   CallbackInfo->ConfigAccess.RouteConfig    = FakeRouteConfig;
   2788   CallbackInfo->ConfigAccess.Callback       = UserIdentifyManagerCallback;
   2789 
   2790   //
   2791   // Locate Hii Database protocol.
   2792   //
   2793   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
   2794   if (EFI_ERROR (Status)) {
   2795     return Status;
   2796   }
   2797   CallbackInfo->HiiDatabase = HiiDatabase;
   2798 
   2799   //
   2800   // Locate HiiString protocol.
   2801   //
   2802   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
   2803   if (EFI_ERROR (Status)) {
   2804     return Status;
   2805   }
   2806   CallbackInfo->HiiString = HiiString;
   2807 
   2808   //
   2809   // Locate Formbrowser2 protocol.
   2810   //
   2811   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
   2812   if (EFI_ERROR (Status)) {
   2813     return Status;
   2814   }
   2815 
   2816   CallbackInfo->FormBrowser2  = FormBrowser2;
   2817   CallbackInfo->DriverHandle  = NULL;
   2818 
   2819   //
   2820   // Install Device Path Protocol and Config Access protocol to driver handle.
   2821   //
   2822   Status = gBS->InstallMultipleProtocolInterfaces (
   2823                   &CallbackInfo->DriverHandle,
   2824                   &gEfiDevicePathProtocolGuid,
   2825                   &mHiiVendorDevicePath,
   2826                   &gEfiHiiConfigAccessProtocolGuid,
   2827                   &CallbackInfo->ConfigAccess,
   2828                   NULL
   2829                   );
   2830   ASSERT_EFI_ERROR (Status);
   2831 
   2832   //
   2833   // Publish HII data.
   2834   //
   2835   CallbackInfo->HiiHandle = HiiAddPackages (
   2836                               &gUserIdentifyManagerGuid,
   2837                               CallbackInfo->DriverHandle,
   2838                               UserIdentifyManagerStrings,
   2839                               UserIdentifyManagerVfrBin,
   2840                               NULL
   2841                               );
   2842   if (CallbackInfo->HiiHandle == NULL) {
   2843     return EFI_OUT_OF_RESOURCES;
   2844   }
   2845 
   2846   mCallbackInfo = CallbackInfo;
   2847 
   2848   return EFI_SUCCESS;
   2849 }
   2850 
   2851 
   2852 /**
   2853   Identify the user whose identification policy supports auto logon.
   2854 
   2855   @param[in]   ProviderIndex   The provider index in the provider list.
   2856   @param[out]  User            Points to user user profile if a user is identified successfully.
   2857 
   2858   @retval EFI_SUCCESS          Identify a user with the specified provider successfully.
   2859   @retval Others               Fail to identify a user.
   2860 
   2861 **/
   2862 EFI_STATUS
   2863 IdentifyAutoLogonUser (
   2864   IN  UINTN                                     ProviderIndex,
   2865   OUT USER_PROFILE_ENTRY                        **User
   2866   )
   2867 {
   2868   EFI_STATUS    Status;
   2869   EFI_USER_INFO *Info;
   2870   UINT8         PolicyType;
   2871 
   2872   Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
   2873   if (Info == NULL) {
   2874     return EFI_OUT_OF_RESOURCES;
   2875   }
   2876 
   2877   Info->InfoType  = EFI_USER_INFO_IDENTIFIER_RECORD;
   2878   Info->InfoSize  = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
   2879 
   2880   //
   2881   // Identify the specified credential provider's auto logon user.
   2882   //
   2883   Status = mProviderDb->Provider[ProviderIndex]->User (
   2884                                                    mProviderDb->Provider[ProviderIndex],
   2885                                                    NULL,
   2886                                                    (EFI_USER_INFO_IDENTIFIER *) (Info + 1)
   2887                                                    );
   2888   if (EFI_ERROR (Status)) {
   2889     FreePool (Info);
   2890     return Status;
   2891   }
   2892 
   2893   //
   2894   // Find user with the specified user ID.
   2895   //
   2896   *User   = NULL;
   2897   Status  = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize);
   2898   FreePool (Info);
   2899   if (EFI_ERROR (Status)) {
   2900     return Status;
   2901   }
   2902 
   2903   Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType);
   2904   if (PolicyType == EFI_USER_INFO_IDENTITY_AND) {
   2905     //
   2906     // The identified user need also identified by other credential provider.
   2907     // This can handle through select user.
   2908     //
   2909     return EFI_NOT_READY;
   2910   }
   2911 
   2912   return Status;
   2913 }
   2914 
   2915 
   2916 /**
   2917   Check whether the given console is ready.
   2918 
   2919   @param[in]   ProtocolGuid   Points to the protocol guid of sonsole .
   2920 
   2921   @retval TRUE     The given console is ready.
   2922   @retval FALSE    The given console is not ready.
   2923 
   2924 **/
   2925 BOOLEAN
   2926 CheckConsole (
   2927   EFI_GUID                     *ProtocolGuid
   2928   )
   2929 {
   2930   EFI_STATUS                   Status;
   2931   UINTN                        HandleCount;
   2932   EFI_HANDLE                   *HandleBuf;
   2933   UINTN                        Index;
   2934   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
   2935 
   2936   //
   2937   // Try to find all the handle driver.
   2938   //
   2939   HandleCount = 0;
   2940   HandleBuf   = NULL;
   2941   Status = gBS->LocateHandleBuffer (
   2942                   ByProtocol,
   2943                   ProtocolGuid,
   2944                   NULL,
   2945                   &HandleCount,
   2946                   &HandleBuf
   2947                   );
   2948   if (EFI_ERROR (Status)) {
   2949     return FALSE;
   2950   }
   2951 
   2952   for (Index = 0; Index < HandleCount; Index++) {
   2953     DevicePath = DevicePathFromHandle (HandleBuf[Index]);
   2954     if (DevicePath != NULL) {
   2955       FreePool (HandleBuf);
   2956       return TRUE;
   2957     }
   2958   }
   2959   FreePool (HandleBuf);
   2960   return FALSE;
   2961 }
   2962 
   2963 
   2964 /**
   2965   Check whether the console is ready.
   2966 
   2967   @retval TRUE     The console is ready.
   2968   @retval FALSE    The console is not ready.
   2969 
   2970 **/
   2971 BOOLEAN
   2972 IsConsoleReady (
   2973   VOID
   2974   )
   2975 {
   2976   if (!CheckConsole (&gEfiSimpleTextOutProtocolGuid)) {
   2977     return FALSE;
   2978   }
   2979 
   2980   if (!CheckConsole (&gEfiSimpleTextInProtocolGuid)) {
   2981     if (!CheckConsole (&gEfiSimpleTextInputExProtocolGuid)) {
   2982     return FALSE;
   2983     }
   2984   }
   2985 
   2986   return TRUE;
   2987 }
   2988 
   2989 
   2990 /**
   2991   Identify a user to logon.
   2992 
   2993   @param[out]  User          Points to user user profile if a user is identified successfully.
   2994 
   2995   @retval EFI_SUCCESS        Identify a user successfully.
   2996 
   2997 **/
   2998 EFI_STATUS
   2999 IdentifyUser (
   3000   OUT USER_PROFILE_ENTRY                        **User
   3001   )
   3002 {
   3003   EFI_STATUS                    Status;
   3004   UINTN                         Index;
   3005   EFI_CREDENTIAL_LOGON_FLAGS    AutoLogon;
   3006   EFI_USER_INFO                 *IdentifyInfo;
   3007   EFI_USER_INFO_IDENTITY_POLICY *Identity;
   3008   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
   3009   USER_PROFILE_ENTRY            *UserEntry;
   3010 
   3011   //
   3012   // Initialize credential providers.
   3013   //
   3014   InitProviderInfo ();
   3015 
   3016   //
   3017   // Initialize user profile database.
   3018   //
   3019   InitUserProfileDb ();
   3020 
   3021   //
   3022   // If only one user in system, and its identify policy is TRUE, then auto logon.
   3023   //
   3024   if (mUserProfileDb->UserProfileNum == 1) {
   3025     UserEntry     = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[0];
   3026     IdentifyInfo  = NULL;
   3027     Status        = FindUserInfoByType (UserEntry, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
   3028     if (EFI_ERROR (Status)) {
   3029       return Status;
   3030     }
   3031     ASSERT (IdentifyInfo != NULL);
   3032 
   3033     Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1));
   3034     if (Identity->Type == EFI_USER_INFO_IDENTITY_TRUE) {
   3035       mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
   3036       UpdateUserInfo (UserEntry);
   3037       *User = UserEntry;
   3038       return EFI_SUCCESS;
   3039     }
   3040   }
   3041 
   3042   //
   3043   // Find and login the default & AutoLogon user.
   3044   //
   3045   for (Index = 0; Index < mProviderDb->Count; Index++) {
   3046     UserCredential = mProviderDb->Provider[Index];
   3047     Status = UserCredential->Default (UserCredential, &AutoLogon);
   3048     if (EFI_ERROR (Status)) {
   3049       continue;
   3050     }
   3051 
   3052     if ((AutoLogon & (EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO)) != 0) {
   3053       Status = IdentifyAutoLogonUser (Index, &UserEntry);
   3054       if (Status == EFI_SUCCESS) {
   3055         mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
   3056         UpdateUserInfo (UserEntry);
   3057         *User = UserEntry;
   3058         return EFI_SUCCESS;
   3059       }
   3060     }
   3061   }
   3062 
   3063   if (!IsConsoleReady ()) {
   3064     //
   3065     // The console is still not ready for user selection.
   3066     //
   3067     return EFI_ACCESS_DENIED;
   3068   }
   3069 
   3070   //
   3071   // Select a user and identify it.
   3072   //
   3073   mCallbackInfo->FormBrowser2->SendForm (
   3074                                  mCallbackInfo->FormBrowser2,
   3075                                  &mCallbackInfo->HiiHandle,
   3076                                  1,
   3077                                  &gUserIdentifyManagerGuid,
   3078                                  0,
   3079                                  NULL,
   3080                                  NULL
   3081                                  );
   3082 
   3083   if (mIdentified) {
   3084     *User = (USER_PROFILE_ENTRY *) mCurrentUser;
   3085     UpdateUserInfo (*User);
   3086     return EFI_SUCCESS;
   3087   }
   3088 
   3089   return EFI_ACCESS_DENIED;
   3090 }
   3091 
   3092 
   3093 /**
   3094   An empty function to pass error checking of CreateEventEx ().
   3095 
   3096   @param  Event         Event whose notification function is being invoked.
   3097   @param  Context       Pointer to the notification function's context,
   3098                         which is implementation-dependent.
   3099 
   3100 **/
   3101 VOID
   3102 EFIAPI
   3103 InternalEmptyFuntion (
   3104   IN EFI_EVENT                Event,
   3105   IN VOID                     *Context
   3106   )
   3107 {
   3108 }
   3109 
   3110 
   3111 /**
   3112   Create, Signal, and Close the User Profile Changed event.
   3113 
   3114 **/
   3115 VOID
   3116 SignalEventUserProfileChanged (
   3117   VOID
   3118   )
   3119 {
   3120   EFI_STATUS    Status;
   3121   EFI_EVENT     Event;
   3122 
   3123   Status = gBS->CreateEventEx (
   3124                   EVT_NOTIFY_SIGNAL,
   3125                   TPL_CALLBACK,
   3126                   InternalEmptyFuntion,
   3127                   NULL,
   3128                   &gEfiEventUserProfileChangedGuid,
   3129                   &Event
   3130                   );
   3131   ASSERT_EFI_ERROR (Status);
   3132   gBS->SignalEvent (Event);
   3133   gBS->CloseEvent (Event);
   3134 }
   3135 
   3136 
   3137 /**
   3138   Create a new user profile.
   3139 
   3140   This function creates a new user profile with only a new user identifier attached and returns
   3141   its handle. The user profile is non-volatile, but the handle User can change across reboots.
   3142 
   3143   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3144   @param[out] User               On return, points to the new user profile handle.
   3145                                  The user profile handle is unique only during this boot.
   3146 
   3147   @retval EFI_SUCCESS            User profile was successfully created.
   3148   @retval EFI_ACCESS_DENIED      Current user does not have sufficient permissions to create a
   3149                                  user profile.
   3150   @retval EFI_UNSUPPORTED        Creation of new user profiles is not supported.
   3151   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
   3152 
   3153 **/
   3154 EFI_STATUS
   3155 EFIAPI
   3156 UserProfileCreate (
   3157   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3158   OUT       EFI_USER_PROFILE_HANDLE             *User
   3159   )
   3160 {
   3161   EFI_STATUS  Status;
   3162 
   3163   if ((This == NULL) || (User == NULL)) {
   3164     return EFI_INVALID_PARAMETER;
   3165   }
   3166 
   3167   //
   3168   // Check the right of the current user.
   3169   //
   3170   if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
   3171     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
   3172       return EFI_ACCESS_DENIED;
   3173     }
   3174   }
   3175 
   3176   //
   3177   // Create new user profile
   3178   //
   3179   Status = CreateUserProfile ((USER_PROFILE_ENTRY **) User);
   3180   if (EFI_ERROR (Status)) {
   3181     return EFI_ACCESS_DENIED;
   3182   }
   3183   return EFI_SUCCESS;
   3184 }
   3185 
   3186 
   3187 /**
   3188   Delete an existing user profile.
   3189 
   3190   @param[in] This                Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3191   @param[in] User                User profile handle.
   3192 
   3193   @retval EFI_SUCCESS            User profile was successfully deleted.
   3194   @retval EFI_ACCESS_DENIED      Current user does not have sufficient permissions to delete a user
   3195                                  profile or there is only one user profile.
   3196   @retval EFI_UNSUPPORTED        Deletion of new user profiles is not supported.
   3197   @retval EFI_INVALID_PARAMETER  User does not refer to a valid user profile.
   3198 
   3199 **/
   3200 EFI_STATUS
   3201 EFIAPI
   3202 UserProfileDelete (
   3203   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3204   IN        EFI_USER_PROFILE_HANDLE             User
   3205   )
   3206 {
   3207   EFI_STATUS  Status;
   3208 
   3209   if (This == NULL) {
   3210     return EFI_INVALID_PARAMETER;
   3211   }
   3212 
   3213   //
   3214   // Check the right of the current user.
   3215   //
   3216   if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
   3217     return EFI_ACCESS_DENIED;
   3218   }
   3219 
   3220   //
   3221   // Delete user profile.
   3222   //
   3223   Status = DelUserProfile (User);
   3224   if (EFI_ERROR (Status)) {
   3225     if (Status != EFI_INVALID_PARAMETER) {
   3226       return EFI_ACCESS_DENIED;
   3227     }
   3228     return EFI_INVALID_PARAMETER;
   3229   }
   3230 
   3231   return EFI_SUCCESS;
   3232 }
   3233 
   3234 
   3235 /**
   3236   Enumerate all of the enrolled users on the platform.
   3237 
   3238   This function returns the next enrolled user profile. To retrieve the first user profile handle,
   3239   point User at a NULL. Each subsequent call will retrieve another user profile handle until there
   3240   are no more, at which point User will point to NULL.
   3241 
   3242   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3243   @param[in, out] User           On entry, points to the previous user profile handle or NULL to
   3244                                  start enumeration. On exit, points to the next user profile handle
   3245                                  or NULL if there are no more user profiles.
   3246 
   3247   @retval EFI_SUCCESS            Next enrolled user profile successfully returned.
   3248   @retval EFI_ACCESS_DENIED      Next enrolled user profile was not successfully returned.
   3249   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
   3250 **/
   3251 EFI_STATUS
   3252 EFIAPI
   3253 UserProfileGetNext (
   3254   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3255   IN OUT    EFI_USER_PROFILE_HANDLE             *User
   3256   )
   3257 {
   3258   EFI_STATUS  Status;
   3259 
   3260   if ((This == NULL) || (User == NULL)) {
   3261     return EFI_INVALID_PARAMETER;
   3262   }
   3263 
   3264   Status = FindUserProfile ((USER_PROFILE_ENTRY **) User, TRUE, NULL);
   3265   if (EFI_ERROR (Status)) {
   3266     return EFI_ACCESS_DENIED;
   3267   }
   3268   return EFI_SUCCESS;
   3269 }
   3270 
   3271 
   3272 /**
   3273   Return the current user profile handle.
   3274 
   3275   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3276   @param[out] CurrentUser        On return, points to the current user profile handle.
   3277 
   3278   @retval EFI_SUCCESS            Current user profile handle returned successfully.
   3279   @retval EFI_INVALID_PARAMETER  The CurrentUser parameter is NULL.
   3280 
   3281 **/
   3282 EFI_STATUS
   3283 EFIAPI
   3284 UserProfileCurrent (
   3285   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3286   OUT       EFI_USER_PROFILE_HANDLE             *CurrentUser
   3287   )
   3288 {
   3289   //
   3290   // Get current user profile.
   3291   //
   3292   if ((This == NULL) || (CurrentUser == NULL)) {
   3293     return EFI_INVALID_PARAMETER;
   3294   }
   3295 
   3296   *CurrentUser = mCurrentUser;
   3297   return EFI_SUCCESS;
   3298 }
   3299 
   3300 
   3301 /**
   3302   Identify a user.
   3303 
   3304   Identify the user and, if authenticated, returns the user handle and changes the current
   3305   user profile. All user information marked as private in a previously selected profile
   3306   is no longer available for inspection.
   3307   Whenever the current user profile is changed then the an event with the GUID
   3308   EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled.
   3309 
   3310   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3311   @param[out] User               On return, points to the user profile handle for the current
   3312                                  user profile.
   3313 
   3314   @retval EFI_SUCCESS            User was successfully identified.
   3315   @retval EFI_ACCESS_DENIED      User was not successfully identified.
   3316   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
   3317 
   3318 **/
   3319 EFI_STATUS
   3320 EFIAPI
   3321 UserProfileIdentify (
   3322   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3323   OUT       EFI_USER_PROFILE_HANDLE             *User
   3324   )
   3325 {
   3326   EFI_STATUS  Status;
   3327 
   3328   if ((This == NULL) || (User == NULL)) {
   3329     return EFI_INVALID_PARAMETER;
   3330   }
   3331 
   3332   if (mCurrentUser != NULL) {
   3333     *User = mCurrentUser;
   3334     return EFI_SUCCESS;
   3335   }
   3336 
   3337   //
   3338   // Identify user
   3339   //
   3340   Status = IdentifyUser ((USER_PROFILE_ENTRY **) User);
   3341   if (EFI_ERROR (Status)) {
   3342     return EFI_ACCESS_DENIED;
   3343   }
   3344 
   3345   //
   3346   // Publish the user info into the EFI system configuration table.
   3347   //
   3348   PublishUserTable ();
   3349 
   3350   //
   3351   // Signal User Profile Changed event.
   3352   //
   3353   SignalEventUserProfileChanged ();
   3354   return EFI_SUCCESS;
   3355 }
   3356 
   3357 /**
   3358   Find a user using a user information record.
   3359 
   3360   This function searches all user profiles for the specified user information record.
   3361   The search starts with the user information record handle following UserInfo and
   3362   continues until either the information is found or there are no more user profiles.
   3363   A match occurs when the Info.InfoType field matches the user information record
   3364   type and the user information record data matches the portion of Info.
   3365 
   3366   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3367   @param[in, out] User           On entry, points to the previously returned user profile
   3368                                  handle, or NULL to start searching with the first user profile.
   3369                                  On return, points to the user profile handle, or NULL if not
   3370                                  found.
   3371   @param[in, out] UserInfo       On entry, points to the previously returned user information
   3372                                  handle, or NULL to start searching with the first. On return,
   3373                                  points to the user information handle of the user information
   3374                                  record, or NULL if not found. Can be NULL, in which case only
   3375                                  one user information record per user can be returned.
   3376   @param[in]      Info           Points to the buffer containing the user information to be
   3377                                  compared to the user information record. If the user information
   3378                                  record data is empty, then only the user information record type
   3379                                  is compared. If InfoSize is 0, then the user information record
   3380                                  must be empty.
   3381 
   3382   @param[in]      InfoSize       The size of Info, in bytes.
   3383 
   3384   @retval EFI_SUCCESS            User information was found. User points to the user profile
   3385                                  handle, and UserInfo points to the user information handle.
   3386   @retval EFI_NOT_FOUND          User information was not found. User points to NULL, and
   3387                                  UserInfo points to NULL.
   3388   @retval EFI_INVALID_PARAMETER  User is NULL. Or Info is NULL.
   3389 
   3390 **/
   3391 EFI_STATUS
   3392 EFIAPI
   3393 UserProfileFind (
   3394   IN     CONST EFI_USER_MANAGER_PROTOCOL        *This,
   3395   IN OUT EFI_USER_PROFILE_HANDLE                *User,
   3396   IN OUT EFI_USER_INFO_HANDLE                   *UserInfo OPTIONAL,
   3397   IN     CONST EFI_USER_INFO                    *Info,
   3398   IN     UINTN                                  InfoSize
   3399   )
   3400 {
   3401   EFI_STATUS  Status;
   3402   UINTN       Size;
   3403 
   3404   if ((This == NULL) || (User == NULL) || (Info == NULL)) {
   3405     return EFI_INVALID_PARAMETER;
   3406   }
   3407 
   3408   if (InfoSize == 0) {
   3409     //
   3410     // If InfoSize is 0, then the user information record must be empty.
   3411     //
   3412     if (Info->InfoSize != sizeof (EFI_USER_INFO)) {
   3413       return EFI_INVALID_PARAMETER;
   3414     }
   3415   } else {
   3416     if (InfoSize != Info->InfoSize) {
   3417       return EFI_INVALID_PARAMETER;
   3418     }
   3419   }
   3420   Size = Info->InfoSize;
   3421 
   3422   //
   3423   // Find user profile accdoring to user information.
   3424   //
   3425   Status = FindUserProfileByInfo (
   3426             (USER_PROFILE_ENTRY **) User,
   3427             (EFI_USER_INFO **) UserInfo,
   3428             (EFI_USER_INFO *) Info,
   3429             Size
   3430             );
   3431   if (EFI_ERROR (Status)) {
   3432     *User = NULL;
   3433     if (UserInfo != NULL) {
   3434       *UserInfo = NULL;
   3435     }
   3436     return EFI_NOT_FOUND;
   3437   }
   3438 
   3439   return EFI_SUCCESS;
   3440 }
   3441 
   3442 
   3443 /**
   3444   Return information attached to the user.
   3445 
   3446   This function returns user information. The format of the information is described in User
   3447   Information. The function may return EFI_ACCESS_DENIED if the information is marked private
   3448   and the handle specified by User is not the current user profile. The function may return
   3449   EFI_ACCESS_DENIED if the information is marked protected and the information is associated
   3450   with a credential provider for which the user has not been authenticated.
   3451 
   3452   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3453   @param[in]      User           Handle of the user whose profile will be retrieved.
   3454   @param[in]      UserInfo       Handle of the user information data record.
   3455   @param[out]     Info           On entry, points to a buffer of at least *InfoSize bytes. On exit,
   3456                                  holds the user information. If the buffer is too small to hold the
   3457                                  information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
   3458                                  updated to contain the number of bytes actually required.
   3459   @param[in, out] InfoSize       On entry, points to the size of Info. On return, points to the size
   3460                                  of the user information.
   3461 
   3462   @retval EFI_SUCCESS            Information returned successfully.
   3463   @retval EFI_ACCESS_DENIED      The information about the specified user cannot be accessed by the
   3464                                  current user.
   3465   @retval EFI_BUFFER_TOO_SMALL   The number of bytes specified by *InfoSize is too small to hold the
   3466                                  returned data. The actual size required is returned in *InfoSize.
   3467   @retval EFI_NOT_FOUND          User does not refer to a valid user profile or UserInfo does not refer
   3468                                  to a valid user info handle.
   3469   @retval EFI_INVALID_PARAMETER  Info is NULL or InfoSize is NULL.
   3470 
   3471 **/
   3472 EFI_STATUS
   3473 EFIAPI
   3474 UserProfileGetInfo (
   3475   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3476   IN        EFI_USER_PROFILE_HANDLE             User,
   3477   IN        EFI_USER_INFO_HANDLE                UserInfo,
   3478   OUT       EFI_USER_INFO                       *Info,
   3479   IN OUT    UINTN                               *InfoSize
   3480   )
   3481 {
   3482   EFI_STATUS  Status;
   3483 
   3484   if ((This == NULL) || (InfoSize == NULL)) {
   3485     return EFI_INVALID_PARAMETER;
   3486   }
   3487 
   3488   if ((*InfoSize != 0) && (Info == NULL)) {
   3489     return EFI_INVALID_PARAMETER;
   3490   }
   3491 
   3492   if ((User == NULL) || (UserInfo == NULL)) {
   3493     return EFI_NOT_FOUND;
   3494   }
   3495 
   3496   Status = GetUserInfo (User, UserInfo, Info, InfoSize, TRUE);
   3497   if (EFI_ERROR (Status)) {
   3498     if (Status == EFI_BUFFER_TOO_SMALL) {
   3499       return EFI_BUFFER_TOO_SMALL;
   3500     }
   3501     return EFI_ACCESS_DENIED;
   3502   }
   3503   return EFI_SUCCESS;
   3504 }
   3505 
   3506 
   3507 /**
   3508   Add or update user information.
   3509 
   3510   This function changes user information.  If NULL is pointed to by UserInfo, then a new user
   3511   information record is created and its handle is returned in UserInfo. Otherwise, the existing
   3512   one is replaced.
   3513   If EFI_USER_INFO_IDENITTY_POLICY_RECORD is changed, it is the caller's responsibility to keep
   3514   it to be synced with the information on credential providers.
   3515   If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same
   3516   type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and UserInfo
   3517   will point to the handle of the existing record.
   3518 
   3519   @param[in]      This            Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3520   @param[in]      User            Handle of the user whose profile will be retrieved.
   3521   @param[in, out] UserInfo        Handle of the user information data record.
   3522   @param[in]      Info            On entry, points to a buffer of at least *InfoSize bytes. On exit,
   3523                                   holds the user information. If the buffer is too small to hold the
   3524                                   information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
   3525                                   updated to contain the number of bytes actually required.
   3526   @param[in]      InfoSize        On entry, points to the size of Info. On return, points to the size
   3527                                   of the user information.
   3528 
   3529   @retval EFI_SUCCESS             Information returned successfully.
   3530   @retval EFI_ACCESS_DENIED       The record is exclusive.
   3531   @retval EFI_SECURITY_VIOLATION  The current user does not have permission to change the specified
   3532                                   user profile or user information record.
   3533   @retval EFI_NOT_FOUND           User does not refer to a valid user profile or UserInfo does not
   3534                                   refer to a valid user info handle.
   3535   @retval EFI_INVALID_PARAMETER   UserInfo is NULL or Info is NULL.
   3536 **/
   3537 EFI_STATUS
   3538 EFIAPI
   3539 UserProfileSetInfo (
   3540   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3541   IN        EFI_USER_PROFILE_HANDLE             User,
   3542   IN OUT    EFI_USER_INFO_HANDLE                *UserInfo,
   3543   IN CONST  EFI_USER_INFO                       *Info,
   3544   IN        UINTN                               InfoSize
   3545   )
   3546 {
   3547   EFI_STATUS  Status;
   3548 
   3549   if ((This == NULL) || (User == NULL) || (UserInfo == NULL) || (Info == NULL)) {
   3550     return EFI_INVALID_PARAMETER;
   3551   }
   3552 
   3553   //
   3554   // Check the right of the current user.
   3555   //
   3556   if (User != mCurrentUser) {
   3557     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
   3558       if (*UserInfo != NULL) {
   3559         //
   3560         // Can't update info in other profiles without MANAGE right.
   3561         //
   3562         return EFI_SECURITY_VIOLATION;
   3563       }
   3564 
   3565       if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
   3566         //
   3567         // Can't add info into other profiles.
   3568         //
   3569         return EFI_SECURITY_VIOLATION;
   3570       }
   3571     }
   3572   }
   3573 
   3574   if (User == mCurrentUser) {
   3575     if (CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_SELF)) {
   3576       //
   3577       // Only identify policy can be added/updated.
   3578       //
   3579       if (Info->InfoType != EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
   3580         return EFI_SECURITY_VIOLATION;
   3581       }
   3582     }
   3583   }
   3584 
   3585   //
   3586   // Modify user information.
   3587   //
   3588   Status = ModifyUserInfo (User, (EFI_USER_INFO **) UserInfo, Info, InfoSize);
   3589   if (EFI_ERROR (Status)) {
   3590     if (Status == EFI_ACCESS_DENIED) {
   3591       return EFI_ACCESS_DENIED;
   3592     }
   3593     return EFI_SECURITY_VIOLATION;
   3594   }
   3595   return EFI_SUCCESS;
   3596 }
   3597 
   3598 
   3599 /**
   3600   Called by credential provider to notify of information change.
   3601 
   3602   This function allows the credential provider to notify the User Identity Manager when user status
   3603   has changed.
   3604   If the User Identity Manager doesn't support asynchronous changes in credentials, then this function
   3605   should return EFI_UNSUPPORTED.
   3606   If current user does not exist, and the credential provider can identify a user, then make the user
   3607   to be current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
   3608   If current user already exists, and the credential provider can identify another user, then switch
   3609   current user to the newly identified user, and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
   3610   If current user was identified by this credential provider and now the credential provider cannot identify
   3611   current user, then logout current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
   3612 
   3613   @param[in] This          Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3614   @param[in] Changed       Handle on which is installed an instance of the EFI_USER_CREDENTIAL2_PROTOCOL
   3615                            where the user has changed.
   3616 
   3617   @retval EFI_SUCCESS      The User Identity Manager has handled the notification.
   3618   @retval EFI_NOT_READY    The function was called while the specified credential provider was not selected.
   3619   @retval EFI_UNSUPPORTED  The User Identity Manager doesn't support asynchronous notifications.
   3620 
   3621 **/
   3622 EFI_STATUS
   3623 EFIAPI
   3624 UserProfileNotify (
   3625   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3626   IN        EFI_HANDLE                          Changed
   3627   )
   3628 {
   3629   return EFI_UNSUPPORTED;
   3630 }
   3631 
   3632 
   3633 /**
   3634   Delete user information.
   3635 
   3636   Delete the user information attached to the user profile specified by the UserInfo.
   3637 
   3638   @param[in] This            Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3639   @param[in] User            Handle of the user whose information will be deleted.
   3640   @param[in] UserInfo        Handle of the user information to remove.
   3641 
   3642   @retval EFI_SUCCESS        User information deleted successfully.
   3643   @retval EFI_NOT_FOUND      User information record UserInfo does not exist in the user profile.
   3644   @retval EFI_ACCESS_DENIED  The current user does not have permission to delete this user information.
   3645 
   3646 **/
   3647 EFI_STATUS
   3648 EFIAPI
   3649 UserProfileDeleteInfo (
   3650   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3651   IN        EFI_USER_PROFILE_HANDLE             User,
   3652   IN        EFI_USER_INFO_HANDLE                UserInfo
   3653   )
   3654 {
   3655   EFI_STATUS  Status;
   3656 
   3657   if (This == NULL) {
   3658     return EFI_INVALID_PARAMETER;
   3659   }
   3660 
   3661   //
   3662   // Check the right of the current user.
   3663   //
   3664   if (User != mCurrentUser) {
   3665     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
   3666       return EFI_ACCESS_DENIED;
   3667     }
   3668   }
   3669 
   3670   //
   3671   // Delete user information.
   3672   //
   3673   Status = DelUserInfo (User, UserInfo, TRUE);
   3674   if (EFI_ERROR (Status)) {
   3675     if (Status == EFI_NOT_FOUND) {
   3676       return EFI_NOT_FOUND;
   3677     }
   3678     return EFI_ACCESS_DENIED;
   3679   }
   3680   return EFI_SUCCESS;
   3681 }
   3682 
   3683 
   3684 /**
   3685   Enumerate user information of all the enrolled users on the platform.
   3686 
   3687   This function returns the next user information record. To retrieve the first user
   3688   information record handle, point UserInfo at a NULL. Each subsequent call will retrieve
   3689   another user information record handle until there are no more, at which point UserInfo
   3690   will point to NULL.
   3691 
   3692   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
   3693   @param[in]      User           Handle of the user whose information will be deleted.
   3694   @param[in, out] UserInfo       Handle of the user information to remove.
   3695 
   3696   @retval EFI_SUCCESS            User information returned.
   3697   @retval EFI_NOT_FOUND          No more user information found.
   3698   @retval EFI_INVALID_PARAMETER  UserInfo is NULL.
   3699 
   3700 **/
   3701 EFI_STATUS
   3702 EFIAPI
   3703 UserProfileGetNextInfo (
   3704   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
   3705   IN        EFI_USER_PROFILE_HANDLE             User,
   3706   IN OUT    EFI_USER_INFO_HANDLE                *UserInfo
   3707   )
   3708 {
   3709   if ((This == NULL) || (UserInfo == NULL)) {
   3710     return EFI_INVALID_PARAMETER;
   3711   }
   3712   //
   3713   // Get next user information entry.
   3714   //
   3715   return FindUserInfo (User, (EFI_USER_INFO **) UserInfo, TRUE, NULL);
   3716 }
   3717 
   3718 
   3719 /**
   3720   Main entry for this driver.
   3721 
   3722   @param[in] ImageHandle     Image handle this driver.
   3723   @param[in] SystemTable     Pointer to SystemTable.
   3724 
   3725   @retval EFI_SUCESS         This function always complete successfully.
   3726 
   3727 **/
   3728 EFI_STATUS
   3729 EFIAPI
   3730 UserIdentifyManagerInit (
   3731   IN EFI_HANDLE        ImageHandle,
   3732   IN EFI_SYSTEM_TABLE  *SystemTable
   3733   )
   3734 {
   3735 
   3736   EFI_STATUS  Status;
   3737 
   3738   //
   3739   // It is NOT robust enough to be included in production.
   3740   //
   3741   #error "This implementation is just a sample, please comment this line if you really want to use this driver."
   3742 
   3743   //
   3744   // Initiate form browser.
   3745   //
   3746   InitFormBrowser ();
   3747 
   3748   //
   3749   // Install protocol interfaces for the User Identity Manager.
   3750   //
   3751   Status = gBS->InstallProtocolInterface (
   3752                   &mCallbackInfo->DriverHandle,
   3753                   &gEfiUserManagerProtocolGuid,
   3754                   EFI_NATIVE_INTERFACE,
   3755                   &gUserIdentifyManager
   3756                   );
   3757   ASSERT_EFI_ERROR (Status);
   3758 
   3759   LoadDeferredImageInit (ImageHandle);
   3760   return EFI_SUCCESS;
   3761 }
   3762 
   3763 
   3764