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