Add security package to repository.
[mirror_edk2.git] / SecurityPkg / UserIdentification / UserIdentifyManagerDxe / UserIdentifyManager.c
CommitLineData
0c18794e 1/** @file\r
2 This driver manages user information and produces user manager protocol.\r
3 \r
4Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "UserIdentifyManager.h"\r
16\r
17//\r
18// Guid used in user profile saving and in form browser.\r
19//\r
20EFI_GUID mUserManagerGuid = USER_IDENTIFY_MANAGER_GUID;\r
21\r
22//\r
23// Default user name.\r
24//\r
25CHAR16 mUserName[] = L"Administrator";\r
26\r
27//\r
28// Points to the user profile database.\r
29//\r
30USER_PROFILE_DB *mUserProfileDb = NULL;\r
31\r
32//\r
33// Points to the credential providers found in system.\r
34//\r
35CREDENTIAL_PROVIDER_INFO *mProviderDb = NULL;\r
36\r
37//\r
38// Current user shared in multi function.\r
39//\r
40EFI_USER_PROFILE_HANDLE mCurrentUser = NULL;\r
41\r
42//\r
43// Flag indicates a user is identified.\r
44//\r
45BOOLEAN mIdentified = FALSE;\r
46USER_MANAGER_CALLBACK_INFO *mCallbackInfo = NULL;\r
47HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {\r
48 {\r
49 {\r
50 HARDWARE_DEVICE_PATH,\r
51 HW_VENDOR_DP,\r
52 {\r
53 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
54 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
55 }\r
56 },\r
57 //\r
58 // {ACA7C06F-743C-454f-9C6D-692138482498}\r
59 //\r
60 { 0xaca7c06f, 0x743c, 0x454f, { 0x9c, 0x6d, 0x69, 0x21, 0x38, 0x48, 0x24, 0x98 } }\r
61 },\r
62 {\r
63 END_DEVICE_PATH_TYPE,\r
64 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
65 {\r
66 (UINT8) (END_DEVICE_PATH_LENGTH),\r
67 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
68 }\r
69 }\r
70};\r
71\r
72\r
73EFI_USER_MANAGER_PROTOCOL gUserIdentifyManager = {\r
74 UserProfileCreate,\r
75 UserProfileDelete,\r
76 UserProfileGetNext,\r
77 UserProfileCurrent,\r
78 UserProfileIdentify,\r
79 UserProfileFind,\r
80 UserProfileNotify,\r
81 UserProfileGetInfo,\r
82 UserProfileSetInfo,\r
83 UserProfileDeleteInfo,\r
84 UserProfileGetNextInfo,\r
85};\r
86\r
87\r
88/**\r
89 Find the specified user in the user database.\r
90\r
91 This function searches the specified user from the beginning of the user database. \r
92 And if NextUser is TRUE, return the next User in the user database. \r
93 \r
94 @param[in, out] User On entry, points to the user profile entry to search. \r
95 On return, points to the user profile entry or NULL if not found.\r
96 @param[in] NextUser If FALSE, find the user in user profile database specifyed by User\r
97 If TRUE, find the next user in user profile database specifyed \r
98 by User. \r
99 @param[out] ProfileIndex A pointer to the index of user profile database that matches the \r
100 user specifyed by User.\r
101\r
102 @retval EFI_NOT_FOUND User was NULL, or User was not found, or the next user was not found.\r
103 @retval EFI_SUCCESS User or the next user are found in user profile database\r
104 \r
105**/\r
106EFI_STATUS\r
107FindUserProfile (\r
108 IN OUT USER_PROFILE_ENTRY **User,\r
109 IN BOOLEAN NextUser,\r
110 OUT UINTN *ProfileIndex OPTIONAL\r
111 )\r
112{\r
113 UINTN Index;\r
114\r
115 //\r
116 // Check parameters\r
117 //\r
118 if ((mUserProfileDb == NULL) || (User == NULL)) {\r
119 return EFI_NOT_FOUND;\r
120 }\r
121 \r
122 //\r
123 // Check whether the user profile is in the user profile database.\r
124 //\r
125 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {\r
126 if (mUserProfileDb->UserProfile[Index] == *User) {\r
127 if (ProfileIndex != NULL) {\r
128 *ProfileIndex = Index;\r
129 }\r
130 break;\r
131 }\r
132 }\r
133\r
134 if (NextUser) {\r
135 //\r
136 // Find the next user profile.\r
137 //\r
138 Index++;\r
139 if (Index < mUserProfileDb->UserProfileNum) {\r
140 *User = mUserProfileDb->UserProfile[Index];\r
141 } else if (Index == mUserProfileDb->UserProfileNum) {\r
142 *User = NULL;\r
143 return EFI_NOT_FOUND;\r
144 } else {\r
145 if ((mUserProfileDb->UserProfileNum > 0) && (*User == NULL)) {\r
146 *User = mUserProfileDb->UserProfile[0];\r
147 } else {\r
148 *User = NULL;\r
149 return EFI_NOT_FOUND;\r
150 }\r
151 }\r
152 } else if (Index == mUserProfileDb->UserProfileNum) {\r
153 return EFI_NOT_FOUND;\r
154 }\r
155\r
156 return EFI_SUCCESS;\r
157}\r
158\r
159/**\r
160 Find the specified user information record in the specified User profile.\r
161\r
162 This function searches the specified user information record from the beginning of the user \r
163 profile. And if NextInfo is TRUE, return the next info in the user profile. \r
164 \r
165 @param[in] User Points to the user profile entry. \r
166 @param[in, out] Info On entry, points to the user information record or NULL to start\r
167 searching with the first user information record.\r
168 On return, points to the user information record or NULL if not found. \r
169 @param[in] NextInfo If FALSE, find the user information record in profile specifyed by User.\r
170 If TRUE, find the next user information record in profile specifyed \r
171 by User. \r
172 @param[out] Offset A pointer to the offset of the information record in the user profile.\r
173\r
174 @retval EFI_INVALID_PARAMETER Info is NULL\r
175 @retval EFI_NOT_FOUND Info was not found, or the next Info was not found.\r
176 @retval EFI_SUCCESS Info or the next info are found in user profile.\r
177 \r
178**/\r
179EFI_STATUS\r
180FindUserInfo (\r
181 IN USER_PROFILE_ENTRY * User,\r
182 IN OUT EFI_USER_INFO **Info,\r
183 IN BOOLEAN NextInfo,\r
184 OUT UINTN *Offset OPTIONAL\r
185 )\r
186{\r
187 EFI_STATUS Status;\r
188 EFI_USER_INFO *UserInfo;\r
189 UINTN InfoLen;\r
190\r
191 if (Info == NULL) {\r
192 return EFI_INVALID_PARAMETER;\r
193 }\r
194 \r
195 //\r
196 // Check user profile entry\r
197 //\r
198 Status = FindUserProfile (&User, FALSE, NULL);\r
199 if (EFI_ERROR (Status)) {\r
200 return Status;\r
201 }\r
202\r
203 //\r
204 // Find user information in the specified user record.\r
205 //\r
206 InfoLen = 0;\r
207 while (InfoLen < User->UserProfileSize) {\r
208 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);\r
209 if (UserInfo == *Info) {\r
210 if (Offset != NULL) {\r
211 *Offset = InfoLen;\r
212 }\r
213 break;\r
214 }\r
215 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);\r
216 }\r
217 \r
218 //\r
219 // Check whether to find the next user information.\r
220 //\r
221 if (NextInfo) {\r
222 if (InfoLen < User->UserProfileSize) {\r
223 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);\r
224 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);\r
225 if (InfoLen < User->UserProfileSize) {\r
226 *Info = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);\r
227 if (Offset != NULL) {\r
228 *Offset = InfoLen;\r
229 }\r
230 } else if (InfoLen == User->UserProfileSize) {\r
231 *Info = NULL;\r
232 return EFI_NOT_FOUND;\r
233 }\r
234 } else {\r
235 if (*Info == NULL) {\r
236 *Info = (EFI_USER_INFO *) User->ProfileInfo;\r
237 if (Offset != NULL) {\r
238 *Offset = 0;\r
239 }\r
240 } else {\r
241 *Info = NULL;\r
242 return EFI_NOT_FOUND;\r
243 }\r
244 }\r
245 } else if (InfoLen == User->UserProfileSize) {\r
246 return EFI_NOT_FOUND;\r
247 }\r
248\r
249 return EFI_SUCCESS;\r
250}\r
251\r
252/**\r
253 Find a user infomation record by the information record type.\r
254\r
255 This function searches all user information records of User. The search starts with the \r
256 user information record following Info and continues until either the information is found \r
257 or there are no more user infomation record.\r
258 A match occurs when a Info.InfoType field matches the user information record type.\r
259\r
260 @param[in] User Points to the user profile record to search. \r
261 @param[in, out] Info On entry, points to the user information record or NULL to start\r
262 searching with the first user information record.\r
263 On return, points to the user information record or NULL if not found.\r
264 @param[in] InfoType The infomation type to be searched.\r
265\r
266 @retval EFI_SUCCESS User information was found. Info points to the user information record.\r
267 @retval EFI_NOT_FOUND User information was not found. \r
268 @retval EFI_INVALID_PARAMETER User is NULL or Info is NULL.\r
269 \r
270**/\r
271EFI_STATUS\r
272FindUserInfoByType (\r
273 IN USER_PROFILE_ENTRY *User,\r
274 IN OUT EFI_USER_INFO **Info,\r
275 IN UINT8 InfoType\r
276 )\r
277{\r
278 EFI_STATUS Status;\r
279 EFI_USER_INFO *UserInfo;\r
280 UINTN InfoLen;\r
281\r
282 if (Info == NULL) {\r
283 return EFI_INVALID_PARAMETER;\r
284 }\r
285 \r
286 //\r
287 // Check whether the user has the specified user information.\r
288 //\r
289 InfoLen = 0;\r
290 if (*Info == NULL) {\r
291 Status = FindUserProfile (&User, FALSE, NULL);\r
292 } else {\r
293 Status = FindUserInfo (User, Info, TRUE, &InfoLen);\r
294 }\r
295\r
296 if (EFI_ERROR (Status)) {\r
297 return EFI_NOT_FOUND;\r
298 }\r
299 \r
300 while (InfoLen < User->UserProfileSize) {\r
301 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);\r
302 if (UserInfo->InfoType == InfoType) {\r
303 if (UserInfo != *Info) {\r
304 *Info = UserInfo;\r
305 return EFI_SUCCESS;\r
306 }\r
307 }\r
308\r
309 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);\r
310 }\r
311\r
312 *Info = NULL;\r
313 return EFI_NOT_FOUND;\r
314}\r
315\r
316/**\r
317 Find a user using a user information record.\r
318\r
319 This function searches all user profiles for the specified user information record. The \r
320 search starts with the user information record handle following UserInfo and continues \r
321 until either the information is found or there are no more user profiles.\r
322 A match occurs when the Info.InfoType field matches the user information record type and the \r
323 user information record data matches the portion of Info passed the EFI_USER_INFO header.\r
324\r
325 @param[in, out] User On entry, points to the previously returned user profile record, \r
326 or NULL to start searching with the first user profile. \r
327 On return, points to the user profile entry, or NULL if not found.\r
328 @param[in, out] UserInfo On entry, points to the previously returned user information record, \r
329 or NULL to start searching with the first. \r
330 On return, points to the user information record, or NULL if not found.\r
331 @param[in] Info Points to the buffer containing the user information to be compared \r
332 to the user information record.\r
333 @param[in] InfoSize The size of Info, in bytes. Same as Info->InfoSize.\r
334\r
335 @retval EFI_SUCCESS User information was found. User points to the user profile record, \r
336 and UserInfo points to the user information record.\r
337 @retval EFI_NOT_FOUND User information was not found. \r
338 @retval EFI_INVALID_PARAMETER User is NULL; Info is NULL; or, InfoSize is too small.\r
339 \r
340**/\r
341EFI_STATUS\r
342FindUserProfileByInfo (\r
343 IN OUT USER_PROFILE_ENTRY **User,\r
344 IN OUT EFI_USER_INFO **UserInfo, OPTIONAL\r
345 IN EFI_USER_INFO *Info,\r
346 IN UINTN InfoSize\r
347 )\r
348{\r
349 EFI_STATUS Status;\r
350 EFI_USER_INFO *InfoEntry;\r
351\r
352\r
353 if ((User == NULL) || (Info == NULL)) {\r
354 return EFI_INVALID_PARAMETER;\r
355 }\r
356\r
357 if (InfoSize < sizeof (EFI_USER_INFO)) {\r
358 return EFI_INVALID_PARAMETER;\r
359 }\r
360\r
361 if (UserInfo != NULL) {\r
362 InfoEntry = *UserInfo;\r
363 } else {\r
364 InfoEntry = NULL;\r
365 }\r
366 //\r
367 // Find user profile according to information.\r
368 //\r
369 if (*User == NULL) {\r
370 *User = mUserProfileDb->UserProfile[0];\r
371 }\r
372 \r
373 //\r
374 // Check user profile handle.\r
375 //\r
376 Status = FindUserProfile (User, FALSE, NULL);\r
377\r
378 while (!EFI_ERROR (Status)) {\r
379 //\r
380 // Find the user information in a user profile.\r
381 //\r
382 while (TRUE) {\r
383 Status = FindUserInfoByType (*User, &InfoEntry, Info->InfoType);\r
384 if (EFI_ERROR (Status)) {\r
385 break;\r
386 }\r
387 \r
388 if (InfoSize == Info->InfoSize) {\r
389 if (CompareMem ((UINT8 *) (InfoEntry + 1), (UINT8 *) (Info + 1), InfoSize - sizeof (EFI_USER_INFO)) == 0) {\r
390 //\r
391 // Found the infomation record.\r
392 //\r
393 if (UserInfo != NULL) {\r
394 *UserInfo = InfoEntry;\r
395 }\r
396 return EFI_SUCCESS;\r
397 }\r
398 } \r
399 }\r
400 \r
401 //\r
402 // Get next user profile.\r
403 //\r
404 InfoEntry = NULL;\r
405 Status = FindUserProfile (User, TRUE, NULL);\r
406 }\r
407\r
408 return EFI_NOT_FOUND;\r
409}\r
410\r
411/**\r
412 Find the credential provider in the specified identity policy.\r
413\r
414 @param[in] FindIdentity Point to the user identity policy.\r
415 @param[in] IdentifyInfo Point to the user information to be searched.\r
416\r
417 @retval TRUE The credential provider was found in the identity policy.\r
418 @retval FALSE The credential provider was not found.\r
419**/\r
420BOOLEAN\r
421FindProvider (\r
422 IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity,\r
423 IN CONST EFI_USER_INFO *IdentifyInfo\r
424 )\r
425{\r
426 UINTN TotalLen;\r
427 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
428\r
429 //\r
430 // Found the credential provider.\r
431 //\r
432 TotalLen = 0;\r
433 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
434 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);\r
435 if ((Identity->Type == FindIdentity->Type) &&\r
436 (Identity->Length == FindIdentity->Length) &&\r
437 CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1))\r
438 ) {\r
439 return TRUE;\r
440 }\r
441\r
442 TotalLen += Identity->Length;\r
443 }\r
444\r
445 return FALSE;\r
446}\r
447\r
448\r
449/**\r
450 Check whether the access policy is valid.\r
451\r
452 @param[in] PolicyInfo Point to the access policy.\r
453 @param[in] InfoLen The policy length.\r
454\r
455 @retval TRUE The policy is a valid access policy.\r
456 @retval FALSE The access policy is not a valid access policy.\r
457 \r
458**/\r
459BOOLEAN\r
460CheckAccessPolicy (\r
461 IN UINT8 *PolicyInfo,\r
462 IN UINTN InfoLen\r
463 )\r
464{\r
465 UINTN TotalLen;\r
466 UINTN ValueLen;\r
467 UINTN OffSet;\r
468 EFI_USER_INFO_ACCESS_CONTROL Access;\r
469 EFI_DEVICE_PATH_PROTOCOL *Path;\r
470 UINTN PathSize;\r
471\r
472 TotalLen = 0;\r
473 while (TotalLen < InfoLen) {\r
474 //\r
475 // Check access policy according to type.\r
476 //\r
477 CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access)); \r
478 ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
479 switch (Access.Type) {\r
480 case EFI_USER_INFO_ACCESS_FORBID_LOAD:\r
481 case EFI_USER_INFO_ACCESS_PERMIT_LOAD:\r
482 case EFI_USER_INFO_ACCESS_FORBID_CONNECT:\r
483 case EFI_USER_INFO_ACCESS_PERMIT_CONNECT:\r
484 OffSet = 0;\r
485 while (OffSet < ValueLen) {\r
486 Path = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet);\r
487 PathSize = GetDevicePathSize (Path);\r
488 OffSet += PathSize;\r
489 }\r
490 if (OffSet != ValueLen) {\r
491 return FALSE;\r
492 }\r
493 break;\r
494\r
495 case EFI_USER_INFO_ACCESS_SETUP:\r
496 if (ValueLen % sizeof (EFI_GUID) != 0) {\r
497 return FALSE;\r
498 }\r
499 break;\r
500\r
501 case EFI_USER_INFO_ACCESS_BOOT_ORDER:\r
502 if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) {\r
503 return FALSE;\r
504 }\r
505 break;\r
506\r
507 case EFI_USER_INFO_ACCESS_ENROLL_SELF:\r
508 case EFI_USER_INFO_ACCESS_ENROLL_OTHERS:\r
509 case EFI_USER_INFO_ACCESS_MANAGE:\r
510 if (ValueLen != 0) {\r
511 return FALSE;\r
512 }\r
513 break;\r
514\r
515 default:\r
516 return FALSE;\r
517 break;\r
518 }\r
519\r
520 TotalLen += Access.Size;\r
521 }\r
522\r
523 if (TotalLen != InfoLen) {\r
524 return FALSE;\r
525 }\r
526\r
527 return TRUE;\r
528}\r
529\r
530\r
531/**\r
532 Check whether the identity policy is valid.\r
533\r
534 @param[in] PolicyInfo Point to the identity policy.\r
535 @param[in] InfoLen The policy length.\r
536\r
537 @retval TRUE The policy is a valid identity policy.\r
538 @retval FALSE The access policy is not a valid identity policy.\r
539 \r
540**/\r
541BOOLEAN\r
542CheckIdentityPolicy (\r
543 IN UINT8 *PolicyInfo,\r
544 IN UINTN InfoLen\r
545 )\r
546{\r
547 UINTN TotalLen;\r
548 UINTN ValueLen;\r
549 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
550\r
551 TotalLen = 0;\r
552\r
553 //\r
554 // Check each part of policy expression.\r
555 //\r
556 while (TotalLen < InfoLen) {\r
557 //\r
558 // Check access polisy according to type.\r
559 //\r
560 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);\r
561 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);\r
562 switch (Identity->Type) {\r
563 //\r
564 // Check False option.\r
565 //\r
566 case EFI_USER_INFO_IDENTITY_FALSE:\r
567 if (ValueLen != 0) {\r
568 return FALSE;\r
569 }\r
570 break;\r
571\r
572 //\r
573 // Check True option.\r
574 //\r
575 case EFI_USER_INFO_IDENTITY_TRUE:\r
576 if (ValueLen != 0) {\r
577 return FALSE;\r
578 }\r
579 break;\r
580\r
581 //\r
582 // Check negative operation.\r
583 //\r
584 case EFI_USER_INFO_IDENTITY_NOT:\r
585 if (ValueLen != 0) {\r
586 return FALSE;\r
587 }\r
588 break;\r
589\r
590 //\r
591 // Check and operation.\r
592 //\r
593 case EFI_USER_INFO_IDENTITY_AND:\r
594 if (ValueLen != 0) {\r
595 return FALSE;\r
596 }\r
597 break;\r
598\r
599 //\r
600 // Check or operation.\r
601 //\r
602 case EFI_USER_INFO_IDENTITY_OR:\r
603 if (ValueLen != 0) {\r
604 return FALSE;\r
605 }\r
606 break;\r
607\r
608 //\r
609 // Check credential provider by type.\r
610 //\r
611 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:\r
612 if (ValueLen != sizeof (EFI_GUID)) {\r
613 return FALSE;\r
614 }\r
615 break;\r
616\r
617 //\r
618 // Check credential provider by ID.\r
619 //\r
620 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:\r
621 if (ValueLen != sizeof (EFI_GUID)) {\r
622 return FALSE;\r
623 }\r
624 break;\r
625\r
626 default:\r
627 return FALSE;\r
628 break;\r
629 }\r
630\r
631 TotalLen += Identity->Length;\r
632 }\r
633\r
634 if (TotalLen != InfoLen) {\r
635 return FALSE;\r
636 }\r
637\r
638 return TRUE;\r
639}\r
640\r
641\r
642/**\r
643 Check whether the user information is a valid user information record.\r
644\r
645 @param[in] Info points to the user information.\r
646\r
647 @retval TRUE The info is a valid user information record.\r
648 @retval FALSE The info is not a valid user information record.\r
649 \r
650**/\r
651BOOLEAN\r
652CheckUserInfo (\r
653 IN CONST EFI_USER_INFO *Info\r
654 )\r
655{\r
656 UINTN InfoLen;\r
657\r
658 if (Info == NULL) {\r
659 return FALSE;\r
660 }\r
661 //\r
662 // Check user information according to information type.\r
663 //\r
664 InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO);\r
665 switch (Info->InfoType) {\r
666 case EFI_USER_INFO_EMPTY_RECORD:\r
667 if (InfoLen != 0) {\r
668 return FALSE;\r
669 }\r
670 break;\r
671\r
672 case EFI_USER_INFO_NAME_RECORD:\r
673 case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD:\r
674 case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD:\r
675 break;\r
676\r
677 case EFI_USER_INFO_CREATE_DATE_RECORD:\r
678 case EFI_USER_INFO_USAGE_DATE_RECORD:\r
679 if (InfoLen != sizeof (EFI_TIME)) {\r
680 return FALSE;\r
681 }\r
682 break;\r
683\r
684 case EFI_USER_INFO_USAGE_COUNT_RECORD:\r
685 if (InfoLen != sizeof (UINT64)) {\r
686 return FALSE;\r
687 }\r
688 break;\r
689\r
690 case EFI_USER_INFO_IDENTIFIER_RECORD:\r
691 if (InfoLen != 16) {\r
692 return FALSE;\r
693 }\r
694 break;\r
695\r
696 case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD:\r
697 case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD:\r
698 case EFI_USER_INFO_GUID_RECORD:\r
699 if (InfoLen != sizeof (EFI_GUID)) {\r
700 return FALSE;\r
701 }\r
702 break;\r
703\r
704 case EFI_USER_INFO_PKCS11_RECORD:\r
705 case EFI_USER_INFO_CBEFF_RECORD:\r
706 break;\r
707\r
708 case EFI_USER_INFO_FAR_RECORD:\r
709 case EFI_USER_INFO_RETRY_RECORD:\r
710 if (InfoLen != 1) {\r
711 return FALSE;\r
712 }\r
713 break;\r
714\r
715 case EFI_USER_INFO_ACCESS_POLICY_RECORD:\r
716 if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) {\r
717 return FALSE;\r
718 }\r
719 break;\r
720\r
721 case EFI_USER_INFO_IDENTITY_POLICY_RECORD:\r
722 if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) {\r
723 return FALSE;\r
724 }\r
725 break;\r
726\r
727 default:\r
728 return FALSE;\r
729 break;\r
730 }\r
731\r
732 return TRUE;\r
733}\r
734\r
735\r
736/**\r
737 Check the user profile data format to be added.\r
738\r
739 @param[in] UserProfileInfo Points to the user profile data.\r
740 @param[in] UserProfileSize The length of user profile data.\r
741\r
742 @retval TRUE It is a valid user profile.\r
743 @retval FALSE It is not a valid user profile.\r
744 \r
745**/\r
746BOOLEAN\r
747CheckProfileInfo (\r
748 IN UINT8 *UserProfileInfo,\r
749 IN UINTN UserProfileSize\r
750 )\r
751{\r
752 UINTN ChkLen;\r
753 EFI_USER_INFO *Info;\r
754\r
755 if (UserProfileInfo == NULL) {\r
756 return FALSE;\r
757 }\r
758 \r
759 //\r
760 // Check user profile information length.\r
761 //\r
762 ChkLen = 0;\r
763 while (ChkLen < UserProfileSize) {\r
764 Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen);\r
765 //\r
766 // Check user information format.\r
767 //\r
768 if (!CheckUserInfo (Info)) {\r
769 return FALSE;\r
770 }\r
771\r
772 ChkLen += ALIGN_VARIABLE (Info->InfoSize);\r
773 }\r
774\r
775 if (ChkLen != UserProfileSize) {\r
776 return FALSE;\r
777 }\r
778\r
779 return TRUE;\r
780}\r
781\r
782\r
783/**\r
784 Find the specified RightType in current user profile.\r
785\r
786 @param[in] RightType Could be EFI_USER_INFO_ACCESS_MANAGE,\r
787 EFI_USER_INFO_ACCESS_ENROLL_OTHERS or\r
788 EFI_USER_INFO_ACCESS_ENROLL_SELF.\r
789 \r
790 @retval TRUE Find the specified RightType in current user profile.\r
791 @retval FALSE Can't find the right in the profile.\r
792 \r
793**/\r
794BOOLEAN\r
795CheckCurrentUserAccessRight (\r
796 IN UINT32 RightType\r
797 )\r
798{\r
799 EFI_STATUS Status;\r
800 EFI_USER_INFO *Info;\r
801 UINTN TotalLen;\r
802 UINTN CheckLen;\r
803 EFI_USER_INFO_ACCESS_CONTROL Access;\r
804\r
805 //\r
806 // Get user access right information.\r
807 //\r
808 Info = NULL;\r
809 Status = FindUserInfoByType (\r
810 (USER_PROFILE_ENTRY *) mCurrentUser,\r
811 &Info,\r
812 EFI_USER_INFO_ACCESS_POLICY_RECORD\r
813 );\r
814 if (EFI_ERROR (Status)) {\r
815 return FALSE;\r
816 }\r
817\r
818 ASSERT (Info != NULL);\r
819 TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO);\r
820 CheckLen = 0;\r
821 while (CheckLen < TotalLen) {\r
822 //\r
823 // Check right according to access type.\r
824 //\r
825 CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access));\r
826 if (Access.Type == RightType) {\r
827 return TRUE;;\r
828 }\r
829\r
830 CheckLen += Access.Size;\r
831 }\r
832\r
833 return FALSE;\r
834}\r
835\r
836\r
837/**\r
838 Create a unique user identifier.\r
839\r
840 @param[out] Identifier This points to the identifier.\r
841\r
842**/\r
843VOID\r
844GenerateIdentifier (\r
845 OUT UINT8 *Identifier\r
846 )\r
847{\r
848 EFI_TIME Time;\r
849 UINT64 MonotonicCount;\r
850 UINT32 *MonotonicPointer;\r
851 UINTN Index;\r
852\r
853 //\r
854 // Create a unique user identifier.\r
855 //\r
856 gRT->GetTime (&Time, NULL);\r
857 CopyMem (Identifier, &Time, sizeof (EFI_TIME));\r
858 //\r
859 // Remove zeros.\r
860 //\r
861 for (Index = 0; Index < sizeof (EFI_TIME); Index++) {\r
862 if (Identifier[Index] == 0) {\r
863 Identifier[Index] = 0x5a;\r
864 }\r
865 }\r
866\r
867 MonotonicPointer = (UINT32 *) Identifier;\r
868 gBS->GetNextMonotonicCount (&MonotonicCount);\r
869 MonotonicPointer[0] += (UINT32) MonotonicCount;\r
870 MonotonicPointer[1] += (UINT32) MonotonicCount;\r
871 MonotonicPointer[2] += (UINT32) MonotonicCount;\r
872 MonotonicPointer[3] += (UINT32) MonotonicCount;\r
873}\r
874\r
875\r
876/**\r
877 Generate unique user ID.\r
878\r
879 @param[out] UserId Points to the user identifer.\r
880\r
881**/\r
882VOID\r
883GenerateUserId (\r
884 OUT UINT8 *UserId\r
885 )\r
886{\r
887 EFI_STATUS Status;\r
888 USER_PROFILE_ENTRY *UserProfile;\r
889 EFI_USER_INFO *UserInfo;\r
890 UINTN Index;\r
891\r
892 //\r
893 // Generate unique user ID\r
894 //\r
895 while (TRUE) {\r
896 GenerateIdentifier (UserId);\r
897 //\r
898 // Check whether it's unique in user profile database.\r
899 //\r
900 if (mUserProfileDb == NULL) {\r
901 return ;\r
902 }\r
903\r
904 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {\r
905 UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]);\r
906 UserInfo = NULL;\r
907 Status = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD);\r
908 if (EFI_ERROR (Status)) {\r
909 continue;\r
910 }\r
911\r
912 if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {\r
913 break;\r
914 }\r
915 }\r
916\r
917 if (Index == mUserProfileDb->UserProfileNum) {\r
918 return ;\r
919 }\r
920 }\r
921}\r
922\r
923\r
924/**\r
925 Expand user profile database.\r
926\r
927 @retval TRUE Success to expand user profile database.\r
928 @retval FALSE Fail to expand user profile database.\r
929 \r
930**/\r
931BOOLEAN\r
932ExpandUsermUserProfileDb (\r
933 VOID\r
934 )\r
935{\r
936 UINTN MaxNum;\r
937 USER_PROFILE_DB *NewDataBase;\r
938\r
939 //\r
940 // Create new user profile database.\r
941 //\r
942 if (mUserProfileDb == NULL) {\r
943 MaxNum = USER_NUMBER_INC;\r
944 } else {\r
945 MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC;\r
946 }\r
947\r
948 NewDataBase = AllocateZeroPool (\r
949 sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) +\r
950 MaxNum * sizeof (EFI_USER_PROFILE_HANDLE)\r
951 );\r
952 if (NewDataBase == NULL) {\r
953 return FALSE;\r
954 }\r
955\r
956 NewDataBase->MaxProfileNum = MaxNum;\r
957\r
958 //\r
959 // Copy old user profile database value\r
960 //\r
961 if (mUserProfileDb == NULL) {\r
962 NewDataBase->UserProfileNum = 0;\r
963 } else {\r
964 NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum;\r
965 CopyMem (\r
966 NewDataBase->UserProfile,\r
967 mUserProfileDb->UserProfile,\r
968 NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE)\r
969 );\r
970 FreePool (mUserProfileDb);\r
971 }\r
972\r
973 mUserProfileDb = NewDataBase;\r
974 return TRUE;\r
975}\r
976\r
977\r
978/**\r
979 Expand user profile\r
980\r
981 @param[in] User Points to user profile.\r
982 @param[in] ExpandSize The size of user profile. \r
983\r
984 @retval TRUE Success to expand user profile size.\r
985 @retval FALSE Fail to expand user profile size.\r
986 \r
987**/\r
988BOOLEAN\r
989ExpandUserProfile (\r
990 IN USER_PROFILE_ENTRY *User,\r
991 IN UINTN ExpandSize\r
992 )\r
993{\r
994 UINT8 *Info;\r
995 UINTN InfoSizeInc;\r
996\r
997 //\r
998 // Allocate new memory.\r
999 //\r
1000 InfoSizeInc = 128;\r
1001 User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc;\r
1002 Info = AllocateZeroPool (User->MaxProfileSize);\r
1003 if (Info == NULL) {\r
1004 return FALSE;\r
1005 }\r
1006 \r
1007 //\r
1008 // Copy exist information.\r
1009 //\r
1010 if (User->UserProfileSize > 0) {\r
1011 CopyMem (Info, User->ProfileInfo, User->UserProfileSize);\r
1012 FreePool (User->ProfileInfo);\r
1013 }\r
1014\r
1015 User->ProfileInfo = Info;\r
1016 return TRUE;\r
1017}\r
1018\r
1019\r
1020/**\r
1021 Add or delete the user's credential record in the provider.\r
1022\r
1023 @param[in] ProviderGuid Point to credential provider guid or class guid.\r
1024 @param[in] ByType If TRUE, Provider is credential class guid.\r
1025 If FALSE, Provider is provider guid.\r
1026 @param[in] User Points to user profile.\r
1027\r
1028 @retval EFI_SUCCESS Add or delete record successfully.\r
1029 @retval Others Fail to add or delete record.\r
1030\r
1031**/\r
1032EFI_STATUS\r
1033ModifyProviderCredential (\r
1034 IN EFI_GUID *Provider,\r
1035 IN BOOLEAN ByType,\r
1036 IN USER_PROFILE_ENTRY *User\r
1037 )\r
1038{\r
1039 UINTN Index;\r
1040 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;\r
1041 \r
1042 if (Provider == NULL) {\r
1043 return EFI_INVALID_PARAMETER;\r
1044 }\r
1045\r
1046 \r
1047 //\r
1048 // Find the specified credential provider.\r
1049 //\r
1050 for (Index = 0; Index < mProviderDb->Count; Index++) {\r
1051 //\r
1052 // Check credential provider ID.\r
1053 //\r
1054 UserCredential = mProviderDb->Provider[Index];\r
1055 if (CompareGuid (&UserCredential->Identifier, Provider)) {\r
1056 return UserCredential->Enroll (UserCredential, User);\r
1057 }\r
1058 }\r
1059\r
1060 return EFI_NOT_FOUND;\r
1061}\r
1062\r
1063\r
1064/**\r
1065 Modify user's credential record in the providers.\r
1066\r
1067 Found the providers information in PolicyInfo, and then add or delete the user's credential\r
1068 record in the providers.\r
1069\r
1070 @param User Points to user profile.\r
1071 @param PolicyInfo Point to identification policy to be modified.\r
1072 @param InfoLen The length of PolicyInfo.\r
1073\r
1074 @retval EFI_SUCCESS Modify PolicyInfo successfully.\r
1075 @retval Others Fail to modify PolicyInfo.\r
1076\r
1077**/\r
1078EFI_STATUS\r
1079ModifyCredentialInfo (\r
1080 IN USER_PROFILE_ENTRY *User,\r
1081 IN UINT8 *PolicyInfo,\r
1082 IN UINTN InfoLen\r
1083 )\r
1084{\r
1085 EFI_STATUS Status;\r
1086 UINTN TotalLen;\r
1087 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
1088\r
1089 //\r
1090 // Modify user's credential.\r
1091 //\r
1092 TotalLen = 0;\r
1093 while (TotalLen < InfoLen) {\r
1094 //\r
1095 // Check identification policy according to type.\r
1096 //\r
1097 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);\r
1098 switch (Identity->Type) {\r
1099 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:\r
1100 Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), TRUE, User);\r
1101 if (EFI_ERROR (Status)) {\r
1102 return Status;\r
1103 }\r
1104 break;\r
1105\r
1106 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:\r
1107 Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), FALSE, User);\r
1108 if (EFI_ERROR (Status)) {\r
1109 return Status;\r
1110 }\r
1111 break;\r
1112\r
1113 default:\r
1114 break;\r
1115 }\r
1116\r
1117 TotalLen += Identity->Length;\r
1118 }\r
1119\r
1120 return EFI_SUCCESS;\r
1121}\r
1122\r
1123\r
1124/**\r
1125 Save the user profile to non-volatile memory, or delete it from non-volatile memory.\r
1126\r
1127 @param[in] User Point to the user profile\r
1128 @param[in] Delete If TRUE, delete the found user profile.\r
1129 If FALSE, save the user profile.\r
1130 @retval EFI_SUCCESS Save or delete user profile successfully.\r
1131 @retval Others Fail to change the profile.\r
1132 \r
1133**/\r
1134EFI_STATUS\r
1135SaveNvUserProfile (\r
1136 IN USER_PROFILE_ENTRY *User,\r
1137 IN BOOLEAN Delete\r
1138 )\r
1139{\r
1140 EFI_STATUS Status;\r
1141\r
1142 //\r
1143 // Check user profile entry.\r
1144 //\r
1145 Status = FindUserProfile (&User, FALSE, NULL);\r
1146 if (EFI_ERROR (Status)) {\r
1147 return Status;\r
1148 }\r
1149 \r
1150 //\r
1151 // Save the user profile to non-volatile memory.\r
1152 //\r
1153 Status = gRT->SetVariable (\r
1154 User->UserVarName,\r
1155 &mUserManagerGuid,\r
1156 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1157 Delete ? 0 : User->UserProfileSize,\r
1158 User->ProfileInfo\r
1159 );\r
1160 return Status;\r
1161}\r
1162\r
1163\r
1164/**\r
1165 Replace the old identity info with NewInfo in NV Flash.\r
1166\r
1167 This function only replace the identity record in the user profile. Don't update\r
1168 the the information on the credential provider.\r
1169 \r
1170 @param[in] User Point to the user profile.\r
1171 @param[in] NewInfo Point to the new identity policy info.\r
1172 @param[out] UserInfo Point to the new added identity info.\r
1173\r
1174 @retval EFI_SUCCESS Replace user identity successfully.\r
1175 @retval Others Fail to Replace user identity.\r
1176\r
1177**/\r
1178EFI_STATUS\r
1179SaveUserIpInfo (\r
1180 IN USER_PROFILE_ENTRY * User,\r
1181 IN CONST EFI_USER_INFO * NewInfo,\r
1182 OUT EFI_USER_INFO **UserInfo OPTIONAL\r
1183 )\r
1184{\r
1185 EFI_STATUS Status;\r
1186 EFI_USER_INFO *OldIpInfo;\r
1187 UINTN Offset;\r
1188 UINTN NextOffset;\r
1189\r
1190 if ((NewInfo == NULL) || (User == NULL)) {\r
1191 return EFI_INVALID_PARAMETER;\r
1192 }\r
1193 \r
1194 //\r
1195 // Get user old identify policy information.\r
1196 //\r
1197 OldIpInfo = NULL;\r
1198 Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
1199 if (EFI_ERROR (Status)) {\r
1200 return Status;\r
1201 }\r
1202 \r
1203 //\r
1204 // Get the old identity policy offset.\r
1205 //\r
1206 Status = FindUserInfo (User, &OldIpInfo, FALSE, &Offset);\r
1207 if (EFI_ERROR (Status)) {\r
1208 return Status;\r
1209 }\r
1210 \r
1211 //\r
1212 // Delete the old identity policy information.\r
1213 //\r
1214 NextOffset = ALIGN_VARIABLE (OldIpInfo->InfoSize) + Offset;\r
1215 User->UserProfileSize -= ALIGN_VARIABLE (OldIpInfo->InfoSize);\r
1216 if (Offset < User->UserProfileSize) {\r
1217 CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);\r
1218 }\r
1219 \r
1220 //\r
1221 // Add new user information.\r
1222 //\r
1223 if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (NewInfo->InfoSize)) {\r
1224 if (!ExpandUserProfile (User, ALIGN_VARIABLE (NewInfo->InfoSize))) {\r
1225 return EFI_OUT_OF_RESOURCES;\r
1226 }\r
1227 }\r
1228\r
1229 CopyMem (User->ProfileInfo + User->UserProfileSize, (VOID *) NewInfo, NewInfo->InfoSize);\r
1230 if (UserInfo != NULL) {\r
1231 *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);\r
1232 }\r
1233\r
1234 User->UserProfileSize += ALIGN_VARIABLE (NewInfo->InfoSize);\r
1235\r
1236 //\r
1237 // Save user profile information.\r
1238 //\r
1239 Status = SaveNvUserProfile (User, FALSE);\r
1240 return Status;\r
1241}\r
1242\r
1243\r
1244/**\r
1245 Remove the provider in FindIdentity from the user identification information record.\r
1246 \r
1247 @param[in, out] NewInfo On entry, points to the user information to remove provider. \r
1248 On return, points to the user information the provider is removed.\r
1249 @param[in] FindIdentity Point to the user identity policy.\r
1250\r
1251 @retval TRUE The provider is removed successfully.\r
1252 @retval FALSE Fail to remove the provider.\r
1253\r
1254**/\r
1255BOOLEAN\r
1256RemoveProvider (\r
1257 IN OUT EFI_USER_INFO **NewInfo,\r
1258 IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity\r
1259 )\r
1260{\r
1261 UINTN TotalLen;\r
1262 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
1263 EFI_USER_INFO *IdentifyInfo;\r
1264 UINT8 *Buffer;\r
1265\r
1266 IdentifyInfo = *NewInfo;\r
1267 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1268 if (TotalLen == FindIdentity->Length) {\r
1269 //\r
1270 // Only one credential provider in the identification policy.\r
1271 // Set the new policy to be TRUE after removed the provider.\r
1272 //\r
1273 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentifyInfo + 1);\r
1274 Identity->Type = EFI_USER_INFO_IDENTITY_TRUE;\r
1275 Identity->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); \r
1276 IdentifyInfo->InfoSize = sizeof (EFI_USER_INFO) + Identity->Length;\r
1277 return TRUE;\r
1278 }\r
1279\r
1280 //\r
1281 // Found the credential provider.\r
1282 //\r
1283 TotalLen = 0;\r
1284 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
1285 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);\r
1286 if ((Identity->Type == FindIdentity->Type) &&\r
1287 (Identity->Length == FindIdentity->Length) &&\r
1288 CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1))\r
1289 ) {\r
1290 //\r
1291 // Found the credential provider to delete\r
1292 //\r
1293 if (Identity == (EFI_USER_INFO_IDENTITY_POLICY *)(IdentifyInfo + 1)) {\r
1294 //\r
1295 // It is the first item in the identification policy, delete it and the connector after it.\r
1296 //\r
1297 Buffer = (UINT8 *) Identity + Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);\r
1298 IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);\r
1299 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1300 CopyMem (Identity, Buffer, TotalLen);\r
1301 } else {\r
1302 //\r
1303 // It is not the first item in the identification policy, delete it and the connector before it.\r
1304 //\r
1305 Buffer = (UINT8 *) Identity + Identity->Length;\r
1306 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1307 TotalLen -= (Buffer - (UINT8 *)(IdentifyInfo + 1));\r
1308 IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);\r
1309 CopyMem ((UINT8 *) (Identity - 1), Buffer, TotalLen);\r
1310 } \r
1311 return TRUE;\r
1312 }\r
1313\r
1314 TotalLen += Identity->Length;\r
1315 } \r
1316 return FALSE;\r
1317}\r
1318\r
1319\r
1320/**\r
1321 This function replaces the old identity policy with a new identity policy.\r
1322\r
1323 This function changes user identity policy information.\r
1324 If enroll new credential failed, recover the old identity policy.\r
1325\r
1326 For new policy:\r
1327 a. For each credential, if it is newly added, try to enroll it.\r
1328 If enroll failed, try to delete the newly added ones.\r
1329 \r
1330 b. For each credential, if it exists in the old policy, delete old one, \r
1331 and enroll new one. If failed to enroll the new one, removed it from new \r
1332 identification policy.\r
1333\r
1334 For old policy: \r
1335 a. For each credential, if it does not exist in new one, delete it.\r
1336\r
1337 @param[in] User Point to the user profile.\r
1338 @param[in] Info Points to the user identity information.\r
1339 @param[in] InfoSize The size of Info (Not used in this function).\r
1340 @param[out] IpInfo The new identification info after modify.\r
1341\r
1342 @retval EFI_SUCCESS Modify user identity policy successfully.\r
1343 @retval Others Fail to modify user identity policy.\r
1344\r
1345**/\r
1346EFI_STATUS\r
1347ModifyUserIpInfo (\r
1348 IN USER_PROFILE_ENTRY *User,\r
1349 IN CONST EFI_USER_INFO *Info,\r
1350 IN UINTN InfoSize,\r
1351 OUT EFI_USER_INFO **IpInfo\r
1352 )\r
1353{\r
1354 EFI_STATUS Status;\r
1355 EFI_USER_INFO *OldIpInfo;\r
1356 UINTN TotalLen;\r
1357 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
1358 UINT32 CredentialCount;\r
1359 EFI_USER_INFO *NewIpInfo;\r
1360\r
1361 //\r
1362 // Get user old identify policy information.\r
1363 //\r
1364 OldIpInfo = NULL;\r
1365 Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
1366 if (EFI_ERROR (Status)) {\r
1367 return Status;\r
1368 }\r
1369 ASSERT (OldIpInfo != NULL);\r
1370 \r
1371 //\r
1372 // Enroll new added credential provider.\r
1373 //\r
1374 CredentialCount = 0;\r
1375 TotalLen = 0;\r
1376 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {\r
1377 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);\r
1378 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {\r
1379 if (!FindProvider (Identity, OldIpInfo)) {\r
1380 //\r
1381 // The credential is NOT found in the old identity policy; add it.\r
1382 //\r
1383 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);\r
1384 if (EFI_ERROR (Status)) {\r
1385 break;\r
1386 }\r
1387 CredentialCount++;\r
1388 }\r
1389 }\r
1390\r
1391 TotalLen += Identity->Length;\r
1392 }\r
1393\r
1394 if (EFI_ERROR (Status)) {\r
1395 //\r
1396 // Enroll new credential failed. Delete the newly enrolled credential, and return.\r
1397 //\r
1398 TotalLen = 0;\r
1399 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {\r
1400 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);\r
1401 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {\r
1402 if (!FindProvider (Identity, OldIpInfo)) {\r
1403 //\r
1404 // The credential is NOT found in the old identity policy. Delete it.\r
1405 //\r
1406 if (CredentialCount == 0) {\r
1407 break;\r
1408 }\r
1409\r
1410 ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);\r
1411 CredentialCount--;\r
1412 }\r
1413 }\r
1414 TotalLen += Identity->Length;\r
1415 }\r
1416\r
1417 return EFI_DEVICE_ERROR;\r
1418 }\r
1419 \r
1420 //\r
1421 // Backup new identification policy\r
1422 //\r
1423 NewIpInfo = AllocateCopyPool (Info->InfoSize, Info); \r
1424 ASSERT (NewIpInfo != NULL);\r
1425\r
1426 //\r
1427 // Enroll the credential that existed in the old identity policy.\r
1428 //\r
1429 TotalLen = 0;\r
1430 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {\r
1431 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);\r
1432 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {\r
1433 if (FindProvider (Identity, OldIpInfo)) {\r
1434 //\r
1435 // The credential is found in the old identity policy, so delete the old credential first.\r
1436 //\r
1437 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);\r
1438 if (EFI_ERROR (Status)) {\r
1439 //\r
1440 // Failed to delete old credential.\r
1441 //\r
1442 FreePool (NewIpInfo);\r
1443 return EFI_DEVICE_ERROR;\r
1444 }\r
1445\r
1446 //\r
1447 // Add the new credential.\r
1448 //\r
1449 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);\r
1450 if (EFI_ERROR (Status)) {\r
1451 //\r
1452 // Failed to enroll the user by new identification policy.\r
1453 // So removed the credential provider from the identification policy \r
1454 //\r
1455 RemoveProvider (&NewIpInfo, Identity);\r
1456 } \r
1457 }\r
1458 }\r
1459 TotalLen += Identity->Length;\r
1460 }\r
1461 \r
1462 //\r
1463 // Delete old credential that didn't exist in the new identity policy.\r
1464 //\r
1465 TotalLen = 0;\r
1466 while (TotalLen < OldIpInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
1467 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (OldIpInfo + 1) + TotalLen);\r
1468 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {\r
1469 if (!FindProvider (Identity, Info)) {\r
1470 //\r
1471 // The credential is NOT found in the new identity policy. Delete the old credential.\r
1472 //\r
1473 ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);\r
1474 }\r
1475 }\r
1476 TotalLen += Identity->Length;\r
1477 }\r
1478\r
1479 *IpInfo = NewIpInfo;\r
1480 return EFI_SUCCESS;\r
1481}\r
1482\r
1483\r
1484/**\r
1485 Add one new user info into the user's profile.\r
1486\r
1487 @param[in] User point to the user profile\r
1488 @param[in] Info Points to the user information payload.\r
1489 @param[in] InfoSize The size of the user information payload, in bytes.\r
1490 @param[out] UserInfo Point to the new info in user profile\r
1491 @param[in] Save If TRUE, save the profile to NV flash.\r
1492 If FALSE, don't need to save the profile to NV flash.\r
1493\r
1494 @retval EFI_SUCCESS Add user info to user profile successfully.\r
1495 @retval Others Fail to add user info to user profile.\r
1496\r
1497**/\r
1498EFI_STATUS\r
1499AddUserInfo (\r
1500 IN USER_PROFILE_ENTRY *User,\r
1501 IN UINT8 *Info,\r
1502 IN UINTN InfoSize,\r
1503 OUT EFI_USER_INFO **UserInfo, OPTIONAL\r
1504 IN BOOLEAN Save\r
1505 )\r
1506{\r
1507 EFI_STATUS Status;\r
1508\r
1509 if ((Info == NULL) || (User == NULL)) {\r
1510 return EFI_INVALID_PARAMETER;\r
1511 }\r
1512 \r
1513 //\r
1514 // Check user profile handle.\r
1515 //\r
1516 Status = FindUserProfile (&User, FALSE, NULL);\r
1517 if (EFI_ERROR (Status)) {\r
1518 return Status;\r
1519 }\r
1520 \r
1521 //\r
1522 // Check user information memory size.\r
1523 //\r
1524 if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) {\r
1525 if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) {\r
1526 return EFI_OUT_OF_RESOURCES;\r
1527 }\r
1528 }\r
1529 \r
1530 //\r
1531 // Add credential.\r
1532 //\r
1533 if (((EFI_USER_INFO *) Info)->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {\r
1534 Status = ModifyCredentialInfo (\r
1535 User,\r
1536 (UINT8 *) ((EFI_USER_INFO *) Info + 1),\r
1537 InfoSize - sizeof (EFI_USER_INFO)\r
1538 );\r
1539 if (EFI_ERROR (Status)) {\r
1540 return Status;\r
1541 }\r
1542 }\r
1543 \r
1544 //\r
1545 // Add new user information.\r
1546 //\r
1547 CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize);\r
1548 if (UserInfo != NULL) {\r
1549 *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);\r
1550 }\r
1551 User->UserProfileSize += ALIGN_VARIABLE (InfoSize);\r
1552\r
1553 //\r
1554 // Save user profile information.\r
1555 //\r
1556 if (Save) {\r
1557 Status = SaveNvUserProfile (User, FALSE);\r
1558 }\r
1559\r
1560 return Status;\r
1561}\r
1562\r
1563\r
1564/**\r
1565 Get the user info from the specified user info handle.\r
1566\r
1567 @param[in] User Point to the user profile.\r
1568 @param[in] UserInfo Point to the user information record to get.\r
1569 @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. \r
1570 On exit, holds the user information.\r
1571 @param[in, out] InfoSize On entry, points to the size of Info. \r
1572 On return, points to the size of the user information.\r
1573 @param[in] ChkRight If TRUE, check the user info attribute.\r
1574 If FALSE, don't check the user info attribute.\r
1575\r
1576\r
1577 @retval EFI_ACCESS_DENIED The information cannot be accessed by the current user.\r
1578 @retval EFI_INVALID_PARAMETER InfoSize is NULL or UserInfo is NULL.\r
1579 @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the \r
1580 returned data. The actual size required is returned in *InfoSize.\r
1581 @retval EFI_SUCCESS Information returned successfully.\r
1582\r
1583**/\r
1584EFI_STATUS\r
1585GetUserInfo (\r
1586 IN USER_PROFILE_ENTRY *User,\r
1587 IN EFI_USER_INFO *UserInfo,\r
1588 OUT EFI_USER_INFO *Info,\r
1589 IN OUT UINTN *InfoSize,\r
1590 IN BOOLEAN ChkRight\r
1591 )\r
1592{\r
1593 EFI_STATUS Status;\r
1594\r
1595 if ((InfoSize == NULL) || (UserInfo == NULL)) {\r
1596 return EFI_INVALID_PARAMETER;\r
1597 }\r
1598\r
1599 if ((*InfoSize != 0) && (Info == NULL)) {\r
1600 return EFI_INVALID_PARAMETER;\r
1601 }\r
1602 \r
1603 //\r
1604 // Find the user information to get.\r
1605 //\r
1606 Status = FindUserInfo (User, &UserInfo, FALSE, NULL);\r
1607 if (EFI_ERROR (Status)) {\r
1608 return Status;\r
1609 }\r
1610 \r
1611 //\r
1612 // Check information attributes.\r
1613 //\r
1614 if (ChkRight) {\r
1615 switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) {\r
1616 case EFI_USER_INFO_PRIVATE:\r
1617 case EFI_USER_INFO_PROTECTED:\r
1618 if (User != mCurrentUser) {\r
1619 return EFI_ACCESS_DENIED;\r
1620 }\r
1621 break;\r
1622\r
1623 case EFI_USER_INFO_PUBLIC:\r
1624 break;\r
1625\r
1626 default:\r
1627 return EFI_INVALID_PARAMETER;\r
1628 break;\r
1629 }\r
1630 }\r
1631 \r
1632 //\r
1633 // Get user information.\r
1634 //\r
1635 if (UserInfo->InfoSize > *InfoSize) {\r
1636 *InfoSize = UserInfo->InfoSize;\r
1637 return EFI_BUFFER_TOO_SMALL;\r
1638 }\r
1639\r
1640 *InfoSize = UserInfo->InfoSize;\r
1641 if (Info != NULL) {\r
1642 CopyMem (Info, UserInfo, *InfoSize);\r
1643 }\r
1644\r
1645 return EFI_SUCCESS;\r
1646}\r
1647\r
1648\r
1649/**\r
1650 Delete the specified user information from user profile.\r
1651\r
1652 @param[in] User Point to the user profile.\r
1653 @param[in] Info Point to the user information record to delete.\r
1654 @param[in] Save If TRUE, save the profile to NV flash.\r
1655 If FALSE, don't need to save the profile to NV flash.\r
1656\r
1657 @retval EFI_SUCCESS Delete user info from user profile successfully.\r
1658 @retval Others Fail to delete user info from user profile.\r
1659\r
1660**/\r
1661EFI_STATUS\r
1662DelUserInfo (\r
1663 IN USER_PROFILE_ENTRY *User,\r
1664 IN EFI_USER_INFO *Info,\r
1665 IN BOOLEAN Save\r
1666 )\r
1667{\r
1668 EFI_STATUS Status;\r
1669 UINTN Offset;\r
1670 UINTN NextOffset;\r
1671\r
1672 //\r
1673 // Check user information handle.\r
1674 //\r
1675 Status = FindUserInfo (User, &Info, FALSE, &Offset);\r
1676 if (EFI_ERROR (Status)) {\r
1677 return Status;\r
1678 }\r
1679\r
1680 if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {\r
1681 return EFI_ACCESS_DENIED;\r
1682 } else if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {\r
1683 Status = ModifyCredentialInfo (User, (UINT8 *) (Info + 1), Info->InfoSize - sizeof (EFI_USER_INFO));\r
1684 if (EFI_ERROR (Status)) {\r
1685 return Status;\r
1686 }\r
1687 }\r
1688 \r
1689 //\r
1690 // Delete the specified user information.\r
1691 //\r
1692 NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize);\r
1693 User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize);\r
1694 if (Offset < User->UserProfileSize) {\r
1695 CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);\r
1696 }\r
1697\r
1698 if (Save) {\r
1699 Status = SaveNvUserProfile (User, FALSE);\r
1700 }\r
1701\r
1702 return Status;\r
1703}\r
1704\r
1705\r
1706/**\r
1707 Add or update user information.\r
1708\r
1709 @param[in] User Point to the user profile.\r
1710 @param[in, out] UserInfo On entry, points to the user information to modify,\r
1711 or NULL to add a new UserInfo. \r
1712 On return, points to the modified user information.\r
1713 @param[in] Info Points to the new user information.\r
1714 @param[in] InfoSize The size of Info,in bytes.\r
1715\r
1716 @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL.\r
1717 @retval EFI_ACCESS_DENIED The record is exclusive.\r
1718 @retval EFI_SUCCESS User information was successfully changed/added.\r
1719\r
1720**/\r
1721EFI_STATUS\r
1722ModifyUserInfo (\r
1723 IN USER_PROFILE_ENTRY *User,\r
1724 IN OUT EFI_USER_INFO **UserInfo,\r
1725 IN CONST EFI_USER_INFO *Info,\r
1726 IN UINTN InfoSize\r
1727 )\r
1728{\r
1729 EFI_STATUS Status;\r
1730 UINTN PayloadLen;\r
1731 EFI_USER_INFO *OldInfo;\r
1732 EFI_USER_INFO *IpInfo;\r
1733\r
1734 if ((UserInfo == NULL) || (Info == NULL)) {\r
1735 return EFI_INVALID_PARAMETER;\r
1736 }\r
1737\r
1738 if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) {\r
1739 return EFI_INVALID_PARAMETER;\r
1740 }\r
1741 \r
1742 //\r
1743 // Check user information.\r
1744 //\r
1745 if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {\r
1746 return EFI_ACCESS_DENIED;\r
1747 }\r
1748 \r
1749 if (!CheckUserInfo (Info)) {\r
1750 return EFI_INVALID_PARAMETER;\r
1751 }\r
1752\r
1753\r
1754 if (*UserInfo == NULL) {\r
1755 //\r
1756 // Add new user information.\r
1757 //\r
1758 OldInfo = NULL;\r
1759 do {\r
1760 Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);\r
1761 if (EFI_ERROR (Status)) {\r
1762 break;\r
1763 }\r
1764 ASSERT (OldInfo != NULL);\r
1765\r
1766 if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) || \r
1767 ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) {\r
1768 //\r
1769 // Same type can not co-exist for exclusive information.\r
1770 //\r
1771 return EFI_ACCESS_DENIED;\r
1772 }\r
1773\r
1774 //\r
1775 // Check whether it exists in DB.\r
1776 //\r
1777 if (Info->InfoSize != OldInfo->InfoSize) {\r
1778 continue;\r
1779 }\r
1780\r
1781 if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) {\r
1782 continue;\r
1783 }\r
1784 \r
1785 PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO);\r
1786 if (PayloadLen == 0) {\r
1787 continue;\r
1788 }\r
1789\r
1790 if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) {\r
1791 continue;\r
1792 }\r
1793\r
1794 //\r
1795 // Yes. The new info is as same as the one in profile.\r
1796 //\r
1797 return EFI_SUCCESS;\r
1798 } while (!EFI_ERROR (Status));\r
1799\r
1800 Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);\r
1801 return Status;\r
1802 }\r
1803 \r
1804 //\r
1805 // Modify existing user information.\r
1806 //\r
1807 OldInfo = *UserInfo;\r
1808 if (OldInfo->InfoType != Info->InfoType) {\r
1809 return EFI_INVALID_PARAMETER;\r
1810 }\r
1811 \r
1812 if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) && \r
1813 (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) {\r
1814 //\r
1815 // Try to add exclusive attrib in new info. \r
1816 // Check whether there is another information with the same type in profile.\r
1817 //\r
1818 OldInfo = NULL;\r
1819 do {\r
1820 Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);\r
1821 if (EFI_ERROR (Status)) {\r
1822 break;\r
1823 }\r
1824 if (OldInfo != *UserInfo) {\r
1825 //\r
1826 // There is another information with the same type in profile.\r
1827 // Therefore, can't modify existing user information to add exclusive attribute.\r
1828 //\r
1829 return EFI_ACCESS_DENIED;\r
1830 }\r
1831 } while (TRUE); \r
1832 }\r
1833\r
1834 if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {\r
1835 //\r
1836 // For user identification policy, need to update the info in credential provider.\r
1837 //\r
1838 IpInfo = NULL;\r
1839 Status = ModifyUserIpInfo (User, Info, InfoSize, &IpInfo);\r
1840 if (EFI_ERROR (Status)) {\r
1841 return Status;\r
1842 }\r
1843\r
1844 ASSERT (IpInfo != NULL);\r
1845 Status = SaveUserIpInfo (User, IpInfo, UserInfo);\r
1846 if (IpInfo->InfoSize != Info->InfoSize) {\r
1847 Status = EFI_DEVICE_ERROR;\r
1848 }\r
1849 FreePool (IpInfo); \r
1850 return Status;\r
1851 }\r
1852\r
1853 Status = DelUserInfo (User, *UserInfo, FALSE);\r
1854 if (EFI_ERROR (Status)) {\r
1855 return Status;\r
1856 }\r
1857\r
1858 return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);\r
1859}\r
1860\r
1861\r
1862/**\r
1863 Delete the user profile from non-volatile memory and database.\r
1864\r
1865 @param[in] User Points to the user profile.\r
1866\r
1867 @retval EFI_SUCCESS Delete user from the user profile successfully.\r
1868 @retval Others Fail to delete user from user profile\r
1869 \r
1870**/\r
1871EFI_STATUS\r
1872DelUserProfile (\r
1873 IN USER_PROFILE_ENTRY *User\r
1874 )\r
1875{\r
1876 EFI_STATUS Status;\r
1877 UINTN Index;\r
1878 EFI_USER_INFO *UserInfo;\r
1879\r
1880 //\r
1881 // Check whether it is in the user profile database.\r
1882 //\r
1883 Status = FindUserProfile (&User, FALSE, &Index);\r
1884 if (EFI_ERROR (Status)) {\r
1885 return EFI_INVALID_PARAMETER;\r
1886 }\r
1887 \r
1888 //\r
1889 // Check whether it is the current user.\r
1890 //\r
1891 if (User == mCurrentUser) {\r
1892 return EFI_ACCESS_DENIED;\r
1893 }\r
1894 \r
1895 //\r
1896 // Delete user credential information.\r
1897 //\r
1898 UserInfo = NULL;\r
1899 Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
1900 if (Status == EFI_SUCCESS) {\r
1901 Status = DelUserInfo (User, UserInfo, FALSE);\r
1902 if (EFI_ERROR (Status)) {\r
1903 return Status;\r
1904 }\r
1905 }\r
1906 \r
1907 //\r
1908 // Delete user profile from the non-volatile memory.\r
1909 //\r
1910 Status = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE);\r
1911 if (EFI_ERROR (Status)) {\r
1912 return Status;\r
1913 }\r
1914 mUserProfileDb->UserProfileNum--;\r
1915\r
1916 //\r
1917 // Modify user profile database.\r
1918 //\r
1919 if (Index != mUserProfileDb->UserProfileNum) {\r
1920 mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum];\r
1921 CopyMem (\r
1922 ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName,\r
1923 User->UserVarName,\r
1924 sizeof (User->UserVarName)\r
1925 );\r
1926 Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE);\r
1927 if (EFI_ERROR (Status)) {\r
1928 return Status;\r
1929 }\r
1930 }\r
1931 //\r
1932 // Delete user profile information.\r
1933 //\r
1934 if (User->ProfileInfo != NULL) {\r
1935 FreePool (User->ProfileInfo);\r
1936 }\r
1937\r
1938 FreePool (User);\r
1939 return EFI_SUCCESS;\r
1940}\r
1941\r
1942\r
1943/**\r
1944 Add user profile to user profile database.\r
1945\r
1946 @param[out] UserProfile Point to the newly added user profile.\r
1947 @param[in] ProfileSize The size of the user profile.\r
1948 @param[in] ProfileInfo Point to the user profie data.\r
1949 @param[in] Save If TRUE, save the new added profile to NV flash.\r
1950 If FALSE, don't save the profile to NV flash.\r
1951\r
1952 @retval EFI_SUCCESS Add user profile to user profile database successfully.\r
1953 @retval Others Fail to add user profile to user profile database.\r
1954\r
1955**/\r
1956EFI_STATUS\r
1957AddUserProfile (\r
1958 OUT USER_PROFILE_ENTRY **UserProfile, OPTIONAL\r
1959 IN UINTN ProfileSize,\r
1960 IN UINT8 *ProfileInfo,\r
1961 IN BOOLEAN Save\r
1962 )\r
1963{\r
1964 EFI_STATUS Status;\r
1965 USER_PROFILE_ENTRY *User;\r
1966\r
1967 //\r
1968 // Check the data format to be added.\r
1969 //\r
1970 if (!CheckProfileInfo (ProfileInfo, ProfileSize)) {\r
1971 return EFI_SECURITY_VIOLATION;\r
1972 }\r
1973 \r
1974 //\r
1975 // Create user profile entry.\r
1976 //\r
1977 User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY));\r
1978 if (User == NULL) {\r
1979 return EFI_OUT_OF_RESOURCES;\r
1980 }\r
1981 //\r
1982 // Add the entry to the user profile database.\r
1983 //\r
1984 if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) {\r
1985 if (!ExpandUsermUserProfileDb ()) {\r
1986 FreePool (User);\r
1987 return EFI_OUT_OF_RESOURCES;\r
1988 }\r
1989 }\r
1990\r
1991 UnicodeSPrint (\r
1992 User->UserVarName, \r
1993 sizeof (User->UserVarName),\r
1994 L"User%04x", \r
1995 mUserProfileDb->UserProfileNum\r
1996 );\r
1997 User->UserProfileSize = 0;\r
1998 User->MaxProfileSize = 0;\r
1999 User->ProfileInfo = NULL;\r
2000 mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User;\r
2001 mUserProfileDb->UserProfileNum++;\r
2002\r
2003 //\r
2004 // Add user profile information.\r
2005 //\r
2006 Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save);\r
2007 if (EFI_ERROR (Status)) {\r
2008 DelUserProfile (User);\r
2009 return Status;\r
2010 }\r
2011 //\r
2012 // Set new user profile handle.\r
2013 //\r
2014 if (UserProfile != NULL) {\r
2015 *UserProfile = User;\r
2016 }\r
2017\r
2018 return EFI_SUCCESS;\r
2019}\r
2020\r
2021\r
2022/**\r
2023 This function creates a new user profile with only a new user identifier\r
2024 attached and returns its handle. The user profile is non-volatile, but the\r
2025 handle User can change across reboots.\r
2026\r
2027 @param[out] User Handle of a new user profile.\r
2028\r
2029 @retval EFI_SUCCESS User profile was successfully created.\r
2030 @retval Others Fail to create user profile\r
2031\r
2032**/\r
2033EFI_STATUS\r
2034CreateUserProfile (\r
2035 OUT USER_PROFILE_ENTRY **User\r
2036 )\r
2037{\r
2038 EFI_STATUS Status;\r
2039 EFI_USER_INFO *UserInfo;\r
2040\r
2041 if (User == NULL) {\r
2042 return EFI_INVALID_PARAMETER;\r
2043 }\r
2044 //\r
2045 // Generate user id information.\r
2046 //\r
2047 UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));\r
2048 if (UserInfo == NULL) {\r
2049 return EFI_OUT_OF_RESOURCES;\r
2050 }\r
2051\r
2052 UserInfo->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD;\r
2053 UserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);\r
2054 UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2055 GenerateUserId ((UINT8 *) (UserInfo + 1));\r
2056 \r
2057 //\r
2058 // Add user profile to the user profile database.\r
2059 //\r
2060 Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE);\r
2061 FreePool (UserInfo);\r
2062 return Status;\r
2063}\r
2064\r
2065\r
2066/**\r
2067 Add a default user profile to user profile database.\r
2068\r
2069 @retval EFI_SUCCESS A default user profile is added successfully.\r
2070 @retval Others Fail to add a default user profile\r
2071 \r
2072**/\r
2073EFI_STATUS\r
2074AddDefaultUserProfile (\r
2075 VOID\r
2076 )\r
2077{\r
2078 EFI_STATUS Status;\r
2079 USER_PROFILE_ENTRY *User;\r
2080 EFI_USER_INFO *Info;\r
2081 EFI_USER_INFO *NewInfo;\r
2082 EFI_USER_INFO_CREATE_DATE CreateDate;\r
2083 EFI_USER_INFO_USAGE_COUNT UsageCount;\r
2084 EFI_USER_INFO_ACCESS_CONTROL *Access;\r
2085 EFI_USER_INFO_IDENTITY_POLICY *Policy;\r
2086 \r
2087 //\r
2088 // Create a user profile.\r
2089 //\r
2090 Status = CreateUserProfile (&User);\r
2091 if (EFI_ERROR (Status)) {\r
2092 return Status;\r
2093 }\r
2094 \r
2095 //\r
2096 // Allocate a buffer to add all default user information.\r
2097 //\r
2098 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE);\r
2099 if (Info == NULL) {\r
2100 return EFI_OUT_OF_RESOURCES;\r
2101 }\r
2102\r
2103 //\r
2104 // Add user name.\r
2105 //\r
2106 Info->InfoType = EFI_USER_INFO_NAME_RECORD;\r
2107 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2108 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (mUserName);\r
2109 CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName));\r
2110 NewInfo = NULL;\r
2111 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2112 if (EFI_ERROR (Status)) {\r
2113 goto Done;\r
2114 }\r
2115 \r
2116 //\r
2117 // Add user profile create date record.\r
2118 //\r
2119 Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;\r
2120 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2121 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);\r
2122 Status = gRT->GetTime (&CreateDate, NULL);\r
2123 if (EFI_ERROR (Status)) {\r
2124 goto Done;\r
2125 }\r
2126\r
2127 CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE));\r
2128 NewInfo = NULL;\r
2129 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2130 if (EFI_ERROR (Status)) {\r
2131 goto Done;\r
2132 }\r
2133 \r
2134 //\r
2135 // Add user profile usage count record.\r
2136 //\r
2137 Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD;\r
2138 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2139 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);\r
2140 UsageCount = 0;\r
2141 CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));\r
2142 NewInfo = NULL;\r
2143 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2144 if (EFI_ERROR (Status)) {\r
2145 goto Done;\r
2146 }\r
2147 \r
2148 //\r
2149 // Add user access right.\r
2150 //\r
2151 Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD;\r
2152 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2153 Access = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1);\r
2154 Access->Type = EFI_USER_INFO_ACCESS_MANAGE;\r
2155 Access->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
2156 Info->InfoSize = sizeof (EFI_USER_INFO) + Access->Size;\r
2157 NewInfo = NULL;\r
2158 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2159 if (EFI_ERROR (Status)) {\r
2160 goto Done;\r
2161 }\r
2162 \r
2163 //\r
2164 // Add user identity policy.\r
2165 //\r
2166 Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD;\r
2167 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE;\r
2168 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1);\r
2169 Policy->Type = EFI_USER_INFO_IDENTITY_TRUE;\r
2170 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); \r
2171 Info->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length;\r
2172 NewInfo = NULL;\r
2173 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2174\r
2175Done:\r
2176 FreePool (Info);\r
2177 return Status;\r
2178}\r
2179\r
2180\r
2181/**\r
2182 Publish current user information into EFI System Configuration Table.\r
2183\r
2184 By UEFI spec, the User Identity Manager will publish the current user profile \r
2185 into the EFI System Configuration Table. Currently, only the user identifier and user\r
2186 name are published.\r
2187\r
2188 @retval EFI_SUCCESS Current user information is published successfully.\r
2189 @retval Others Fail to publish current user information\r
2190\r
2191**/\r
2192EFI_STATUS\r
2193PublishUserTable (\r
2194 VOID\r
2195 )\r
2196{\r
2197 EFI_STATUS Status;\r
2198 EFI_CONFIGURATION_TABLE *EfiConfigurationTable;\r
2199 EFI_USER_INFO_TABLE *UserInfoTable;\r
2200 EFI_USER_INFO *IdInfo;\r
2201 EFI_USER_INFO *NameInfo;\r
2202\r
2203 Status = EfiGetSystemConfigurationTable (\r
2204 &gEfiUserManagerProtocolGuid,\r
2205 (VOID **) &EfiConfigurationTable\r
2206 );\r
2207 if (!EFI_ERROR (Status)) {\r
2208 //\r
2209 // The table existed! \r
2210 //\r
2211 return EFI_SUCCESS;\r
2212 }\r
2213\r
2214 //\r
2215 // Get user ID information.\r
2216 //\r
2217 IdInfo = NULL;\r
2218 Status = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);\r
2219 if (EFI_ERROR (Status)) {\r
2220 return Status;\r
2221\r
2222 }\r
2223 //\r
2224 // Get user name information.\r
2225 //\r
2226 NameInfo = NULL;\r
2227 Status = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD);\r
2228 if (EFI_ERROR (Status)) {\r
2229 return Status;\r
2230 }\r
2231 \r
2232 //\r
2233 // Allocate a buffer for user information table.\r
2234 //\r
2235 UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool (\r
2236 sizeof (EFI_USER_INFO_TABLE) + \r
2237 IdInfo->InfoSize + \r
2238 NameInfo->InfoSize\r
2239 );\r
2240 if (UserInfoTable == NULL) {\r
2241 Status = EFI_OUT_OF_RESOURCES;\r
2242 return Status;\r
2243 }\r
2244\r
2245 UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE); \r
2246 \r
2247 //\r
2248 // Append the user information to the user info table\r
2249 //\r
2250 CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize);\r
2251 UserInfoTable->Size += IdInfo->InfoSize;\r
2252\r
2253 CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize);\r
2254 UserInfoTable->Size += NameInfo->InfoSize;\r
2255\r
2256 Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable);\r
2257 return Status;\r
2258}\r
2259\r
2260\r
2261/**\r
2262 Get the user's identity type.\r
2263\r
2264 The identify manager only supports the identity policy in which the credential \r
2265 provider handles are connected by the operator 'AND' or 'OR'.\r
2266\r
2267\r
2268 @param[in] User Handle of a user profile.\r
2269 @param[out] PolicyType Point to the identity type.\r
2270\r
2271 @retval EFI_SUCCESS Get user's identity type successfully.\r
2272 @retval Others Fail to get user's identity type.\r
2273\r
2274**/\r
2275EFI_STATUS\r
2276GetIdentifyType (\r
2277 IN EFI_USER_PROFILE_HANDLE User,\r
2278 OUT UINT8 *PolicyType\r
2279 )\r
2280{\r
2281 EFI_STATUS Status;\r
2282 EFI_USER_INFO *IdentifyInfo;\r
2283 UINTN TotalLen;\r
2284 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
2285\r
2286 //\r
2287 // Get user identify policy information.\r
2288 //\r
2289 IdentifyInfo = NULL;\r
2290 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
2291 if (EFI_ERROR (Status)) {\r
2292 return Status;\r
2293 }\r
2294 ASSERT (IdentifyInfo != NULL);\r
2295 \r
2296 //\r
2297 // Search the user identify policy according to type.\r
2298 //\r
2299 TotalLen = 0;\r
2300 *PolicyType = EFI_USER_INFO_IDENTITY_FALSE;\r
2301 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
2302 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);\r
2303 if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) {\r
2304 *PolicyType = EFI_USER_INFO_IDENTITY_AND;\r
2305 break;\r
2306 }\r
2307\r
2308 if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) {\r
2309 *PolicyType = EFI_USER_INFO_IDENTITY_OR;\r
2310 break;\r
2311 }\r
2312 TotalLen += Identity->Length;\r
2313 }\r
2314 return EFI_SUCCESS;\r
2315}\r
2316\r
2317\r
2318/**\r
2319 Identify the User by the specfied provider.\r
2320\r
2321 @param[in] User Handle of a user profile.\r
2322 @param[in] Provider Points to the identifir of credential provider.\r
2323\r
2324 @retval EFI_INVALID_PARAMETER Provider is NULL.\r
2325 @retval EFI_NOT_FOUND Fail to identify the specified user.\r
2326 @retval EFI_SUCCESS User is identified successfully.\r
2327\r
2328**/\r
2329EFI_STATUS\r
2330IdentifyByProviderId (\r
2331 IN EFI_USER_PROFILE_HANDLE User,\r
2332 IN EFI_GUID *Provider\r
2333 )\r
2334{\r
2335 EFI_STATUS Status;\r
2336 EFI_USER_INFO_IDENTIFIER UserId;\r
2337 UINTN Index;\r
2338 EFI_CREDENTIAL_LOGON_FLAGS AutoLogon;\r
2339 EFI_HII_HANDLE HiiHandle;\r
2340 EFI_GUID FormSetId;\r
2341 EFI_FORM_ID FormId;\r
2342 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;\r
2343 EFI_USER_INFO *IdInfo;\r
2344\r
2345 if (Provider == NULL) {\r
2346 return EFI_INVALID_PARAMETER;\r
2347 }\r
2348 \r
2349 //\r
2350 // Check the user ID identified by the specified credential provider.\r
2351 //\r
2352 for (Index = 0; Index < mProviderDb->Count; Index++) {\r
2353 //\r
2354 // Check credential provider class.\r
2355 //\r
2356 UserCredential = mProviderDb->Provider[Index];\r
2357 if (CompareGuid (&UserCredential->Identifier, Provider)) {\r
2358 Status = UserCredential->Select (UserCredential, &AutoLogon);\r
2359 if (EFI_ERROR (Status)) {\r
2360 return Status;\r
2361 }\r
2362\r
2363 if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) {\r
2364 //\r
2365 // Get credential provider form.\r
2366 //\r
2367 Status = UserCredential->Form (\r
2368 UserCredential, \r
2369 &HiiHandle, \r
2370 &FormSetId, \r
2371 &FormId\r
2372 );\r
2373 if (!EFI_ERROR (Status)) { \r
2374 //\r
2375 // Send form to get user input.\r
2376 //\r
2377 Status = mCallbackInfo->FormBrowser2->SendForm (\r
2378 mCallbackInfo->FormBrowser2,\r
2379 &HiiHandle,\r
2380 1,\r
2381 &FormSetId,\r
2382 FormId,\r
2383 NULL,\r
2384 NULL\r
2385 );\r
2386 if (EFI_ERROR (Status)) {\r
2387 return Status;\r
2388 } \r
2389 } \r
2390 }\r
2391\r
2392 Status = UserCredential->User (UserCredential, User, &UserId);\r
2393 if (EFI_ERROR (Status)) {\r
2394 return Status;\r
2395 }\r
2396\r
2397 Status = UserCredential->Deselect (UserCredential);\r
2398 if (EFI_ERROR (Status)) {\r
2399 return Status;\r
2400 }\r
2401\r
2402 if (User == NULL) {\r
2403 return EFI_SUCCESS;\r
2404 }\r
2405 \r
2406 //\r
2407 // Get user ID information.\r
2408 //\r
2409 IdInfo = NULL;\r
2410 Status = FindUserInfoByType (User, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);\r
2411 ASSERT (IdInfo != NULL);\r
2412\r
2413 if (CompareMem ((UINT8 *) (IdInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) != 0) {\r
2414 //\r
2415 // One user name is selected, but the other's credential is given. Here no user passed.\r
2416 //\r
2417 break;\r
2418 }\r
2419 return EFI_SUCCESS;\r
2420 }\r
2421 }\r
2422\r
2423 return EFI_NOT_FOUND;\r
2424}\r
2425\r
2426\r
2427/**\r
2428 Update user information when user is logon on successfully.\r
2429\r
2430 @param[in] User Points to user profile.\r
2431\r
2432 @retval EFI_SUCCESS Update user information successfully.\r
2433 @retval Others Fail to update user information.\r
2434\r
2435**/\r
2436EFI_STATUS\r
2437UpdateUserInfo (\r
2438 IN USER_PROFILE_ENTRY *User\r
2439 )\r
2440{\r
2441 EFI_STATUS Status;\r
2442 EFI_USER_INFO *Info;\r
2443 EFI_USER_INFO *NewInfo;\r
2444 EFI_USER_INFO_CREATE_DATE Date;\r
2445 EFI_USER_INFO_USAGE_COUNT UsageCount;\r
2446 UINTN InfoLen;\r
2447\r
2448 //\r
2449 // Allocate a buffer to update user's date record and usage record.\r
2450 //\r
2451 InfoLen = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT));\r
2452 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen);\r
2453 if (Info == NULL) {\r
2454 return EFI_OUT_OF_RESOURCES;\r
2455 }\r
2456 \r
2457 //\r
2458 // Check create date record.\r
2459 //\r
2460 NewInfo = NULL;\r
2461 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD);\r
2462 if (Status == EFI_NOT_FOUND) {\r
2463 Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;\r
2464 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2465 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);\r
2466 Status = gRT->GetTime (&Date, NULL);\r
2467 if (EFI_ERROR (Status)) {\r
2468 FreePool (Info);\r
2469 return Status;\r
2470 }\r
2471\r
2472 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));\r
2473 NewInfo = NULL;\r
2474 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2475 if (EFI_ERROR (Status)) {\r
2476 FreePool (Info);\r
2477 return Status;\r
2478 }\r
2479 }\r
2480 \r
2481 //\r
2482 // Update usage date record.\r
2483 //\r
2484 NewInfo = NULL;\r
2485 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD);\r
2486 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {\r
2487 Info->InfoType = EFI_USER_INFO_USAGE_DATE_RECORD;\r
2488 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2489 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE);\r
2490 Status = gRT->GetTime (&Date, NULL);\r
2491 if (EFI_ERROR (Status)) {\r
2492 FreePool (Info);\r
2493 return Status;\r
2494 }\r
2495\r
2496 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE));\r
2497 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2498 if (EFI_ERROR (Status)) {\r
2499 FreePool (Info);\r
2500 return Status;\r
2501 }\r
2502 }\r
2503 \r
2504 //\r
2505 // Update usage count record.\r
2506 //\r
2507 UsageCount = 0;\r
2508 NewInfo = NULL;\r
2509 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD);\r
2510 //\r
2511 // Get usage count.\r
2512 //\r
2513 if (Status == EFI_SUCCESS) {\r
2514 CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT));\r
2515 }\r
2516\r
2517 UsageCount++;\r
2518 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {\r
2519 Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD;\r
2520 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;\r
2521 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);\r
2522 CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));\r
2523 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);\r
2524 if (EFI_ERROR (Status)) {\r
2525 FreePool (Info);\r
2526 return Status;\r
2527 }\r
2528 }\r
2529\r
2530 FreePool (Info);\r
2531 return EFI_SUCCESS;\r
2532}\r
2533\r
2534\r
2535/**\r
2536 Add a credenetial provider item in form.\r
2537\r
2538 @param[in] ProviderGuid Points to the identifir of credential provider.\r
2539 @param[in] OpCodeHandle Points to container for dynamic created opcodes.\r
2540\r
2541**/\r
2542VOID\r
2543AddProviderSelection (\r
2544 IN EFI_GUID *ProviderGuid,\r
2545 IN VOID *OpCodeHandle\r
2546 )\r
2547{\r
2548 EFI_HII_HANDLE HiiHandle;\r
2549 EFI_STRING_ID ProvID;\r
2550 CHAR16 *ProvStr;\r
2551 UINTN Index;\r
2552 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;\r
2553\r
2554 for (Index = 0; Index < mProviderDb->Count; Index++) {\r
2555 UserCredential = mProviderDb->Provider[Index];\r
2556 if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) {\r
2557 //\r
2558 // Add credential provider selection.\r
2559 //\r
2560 UserCredential->Title (UserCredential, &HiiHandle, &ProvID);\r
2561 ProvStr = HiiGetString (HiiHandle, ProvID, NULL);\r
2562 if (ProvStr == NULL) {\r
2563 continue ;\r
2564 }\r
2565 ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);\r
2566 FreePool (ProvStr);\r
2567 HiiCreateActionOpCode (\r
2568 OpCodeHandle, // Container for dynamic created opcodes\r
2569 (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index), // Question ID\r
2570 ProvID, // Prompt text\r
2571 STRING_TOKEN (STR_NULL_STRING), // Help text\r
2572 EFI_IFR_FLAG_CALLBACK, // Question flag\r
2573 0 // Action String ID\r
2574 );\r
2575 break;\r
2576 }\r
2577 }\r
2578}\r
2579\r
2580\r
2581/**\r
2582 Add a username item in form.\r
2583\r
2584 @param[in] Index The index of the user in the user name list.\r
2585 @param[in] User Points to the user profile whose username is added. \r
2586 @param[in] OpCodeHandle Points to container for dynamic created opcodes.\r
2587\r
2588 @retval EFI_SUCCESS Add a username successfully.\r
2589 @retval Others Fail to add a username.\r
2590\r
2591**/\r
2592EFI_STATUS\r
2593AddUserSelection (\r
2594 IN UINT16 Index,\r
2595 IN USER_PROFILE_ENTRY *User,\r
2596 IN VOID *OpCodeHandle\r
2597 )\r
2598{\r
2599 EFI_STRING_ID UserName;\r
2600 EFI_STATUS Status;\r
2601 EFI_USER_INFO *UserInfo;\r
2602\r
2603 UserInfo = NULL;\r
2604 Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD);\r
2605 if (EFI_ERROR (Status)) {\r
2606 return Status;\r
2607 }\r
2608 \r
2609 //\r
2610 // Add user name selection.\r
2611 //\r
2612 UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL);\r
2613 if (UserName == 0) {\r
2614 return EFI_OUT_OF_RESOURCES;\r
2615 }\r
2616\r
2617 HiiCreateGotoOpCode (\r
2618 OpCodeHandle, // Container for dynamic created opcodes\r
2619 FORMID_PROVIDER_FORM, // Target Form ID\r
2620 UserName, // Prompt text\r
2621 STRING_TOKEN (STR_NULL_STRING), // Help text\r
2622 EFI_IFR_FLAG_CALLBACK, // Question flag\r
2623 (UINT16) Index // Question ID\r
2624 );\r
2625\r
2626 return EFI_SUCCESS;\r
2627}\r
2628\r
2629\r
2630/**\r
2631 Identify the user whose identity policy does not contain the operator 'OR'.\r
2632 \r
2633 @param[in] User Points to the user profile.\r
2634\r
2635 @retval EFI_SUCCESS The specified user is identified successfully.\r
2636 @retval Others Fail to identify the user.\r
2637 \r
2638**/\r
2639EFI_STATUS\r
2640IdentifyAndTypeUser (\r
2641 IN USER_PROFILE_ENTRY *User\r
2642 )\r
2643{\r
2644 EFI_STATUS Status;\r
2645 EFI_USER_INFO *IdentifyInfo;\r
2646 BOOLEAN Success;\r
2647 UINTN TotalLen;\r
2648 UINTN ValueLen;\r
2649 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
2650\r
2651 //\r
2652 // Get user identify policy information.\r
2653 //\r
2654 IdentifyInfo = NULL;\r
2655 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
2656 if (EFI_ERROR (Status)) {\r
2657 return Status;\r
2658 }\r
2659 ASSERT (IdentifyInfo != NULL);\r
2660 \r
2661 //\r
2662 // Check each part of identification policy expression.\r
2663 //\r
2664 Success = FALSE;\r
2665 TotalLen = 0;\r
2666 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
2667 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);\r
2668 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);\r
2669 switch (Identity->Type) {\r
2670\r
2671 case EFI_USER_INFO_IDENTITY_FALSE:\r
2672 //\r
2673 // Check False option.\r
2674 //\r
2675 Success = FALSE;\r
2676 break;\r
2677\r
2678 case EFI_USER_INFO_IDENTITY_TRUE:\r
2679 //\r
2680 // Check True option.\r
2681 //\r
2682 Success = TRUE;\r
2683 break;\r
2684\r
2685 case EFI_USER_INFO_IDENTITY_NOT:\r
2686 //\r
2687 // Check negative operation.\r
2688 //\r
2689 break;\r
2690\r
2691 case EFI_USER_INFO_IDENTITY_AND:\r
2692 //\r
2693 // Check and operation.\r
2694 //\r
2695 if (!Success) {\r
2696 return EFI_NOT_READY;\r
2697 }\r
2698\r
2699 Success = FALSE;\r
2700 break;\r
2701\r
2702 case EFI_USER_INFO_IDENTITY_OR:\r
2703 //\r
2704 // Check or operation.\r
2705 //\r
2706 if (Success) {\r
2707 return EFI_SUCCESS;\r
2708 }\r
2709 break;\r
2710\r
2711 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:\r
2712 //\r
2713 // Check credential provider by type.\r
2714 //\r
2715 break;\r
2716\r
2717 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:\r
2718 //\r
2719 // Check credential provider by ID.\r
2720 //\r
2721 if (ValueLen != sizeof (EFI_GUID)) {\r
2722 return EFI_INVALID_PARAMETER;\r
2723 }\r
2724\r
2725 Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1));\r
2726 if (EFI_ERROR (Status)) {\r
2727 return Status;\r
2728 }\r
2729\r
2730 Success = TRUE;\r
2731 break;\r
2732\r
2733 default:\r
2734 return EFI_INVALID_PARAMETER;\r
2735 break;\r
2736 }\r
2737\r
2738 TotalLen += Identity->Length;\r
2739 }\r
2740\r
2741 if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
2742 return EFI_INVALID_PARAMETER;\r
2743 }\r
2744\r
2745 if (!Success) {\r
2746 return EFI_NOT_READY;\r
2747 }\r
2748\r
2749 return EFI_SUCCESS;\r
2750}\r
2751\r
2752\r
2753/**\r
2754 Identify the user whose identity policy does not contain the operator 'AND'.\r
2755 \r
2756 @param[in] User Points to the user profile.\r
2757\r
2758 @retval EFI_SUCCESS The specified user is identified successfully.\r
2759 @retval Others Fail to identify the user.\r
2760 \r
2761**/\r
2762EFI_STATUS\r
2763IdentifyOrTypeUser (\r
2764 IN USER_PROFILE_ENTRY *User\r
2765 )\r
2766{\r
2767 EFI_STATUS Status;\r
2768 EFI_USER_INFO *IdentifyInfo;\r
2769 UINTN TotalLen;\r
2770 UINTN ValueLen;\r
2771 EFI_USER_INFO_IDENTITY_POLICY *Identity;\r
2772 VOID *StartOpCodeHandle;\r
2773 VOID *EndOpCodeHandle;\r
2774 EFI_IFR_GUID_LABEL *StartLabel;\r
2775 EFI_IFR_GUID_LABEL *EndLabel;\r
2776\r
2777 //\r
2778 // Get user identify policy information.\r
2779 //\r
2780 IdentifyInfo = NULL;\r
2781 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);\r
2782 if (EFI_ERROR (Status)) {\r
2783 return Status;\r
2784 }\r
2785 ASSERT (IdentifyInfo != NULL);\r
2786 \r
2787 //\r
2788 // Initialize the container for dynamic opcodes.\r
2789 //\r
2790 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2791 ASSERT (StartOpCodeHandle != NULL);\r
2792\r
2793 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2794 ASSERT (EndOpCodeHandle != NULL);\r
2795\r
2796 //\r
2797 // Create Hii Extend Label OpCode.\r
2798 //\r
2799 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2800 StartOpCodeHandle,\r
2801 &gEfiIfrTianoGuid,\r
2802 NULL,\r
2803 sizeof (EFI_IFR_GUID_LABEL)\r
2804 );\r
2805 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2806 StartLabel->Number = LABEL_PROVIDER_NAME;\r
2807\r
2808 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2809 EndOpCodeHandle,\r
2810 &gEfiIfrTianoGuid,\r
2811 NULL,\r
2812 sizeof (EFI_IFR_GUID_LABEL)\r
2813 );\r
2814 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2815 EndLabel->Number = LABEL_END;\r
2816\r
2817 //\r
2818 // Add the providers that exists in the user's policy.\r
2819 //\r
2820 TotalLen = 0;\r
2821 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {\r
2822 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);\r
2823 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);\r
2824 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {\r
2825 AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle);\r
2826 }\r
2827\r
2828 TotalLen += Identity->Length;\r
2829 }\r
2830\r
2831 HiiUpdateForm (\r
2832 mCallbackInfo->HiiHandle, // HII handle\r
2833 &mUserManagerGuid, // Formset GUID\r
2834 FORMID_PROVIDER_FORM, // Form ID\r
2835 StartOpCodeHandle, // Label for where to insert opcodes\r
2836 EndOpCodeHandle // Replace data\r
2837 );\r
2838\r
2839 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2840 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2841\r
2842 return EFI_SUCCESS;\r
2843}\r
2844\r
2845\r
2846/**\r
2847 This function processes the results of changes in configuration.\r
2848\r
2849 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2850 @param Action Specifies the type of action taken by the browser.\r
2851 @param QuestionId A unique value which is sent to the original\r
2852 exporting driver so that it can identify the type\r
2853 of data to expect.\r
2854 @param Type The type of value for the question.\r
2855 @param Value A pointer to the data being sent to the original\r
2856 exporting driver.\r
2857 @param ActionRequest On return, points to the action requested by the\r
2858 callback function.\r
2859\r
2860 @retval EFI_SUCCESS The callback successfully handled the action.\r
2861 @retval Others Fail to handle the action.\r
2862\r
2863**/\r
2864EFI_STATUS\r
2865EFIAPI\r
2866UserIdentifyManagerCallback (\r
2867 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2868 IN EFI_BROWSER_ACTION Action,\r
2869 IN EFI_QUESTION_ID QuestionId,\r
2870 IN UINT8 Type,\r
2871 IN EFI_IFR_TYPE_VALUE *Value,\r
2872 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2873 )\r
2874{\r
2875 EFI_STATUS Status;\r
2876 USER_PROFILE_ENTRY *User;\r
2877 UINT8 PolicyType;\r
2878 UINT16 Index;\r
2879 VOID *StartOpCodeHandle;\r
2880 VOID *EndOpCodeHandle;\r
2881 EFI_IFR_GUID_LABEL *StartLabel;\r
2882 EFI_IFR_GUID_LABEL *EndLabel;\r
2883\r
2884 Status = EFI_SUCCESS;\r
2885\r
2886 switch (Action) {\r
2887 case EFI_BROWSER_ACTION_FORM_OPEN:\r
2888 {\r
2889 //\r
2890 // Update user Form when user Form is opened.\r
2891 // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form.\r
2892 //\r
2893 if (QuestionId != FORM_OPEN_QUESTION_ID) {\r
2894 return EFI_SUCCESS;\r
2895 }\r
2896 \r
2897 //\r
2898 // Initialize the container for dynamic opcodes.\r
2899 //\r
2900 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2901 ASSERT (StartOpCodeHandle != NULL);\r
2902 \r
2903 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2904 ASSERT (EndOpCodeHandle != NULL);\r
2905 \r
2906 //\r
2907 // Create Hii Extend Label OpCode.\r
2908 //\r
2909 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2910 StartOpCodeHandle,\r
2911 &gEfiIfrTianoGuid,\r
2912 NULL,\r
2913 sizeof (EFI_IFR_GUID_LABEL)\r
2914 );\r
2915 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2916 StartLabel->Number = LABEL_USER_NAME;\r
2917 \r
2918 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
2919 EndOpCodeHandle,\r
2920 &gEfiIfrTianoGuid,\r
2921 NULL,\r
2922 sizeof (EFI_IFR_GUID_LABEL)\r
2923 );\r
2924 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2925 EndLabel->Number = LABEL_END;\r
2926 \r
2927 //\r
2928 // Add all the user profile in the user profile database.\r
2929 //\r
2930 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {\r
2931 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index];\r
2932 AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle);\r
2933 }\r
2934 \r
2935 HiiUpdateForm (\r
2936 mCallbackInfo->HiiHandle, // HII handle\r
2937 &mUserManagerGuid, // Formset GUID\r
2938 FORMID_USER_FORM, // Form ID\r
2939 StartOpCodeHandle, // Label for where to insert opcodes\r
2940 EndOpCodeHandle // Replace data\r
2941 );\r
2942 \r
2943 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2944 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2945 \r
2946 return EFI_SUCCESS;\r
2947 }\r
2948 break;\r
2949\r
2950 case EFI_BROWSER_ACTION_FORM_CLOSE:\r
2951 Status = EFI_SUCCESS;\r
2952 break;\r
2953\r
2954 case EFI_BROWSER_ACTION_CHANGING:\r
2955 {\r
2956 if (QuestionId >= LABEL_PROVIDER_NAME) {\r
2957 //\r
2958 // QuestionId comes from the second Form (Select a Credential Provider if identity \r
2959 // policy is OR type). Identify the user by the selected provider.\r
2960 //\r
2961 Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier);\r
2962 if (Status == EFI_SUCCESS) {\r
2963 mIdentified = TRUE;\r
2964 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
2965 }\r
2966 return EFI_SUCCESS;\r
2967 }\r
2968\r
2969 //\r
2970 // QuestionId comes from the first Form (Select a user to identify).\r
2971 //\r
2972 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF];\r
2973 Status = GetIdentifyType (User, &PolicyType);\r
2974 if (EFI_ERROR (Status)) {\r
2975 return Status;\r
2976 }\r
2977\r
2978 if (PolicyType == EFI_USER_INFO_IDENTITY_OR) {\r
2979 //\r
2980 // Identify the user by "OR" logical.\r
2981 //\r
2982 Status = IdentifyOrTypeUser (User);\r
2983 if (EFI_ERROR (Status)) {\r
2984 return Status;\r
2985 }\r
2986\r
2987 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;\r
2988 } else {\r
2989 //\r
2990 // Identify the user by "AND" logical.\r
2991 //\r
2992 Status = IdentifyAndTypeUser (User);\r
2993 if (EFI_ERROR (Status)) {\r
2994 return Status;\r
2995 }\r
2996\r
2997 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;\r
2998 mIdentified = TRUE;\r
2999 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
3000 }\r
3001 }\r
3002 break;\r
3003\r
3004 default:\r
3005 //\r
3006 // All other action return unsupported.\r
3007 //\r
3008 Status = EFI_UNSUPPORTED;\r
3009 break;\r
3010 }\r
3011\r
3012\r
3013 return Status;\r
3014}\r
3015\r
3016\r
3017/**\r
3018 This function construct user profile database from user data saved in the Flash.\r
3019 If no user is found in Flash, add one default user "administrator" in the user \r
3020 profile database.\r
3021\r
3022 @retval EFI_SUCCESS Init user profile database successfully.\r
3023 @retval Others Fail to init user profile database.\r
3024 \r
3025**/\r
3026EFI_STATUS\r
3027InitUserProfileDb (\r
3028 VOID\r
3029 )\r
3030{\r
3031 EFI_STATUS Status;\r
3032 UINT8 *VarData;\r
3033 UINTN VarSize;\r
3034 UINTN CurVarSize;\r
3035 CHAR16 VarName[10];\r
3036 UINTN Index;\r
3037 UINT32 VarAttr;\r
3038\r
3039 if (mUserProfileDb != NULL) {\r
3040 //\r
3041 // The user profiles had been already initialized.\r
3042 //\r
3043 return EFI_SUCCESS;\r
3044 }\r
3045\r
3046 //\r
3047 // Init user profile database structure.\r
3048 //\r
3049 if (!ExpandUsermUserProfileDb ()) {\r
3050 return EFI_OUT_OF_RESOURCES;\r
3051 }\r
3052\r
3053 CurVarSize = DEFAULT_PROFILE_SIZE;\r
3054 VarData = AllocateZeroPool (CurVarSize);\r
3055 if (VarData == NULL) {\r
3056 return EFI_OUT_OF_RESOURCES;\r
3057 }\r
3058 \r
3059 //\r
3060 // Get all user proifle entries.\r
3061 //\r
3062 Index = 0;\r
3063 while (TRUE) {\r
3064 //\r
3065 // Get variable name.\r
3066 //\r
3067 UnicodeSPrint (\r
3068 VarName, \r
3069 sizeof (VarName),\r
3070 L"User%04x", \r
3071 Index\r
3072 );\r
3073 Index++;\r
3074\r
3075 //\r
3076 // Get variable value.\r
3077 //\r
3078 VarSize = CurVarSize;\r
3079 Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData);\r
3080 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3081 FreePool (VarData);\r
3082 VarData = AllocatePool (VarSize);\r
3083 if (VarData == NULL) {\r
3084 Status = EFI_OUT_OF_RESOURCES;\r
3085 break;\r
3086 }\r