]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c
e105579115a89cf1864dfc5fb7962f4677049a79
[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 identifir 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 EFI_USER_INFO *IdInfo;
2344
2345 if (Provider == NULL) {
2346 return EFI_INVALID_PARAMETER;
2347 }
2348
2349 //
2350 // Check the user ID identified by the specified credential provider.
2351 //
2352 for (Index = 0; Index < mProviderDb->Count; Index++) {
2353 //
2354 // Check credential provider class.
2355 //
2356 UserCredential = mProviderDb->Provider[Index];
2357 if (CompareGuid (&UserCredential->Identifier, Provider)) {
2358 Status = UserCredential->Select (UserCredential, &AutoLogon);
2359 if (EFI_ERROR (Status)) {
2360 return Status;
2361 }
2362
2363 if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) {
2364 //
2365 // Get credential provider form.
2366 //
2367 Status = UserCredential->Form (
2368 UserCredential,
2369 &HiiHandle,
2370 &FormSetId,
2371 &FormId
2372 );
2373 if (!EFI_ERROR (Status)) {
2374 //
2375 // Send form to get user input.
2376 //
2377 Status = mCallbackInfo->FormBrowser2->SendForm (
2378 mCallbackInfo->FormBrowser2,
2379 &HiiHandle,
2380 1,
2381 &FormSetId,
2382 FormId,
2383 NULL,
2384 NULL
2385 );
2386 if (EFI_ERROR (Status)) {
2387 return Status;
2388 }
2389 }
2390 }
2391
2392 Status = UserCredential->User (UserCredential, User, &UserId);
2393 if (EFI_ERROR (Status)) {
2394 return Status;
2395 }
2396
2397 Status = UserCredential->Deselect (UserCredential);
2398 if (EFI_ERROR (Status)) {
2399 return Status;
2400 }
2401
2402 if (User == NULL) {
2403 return EFI_SUCCESS;
2404 }
2405
2406 //
2407 // Get user ID information.
2408 //
2409 IdInfo = NULL;
2410 Status = FindUserInfoByType (User, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
2411 ASSERT (IdInfo != NULL);
2412
2413 if (CompareMem ((UINT8 *) (IdInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) != 0) {
2414 //
2415 // One user name is selected, but the other's credential is given. Here no user passed.
2416 //
2417 break;
2418 }
2419 return EFI_SUCCESS;
2420 }
2421 }
2422
2423 return EFI_NOT_FOUND;
2424 }
2425
2426
2427 /**
2428 Update user information when user is logon on successfully.
2429
2430 @param[in] User Points to user profile.
2431
2432 @retval EFI_SUCCESS Update user information successfully.
2433 @retval Others Fail to update user information.
2434
2435 **/
2436 EFI_STATUS
2437 UpdateUserInfo (
2438 IN USER_PROFILE_ENTRY *User
2439 )
2440 {
2441 EFI_STATUS Status;
2442 EFI_USER_INFO *Info;
2443 EFI_USER_INFO *NewInfo;
2444 EFI_USER_INFO_CREATE_DATE Date;
2445 EFI_USER_INFO_USAGE_COUNT UsageCount;
2446 UINTN InfoLen;
2447
2448 //
2449 // Allocate a buffer to update user's date record and usage record.
2450 //
2451 InfoLen = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT));
2452 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen);
2453 if (Info == NULL) {
2454 return EFI_OUT_OF_RESOURCES;
2455 }
2456
2457 //
2458 // Check create date record.
2459 //
2460 NewInfo = NULL;
2461 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD);
2462 if (Status == EFI_NOT_FOUND) {
2463 Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;
2464 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2465 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
2466 Status = gRT->GetTime (&Date, NULL);
2467 if (EFI_ERROR (Status)) {
2468 FreePool (Info);
2469 return Status;
2470 }
2471
2472 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));
2473 NewInfo = NULL;
2474 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2475 if (EFI_ERROR (Status)) {
2476 FreePool (Info);
2477 return Status;
2478 }
2479 }
2480
2481 //
2482 // Update usage date record.
2483 //
2484 NewInfo = NULL;
2485 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD);
2486 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
2487 Info->InfoType = EFI_USER_INFO_USAGE_DATE_RECORD;
2488 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2489 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE);
2490 Status = gRT->GetTime (&Date, NULL);
2491 if (EFI_ERROR (Status)) {
2492 FreePool (Info);
2493 return Status;
2494 }
2495
2496 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE));
2497 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2498 if (EFI_ERROR (Status)) {
2499 FreePool (Info);
2500 return Status;
2501 }
2502 }
2503
2504 //
2505 // Update usage count record.
2506 //
2507 UsageCount = 0;
2508 NewInfo = NULL;
2509 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD);
2510 //
2511 // Get usage count.
2512 //
2513 if (Status == EFI_SUCCESS) {
2514 CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT));
2515 }
2516
2517 UsageCount++;
2518 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
2519 Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD;
2520 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2521 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
2522 CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
2523 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2524 if (EFI_ERROR (Status)) {
2525 FreePool (Info);
2526 return Status;
2527 }
2528 }
2529
2530 FreePool (Info);
2531 return EFI_SUCCESS;
2532 }
2533
2534
2535 /**
2536 Add a credenetial provider item in form.
2537
2538 @param[in] ProviderGuid Points to the identifir of credential provider.
2539 @param[in] OpCodeHandle Points to container for dynamic created opcodes.
2540
2541 **/
2542 VOID
2543 AddProviderSelection (
2544 IN EFI_GUID *ProviderGuid,
2545 IN VOID *OpCodeHandle
2546 )
2547 {
2548 EFI_HII_HANDLE HiiHandle;
2549 EFI_STRING_ID ProvID;
2550 CHAR16 *ProvStr;
2551 UINTN Index;
2552 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
2553
2554 for (Index = 0; Index < mProviderDb->Count; Index++) {
2555 UserCredential = mProviderDb->Provider[Index];
2556 if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) {
2557 //
2558 // Add credential provider selection.
2559 //
2560 UserCredential->Title (UserCredential, &HiiHandle, &ProvID);
2561 ProvStr = HiiGetString (HiiHandle, ProvID, NULL);
2562 if (ProvStr == NULL) {
2563 continue ;
2564 }
2565 ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);
2566 FreePool (ProvStr);
2567 HiiCreateActionOpCode (
2568 OpCodeHandle, // Container for dynamic created opcodes
2569 (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index), // Question ID
2570 ProvID, // Prompt text
2571 STRING_TOKEN (STR_NULL_STRING), // Help text
2572 EFI_IFR_FLAG_CALLBACK, // Question flag
2573 0 // Action String ID
2574 );
2575 break;
2576 }
2577 }
2578 }
2579
2580
2581 /**
2582 Add a username item in form.
2583
2584 @param[in] Index The index of the user in the user name list.
2585 @param[in] User Points to the user profile whose username is added.
2586 @param[in] OpCodeHandle Points to container for dynamic created opcodes.
2587
2588 @retval EFI_SUCCESS Add a username successfully.
2589 @retval Others Fail to add a username.
2590
2591 **/
2592 EFI_STATUS
2593 AddUserSelection (
2594 IN UINT16 Index,
2595 IN USER_PROFILE_ENTRY *User,
2596 IN VOID *OpCodeHandle
2597 )
2598 {
2599 EFI_STRING_ID UserName;
2600 EFI_STATUS Status;
2601 EFI_USER_INFO *UserInfo;
2602
2603 UserInfo = NULL;
2604 Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD);
2605 if (EFI_ERROR (Status)) {
2606 return Status;
2607 }
2608
2609 //
2610 // Add user name selection.
2611 //
2612 UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL);
2613 if (UserName == 0) {
2614 return EFI_OUT_OF_RESOURCES;
2615 }
2616
2617 HiiCreateGotoOpCode (
2618 OpCodeHandle, // Container for dynamic created opcodes
2619 FORMID_PROVIDER_FORM, // Target Form ID
2620 UserName, // Prompt text
2621 STRING_TOKEN (STR_NULL_STRING), // Help text
2622 EFI_IFR_FLAG_CALLBACK, // Question flag
2623 (UINT16) Index // Question ID
2624 );
2625
2626 return EFI_SUCCESS;
2627 }
2628
2629
2630 /**
2631 Identify the user whose identity policy does not contain the operator 'OR'.
2632
2633 @param[in] User Points to the user profile.
2634
2635 @retval EFI_SUCCESS The specified user is identified successfully.
2636 @retval Others Fail to identify the user.
2637
2638 **/
2639 EFI_STATUS
2640 IdentifyAndTypeUser (
2641 IN USER_PROFILE_ENTRY *User
2642 )
2643 {
2644 EFI_STATUS Status;
2645 EFI_USER_INFO *IdentifyInfo;
2646 BOOLEAN Success;
2647 UINTN TotalLen;
2648 UINTN ValueLen;
2649 EFI_USER_INFO_IDENTITY_POLICY *Identity;
2650
2651 //
2652 // Get user identify policy information.
2653 //
2654 IdentifyInfo = NULL;
2655 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2656 if (EFI_ERROR (Status)) {
2657 return Status;
2658 }
2659 ASSERT (IdentifyInfo != NULL);
2660
2661 //
2662 // Check each part of identification policy expression.
2663 //
2664 Success = FALSE;
2665 TotalLen = 0;
2666 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2667 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2668 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2669 switch (Identity->Type) {
2670
2671 case EFI_USER_INFO_IDENTITY_FALSE:
2672 //
2673 // Check False option.
2674 //
2675 Success = FALSE;
2676 break;
2677
2678 case EFI_USER_INFO_IDENTITY_TRUE:
2679 //
2680 // Check True option.
2681 //
2682 Success = TRUE;
2683 break;
2684
2685 case EFI_USER_INFO_IDENTITY_NOT:
2686 //
2687 // Check negative operation.
2688 //
2689 break;
2690
2691 case EFI_USER_INFO_IDENTITY_AND:
2692 //
2693 // Check and operation.
2694 //
2695 if (!Success) {
2696 return EFI_NOT_READY;
2697 }
2698
2699 Success = FALSE;
2700 break;
2701
2702 case EFI_USER_INFO_IDENTITY_OR:
2703 //
2704 // Check or operation.
2705 //
2706 if (Success) {
2707 return EFI_SUCCESS;
2708 }
2709 break;
2710
2711 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
2712 //
2713 // Check credential provider by type.
2714 //
2715 break;
2716
2717 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
2718 //
2719 // Check credential provider by ID.
2720 //
2721 if (ValueLen != sizeof (EFI_GUID)) {
2722 return EFI_INVALID_PARAMETER;
2723 }
2724
2725 Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1));
2726 if (EFI_ERROR (Status)) {
2727 return Status;
2728 }
2729
2730 Success = TRUE;
2731 break;
2732
2733 default:
2734 return EFI_INVALID_PARAMETER;
2735 break;
2736 }
2737
2738 TotalLen += Identity->Length;
2739 }
2740
2741 if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2742 return EFI_INVALID_PARAMETER;
2743 }
2744
2745 if (!Success) {
2746 return EFI_NOT_READY;
2747 }
2748
2749 return EFI_SUCCESS;
2750 }
2751
2752
2753 /**
2754 Identify the user whose identity policy does not contain the operator 'AND'.
2755
2756 @param[in] User Points to the user profile.
2757
2758 @retval EFI_SUCCESS The specified user is identified successfully.
2759 @retval Others Fail to identify the user.
2760
2761 **/
2762 EFI_STATUS
2763 IdentifyOrTypeUser (
2764 IN USER_PROFILE_ENTRY *User
2765 )
2766 {
2767 EFI_STATUS Status;
2768 EFI_USER_INFO *IdentifyInfo;
2769 UINTN TotalLen;
2770 UINTN ValueLen;
2771 EFI_USER_INFO_IDENTITY_POLICY *Identity;
2772 VOID *StartOpCodeHandle;
2773 VOID *EndOpCodeHandle;
2774 EFI_IFR_GUID_LABEL *StartLabel;
2775 EFI_IFR_GUID_LABEL *EndLabel;
2776
2777 //
2778 // Get user identify policy information.
2779 //
2780 IdentifyInfo = NULL;
2781 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2782 if (EFI_ERROR (Status)) {
2783 return Status;
2784 }
2785 ASSERT (IdentifyInfo != NULL);
2786
2787 //
2788 // Initialize the container for dynamic opcodes.
2789 //
2790 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2791 ASSERT (StartOpCodeHandle != NULL);
2792
2793 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2794 ASSERT (EndOpCodeHandle != NULL);
2795
2796 //
2797 // Create Hii Extend Label OpCode.
2798 //
2799 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2800 StartOpCodeHandle,
2801 &gEfiIfrTianoGuid,
2802 NULL,
2803 sizeof (EFI_IFR_GUID_LABEL)
2804 );
2805 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2806 StartLabel->Number = LABEL_PROVIDER_NAME;
2807
2808 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2809 EndOpCodeHandle,
2810 &gEfiIfrTianoGuid,
2811 NULL,
2812 sizeof (EFI_IFR_GUID_LABEL)
2813 );
2814 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2815 EndLabel->Number = LABEL_END;
2816
2817 //
2818 // Add the providers that exists in the user's policy.
2819 //
2820 TotalLen = 0;
2821 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2822 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2823 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2824 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
2825 AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle);
2826 }
2827
2828 TotalLen += Identity->Length;
2829 }
2830
2831 HiiUpdateForm (
2832 mCallbackInfo->HiiHandle, // HII handle
2833 &mUserManagerGuid, // Formset GUID
2834 FORMID_PROVIDER_FORM, // Form ID
2835 StartOpCodeHandle, // Label for where to insert opcodes
2836 EndOpCodeHandle // Replace data
2837 );
2838
2839 HiiFreeOpCodeHandle (StartOpCodeHandle);
2840 HiiFreeOpCodeHandle (EndOpCodeHandle);
2841
2842 return EFI_SUCCESS;
2843 }
2844
2845
2846 /**
2847 This function processes the results of changes in configuration.
2848
2849 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2850 @param Action Specifies the type of action taken by the browser.
2851 @param QuestionId A unique value which is sent to the original
2852 exporting driver so that it can identify the type
2853 of data to expect.
2854 @param Type The type of value for the question.
2855 @param Value A pointer to the data being sent to the original
2856 exporting driver.
2857 @param ActionRequest On return, points to the action requested by the
2858 callback function.
2859
2860 @retval EFI_SUCCESS The callback successfully handled the action.
2861 @retval Others Fail to handle the action.
2862
2863 **/
2864 EFI_STATUS
2865 EFIAPI
2866 UserIdentifyManagerCallback (
2867 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2868 IN EFI_BROWSER_ACTION Action,
2869 IN EFI_QUESTION_ID QuestionId,
2870 IN UINT8 Type,
2871 IN EFI_IFR_TYPE_VALUE *Value,
2872 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
2873 )
2874 {
2875 EFI_STATUS Status;
2876 USER_PROFILE_ENTRY *User;
2877 UINT8 PolicyType;
2878 UINT16 Index;
2879 VOID *StartOpCodeHandle;
2880 VOID *EndOpCodeHandle;
2881 EFI_IFR_GUID_LABEL *StartLabel;
2882 EFI_IFR_GUID_LABEL *EndLabel;
2883
2884 Status = EFI_SUCCESS;
2885
2886 switch (Action) {
2887 case EFI_BROWSER_ACTION_FORM_OPEN:
2888 {
2889 //
2890 // Update user Form when user Form is opened.
2891 // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form.
2892 //
2893 if (QuestionId != FORM_OPEN_QUESTION_ID) {
2894 return EFI_SUCCESS;
2895 }
2896
2897 //
2898 // Initialize the container for dynamic opcodes.
2899 //
2900 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2901 ASSERT (StartOpCodeHandle != NULL);
2902
2903 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2904 ASSERT (EndOpCodeHandle != NULL);
2905
2906 //
2907 // Create Hii Extend Label OpCode.
2908 //
2909 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2910 StartOpCodeHandle,
2911 &gEfiIfrTianoGuid,
2912 NULL,
2913 sizeof (EFI_IFR_GUID_LABEL)
2914 );
2915 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2916 StartLabel->Number = LABEL_USER_NAME;
2917
2918 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2919 EndOpCodeHandle,
2920 &gEfiIfrTianoGuid,
2921 NULL,
2922 sizeof (EFI_IFR_GUID_LABEL)
2923 );
2924 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2925 EndLabel->Number = LABEL_END;
2926
2927 //
2928 // Add all the user profile in the user profile database.
2929 //
2930 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
2931 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index];
2932 AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle);
2933 }
2934
2935 HiiUpdateForm (
2936 mCallbackInfo->HiiHandle, // HII handle
2937 &mUserManagerGuid, // Formset GUID
2938 FORMID_USER_FORM, // Form ID
2939 StartOpCodeHandle, // Label for where to insert opcodes
2940 EndOpCodeHandle // Replace data
2941 );
2942
2943 HiiFreeOpCodeHandle (StartOpCodeHandle);
2944 HiiFreeOpCodeHandle (EndOpCodeHandle);
2945
2946 return EFI_SUCCESS;
2947 }
2948 break;
2949
2950 case EFI_BROWSER_ACTION_FORM_CLOSE:
2951 Status = EFI_SUCCESS;
2952 break;
2953
2954 case EFI_BROWSER_ACTION_CHANGING:
2955 {
2956 if (QuestionId >= LABEL_PROVIDER_NAME) {
2957 //
2958 // QuestionId comes from the second Form (Select a Credential Provider if identity
2959 // policy is OR type). Identify the user by the selected provider.
2960 //
2961 Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier);
2962 if (Status == EFI_SUCCESS) {
2963 mIdentified = TRUE;
2964 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
2965 }
2966 return EFI_SUCCESS;
2967 }
2968
2969 //
2970 // QuestionId comes from the first Form (Select a user to identify).
2971 //
2972 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF];
2973 Status = GetIdentifyType (User, &PolicyType);
2974 if (EFI_ERROR (Status)) {
2975 return Status;
2976 }
2977
2978 if (PolicyType == EFI_USER_INFO_IDENTITY_OR) {
2979 //
2980 // Identify the user by "OR" logical.
2981 //
2982 Status = IdentifyOrTypeUser (User);
2983 if (EFI_ERROR (Status)) {
2984 return Status;
2985 }
2986
2987 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
2988 } else {
2989 //
2990 // Identify the user by "AND" logical.
2991 //
2992 Status = IdentifyAndTypeUser (User);
2993 if (EFI_ERROR (Status)) {
2994 return Status;
2995 }
2996
2997 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
2998 mIdentified = TRUE;
2999 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
3000 }
3001 }
3002 break;
3003
3004 default:
3005 //
3006 // All other action return unsupported.
3007 //
3008 Status = EFI_UNSUPPORTED;
3009 break;
3010 }
3011
3012
3013 return Status;
3014 }
3015
3016
3017 /**
3018 This function construct user profile database from user data saved in the Flash.
3019 If no user is found in Flash, add one default user "administrator" in the user
3020 profile database.
3021
3022 @retval EFI_SUCCESS Init user profile database successfully.
3023 @retval Others Fail to init user profile database.
3024
3025 **/
3026 EFI_STATUS
3027 InitUserProfileDb (
3028 VOID
3029 )
3030 {
3031 EFI_STATUS Status;
3032 UINT8 *VarData;
3033 UINTN VarSize;
3034 UINTN CurVarSize;
3035 CHAR16 VarName[10];
3036 UINTN Index;
3037 UINT32 VarAttr;
3038
3039 if (mUserProfileDb != NULL) {
3040 //
3041 // The user profiles had been already initialized.
3042 //
3043 return EFI_SUCCESS;
3044 }
3045
3046 //
3047 // Init user profile database structure.
3048 //
3049 if (!ExpandUsermUserProfileDb ()) {
3050 return EFI_OUT_OF_RESOURCES;
3051 }
3052
3053 CurVarSize = DEFAULT_PROFILE_SIZE;
3054 VarData = AllocateZeroPool (CurVarSize);
3055 if (VarData == NULL) {
3056 return EFI_OUT_OF_RESOURCES;
3057 }
3058
3059 //
3060 // Get all user proifle entries.
3061 //
3062 Index = 0;
3063 while (TRUE) {
3064 //
3065 // Get variable name.
3066 //
3067 UnicodeSPrint (
3068 VarName,
3069 sizeof (VarName),
3070 L"User%04x",
3071 Index
3072 );
3073 Index++;
3074
3075 //
3076 // Get variable value.
3077 //
3078 VarSize = CurVarSize;
3079 Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData);
3080 if (Status == EFI_BUFFER_TOO_SMALL) {
3081 FreePool (VarData);
3082 VarData = AllocatePool (VarSize);
3083 if (VarData == NULL) {
3084 Status = EFI_OUT_OF_RESOURCES;
3085 break;
3086 }
3087
3088 CurVarSize = VarSize;
3089 Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData);
3090 }
3091
3092 if (EFI_ERROR (Status)) {
3093 if (Status == EFI_NOT_FOUND) {
3094 Status = EFI_SUCCESS;
3095 }
3096 break;
3097 }
3098
3099 //
3100 // Check variable attributes.
3101 //
3102 if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
3103 Status = gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL);
3104 continue;
3105 }
3106
3107 //
3108 // Add user profile to the user profile database.
3109 //
3110 Status = AddUserProfile (NULL, VarSize, VarData, FALSE);
3111 if (EFI_ERROR (Status)) {
3112 if (Status == EFI_SECURITY_VIOLATION) {
3113 //
3114 // Delete invalid user profile
3115 //
3116 gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL);
3117 } else if (Status == EFI_OUT_OF_RESOURCES) {
3118 break;
3119 }
3120 } else {
3121 //
3122 // Delete and save the profile again if some invalid profiles are deleted.
3123 //
3124 if (mUserProfileDb->UserProfileNum < Index) {
3125 gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL);
3126 SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE);
3127 }
3128 }
3129 }
3130
3131 if (VarData != NULL) {
3132 FreePool (VarData);
3133 }
3134
3135 if (EFI_ERROR (Status)) {
3136 return Status;
3137 }
3138
3139 //
3140 // Check whether the user profile database is empty.
3141 //
3142 if (mUserProfileDb->UserProfileNum == 0) {
3143 Status = AddDefaultUserProfile ();
3144 }
3145
3146 return Status;
3147 }
3148
3149
3150 /**
3151 This function collects all the credential providers and saves to mProviderDb.
3152
3153 @retval EFI_SUCCESS Collect credential providers successfully.
3154 @retval Others Fail to collect credential providers.
3155
3156 **/
3157 EFI_STATUS
3158 InitProviderInfo (
3159 VOID
3160 )
3161 {
3162 EFI_STATUS Status;
3163 UINTN HandleCount;
3164 EFI_HANDLE *HandleBuf;
3165 UINTN Index;
3166
3167 if (mProviderDb != NULL) {
3168 //
3169 // The credential providers had been collected before.
3170 //
3171 return EFI_SUCCESS;
3172 }
3173
3174 //
3175 // Try to find all the user credential provider driver.
3176 //
3177 HandleCount = 0;
3178 HandleBuf = NULL;
3179 Status = gBS->LocateHandleBuffer (
3180 ByProtocol,
3181 &gEfiUserCredentialProtocolGuid,
3182 NULL,
3183 &HandleCount,
3184 &HandleBuf
3185 );
3186 if (EFI_ERROR (Status)) {
3187 return Status;
3188 }
3189
3190 //
3191 // Get provider infomation.
3192 //
3193 mProviderDb = AllocateZeroPool (
3194 sizeof (CREDENTIAL_PROVIDER_INFO) -
3195 sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) +
3196 HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *)
3197 );
3198 if (mProviderDb == NULL) {
3199 FreePool (HandleBuf);
3200 return EFI_OUT_OF_RESOURCES;
3201 }
3202
3203 mProviderDb->Count = HandleCount;
3204 for (Index = 0; Index < HandleCount; Index++) {
3205 Status = gBS->HandleProtocol (
3206 HandleBuf[Index],
3207 &gEfiUserCredentialProtocolGuid,
3208 (VOID **) &mProviderDb->Provider[Index]
3209 );
3210 if (EFI_ERROR (Status)) {
3211 FreePool (HandleBuf);
3212 FreePool (mProviderDb);
3213 mProviderDb = NULL;
3214 return Status;
3215 }
3216 }
3217
3218 FreePool (HandleBuf);
3219 return EFI_SUCCESS;
3220 }
3221
3222
3223 /**
3224 This function allows a caller to extract the current configuration for one
3225 or more named elements from the target driver.
3226
3227
3228 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3229 @param Request A null-terminated Unicode string in <ConfigRequest> format.
3230 @param Progress On return, points to a character in the Request string.
3231 Points to the string's null terminator if request was successful.
3232 Points to the most recent '&' before the first failing name/value
3233 pair (or the beginning of the string if the failure is in the
3234 first name/value pair) if the request was not successful.
3235 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
3236 has all values filled in for the names in the Request string.
3237 String to be allocated by the called function.
3238
3239 @retval EFI_SUCCESS The Results is filled with the requested values.
3240 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3241 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3242 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
3243
3244 **/
3245 EFI_STATUS
3246 EFIAPI
3247 FakeExtractConfig (
3248 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3249 IN CONST EFI_STRING Request,
3250 OUT EFI_STRING *Progress,
3251 OUT EFI_STRING *Results
3252 )
3253 {
3254 if (Progress == NULL || Results == NULL) {
3255 return EFI_INVALID_PARAMETER;
3256 }
3257 *Progress = Request;
3258 return EFI_NOT_FOUND;
3259 }
3260
3261 /**
3262 This function processes the results of changes in configuration.
3263
3264
3265 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3266 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
3267 @param Progress A pointer to a string filled in with the offset of the most
3268 recent '&' before the first failing name/value pair (or the
3269 beginning of the string if the failure is in the first
3270 name/value pair) or the terminating NULL if all was successful.
3271
3272 @retval EFI_SUCCESS The Results is processed successfully.
3273 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3274 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
3275
3276 **/
3277 EFI_STATUS
3278 EFIAPI
3279 FakeRouteConfig (
3280 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3281 IN CONST EFI_STRING Configuration,
3282 OUT EFI_STRING *Progress
3283 )
3284 {
3285 if (Configuration == NULL || Progress == NULL) {
3286 return EFI_INVALID_PARAMETER;
3287 }
3288
3289 return EFI_NOT_FOUND;
3290 }
3291
3292
3293 /**
3294 This function initialize the data mainly used in form browser.
3295
3296 @retval EFI_SUCCESS Initialize form data successfully.
3297 @retval Others Fail to Initialize form data.
3298
3299 **/
3300 EFI_STATUS
3301 InitFormBrowser (
3302 VOID
3303 )
3304 {
3305 EFI_STATUS Status;
3306 USER_MANAGER_CALLBACK_INFO *CallbackInfo;
3307 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
3308 EFI_HII_STRING_PROTOCOL *HiiString;
3309 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
3310
3311 //
3312 // Initialize driver private data.
3313 //
3314 CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO));
3315 if (CallbackInfo == NULL) {
3316 return EFI_OUT_OF_RESOURCES;
3317 }
3318
3319 CallbackInfo->Signature = USER_MANAGER_SIGNATURE;
3320 CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig;
3321 CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig;
3322 CallbackInfo->ConfigAccess.Callback = UserIdentifyManagerCallback;
3323
3324 //
3325 // Locate Hii Database protocol.
3326 //
3327 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
3328 if (EFI_ERROR (Status)) {
3329 return Status;
3330 }
3331 CallbackInfo->HiiDatabase = HiiDatabase;
3332
3333 //
3334 // Locate HiiString protocol.
3335 //
3336 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
3337 if (EFI_ERROR (Status)) {
3338 return Status;
3339 }
3340 CallbackInfo->HiiString = HiiString;
3341
3342 //
3343 // Locate Formbrowser2 protocol.
3344 //
3345 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
3346 if (EFI_ERROR (Status)) {
3347 return Status;
3348 }
3349
3350 CallbackInfo->FormBrowser2 = FormBrowser2;
3351 CallbackInfo->DriverHandle = NULL;
3352
3353 //
3354 // Install Device Path Protocol and Config Access protocol to driver handle.
3355 //
3356 Status = gBS->InstallMultipleProtocolInterfaces (
3357 &CallbackInfo->DriverHandle,
3358 &gEfiDevicePathProtocolGuid,
3359 &mHiiVendorDevicePath,
3360 &gEfiHiiConfigAccessProtocolGuid,
3361 &CallbackInfo->ConfigAccess,
3362 NULL
3363 );
3364 ASSERT_EFI_ERROR (Status);
3365
3366 //
3367 // Publish HII data.
3368 //
3369 CallbackInfo->HiiHandle = HiiAddPackages (
3370 &mUserManagerGuid,
3371 CallbackInfo->DriverHandle,
3372 UserIdentifyManagerStrings,
3373 UserIdentifyManagerVfrBin,
3374 NULL
3375 );
3376 if (CallbackInfo->HiiHandle == NULL) {
3377 return EFI_OUT_OF_RESOURCES;
3378 }
3379
3380 mCallbackInfo = CallbackInfo;
3381
3382 return EFI_SUCCESS;
3383 }
3384
3385
3386 /**
3387 Identify the user whose identification policy supports auto logon.
3388
3389 @param[in] ProviderIndex The provider index in the provider list.
3390 @param[out] User Points to user user profile if a user is identified successfully.
3391
3392 @retval EFI_SUCCESS Identify a user with the specified provider successfully.
3393 @retval Others Fail to identify a user.
3394
3395 **/
3396 EFI_STATUS
3397 IdentifyAutoLogonUser (
3398 IN UINTN ProviderIndex,
3399 OUT USER_PROFILE_ENTRY **User
3400 )
3401 {
3402 EFI_STATUS Status;
3403 EFI_USER_INFO *Info;
3404 UINT8 PolicyType;
3405
3406 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
3407 if (Info == NULL) {
3408 return EFI_OUT_OF_RESOURCES;
3409 }
3410
3411 Info->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD;
3412 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
3413
3414 //
3415 // Identify the specified credential provider's auto logon user.
3416 //
3417 Status = mProviderDb->Provider[ProviderIndex]->User (
3418 mProviderDb->Provider[ProviderIndex],
3419 NULL,
3420 (EFI_USER_INFO_IDENTIFIER *) (Info + 1)
3421 );
3422 if (EFI_ERROR (Status)) {
3423 FreePool (Info);
3424 return Status;
3425 }
3426
3427 //
3428 // Find user with the specified user ID.
3429 //
3430 *User = NULL;
3431 Status = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize);
3432 FreePool (Info);
3433 if (EFI_ERROR (Status)) {
3434 return Status;
3435 }
3436
3437 Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType);
3438 if (PolicyType == EFI_USER_INFO_IDENTITY_AND) {
3439 //
3440 // The identified user need also identified by other credential provider.
3441 // This can handle through select user.
3442 //
3443 return EFI_NOT_READY;
3444 }
3445
3446 return Status;
3447 }
3448
3449
3450 /**
3451 Check whether the given console is ready.
3452
3453 @param[in] ProtocolGuid Points to the protocol guid of sonsole .
3454
3455 @retval TRUE The given console is ready.
3456 @retval FALSE The given console is not ready.
3457
3458 **/
3459 BOOLEAN
3460 CheckConsole (
3461 EFI_GUID *ProtocolGuid
3462 )
3463 {
3464 EFI_STATUS Status;
3465 UINTN HandleCount;
3466 EFI_HANDLE *HandleBuf;
3467 UINTN Index;
3468 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3469
3470 //
3471 // Try to find all the handle driver.
3472 //
3473 HandleCount = 0;
3474 HandleBuf = NULL;
3475 Status = gBS->LocateHandleBuffer (
3476 ByProtocol,
3477 ProtocolGuid,
3478 NULL,
3479 &HandleCount,
3480 &HandleBuf
3481 );
3482 if (EFI_ERROR (Status)) {
3483 return FALSE;
3484 }
3485
3486 for (Index = 0; Index < HandleCount; Index++) {
3487 DevicePath = DevicePathFromHandle (HandleBuf[Index]);
3488 if (DevicePath != NULL) {
3489 FreePool (HandleBuf);
3490 return TRUE;
3491 }
3492 }
3493 FreePool (HandleBuf);
3494 return FALSE;
3495 }
3496
3497
3498 /**
3499 Check whether the console is ready.
3500
3501 @retval TRUE The console is ready.
3502 @retval FALSE The console is not ready.
3503
3504 **/
3505 BOOLEAN
3506 IsConsoleReady (
3507 VOID
3508 )
3509 {
3510 if (!CheckConsole (&gEfiSimpleTextOutProtocolGuid)) {
3511 return FALSE;
3512 }
3513
3514 if (!CheckConsole (&gEfiSimpleTextInProtocolGuid)) {
3515 if (!CheckConsole (&gEfiSimpleTextInputExProtocolGuid)) {
3516 return FALSE;
3517 }
3518 }
3519
3520 return TRUE;
3521 }
3522
3523
3524 /**
3525 Identify a user to logon.
3526
3527 @param[out] User Points to user user profile if a user is identified successfully.
3528
3529 @retval EFI_SUCCESS Identify a user successfully.
3530
3531 **/
3532 EFI_STATUS
3533 IdentifyUser (
3534 OUT USER_PROFILE_ENTRY **User
3535 )
3536 {
3537 EFI_STATUS Status;
3538 UINTN Index;
3539 EFI_CREDENTIAL_LOGON_FLAGS AutoLogon;
3540 EFI_USER_INFO *IdentifyInfo;
3541 EFI_USER_INFO_IDENTITY_POLICY *Identity;
3542 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
3543 USER_PROFILE_ENTRY *UserEntry;
3544
3545 //
3546 // Initialize credential providers.
3547 //
3548 InitProviderInfo ();
3549
3550 //
3551 // Initialize user profile database.
3552 //
3553 InitUserProfileDb ();
3554
3555 //
3556 // If only one user in system, and its identify policy is TRUE, then auto logon.
3557 //
3558 if (mUserProfileDb->UserProfileNum == 1) {
3559 UserEntry = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[0];
3560 IdentifyInfo = NULL;
3561 Status = FindUserInfoByType (UserEntry, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
3562 if (EFI_ERROR (Status)) {
3563 return Status;
3564 }
3565 ASSERT (IdentifyInfo != NULL);
3566
3567 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1));
3568 if (Identity->Type == EFI_USER_INFO_IDENTITY_TRUE) {
3569 mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
3570 UpdateUserInfo (UserEntry);
3571 *User = UserEntry;
3572 return EFI_SUCCESS;
3573 }
3574 }
3575
3576 //
3577 // Find and login the default & AutoLogon user.
3578 //
3579 for (Index = 0; Index < mProviderDb->Count; Index++) {
3580 UserCredential = mProviderDb->Provider[Index];
3581 Status = UserCredential->Default (UserCredential, &AutoLogon);
3582 if (EFI_ERROR (Status)) {
3583 continue;
3584 }
3585
3586 if ((AutoLogon & (EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO)) != 0) {
3587 Status = IdentifyAutoLogonUser (Index, &UserEntry);
3588 if (Status == EFI_SUCCESS) {
3589 mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
3590 UpdateUserInfo (UserEntry);
3591 *User = UserEntry;
3592 return EFI_SUCCESS;
3593 }
3594 }
3595 }
3596
3597 if (!IsConsoleReady ()) {
3598 //
3599 // The console is still not ready for user selection.
3600 //
3601 return EFI_ACCESS_DENIED;
3602 }
3603
3604 //
3605 // Select a user and identify it.
3606 //
3607 mCallbackInfo->FormBrowser2->SendForm (
3608 mCallbackInfo->FormBrowser2,
3609 &mCallbackInfo->HiiHandle,
3610 1,
3611 &mUserManagerGuid,
3612 0,
3613 NULL,
3614 NULL
3615 );
3616
3617 if (mIdentified) {
3618 *User = (USER_PROFILE_ENTRY *) mCurrentUser;
3619 UpdateUserInfo (*User);
3620 return EFI_SUCCESS;
3621 }
3622
3623 return EFI_ACCESS_DENIED;
3624 }
3625
3626
3627 /**
3628 An empty function to pass error checking of CreateEventEx ().
3629
3630 @param Event Event whose notification function is being invoked.
3631 @param Context Pointer to the notification function's context,
3632 which is implementation-dependent.
3633
3634 **/
3635 VOID
3636 EFIAPI
3637 InternalEmptyFuntion (
3638 IN EFI_EVENT Event,
3639 IN VOID *Context
3640 )
3641 {
3642 }
3643
3644
3645 /**
3646 Create, Signal, and Close the User Profile Changed event.
3647
3648 **/
3649 VOID
3650 SignalEventUserProfileChanged (
3651 VOID
3652 )
3653 {
3654 EFI_STATUS Status;
3655 EFI_EVENT Event;
3656
3657 Status = gBS->CreateEventEx (
3658 EVT_NOTIFY_SIGNAL,
3659 TPL_CALLBACK,
3660 InternalEmptyFuntion,
3661 NULL,
3662 &gEfiEventUserProfileChangedGuid,
3663 &Event
3664 );
3665 ASSERT_EFI_ERROR (Status);
3666 gBS->SignalEvent (Event);
3667 gBS->CloseEvent (Event);
3668 }
3669
3670
3671 /**
3672 Create a new user profile.
3673
3674 This function creates a new user profile with only a new user identifier attached and returns
3675 its handle. The user profile is non-volatile, but the handle User can change across reboots.
3676
3677 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3678 @param[out] User On return, points to the new user profile handle.
3679 The user profile handle is unique only during this boot.
3680
3681 @retval EFI_SUCCESS User profile was successfully created.
3682 @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to create a
3683 user profile.
3684 @retval EFI_UNSUPPORTED Creation of new user profiles is not supported.
3685 @retval EFI_INVALID_PARAMETER The User parameter is NULL.
3686
3687 **/
3688 EFI_STATUS
3689 EFIAPI
3690 UserProfileCreate (
3691 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3692 OUT EFI_USER_PROFILE_HANDLE *User
3693 )
3694 {
3695 EFI_STATUS Status;
3696
3697 if ((This == NULL) || (User == NULL)) {
3698 return EFI_INVALID_PARAMETER;
3699 }
3700
3701 //
3702 // Check the right of the current user.
3703 //
3704 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3705 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
3706 return EFI_ACCESS_DENIED;
3707 }
3708 }
3709
3710 //
3711 // Create new user profile
3712 //
3713 Status = CreateUserProfile ((USER_PROFILE_ENTRY **) User);
3714 if (EFI_ERROR (Status)) {
3715 return EFI_ACCESS_DENIED;
3716 }
3717 return EFI_SUCCESS;
3718 }
3719
3720
3721 /**
3722 Delete an existing user profile.
3723
3724 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3725 @param[in] User User profile handle.
3726
3727 @retval EFI_SUCCESS User profile was successfully deleted.
3728 @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to delete a user
3729 profile or there is only one user profile.
3730 @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported.
3731 @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile.
3732
3733 **/
3734 EFI_STATUS
3735 EFIAPI
3736 UserProfileDelete (
3737 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3738 IN EFI_USER_PROFILE_HANDLE User
3739 )
3740 {
3741 EFI_STATUS Status;
3742
3743 if (This == NULL) {
3744 return EFI_INVALID_PARAMETER;
3745 }
3746
3747 //
3748 // Check the right of the current user.
3749 //
3750 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3751 return EFI_ACCESS_DENIED;
3752 }
3753
3754 //
3755 // Delete user profile.
3756 //
3757 Status = DelUserProfile (User);
3758 if (EFI_ERROR (Status)) {
3759 if (Status != EFI_INVALID_PARAMETER) {
3760 return EFI_ACCESS_DENIED;
3761 }
3762 return EFI_INVALID_PARAMETER;
3763 }
3764
3765 return EFI_SUCCESS;
3766 }
3767
3768
3769 /**
3770 Enumerate all of the enrolled users on the platform.
3771
3772 This function returns the next enrolled user profile. To retrieve the first user profile handle,
3773 point User at a NULL. Each subsequent call will retrieve another user profile handle until there
3774 are no more, at which point User will point to NULL.
3775
3776 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3777 @param[in, out] User On entry, points to the previous user profile handle or NULL to
3778 start enumeration. On exit, points to the next user profile handle
3779 or NULL if there are no more user profiles.
3780
3781 @retval EFI_SUCCESS Next enrolled user profile successfully returned.
3782 @retval EFI_ACCESS_DENIED Next enrolled user profile was not successfully returned.
3783 @retval EFI_INVALID_PARAMETER The User parameter is NULL.
3784 **/
3785 EFI_STATUS
3786 EFIAPI
3787 UserProfileGetNext (
3788 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3789 IN OUT EFI_USER_PROFILE_HANDLE *User
3790 )
3791 {
3792 EFI_STATUS Status;
3793
3794 if ((This == NULL) || (User == NULL)) {
3795 return EFI_INVALID_PARAMETER;
3796 }
3797
3798 Status = FindUserProfile ((USER_PROFILE_ENTRY **) User, TRUE, NULL);
3799 if (EFI_ERROR (Status)) {
3800 return EFI_ACCESS_DENIED;
3801 }
3802 return EFI_SUCCESS;
3803 }
3804
3805
3806 /**
3807 Return the current user profile handle.
3808
3809 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3810 @param[out] CurrentUser On return, points to the current user profile handle.
3811
3812 @retval EFI_SUCCESS Current user profile handle returned successfully.
3813 @retval EFI_INVALID_PARAMETER The CurrentUser parameter is NULL.
3814
3815 **/
3816 EFI_STATUS
3817 EFIAPI
3818 UserProfileCurrent (
3819 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3820 OUT EFI_USER_PROFILE_HANDLE *CurrentUser
3821 )
3822 {
3823 //
3824 // Get current user profile.
3825 //
3826 if ((This == NULL) || (CurrentUser == NULL)) {
3827 return EFI_INVALID_PARAMETER;
3828 }
3829
3830 *CurrentUser = mCurrentUser;
3831 return EFI_SUCCESS;
3832 }
3833
3834
3835 /**
3836 Identify a user.
3837
3838 Identify the user and, if authenticated, returns the user handle and changes the current
3839 user profile. All user information marked as private in a previously selected profile
3840 is no longer available for inspection.
3841 Whenever the current user profile is changed then the an event with the GUID
3842 EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled.
3843
3844 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3845 @param[out] User On return, points to the user profile handle for the current
3846 user profile.
3847
3848 @retval EFI_SUCCESS User was successfully identified.
3849 @retval EFI_ACCESS_DENIED User was not successfully identified.
3850 @retval EFI_INVALID_PARAMETER The User parameter is NULL.
3851
3852 **/
3853 EFI_STATUS
3854 EFIAPI
3855 UserProfileIdentify (
3856 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3857 OUT EFI_USER_PROFILE_HANDLE *User
3858 )
3859 {
3860 EFI_STATUS Status;
3861
3862 if ((This == NULL) || (User == NULL)) {
3863 return EFI_INVALID_PARAMETER;
3864 }
3865
3866 if (mCurrentUser != NULL) {
3867 *User = mCurrentUser;
3868 return EFI_SUCCESS;
3869 }
3870
3871 //
3872 // Identify user
3873 //
3874 Status = IdentifyUser ((USER_PROFILE_ENTRY **) User);
3875 if (EFI_ERROR (Status)) {
3876 return EFI_ACCESS_DENIED;
3877 }
3878
3879 //
3880 // Publish the user info into the EFI system configuration table.
3881 //
3882 PublishUserTable ();
3883
3884 //
3885 // Signal User Profile Changed event.
3886 //
3887 SignalEventUserProfileChanged ();
3888 return EFI_SUCCESS;
3889 }
3890
3891 /**
3892 Find a user using a user information record.
3893
3894 This function searches all user profiles for the specified user information record.
3895 The search starts with the user information record handle following UserInfo and
3896 continues until either the information is found or there are no more user profiles.
3897 A match occurs when the Info.InfoType field matches the user information record
3898 type and the user information record data matches the portion of Info.
3899
3900 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3901 @param[in, out] User On entry, points to the previously returned user profile
3902 handle, or NULL to start searching with the first user profile.
3903 On return, points to the user profile handle, or NULL if not
3904 found.
3905 @param[in, out] UserInfo On entry, points to the previously returned user information
3906 handle, or NULL to start searching with the first. On return,
3907 points to the user information handle of the user information
3908 record, or NULL if not found. Can be NULL, in which case only
3909 one user information record per user can be returned.
3910 @param[in] Info Points to the buffer containing the user information to be
3911 compared to the user information record. If the user information
3912 record data is empty, then only the user information record type
3913 is compared. If InfoSize is 0, then the user information record
3914 must be empty.
3915
3916 @param[in] InfoSize The size of Info, in bytes.
3917
3918 @retval EFI_SUCCESS User information was found. User points to the user profile
3919 handle, and UserInfo points to the user information handle.
3920 @retval EFI_NOT_FOUND User information was not found. User points to NULL, and
3921 UserInfo points to NULL.
3922 @retval EFI_INVALID_PARAMETER User is NULL. Or Info is NULL.
3923
3924 **/
3925 EFI_STATUS
3926 EFIAPI
3927 UserProfileFind (
3928 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
3929 IN OUT EFI_USER_PROFILE_HANDLE *User,
3930 IN OUT EFI_USER_INFO_HANDLE *UserInfo OPTIONAL,
3931 IN CONST EFI_USER_INFO *Info,
3932 IN UINTN InfoSize
3933 )
3934 {
3935 EFI_STATUS Status;
3936 UINTN Size;
3937
3938 if ((This == NULL) || (User == NULL) || (Info == NULL)) {
3939 return EFI_INVALID_PARAMETER;
3940 }
3941
3942 if (InfoSize == 0) {
3943 //
3944 // If InfoSize is 0, then the user information record must be empty.
3945 //
3946 if (Info->InfoSize != sizeof (EFI_USER_INFO)) {
3947 return EFI_INVALID_PARAMETER;
3948 }
3949 } else {
3950 if (InfoSize != Info->InfoSize) {
3951 return EFI_INVALID_PARAMETER;
3952 }
3953 }
3954 Size = Info->InfoSize;
3955
3956 //
3957 // Find user profile accdoring to user information.
3958 //
3959 Status = FindUserProfileByInfo (
3960 (USER_PROFILE_ENTRY **) User,
3961 (EFI_USER_INFO **) UserInfo,
3962 (EFI_USER_INFO *) Info,
3963 Size
3964 );
3965 if (EFI_ERROR (Status)) {
3966 *User = NULL;
3967 if (UserInfo != NULL) {
3968 *UserInfo = NULL;
3969 }
3970 return EFI_NOT_FOUND;
3971 }
3972
3973 return EFI_SUCCESS;
3974 }
3975
3976
3977 /**
3978 Return information attached to the user.
3979
3980 This function returns user information. The format of the information is described in User
3981 Information. The function may return EFI_ACCESS_DENIED if the information is marked private
3982 and the handle specified by User is not the current user profile. The function may return
3983 EFI_ACCESS_DENIED if the information is marked protected and the information is associated
3984 with a credential provider for which the user has not been authenticated.
3985
3986 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3987 @param[in] User Handle of the user whose profile will be retrieved.
3988 @param[in] UserInfo Handle of the user information data record.
3989 @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit,
3990 holds the user information. If the buffer is too small to hold the
3991 information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
3992 updated to contain the number of bytes actually required.
3993 @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the size
3994 of the user information.
3995
3996 @retval EFI_SUCCESS Information returned successfully.
3997 @retval EFI_ACCESS_DENIED The information about the specified user cannot be accessed by the
3998 current user.
3999 @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the
4000 returned data. The actual size required is returned in *InfoSize.
4001 @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not refer
4002 to a valid user info handle.
4003 @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
4004
4005 **/
4006 EFI_STATUS
4007 EFIAPI
4008 UserProfileGetInfo (
4009 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
4010 IN EFI_USER_PROFILE_HANDLE User,
4011 IN EFI_USER_INFO_HANDLE UserInfo,
4012 OUT EFI_USER_INFO *Info,
4013 IN OUT UINTN *InfoSize
4014 )
4015 {
4016 EFI_STATUS Status;
4017
4018 if ((This == NULL) || (InfoSize == NULL)) {
4019 return EFI_INVALID_PARAMETER;
4020 }
4021
4022 if ((*InfoSize != 0) && (Info == NULL)) {
4023 return EFI_INVALID_PARAMETER;
4024 }
4025
4026 if ((User == NULL) || (UserInfo == NULL)) {
4027 return EFI_NOT_FOUND;
4028 }
4029
4030 Status = GetUserInfo (User, UserInfo, Info, InfoSize, TRUE);
4031 if (EFI_ERROR (Status)) {
4032 if (Status == EFI_BUFFER_TOO_SMALL) {
4033 return EFI_BUFFER_TOO_SMALL;
4034 }
4035 return EFI_ACCESS_DENIED;
4036 }
4037 return EFI_SUCCESS;
4038 }
4039
4040
4041 /**
4042 Add or update user information.
4043
4044 This function changes user information. If NULL is pointed to by UserInfo, then a new user
4045 information record is created and its handle is returned in UserInfo. Otherwise, the existing
4046 one is replaced.
4047 If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same
4048 type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and UserInfo
4049 will point to the handle of the existing record.
4050
4051 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
4052 @param[in] User Handle of the user whose profile will be retrieved.
4053 @param[in, out] UserInfo Handle of the user information data record.
4054 @param[in] Info On entry, points to a buffer of at least *InfoSize bytes. On exit,
4055 holds the user information. If the buffer is too small to hold the
4056 information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
4057 updated to contain the number of bytes actually required.
4058 @param[in] InfoSize On entry, points to the size of Info. On return, points to the size
4059 of the user information.
4060
4061 @retval EFI_SUCCESS Information returned successfully.
4062 @retval EFI_ACCESS_DENIED The record is exclusive.
4063 @retval EFI_SECURITY_VIOLATION The current user does not have permission to change the specified
4064 user profile or user information record.
4065 @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not
4066 refer to a valid user info handle.
4067 @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL.
4068 **/
4069 EFI_STATUS
4070 EFIAPI
4071 UserProfileSetInfo (
4072 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
4073 IN EFI_USER_PROFILE_HANDLE User,
4074 IN OUT EFI_USER_INFO_HANDLE *UserInfo,
4075 IN CONST EFI_USER_INFO *Info,
4076 IN UINTN InfoSize
4077 )
4078 {
4079 EFI_STATUS Status;
4080
4081 if ((This == NULL) || (User == NULL) || (UserInfo == NULL) || (Info == NULL)) {
4082 return EFI_INVALID_PARAMETER;
4083 }
4084
4085 //
4086 // Check the right of the current user.
4087 //
4088 if (User != mCurrentUser) {
4089 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
4090 if (*UserInfo != NULL) {
4091 //
4092 // Can't update info in other profiles without MANAGE right.
4093 //
4094 return EFI_SECURITY_VIOLATION;
4095 }
4096
4097 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
4098 //
4099 // Can't add info into other profiles.
4100 //
4101 return EFI_SECURITY_VIOLATION;
4102 }
4103 }
4104 }
4105
4106 if (User == mCurrentUser) {
4107 if (CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_SELF)) {
4108 //
4109 // Only identify policy can be added/updated.
4110 //
4111 if (Info->InfoType != EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
4112 return EFI_SECURITY_VIOLATION;
4113 }
4114 }
4115 }
4116
4117 //
4118 // Modify user information.
4119 //
4120 Status = ModifyUserInfo (User, (EFI_USER_INFO **) UserInfo, Info, InfoSize);
4121 if (EFI_ERROR (Status)) {
4122 if (Status == EFI_ACCESS_DENIED) {
4123 return EFI_ACCESS_DENIED;
4124 }
4125 return EFI_SECURITY_VIOLATION;
4126 }
4127 return EFI_SUCCESS;
4128 }
4129
4130
4131 /**
4132 Called by credential provider to notify of information change.
4133
4134 This function allows the credential provider to notify the User Identity Manager when user status
4135 has changed while deselected.
4136 If the User Identity Manager doesn't support asynchronous changes in credentials, then this function
4137 should return EFI_UNSUPPORTED.
4138 If the User Identity Manager supports this, it will call User() to get the user identifier and then
4139 GetNextInfo() and GetInfo() in the User Credential Protocol to get all of the information from the
4140 credential and add it.
4141
4142 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
4143 @param[in] Changed Handle on which is installed an instance of the EFI_USER_CREDENTIAL_PROTOCOL
4144 where the user has changed.
4145
4146 @retval EFI_SUCCESS The User Identity Manager has handled the notification.
4147 @retval EFI_NOT_READY The function was called while the specified credential provider was not selected.
4148 @retval EFI_UNSUPPORTED The User Identity Manager doesn't support asynchronous notifications.
4149
4150 **/
4151 EFI_STATUS
4152 EFIAPI
4153 UserProfileNotify (
4154 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
4155 IN EFI_HANDLE Changed
4156 )
4157 {
4158 EFI_STATUS Status;
4159 EFI_USER_CREDENTIAL_PROTOCOL *Provider;
4160 EFI_USER_INFO_IDENTIFIER UserId;
4161 EFI_USER_INFO_HANDLE UserInfo;
4162 EFI_USER_INFO_HANDLE UserInfo2;
4163 UINTN InfoSize;
4164 EFI_USER_INFO *Info;
4165 USER_PROFILE_ENTRY *User;
4166
4167 if (This == NULL) {
4168 return EFI_INVALID_PARAMETER;
4169 }
4170
4171 Status = gBS->HandleProtocol (
4172 Changed,
4173 &gEfiUserCredentialProtocolGuid,
4174 (VOID **) &Provider
4175 );
4176 if (EFI_ERROR (Status)) {
4177 return Status;
4178 }
4179
4180 Status = Provider->User (Provider, NULL, &UserId);
4181 if (EFI_ERROR (Status)) {
4182 return EFI_NOT_READY;
4183 }
4184
4185 //
4186 // Find user with the UserId.
4187 //
4188 User = NULL;
4189 while (TRUE) {
4190 //
4191 // Find next user profile.
4192 //
4193 Status = FindUserProfile (&User, TRUE, NULL);
4194 if (EFI_ERROR (Status)) {
4195 return Status;
4196 }
4197
4198 //
4199 // Find the user information.
4200 //
4201 Info = NULL;
4202 FindUserInfoByType (User, &Info, EFI_USER_INFO_IDENTIFIER_RECORD);
4203 if (CompareMem ((UINT8 *) (Info + 1), UserId, sizeof (UserId)) == 0) {
4204 //
4205 // Found the infomation record.
4206 //
4207 break;
4208 }
4209 }
4210
4211 UserInfo = NULL;
4212 do {
4213 //
4214 // Get user info handle.
4215 //
4216 Status = Provider->GetNextInfo(Provider, &UserInfo);
4217 if (EFI_ERROR (Status)) {
4218 return EFI_SUCCESS;
4219 }
4220
4221 //
4222 // Get the user information from the user info handle.
4223 //
4224 InfoSize = 0;
4225 Status = Provider->GetInfo(Provider, UserInfo, NULL, &InfoSize);
4226 if (EFI_ERROR (Status)) {
4227 if (Status == EFI_BUFFER_TOO_SMALL) {
4228 Info = AllocateZeroPool (InfoSize);
4229 if (Info == NULL) {
4230 return EFI_OUT_OF_RESOURCES;
4231 }
4232 Status = Provider->GetInfo(Provider, UserInfo, Info, &InfoSize);
4233 if (EFI_ERROR (Status)) {
4234 FreePool (Info);
4235 break;
4236 }
4237 }
4238 break;
4239 }
4240
4241 //
4242 // Save the user information.
4243 //
4244 UserInfo2 = NULL;
4245 Status = UserProfileSetInfo (&gUserIdentifyManager, (EFI_USER_PROFILE_HANDLE)User, &UserInfo2, Info, InfoSize);
4246 FreePool (Info);
4247 if (EFI_ERROR (Status)) {
4248 break;
4249 }
4250 } while (TRUE);
4251
4252 return Status;
4253 }
4254
4255
4256 /**
4257 Delete user information.
4258
4259 Delete the user information attached to the user profile specified by the UserInfo.
4260
4261 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
4262 @param[in] User Handle of the user whose information will be deleted.
4263 @param[in] UserInfo Handle of the user information to remove.
4264
4265 @retval EFI_SUCCESS User information deleted successfully.
4266 @retval EFI_NOT_FOUND User information record UserInfo does not exist in the user profile.
4267 @retval EFI_ACCESS_DENIED The current user does not have permission to delete this user information.
4268
4269 **/
4270 EFI_STATUS
4271 EFIAPI
4272 UserProfileDeleteInfo (
4273 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
4274 IN EFI_USER_PROFILE_HANDLE User,
4275 IN EFI_USER_INFO_HANDLE UserInfo
4276 )
4277 {
4278 EFI_STATUS Status;
4279
4280 if (This == NULL) {
4281 return EFI_INVALID_PARAMETER;
4282 }
4283
4284 //
4285 // Check the right of the current user.
4286 //
4287 if (User != mCurrentUser) {
4288 if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
4289 return EFI_ACCESS_DENIED;
4290 }
4291 }
4292
4293 //
4294 // Delete user information.
4295 //
4296 Status = DelUserInfo (User, UserInfo, TRUE);
4297 if (EFI_ERROR (Status)) {
4298 if (Status == EFI_NOT_FOUND) {
4299 return EFI_NOT_FOUND;
4300 }
4301 return EFI_ACCESS_DENIED;
4302 }
4303 return EFI_SUCCESS;
4304 }
4305
4306
4307 /**
4308 Enumerate user information of all the enrolled users on the platform.
4309
4310 This function returns the next user information record. To retrieve the first user
4311 information record handle, point UserInfo at a NULL. Each subsequent call will retrieve
4312 another user information record handle until there are no more, at which point UserInfo
4313 will point to NULL.
4314
4315 @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
4316 @param[in] User Handle of the user whose information will be deleted.
4317 @param[in, out] UserInfo Handle of the user information to remove.
4318
4319 @retval EFI_SUCCESS User information returned.
4320 @retval EFI_NOT_FOUND No more user information found.
4321 @retval EFI_INVALID_PARAMETER UserInfo is NULL.
4322
4323 **/
4324 EFI_STATUS
4325 EFIAPI
4326 UserProfileGetNextInfo (
4327 IN CONST EFI_USER_MANAGER_PROTOCOL *This,
4328 IN EFI_USER_PROFILE_HANDLE User,
4329 IN OUT EFI_USER_INFO_HANDLE *UserInfo
4330 )
4331 {
4332 if ((This == NULL) || (UserInfo == NULL)) {
4333 return EFI_INVALID_PARAMETER;
4334 }
4335 //
4336 // Get next user information entry.
4337 //
4338 return FindUserInfo (User, (EFI_USER_INFO **) UserInfo, TRUE, NULL);
4339 }
4340
4341
4342 /**
4343 Main entry for this driver.
4344
4345 @param[in] ImageHandle Image handle this driver.
4346 @param[in] SystemTable Pointer to SystemTable.
4347
4348 @retval EFI_SUCESS This function always complete successfully.
4349
4350 **/
4351 EFI_STATUS
4352 EFIAPI
4353 UserIdentifyManagerInit (
4354 IN EFI_HANDLE ImageHandle,
4355 IN EFI_SYSTEM_TABLE *SystemTable
4356 )
4357 {
4358
4359 EFI_STATUS Status;
4360
4361 //
4362 // Initiate form browser.
4363 //
4364 InitFormBrowser ();
4365
4366 //
4367 // Install protocol interfaces for the User Identity Manager.
4368 //
4369 Status = gBS->InstallProtocolInterface (
4370 &mCallbackInfo->DriverHandle,
4371 &gEfiUserManagerProtocolGuid,
4372 EFI_NATIVE_INTERFACE,
4373 &gUserIdentifyManager
4374 );
4375 ASSERT_EFI_ERROR (Status);
4376
4377 LoadDeferredImageInit (ImageHandle);
4378 return EFI_SUCCESS;
4379 }
4380
4381