]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/EfiIfrSupportLib/IfrCommon.c
Add in Macro named SUPPORT_DEPRECATED_IFRSUPPORTLIB_API to comment out the functions...
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / EfiIfrSupportLib / IfrCommon.c
1 /*++
2 Copyright (c) 2004 - 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module Name:
12 IfrCommon.c
13
14 Abstract:
15
16 Common Library Routines to assist in IFR creation on-the-fly
17
18 --*/
19
20 #include "IfrLibrary.h"
21
22 EFI_STATUS
23 GetCurrentLanguage (
24 OUT CHAR16 *Lang
25 )
26 /*++
27
28 Routine Description:
29
30 Determine what is the current language setting
31
32 Arguments:
33
34 Lang - Pointer of system language
35
36 Returns:
37
38 Status code
39
40 --*/
41 {
42 EFI_STATUS Status;
43 UINTN Size;
44 UINTN Index;
45 CHAR8 Language[4];
46
47 //
48 // Getting the system language and placing it into our Global Data
49 //
50 Size = sizeof (Language);
51
52 Status = gRT->GetVariable (
53 L"Lang",
54 &gEfiGlobalVariableGuid,
55 NULL,
56 &Size,
57 Language
58 );
59
60 if (EFI_ERROR (Status)) {
61 EfiAsciiStrCpy (Language, (CHAR8 *) "eng");
62 }
63
64 for (Index = 0; Index < 3; Index++) {
65 //
66 // Bitwise AND ascii value with 0xDF yields an uppercase value.
67 // Sign extend into a unicode value
68 //
69 Lang[Index] = (CHAR16) (Language[Index] & 0xDF);
70 }
71
72 //
73 // Null-terminate the value
74 //
75 Lang[3] = (CHAR16) 0;
76
77 return Status;
78 }
79
80
81 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
82 EFI_STATUS
83 AddString (
84 IN VOID *StringBuffer,
85 IN CHAR16 *Language,
86 IN CHAR16 *String,
87 IN OUT STRING_REF *StringToken
88 )
89 /*++
90
91 Routine Description:
92
93 Add a string to the incoming buffer and return the token and offset data
94
95 Arguments:
96
97 StringBuffer - The incoming buffer
98
99 Language - Currrent language
100
101 String - The string to be added
102
103 StringToken - The index where the string placed
104
105 Returns:
106
107 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
108
109 EFI_SUCCESS - String successfully added to the incoming buffer
110
111 --*/
112 {
113 EFI_HII_STRING_PACK *StringPack;
114 EFI_HII_STRING_PACK *StringPackBuffer;
115 VOID *NewBuffer;
116 RELOFST *PackSource;
117 RELOFST *PackDestination;
118 UINT8 *Source;
119 UINT8 *Destination;
120 UINTN Index;
121 BOOLEAN Finished;
122
123 StringPack = (EFI_HII_STRING_PACK *) StringBuffer;
124 Finished = FALSE;
125
126 //
127 // Pre-allocate a buffer sufficient for us to work on.
128 // We will use it as a destination scratch pad to build data on
129 // and when complete shift the data back to the original buffer
130 //
131 NewBuffer = EfiLibAllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);
132 if (NewBuffer == NULL) {
133 return EFI_OUT_OF_RESOURCES;
134 }
135
136 StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;
137
138 //
139 // StringPack is terminated with a length 0 entry
140 //
141 for (; StringPack->Header.Length != 0;) {
142 //
143 // If this stringpack's language is same as CurrentLanguage, use it
144 //
145 if (EfiCompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {
146 //
147 // We have some data in this string pack, copy the string package up to the string data
148 //
149 EfiCopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));
150
151 //
152 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
153 //
154 StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));
155 StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));
156
157 PackSource = (RELOFST *) (StringPack + 1);
158 PackDestination = (RELOFST *) (StringPackBuffer + 1);
159 for (Index = 0; PackSource[Index] != 0x0000; Index++) {
160 //
161 // Copy the stringpointers from old to new buffer
162 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
163 //
164 PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));
165 }
166
167 //
168 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
169 //
170 PackDestination[Index] = (UINT16)(PackDestination[Index-1] +
171 EfiStrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1])));
172 PackDestination[Index + 1] = (UINT16) 0;
173
174 //
175 // Index is the token value for the new string
176 //
177 *StringToken = (UINT16) Index;
178
179 //
180 // Source now points to the beginning of the old buffer strings
181 // Destination now points to the beginning of the new buffer strings
182 //
183 Source = (UINT8 *) &PackSource[Index + 1];
184 Destination = (UINT8 *) &PackDestination[Index + 2];
185
186 //
187 // This should copy all the strings from the old buffer to the new buffer
188 //
189 for (; Index != 0; Index--) {
190 //
191 // Copy Source string to destination buffer
192 //
193 EfiStrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);
194
195 //
196 // Adjust the source/destination to the next string location
197 //
198 Destination = Destination + EfiStrSize ((CHAR16 *) Source);
199 Source = Source + EfiStrSize ((CHAR16 *) Source);
200 }
201
202 //
203 // This copies the new string to the destination buffer
204 //
205 EfiStrCpy ((CHAR16 *) Destination, (CHAR16 *) String);
206
207 //
208 // Adjust the size of the changed string pack by adding the size of the new string
209 // along with the size of the additional offset entry for the new string
210 //
211 StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + EfiStrSize (String) + sizeof (RELOFST));
212
213 //
214 // Advance the buffers to point to the next spots.
215 //
216 StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);
217 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
218 Finished = TRUE;
219 continue;
220 }
221 //
222 // This isn't the language of the stringpack we were asked to add a string to
223 // so we need to copy it to the new buffer.
224 //
225 EfiCopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);
226
227 //
228 // Advance the buffers to point to the next spots.
229 //
230 StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);
231 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
232 }
233
234 //
235 // If we didn't copy the new data to a stringpack yet
236 //
237 if (!Finished) {
238 PackDestination = (RELOFST *) (StringPackBuffer + 1);
239 //
240 // Pointing to a new string pack location
241 //
242 StringPackBuffer->Header.Length = (UINT32)
243 (
244 sizeof (EFI_HII_STRING_PACK) -
245 sizeof (EFI_STRING) +
246 sizeof (RELOFST) +
247 sizeof (RELOFST) +
248 EfiStrSize (Language) +
249 EfiStrSize (String)
250 );
251 StringPackBuffer->Header.Type = EFI_HII_STRING;
252 StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
253 StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
254 StringPackBuffer->Attributes = 0;
255 PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
256 PackDestination[1] = (UINT16) (PackDestination[0] + EfiStrSize (Language));
257 PackDestination[2] = (UINT16) 0;
258
259 //
260 // The first string location will be set to destination. The minimum number of strings
261 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
262 // and token 1 as the new string being added and and null entry for the stringpointers
263 //
264 Destination = (CHAR8 *) &PackDestination[3];
265
266 //
267 // Copy the language name string to the new buffer
268 //
269 EfiStrCpy ((CHAR16 *) Destination, Language);
270
271 //
272 // Advance the destination to the new empty spot
273 //
274 Destination = Destination + EfiStrSize (Language);
275
276 //
277 // Copy the string to the new buffer
278 //
279 EfiStrCpy ((CHAR16 *) Destination, String);
280
281 //
282 // Since we are starting with a new string pack - we know the new string is token 1
283 //
284 *StringToken = (UINT16) 1;
285 }
286
287 //
288 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
289 //
290 EfiZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);
291 EfiCopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);
292
293 //
294 // Free the newly created buffer since we don't need it anymore
295 //
296 gBS->FreePool (NewBuffer);
297 return EFI_SUCCESS;
298 }
299
300
301 EFI_STATUS
302 AddOpCode (
303 IN VOID *FormBuffer,
304 IN OUT VOID *OpCodeData
305 )
306 /*++
307
308 Routine Description:
309
310 Add op-code data to the FormBuffer
311
312 Arguments:
313
314 FormBuffer - Form buffer to be inserted to
315
316 OpCodeData - Op-code data to be inserted
317
318 Returns:
319
320 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
321
322 EFI_SUCCESS - Op-code data successfully inserted
323
324 --*/
325 {
326 EFI_HII_PACK_HEADER *NewBuffer;
327 UINT8 *Source;
328 UINT8 *Destination;
329
330 //
331 // Pre-allocate a buffer sufficient for us to work on.
332 // We will use it as a destination scratch pad to build data on
333 // and when complete shift the data back to the original buffer
334 //
335 NewBuffer = EfiLibAllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);
336 if (NewBuffer == NULL) {
337 return EFI_OUT_OF_RESOURCES;
338 }
339
340 Source = (UINT8 *) FormBuffer;
341 Destination = (UINT8 *) NewBuffer;
342
343 //
344 // Copy the IFR Package header to the new buffer
345 //
346 EfiCopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));
347
348 //
349 // Advance Source and Destination to next op-code
350 //
351 Source = Source + sizeof (EFI_HII_PACK_HEADER);
352 Destination = Destination + sizeof (EFI_HII_PACK_HEADER);
353
354 //
355 // Copy data to the new buffer until we run into the end_form
356 //
357 for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) {
358 //
359 // If the this opcode is an end_form_set we better be creating and endform
360 // Nonetheless, we will add data before the end_form_set. This also provides
361 // for interesting behavior in the code we will run, but has no bad side-effects
362 // since we will possibly do a 0 byte copy in this particular end-case.
363 //
364 if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) {
365 break;
366 }
367
368 //
369 // Copy data to new buffer
370 //
371 EfiCopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
372
373 //
374 // Adjust Source/Destination to next op-code location
375 //
376 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
377 Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
378 }
379
380 //
381 // Prior to the end_form is where we insert the new op-code data
382 //
383 EfiCopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);
384 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
385
386 NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length));
387
388 //
389 // Copy end-form data to new buffer
390 //
391 EfiCopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
392
393 //
394 // Adjust Source/Destination to next op-code location
395 //
396 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
397 Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
398
399 //
400 // Copy end-formset data to new buffer
401 //
402 EfiCopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
403
404 //
405 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
406 //
407 EfiZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);
408 EfiCopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);
409
410 //
411 // Free the newly created buffer since we don't need it anymore
412 //
413 gBS->FreePool (NewBuffer);
414 return EFI_SUCCESS;
415 }
416 #endif
417
418
419 EFI_STATUS
420 GetHiiInterface (
421 OUT EFI_HII_PROTOCOL **Hii
422 )
423 /*++
424
425 Routine Description:
426
427 Get the HII protocol interface
428
429 Arguments:
430
431 Hii - HII protocol interface
432
433 Returns:
434
435 Status code
436
437 --*/
438 {
439 EFI_STATUS Status;
440
441 //
442 // There should only be one HII protocol
443 //
444 Status = gBS->LocateProtocol (
445 &gEfiHiiProtocolGuid,
446 NULL,
447 (VOID **) Hii
448 );
449
450 return Status;;
451 }
452
453
454 EFI_STATUS
455 ExtractDataFromHiiHandle (
456 IN EFI_HII_HANDLE HiiHandle,
457 IN OUT UINT16 *ImageLength,
458 OUT UINT8 *DefaultImage,
459 OUT EFI_GUID *Guid
460 )
461 /*++
462
463 Routine Description:
464
465 Extract information pertaining to the HiiHandle
466
467 Arguments:
468
469 HiiHandle - Hii handle
470
471 ImageLength - For input, length of DefaultImage;
472 For output, length of actually required
473
474 DefaultImage - Image buffer prepared by caller
475
476 Guid - Guid information about the form
477
478 Returns:
479
480 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
481
482 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
483
484 EFI_SUCCESS - Successfully extract data from Hii database.
485
486
487 --*/
488 {
489 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
490
491 EFI_STATUS Status;
492 EFI_HII_PROTOCOL *Hii;
493 UINTN DataLength;
494 UINT8 *RawData;
495 UINT8 *OldData;
496 UINTN Index;
497 UINTN Temp;
498 UINTN SizeOfNvStore;
499 UINTN CachedStart;
500
501 DataLength = DEFAULT_FORM_BUFFER_SIZE;
502 SizeOfNvStore = 0;
503 CachedStart = 0;
504
505 Status = GetHiiInterface (&Hii);
506
507 if (EFI_ERROR (Status)) {
508 return Status;
509 }
510
511 //
512 // Allocate space for retrieval of IFR data
513 //
514 RawData = EfiLibAllocateZeroPool ((UINTN) DataLength);
515 if (RawData == NULL) {
516 return EFI_OUT_OF_RESOURCES;
517 }
518
519 //
520 // Get all the forms associated with this HiiHandle
521 //
522 Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
523
524 if (EFI_ERROR (Status)) {
525 gBS->FreePool (RawData);
526
527 //
528 // Allocate space for retrieval of IFR data
529 //
530 RawData = EfiLibAllocateZeroPool ((UINTN) DataLength);
531 if (RawData == NULL) {
532 return EFI_OUT_OF_RESOURCES;
533 }
534
535 //
536 // Get all the forms associated with this HiiHandle
537 //
538 Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
539 }
540
541 OldData = RawData;
542
543 //
544 // Point RawData to the beginning of the form data
545 //
546 RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
547
548 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
549 switch (RawData[Index]) {
550 case EFI_IFR_FORM_SET_OP:
551 //
552 // Copy the GUID information from this handle
553 //
554 EfiCopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
555 break;
556
557 case EFI_IFR_ONE_OF_OP:
558 case EFI_IFR_CHECKBOX_OP:
559 case EFI_IFR_NUMERIC_OP:
560 case EFI_IFR_DATE_OP:
561 case EFI_IFR_TIME_OP:
562 case EFI_IFR_PASSWORD_OP:
563 case EFI_IFR_STRING_OP:
564 //
565 // Remember, multiple op-codes may reference the same item, so let's keep a running
566 // marker of what the highest QuestionId that wasn't zero length. This will accurately
567 // maintain the Size of the NvStore
568 //
569 if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
570 Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
571 if (SizeOfNvStore < Temp) {
572 SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
573 }
574 }
575 }
576
577 Index = RawData[Index + 1] + Index;
578 }
579
580 //
581 // Return an error if buffer is too small
582 //
583 if (SizeOfNvStore > *ImageLength) {
584 gBS->FreePool (OldData);
585 *ImageLength = (UINT16) SizeOfNvStore;
586 return EFI_BUFFER_TOO_SMALL;
587 }
588
589 EfiZeroMem (DefaultImage, SizeOfNvStore);
590
591 //
592 // Copy the default image information to the user's buffer
593 //
594 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
595 switch (RawData[Index]) {
596 case EFI_IFR_ONE_OF_OP:
597 CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
598 break;
599
600 case EFI_IFR_ONE_OF_OPTION_OP:
601 if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) {
602 EfiCopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);
603 }
604 break;
605
606 case EFI_IFR_CHECKBOX_OP:
607 DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECK_BOX *) &RawData[Index])->Flags;
608 break;
609
610 case EFI_IFR_NUMERIC_OP:
611 EfiCopyMem (
612 &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],
613 &((EFI_IFR_NUMERIC *) &RawData[Index])->Default,
614 2
615 );
616 break;
617
618 }
619
620 Index = RawData[Index + 1] + Index;
621 }
622
623 *ImageLength = (UINT16) SizeOfNvStore;
624
625 //
626 // Free our temporary repository of form data
627 //
628 gBS->FreePool (OldData);
629
630 return EFI_SUCCESS;
631 #else
632 //
633 // The implementation will be added later.
634 //
635 ASSERT (FALSE);
636 return EFI_UNSUPPORTED;
637 #endif
638 }
639
640
641 EFI_HII_HANDLE
642 FindHiiHandle (
643 IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL
644 IN EFI_GUID *Guid
645 )
646 /*++
647
648 Routine Description:
649 Finds HII handle for given pack GUID previously registered with the HII.
650
651 Arguments:
652 HiiProtocol - pointer to pointer to HII protocol interface.
653 If NULL, the interface will be found but not returned.
654 If it points to NULL, the interface will be found and
655 written back to the pointer that is pointed to.
656 Guid - The GUID of the pack that registered with the HII.
657
658 Returns:
659 Handle to the HII pack previously registered by the memory driver.
660
661 --*/
662 {
663 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
664 EFI_STATUS Status;
665
666 EFI_HII_HANDLE *HiiHandleBuffer;
667 EFI_HII_HANDLE HiiHandle;
668 UINT16 HiiHandleBufferLength;
669 UINT32 NumberOfHiiHandles;
670 EFI_GUID HiiGuid;
671 EFI_HII_PROTOCOL *HiiProt;
672 UINT32 Index;
673 UINT16 Length;
674
675 HiiHandle = 0;
676 if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {
677 //
678 // The protocol has been passed in
679 //
680 HiiProt = *HiiProtocol;
681 } else {
682 gBS->LocateProtocol (
683 &gEfiHiiProtocolGuid,
684 NULL,
685 (VOID **) &HiiProt
686 );
687 if (HiiProt == NULL) {
688 return HiiHandle;
689 }
690
691 if (HiiProtocol != NULL) {
692 //
693 // Return back the HII protocol for the caller as promissed
694 //
695 *HiiProtocol = HiiProt;
696 }
697 }
698 //
699 // Allocate buffer
700 //
701 HiiHandleBufferLength = 10;
702 HiiHandleBuffer = EfiLibAllocatePool (HiiHandleBufferLength);
703 ASSERT (HiiHandleBuffer != NULL);
704
705 //
706 // Get the Handles of the packages that were registered with Hii
707 //
708 Status = HiiProt->FindHandles (
709 HiiProt,
710 &HiiHandleBufferLength,
711 HiiHandleBuffer
712 );
713
714 //
715 // Get a bigger bugffer if this one is to small, and try again
716 //
717 if (Status == EFI_BUFFER_TOO_SMALL) {
718
719 gBS->FreePool (HiiHandleBuffer);
720
721 HiiHandleBuffer = EfiLibAllocatePool (HiiHandleBufferLength);
722 ASSERT (HiiHandleBuffer != NULL);
723
724 Status = HiiProt->FindHandles (
725 HiiProt,
726 &HiiHandleBufferLength,
727 HiiHandleBuffer
728 );
729 }
730
731 if (EFI_ERROR (Status)) {
732 goto lbl_exit;
733 }
734
735 NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE);
736
737 //
738 // Iterate Hii handles and look for the one that matches our Guid
739 //
740 for (Index = 0; Index < NumberOfHiiHandles; Index++) {
741
742 Length = 0;
743 ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);
744
745 if (EfiCompareGuid (&HiiGuid, Guid)) {
746
747 HiiHandle = HiiHandleBuffer[Index];
748 break;
749 }
750 }
751
752 lbl_exit:
753 gBS->FreePool (HiiHandleBuffer);
754 return HiiHandle;
755 #else
756 //
757 // The implementation will be added later.
758 //
759 ASSERT (FALSE);
760 return (EFI_HII_HANDLE) 0;
761 #endif
762 }
763
764 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
765 EFI_STATUS
766 ValidateDataFromHiiHandle (
767 IN EFI_HII_HANDLE HiiHandle,
768 OUT BOOLEAN *Results
769 )
770 /*++
771
772 Routine Description:
773
774 Validate that the data associated with the HiiHandle in NVRAM is within
775 the reasonable parameters for that FormSet. Values for strings and passwords
776 are not verified due to their not having the equivalent of valid range settings.
777
778 Arguments:
779
780 HiiHandle - Handle of the HII database entry to query
781
782 Results - If return Status is EFI_SUCCESS, Results provides valid data
783 TRUE = NVRAM Data is within parameters
784 FALSE = NVRAM Data is NOT within parameters
785
786 Returns:
787
788 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
789
790 EFI_SUCCESS - Data successfully validated
791 --*/
792 {
793 EFI_STATUS Status;
794 EFI_HII_PROTOCOL *Hii;
795 EFI_GUID Guid;
796 UINT8 *RawData;
797 UINT8 *OldData;
798 UINTN RawDataLength;
799 UINT8 *VariableData;
800 UINTN Index;
801 UINTN Temp;
802 UINTN SizeOfNvStore;
803 UINTN CachedStart;
804 BOOLEAN GotMatch;
805
806 RawDataLength = DEFAULT_FORM_BUFFER_SIZE;
807 SizeOfNvStore = 0;
808 CachedStart = 0;
809 GotMatch = FALSE;
810 *Results = TRUE;
811
812 Status = GetHiiInterface (&Hii);
813
814 if (EFI_ERROR (Status)) {
815 return Status;
816 }
817
818 //
819 // Allocate space for retrieval of IFR data
820 //
821 RawData = EfiLibAllocateZeroPool (RawDataLength);
822 if (RawData == NULL) {
823 return EFI_OUT_OF_RESOURCES;
824 }
825
826 //
827 // Get all the forms associated with this HiiHandle
828 //
829 Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
830
831 if (EFI_ERROR (Status)) {
832 gBS->FreePool (RawData);
833
834 //
835 // Allocate space for retrieval of IFR data
836 //
837 RawData = EfiLibAllocateZeroPool (RawDataLength);
838 if (RawData == NULL) {
839 return EFI_OUT_OF_RESOURCES;
840 }
841
842 //
843 // Get all the forms associated with this HiiHandle
844 //
845 Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
846 }
847
848 OldData = RawData;
849
850 //
851 // Point RawData to the beginning of the form data
852 //
853 RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
854
855 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
856 if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
857 EfiCopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
858 break;
859 }
860
861 Index = RawData[Index + 1] + Index;
862 }
863
864 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
865 switch (RawData[Index]) {
866 case EFI_IFR_FORM_SET_OP:
867 break;
868
869 case EFI_IFR_ONE_OF_OP:
870 case EFI_IFR_CHECKBOX_OP:
871 case EFI_IFR_NUMERIC_OP:
872 case EFI_IFR_DATE_OP:
873 case EFI_IFR_TIME_OP:
874 case EFI_IFR_PASSWORD_OP:
875 case EFI_IFR_STRING_OP:
876 //
877 // Remember, multiple op-codes may reference the same item, so let's keep a running
878 // marker of what the highest QuestionId that wasn't zero length. This will accurately
879 // maintain the Size of the NvStore
880 //
881 if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
882 Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
883 if (SizeOfNvStore < Temp) {
884 SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
885 }
886 }
887 }
888
889 Index = RawData[Index + 1] + Index;
890 }
891
892 //
893 // Allocate memory for our File Form Tags
894 //
895 VariableData = EfiLibAllocateZeroPool (SizeOfNvStore);
896 if (VariableData == NULL) {
897 return EFI_OUT_OF_RESOURCES;
898 }
899
900 Status = gRT->GetVariable (
901 L"Setup",
902 &Guid,
903 NULL,
904 &SizeOfNvStore,
905 (VOID *) VariableData
906 );
907
908 if (EFI_ERROR (Status)) {
909
910 //
911 // If there is a variable that exists already and it is larger than what we calculated the
912 // storage needs to be, we must assume the variable size from GetVariable is correct and not
913 // allow the truncation of the variable. It is very possible that the user who created the IFR
914 // we are cracking is not referring to a variable that was in a previous map, however we cannot
915 // allow it's truncation.
916 //
917 if (Status == EFI_BUFFER_TOO_SMALL) {
918 //
919 // Free the buffer that was allocated that was too small
920 //
921 gBS->FreePool (VariableData);
922
923 VariableData = EfiLibAllocatePool (SizeOfNvStore);
924 if (VariableData == NULL) {
925 return EFI_OUT_OF_RESOURCES;
926 }
927
928 Status = gRT->GetVariable (
929 L"Setup",
930 &Guid,
931 NULL,
932 &SizeOfNvStore,
933 (VOID *) VariableData
934 );
935 }
936 }
937
938 //
939 // Walk through the form and see that the variable data it refers to is ok.
940 // This allows for the possibility of stale (obsoleted) data in the variable
941 // can be overlooked without causing an error
942 //
943 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
944 switch (RawData[Index]) {
945 case EFI_IFR_ONE_OF_OP:
946 //
947 // A one_of has no data, its the option that does - cache the storage Id
948 //
949 CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
950 break;
951
952 case EFI_IFR_ONE_OF_OPTION_OP:
953 //
954 // A one_of_option can be any value
955 //
956 if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {
957 GotMatch = TRUE;
958 }
959 break;
960
961 case EFI_IFR_END_ONE_OF_OP:
962 //
963 // At this point lets make sure that the data value in the NVRAM matches one of the options
964 //
965 if (!GotMatch) {
966 *Results = FALSE;
967 return EFI_SUCCESS;
968 }
969 break;
970
971 case EFI_IFR_CHECKBOX_OP:
972 //
973 // A checkbox is a boolean, so 0 and 1 are valid
974 // Remember, QuestionId corresponds to the offset location of the data in the variable
975 //
976 if (VariableData[((EFI_IFR_CHECK_BOX *) &RawData[Index])->QuestionId] > 1) {
977 *Results = FALSE;
978 return EFI_SUCCESS;
979 }
980 break;
981
982 case EFI_IFR_NUMERIC_OP:
983 if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||
984 (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {
985 *Results = FALSE;
986 return EFI_SUCCESS;
987 }
988 break;
989
990 }
991
992 Index = RawData[Index + 1] + Index;
993 }
994
995 //
996 // Free our temporary repository of form data
997 //
998 gBS->FreePool (OldData);
999 gBS->FreePool (VariableData);
1000
1001 return EFI_SUCCESS;
1002 }
1003 #endif
1004
1005 EFI_HII_PACKAGES *
1006 PreparePackages (
1007 IN UINTN NumberOfPackages,
1008 IN EFI_GUID *GuidId,
1009 ...
1010 )
1011 /*++
1012
1013 Routine Description:
1014
1015 Assemble EFI_HII_PACKAGES according to the passed in packages.
1016
1017 Arguments:
1018
1019 NumberOfPackages - Number of packages.
1020 GuidId - Package GUID.
1021
1022 Returns:
1023
1024 Pointer of EFI_HII_PACKAGES.
1025
1026 --*/
1027 {
1028 VA_LIST args;
1029 EFI_HII_PACKAGES *HiiPackages;
1030 VOID **Package;
1031 UINTN Index;
1032
1033 ASSERT (NumberOfPackages > 0);
1034
1035 HiiPackages = EfiLibAllocateZeroPool (sizeof (EFI_HII_PACKAGES) + NumberOfPackages * sizeof (VOID *));
1036
1037 HiiPackages->GuidId = GuidId;
1038 HiiPackages->NumberOfPackages = NumberOfPackages;
1039 Package = (VOID **) (((UINT8 *) HiiPackages) + sizeof (EFI_HII_PACKAGES));
1040
1041 VA_START (args, GuidId);
1042
1043 for (Index = 0; Index < NumberOfPackages; Index++) {
1044 *Package = VA_ARG (args, VOID *);
1045 Package++;
1046 }
1047
1048 VA_END (args);
1049
1050 return HiiPackages;
1051 }