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