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