1/** @file
2  This driver manages user information and produces user manager protocol.
3
4Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "UserIdentifyManager.h"
16
17//
18// Default user name.
19//
20CHAR16                      mUserName[]       = L"Administrator";
21
22//
23// Points to the user profile database.
24//
25USER_PROFILE_DB             *mUserProfileDb   = NULL;
26
27//
28// Points to the credential providers found in system.
29//
30CREDENTIAL_PROVIDER_INFO    *mProviderDb      = NULL;
31
32//
33// Current user shared in multi function.
34//
35EFI_USER_PROFILE_HANDLE     mCurrentUser      = NULL;
36
37//
38// Flag indicates a user is identified.
39//
40BOOLEAN                     mIdentified       = FALSE;
41USER_MANAGER_CALLBACK_INFO  *mCallbackInfo    = NULL;
42HII_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
65EFI_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**/
98EFI_STATUS
99FindUserProfile (
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**/
171EFI_STATUS
172FindUserInfo (
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**/
263EFI_STATUS
264FindUserInfoByType (
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**/
333EFI_STATUS
334FindUserProfileByInfo (
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**/
414BOOLEAN
415CheckAccessPolicy (
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**/
496BOOLEAN
497CheckIdentityPolicy (
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**/
606BOOLEAN
607CheckUserInfo (
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**/
701BOOLEAN
702CheckProfileInfo (
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**/
749BOOLEAN
750CheckCurrentUserAccessRight (
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**/
798VOID
799GenerateIdentifier (
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**/
837VOID
838GenerateUserId (
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**/
886BOOLEAN
887ExpandUsermUserProfileDb (
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**/
943BOOLEAN
944ExpandUserProfile (
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**/
985EFI_STATUS
986SaveNvUserProfile (
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**/
1028EFI_STATUS
1029AddUserInfo (
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**/
1100EFI_STATUS
1101GetUserInfo (
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**/
1177EFI_STATUS
1178DelUserInfo (
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**/
1232EFI_STATUS
1233ModifyUserInfo (
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**/
1362EFI_STATUS
1363DelUserProfile (
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**/
1434EFI_STATUS
1435AddUserProfile (
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**/
1511EFI_STATUS
1512CreateUserProfile (
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**/
1551EFI_STATUS
1552AddDefaultUserProfile (
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
1653Done:
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**/
1670EFI_STATUS
1671PublishUserTable (
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**/
1753EFI_STATUS
1754GetIdentifyType (
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**/
1807EFI_STATUS
1808IdentifyByProviderId (
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**/
1896EFI_STATUS
1897UpdateUserInfo (
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**/
2002VOID
2003AddProviderSelection (
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**/
2052EFI_STATUS
2053AddUserSelection (
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**/
2099EFI_STATUS
2100IdentifyAndTypeUser (
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**/
2222EFI_STATUS
2223IdentifyOrTypeUser (
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**/
2324EFI_STATUS
2325EFIAPI
2326UserIdentifyManagerCallback (
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**/
2492EFI_STATUS
2493InitUserProfileDb (
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**/
2623EFI_STATUS
2624InitProviderInfo (
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**/
2711EFI_STATUS
2712EFIAPI
2713FakeExtractConfig (
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**/
2743EFI_STATUS
2744EFIAPI
2745FakeRouteConfig (
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**/
2766EFI_STATUS
2767InitFormBrowser (
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**/
2862EFI_STATUS
2863IdentifyAutoLogonUser (
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**/
2925BOOLEAN
2926CheckConsole (
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**/
2971BOOLEAN
2972IsConsoleReady (
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**/
2998EFI_STATUS
2999IdentifyUser (
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**/
3101VOID
3102EFIAPI
3103InternalEmptyFuntion (
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**/
3115VOID
3116SignalEventUserProfileChanged (
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**/
3154EFI_STATUS
3155EFIAPI
3156UserProfileCreate (
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**/
3200EFI_STATUS
3201EFIAPI
3202UserProfileDelete (
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**/
3251EFI_STATUS
3252EFIAPI
3253UserProfileGetNext (
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**/
3282EFI_STATUS
3283EFIAPI
3284UserProfileCurrent (
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**/
3319EFI_STATUS
3320EFIAPI
3321UserProfileIdentify (
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**/
3391EFI_STATUS
3392EFIAPI
3393UserProfileFind (
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**/
3472EFI_STATUS
3473EFIAPI
3474UserProfileGetInfo (
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**/
3537EFI_STATUS
3538EFIAPI
3539UserProfileSetInfo (
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**/
3622EFI_STATUS
3623EFIAPI
3624UserProfileNotify (
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**/
3647EFI_STATUS
3648EFIAPI
3649UserProfileDeleteInfo (
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**/
3701EFI_STATUS
3702EFIAPI
3703UserProfileGetNextInfo (
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**/
3728EFI_STATUS
3729EFIAPI
3730UserIdentifyManagerInit (
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