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 //