]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
OvmfPkg/*.fdf: Adjust FV/FD sizes for UNIXGCC DEBUG builds
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
1 /** @file
2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
3
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate;
18
19 /**
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
22
23 This is a internal function.
24
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
27
28 @return The number of Unicode characters.
29
30 **/
31 UINTN
32 CalculateConfigStringLen (
33 IN EFI_STRING String
34 )
35 {
36 EFI_STRING TmpPtr;
37
38 //
39 // "GUID=" should be the first element of incoming string.
40 //
41 ASSERT (String != NULL);
42 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
43
44 //
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
47 //
48 TmpPtr = StrStr (String, L"&GUID=");
49 if (TmpPtr == NULL) {
50 return StrLen (String);
51 }
52
53 return (TmpPtr - String);
54 }
55
56
57 /**
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
60
61 This is a internal function.
62
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
65
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
70 binary format.
71
72 **/
73 EFI_STATUS
74 GetDevicePath (
75 IN EFI_STRING String,
76 OUT UINT8 **DevicePathData
77 )
78 {
79 UINTN Length;
80 EFI_STRING PathHdr;
81 UINT8 *DevicePathBuffer;
82 CHAR16 TemStr[2];
83 UINTN Index;
84 UINT8 DigitUint8;
85 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
86
87
88 if (String == NULL || DevicePathData == NULL) {
89 return EFI_INVALID_PARAMETER;
90 }
91
92 //
93 // Find the 'PATH=' of <PathHdr> and skip it.
94 //
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
96 if (*String == 0) {
97 return EFI_INVALID_PARAMETER;
98 }
99 //
100 // Check whether path data does exist.
101 //
102 String += StrLen (L"PATH=");
103 if (*String == 0) {
104 return EFI_INVALID_PARAMETER;
105 }
106 PathHdr = String;
107
108 //
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
112 //
113 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
114 //
115 // Check DevicePath Length
116 //
117 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
118 return EFI_NOT_FOUND;
119 }
120
121 //
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
125 //
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
127 if (DevicePathBuffer == NULL) {
128 return EFI_OUT_OF_RESOURCES;
129 }
130
131 //
132 // Convert DevicePath
133 //
134 ZeroMem (TemStr, sizeof (TemStr));
135 for (Index = 0; Index < Length; Index ++) {
136 TemStr[0] = PathHdr[Index];
137 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
138 if ((Index & 1) == 0) {
139 DevicePathBuffer [Index/2] = DigitUint8;
140 } else {
141 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
142 }
143 }
144
145 //
146 // Validate DevicePath
147 //
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;
149 while (!IsDevicePathEnd (DevicePath)) {
150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
151 //
152 // Invalid device path
153 //
154 FreePool (DevicePathBuffer);
155 return EFI_NOT_FOUND;
156 }
157 DevicePath = NextDevicePathNode (DevicePath);
158 }
159
160 //
161 // return the device path
162 //
163 *DevicePathData = DevicePathBuffer;
164 return EFI_SUCCESS;
165 }
166
167 /**
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
170
171 @param ConfigString String to be converted
172
173 **/
174 VOID
175 EFIAPI
176 HiiToLower (
177 IN EFI_STRING ConfigString
178 )
179 {
180 EFI_STRING String;
181 BOOLEAN Lower;
182
183 ASSERT (ConfigString != NULL);
184
185 //
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
187 //
188 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
189 if (*String == L'=') {
190 Lower = TRUE;
191 } else if (*String == L'&') {
192 Lower = FALSE;
193 } else if (Lower && *String >= L'A' && *String <= L'F') {
194 *String = (CHAR16) (*String - L'A' + L'a');
195 }
196 }
197
198 return;
199 }
200
201 /**
202 Generate a sub string then output it.
203
204 This is a internal function.
205
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
208
209 @param BufferLen The length of the Buffer in bytes.
210
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
213
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
217
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
220
221
222 **/
223 VOID
224 GenerateSubStr (
225 IN CONST EFI_STRING String,
226 IN UINTN BufferLen,
227 IN VOID *Buffer,
228 IN UINT8 Flag,
229 OUT EFI_STRING *SubStr
230 )
231 {
232 UINTN Length;
233 EFI_STRING Str;
234 EFI_STRING StringHeader;
235 CHAR16 *TemString;
236 CHAR16 *TemName;
237 UINT8 *TemBuffer;
238 UINTN Index;
239
240 ASSERT (String != NULL && SubStr != NULL);
241
242 if (Buffer == NULL) {
243 *SubStr = AllocateCopyPool (StrSize (String), String);
244 ASSERT (*SubStr != NULL);
245 return ;
246 }
247
248 //
249 // Header + Data + '&' + '\0'
250 //
251 Length = StrLen (String) + BufferLen * 2 + 1 + 1;
252 Str = AllocateZeroPool (Length * sizeof (CHAR16));
253 ASSERT (Str != NULL);
254
255 StrCpy (Str, String);
256 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);
257
258 StringHeader = Str + StrLen (String);
259 TemString = (CHAR16 *) StringHeader;
260
261 switch (Flag) {
262 case 1:
263 //
264 // Convert Buffer to Hex String in reverse order
265 //
266 TemBuffer = ((UINT8 *) Buffer);
267 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
268 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
269 }
270 break;
271 case 2:
272 //
273 // Check buffer is enough
274 //
275 TemName = (CHAR16 *) Buffer;
276 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
277 //
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 //
280 for (; *TemName != L'\0'; TemName++) {
281 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
282 }
283 break;
284 case 3:
285 //
286 // Convert Buffer to Hex String
287 //
288 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
289 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
290 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
291 }
292 break;
293 default:
294 break;
295 }
296
297 //
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 //
300 StrCat (Str, L"&");
301 HiiToLower (Str);
302
303 *SubStr = Str;
304 }
305
306
307 /**
308 Retrieve the <ConfigBody> from String then output it.
309
310 This is a internal function.
311
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
316
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
320
321 **/
322 EFI_STATUS
323 OutputConfigBody (
324 IN EFI_STRING String,
325 OUT EFI_STRING *ConfigBody
326 )
327 {
328 EFI_STRING TmpPtr;
329 EFI_STRING Result;
330 UINTN Length;
331
332 if (String == NULL || ConfigBody == NULL) {
333 return EFI_INVALID_PARAMETER;
334 }
335
336 //
337 // The setting information should start OFFSET, not ALTCFG.
338 //
339 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 TmpPtr = StrStr (String, L"GUID=");
344 if (TmpPtr == NULL) {
345 //
346 // It is the last <ConfigResp> of the incoming configuration string.
347 //
348 Result = AllocateCopyPool (StrSize (String), String);
349 if (Result == NULL) {
350 return EFI_OUT_OF_RESOURCES;
351 } else {
352 *ConfigBody = Result;
353 return EFI_SUCCESS;
354 }
355 }
356
357 Length = TmpPtr - String;
358 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
359 if (Result == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362
363 *(Result + Length - 1) = 0;
364 *ConfigBody = Result;
365 return EFI_SUCCESS;
366 }
367
368 /**
369 Append a string to a multi-string format.
370
371 This is a internal function.
372
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
377 might be updated.
378 @param AppendString NULL-terminated Unicode string.
379
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
382
383 **/
384 EFI_STATUS
385 AppendToMultiString (
386 IN OUT EFI_STRING *MultiString,
387 IN EFI_STRING AppendString
388 )
389 {
390 UINTN AppendStringSize;
391 UINTN MultiStringSize;
392
393 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
394 return EFI_INVALID_PARAMETER;
395 }
396
397 AppendStringSize = StrSize (AppendString);
398 MultiStringSize = StrSize (*MultiString);
399
400 //
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
402 //
403 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
404 MultiStringSize > MAX_STRING_LENGTH) {
405 *MultiString = (EFI_STRING) ReallocatePool (
406 MultiStringSize,
407 MultiStringSize + AppendStringSize,
408 (VOID *) (*MultiString)
409 );
410 ASSERT (*MultiString != NULL);
411 }
412 //
413 // Append the incoming string
414 //
415 StrCat (*MultiString, AppendString);
416
417 return EFI_SUCCESS;
418 }
419
420
421 /**
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
423 or WIDTH or VALUE.
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
425
426 This is a internal function.
427
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
431 to free memory.
432 @param Len Length of the <Number>, in characters.
433
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
435 structures.
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
437 successfully.
438
439 **/
440 EFI_STATUS
441 GetValueOfNumber (
442 IN EFI_STRING StringPtr,
443 OUT UINT8 **Number,
444 OUT UINTN *Len
445 )
446 {
447 EFI_STRING TmpPtr;
448 UINTN Length;
449 EFI_STRING Str;
450 UINT8 *Buf;
451 EFI_STATUS Status;
452 UINT8 DigitUint8;
453 UINTN Index;
454 CHAR16 TemStr[2];
455
456 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 Buf = NULL;
461
462 TmpPtr = StringPtr;
463 while (*StringPtr != L'\0' && *StringPtr != L'&') {
464 StringPtr++;
465 }
466 *Len = StringPtr - TmpPtr;
467 Length = *Len + 1;
468
469 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
470 if (Str == NULL) {
471 Status = EFI_OUT_OF_RESOURCES;
472 goto Exit;
473 }
474 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
475 *(Str + *Len) = L'\0';
476
477 Length = (Length + 1) / 2;
478 Buf = (UINT8 *) AllocateZeroPool (Length);
479 if (Buf == NULL) {
480 Status = EFI_OUT_OF_RESOURCES;
481 goto Exit;
482 }
483
484 Length = *Len;
485 ZeroMem (TemStr, sizeof (TemStr));
486 for (Index = 0; Index < Length; Index ++) {
487 TemStr[0] = Str[Length - Index - 1];
488 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
489 if ((Index & 1) == 0) {
490 Buf [Index/2] = DigitUint8;
491 } else {
492 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
493 }
494 }
495
496 *Number = Buf;
497 Status = EFI_SUCCESS;
498
499 Exit:
500 if (Str != NULL) {
501 FreePool (Str);
502 }
503
504 return Status;
505 }
506
507 /**
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
510
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
518
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
521 **/
522 EFI_STATUS
523 EFIAPI
524 MergeDefaultString (
525 IN OUT EFI_STRING *AltCfgResp,
526 IN EFI_STRING DefaultAltCfgResp
527 )
528 {
529 EFI_STRING StringPtrDefault;
530 EFI_STRING StringPtrEnd;
531 CHAR16 TempChar;
532 EFI_STRING StringPtr;
533 EFI_STRING AltConfigHdr;
534 UINTN HeaderLength;
535 UINTN SizeAltCfgResp;
536
537 if (*AltCfgResp == NULL) {
538 return EFI_INVALID_PARAMETER;
539 }
540
541 //
542 // Get the requestr ConfigHdr
543 //
544 SizeAltCfgResp = 0;
545 StringPtr = *AltCfgResp;
546
547 //
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
549 //
550 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER;
552 }
553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
554 StringPtr++;
555 }
556 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
557 StringPtr++;
558 }
559 if (*StringPtr == L'\0') {
560 return EFI_INVALID_PARAMETER;
561 }
562 StringPtr += StrLen (L"&PATH=");
563 while (*StringPtr != L'\0' && *StringPtr != L'&') {
564 StringPtr ++;
565 }
566 HeaderLength = StringPtr - *AltCfgResp;
567
568 //
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
571 //
572 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));
573 if (AltConfigHdr == NULL) {
574 return EFI_OUT_OF_RESOURCES;
575 }
576 StrCpy (AltConfigHdr, L"&");
577 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);
578 StrCat (AltConfigHdr, L"&ALTCFG=");
579 HeaderLength = StrLen (AltConfigHdr);
580
581 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
582 while (StringPtrDefault != NULL) {
583 //
584 // Get AltCfg Name
585 //
586 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);
587 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
588
589 //
590 // Append the found default value string to the input AltCfgResp
591 //
592 if (StringPtr == NULL) {
593 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
594 SizeAltCfgResp = StrSize (*AltCfgResp);
595 if (StringPtrEnd == NULL) {
596 //
597 // No more default string is found.
598 //
599 *AltCfgResp = (EFI_STRING) ReallocatePool (
600 SizeAltCfgResp,
601 SizeAltCfgResp + StrSize (StringPtrDefault),
602 (VOID *) (*AltCfgResp)
603 );
604 if (*AltCfgResp == NULL) {
605 FreePool (AltConfigHdr);
606 return EFI_OUT_OF_RESOURCES;
607 }
608 StrCat (*AltCfgResp, StringPtrDefault);
609 break;
610 } else {
611 TempChar = *StringPtrEnd;
612 *StringPtrEnd = L'\0';
613 *AltCfgResp = (EFI_STRING) ReallocatePool (
614 SizeAltCfgResp,
615 SizeAltCfgResp + StrSize (StringPtrDefault),
616 (VOID *) (*AltCfgResp)
617 );
618 if (*AltCfgResp == NULL) {
619 FreePool (AltConfigHdr);
620 return EFI_OUT_OF_RESOURCES;
621 }
622 StrCat (*AltCfgResp, StringPtrDefault);
623 *StringPtrEnd = TempChar;
624 }
625 }
626
627 //
628 // Find next AltCfg String
629 //
630 *(AltConfigHdr + HeaderLength) = L'\0';
631 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
632 }
633
634 FreePool (AltConfigHdr);
635 return EFI_SUCCESS;
636 }
637
638 /**
639 This function finds the matched DefaultName for the input DefaultId
640
641 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.
642 @param VarDefaultId Default Id
643 @param VarDefaultName Default Name string ID for the input default ID.
644
645 @retval EFI_SUCCESS The mapped default name string ID is found.
646 @retval EFI_NOT_FOUND The mapped default name string ID is not found.
647 **/
648 EFI_STATUS
649 FindDefaultName (
650 IN IFR_DEFAULT_DATA *DefaultIdArray,
651 IN UINT16 VarDefaultId,
652 OUT EFI_STRING_ID *VarDefaultName
653 )
654 {
655 LIST_ENTRY *Link;
656 IFR_DEFAULT_DATA *DefaultData;
657
658 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
659 DefaultData = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
660 if (DefaultData->DefaultId == VarDefaultId) {
661 *VarDefaultName = DefaultData->DefaultName;
662 return EFI_SUCCESS;
663 }
664 }
665
666 return EFI_NOT_FOUND;
667 }
668
669 /**
670 This function inserts new DefaultValueData into the BlockData DefaultValue array.
671
672 @param BlockData The BlockData is updated to add new default value.
673 @param DefaultValueData The DefaultValue is added.
674
675 **/
676 VOID
677 InsertDefaultValue (
678 IN IFR_BLOCK_DATA *BlockData,
679 IN IFR_DEFAULT_DATA *DefaultValueData
680 )
681 {
682 LIST_ENTRY *Link;
683 IFR_DEFAULT_DATA *DefaultValueArray;
684
685 for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {
686 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
687 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
688 if (DefaultValueData->OpCode == EFI_IFR_DEFAULT_OP) {
689 //
690 // Update the default value array in BlockData.
691 //
692 DefaultValueArray->Value = DefaultValueData->Value;
693 } else if (DefaultValueArray->OpCode != EFI_IFR_DEFAULT_OP) {
694 //
695 // Update the default value array in BlockData.
696 //
697 DefaultValueArray->Value = DefaultValueData->Value;
698 }
699 FreePool (DefaultValueData);
700 return;
701 } else if (DefaultValueArray->DefaultId > DefaultValueData->DefaultId) {
702 //
703 // Insert new default value data in the front of this default value array.
704 //
705 InsertTailList (Link, &DefaultValueData->Entry);
706 return;
707 }
708 }
709
710 //
711 // Insert new default value data in tail.
712 //
713 InsertTailList (Link, &DefaultValueData->Entry);
714 return;
715 }
716
717 /**
718 This function inserts new BlockData into the block link
719
720 @param BlockLink The list entry points to block array.
721 @param BlockData The point to BlockData is added.
722
723 **/
724 VOID
725 InsertBlockData (
726 IN LIST_ENTRY *BlockLink,
727 IN IFR_BLOCK_DATA **BlockData
728 )
729 {
730 LIST_ENTRY *Link;
731 IFR_BLOCK_DATA *BlockArray;
732 IFR_BLOCK_DATA *BlockSingleData;
733
734 BlockSingleData = *BlockData;
735
736 //
737 // Insert block data in its Offset and Width order.
738 //
739 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
740 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
741 if (BlockArray->Offset == BlockSingleData->Offset) {
742 if (BlockArray->Width > BlockSingleData->Width) {
743 //
744 // Insert this block data in the front of block array
745 //
746 InsertTailList (Link, &BlockSingleData->Entry);
747 return;
748 }
749
750 if (BlockArray->Width == BlockSingleData->Width) {
751 //
752 // The same block array has been added.
753 //
754 FreePool (BlockSingleData);
755 *BlockData = BlockArray;
756 return;
757 }
758 } else if (BlockArray->Offset > BlockSingleData->Offset) {
759 //
760 // Insert new block data in the front of block array
761 //
762 InsertTailList (Link, &BlockSingleData->Entry);
763 return;
764 }
765 }
766
767 //
768 // Add new block data into the tail.
769 //
770 InsertTailList (Link, &BlockSingleData->Entry);
771 return;
772 }
773
774 /**
775 This function checks VarOffset and VarWidth is in the block range.
776
777 @param RequestBlockArray The block array is to be checked.
778 @param VarOffset Offset of var to the structure
779 @param VarWidth Width of var.
780
781 @retval TRUE This Var is in the block range.
782 @retval FALSE This Var is not in the block range.
783 **/
784 BOOLEAN
785 BlockArrayCheck (
786 IN IFR_BLOCK_DATA *RequestBlockArray,
787 IN UINT16 VarOffset,
788 IN UINT16 VarWidth
789 )
790 {
791 LIST_ENTRY *Link;
792 IFR_BLOCK_DATA *BlockData;
793
794 //
795 // No Request Block array, all vars are got.
796 //
797 if (RequestBlockArray == NULL) {
798 return TRUE;
799 }
800
801 //
802 // Check the input var is in the request block range.
803 //
804 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
805 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
806 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
807 return TRUE;
808 }
809 }
810
811 return FALSE;
812 }
813
814 /**
815 This function parses Form Package to get the block array and the default
816 value array according to the request ConfigHdr.
817
818 @param Package Pointer to the form package data.
819 @param PackageLength Length of the pacakge.
820 @param ConfigHdr Request string ConfigHdr. If it is NULL,
821 the first found varstore will be as ConfigHdr.
822 @param RequestBlockArray The block array is retrieved from the request string.
823 @param VarStorageData VarStorage structure contains the got block and default value.
824 @param PIfrDefaultIdArray Point to the got default id and default name array.
825
826 @retval EFI_SUCCESS The block array and the default value array are got.
827 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
828 are conflicted.
829 @retval EFI_OUT_OF_RESOURCES No enough memory.
830 **/
831 EFI_STATUS
832 EFIAPI
833 ParseIfrData (
834 IN UINT8 *Package,
835 IN UINT32 PackageLength,
836 IN EFI_STRING ConfigHdr,
837 IN IFR_BLOCK_DATA *RequestBlockArray,
838 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
839 OUT IFR_DEFAULT_DATA *DefaultIdArray
840 )
841 {
842 EFI_STATUS Status;
843 UINTN IfrOffset;
844 EFI_IFR_VARSTORE *IfrVarStore;
845 EFI_IFR_OP_HEADER *IfrOpHdr;
846 EFI_IFR_ONE_OF *IfrOneOf;
847 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
848 EFI_IFR_DEFAULT *IfrDefault;
849 EFI_IFR_ORDERED_LIST *IfrOrderedList;
850 EFI_IFR_CHECKBOX *IfrCheckBox;
851 EFI_IFR_PASSWORD *IfrPassword;
852 EFI_IFR_STRING *IfrString;
853 IFR_DEFAULT_DATA *DefaultData;
854 IFR_BLOCK_DATA *BlockData;
855 CHAR16 *VarStoreName;
856 UINT16 VarOffset;
857 UINT16 VarWidth;
858 EFI_STRING_ID VarDefaultName;
859 UINT16 VarDefaultId;
860 EFI_STRING GuidStr;
861 EFI_STRING NameStr;
862 EFI_STRING TempStr;
863 UINTN LengthString;
864 BOOLEAN FirstOneOfOption;
865
866 LengthString = 0;
867 Status = EFI_SUCCESS;
868 GuidStr = NULL;
869 NameStr = NULL;
870 TempStr = NULL;
871 BlockData = NULL;
872 DefaultData = NULL;
873 VarDefaultName = 0;
874 FirstOneOfOption = FALSE;
875
876 //
877 // Go through the form package to parse OpCode one by one.
878 //
879 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
880 while (IfrOffset < PackageLength) {
881 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
882
883 switch (IfrOpHdr->OpCode) {
884 case EFI_IFR_VARSTORE_OP:
885 //
886 // VarStore is found. Don't need to search any more.
887 //
888 if (VarStorageData->Size != 0) {
889 break;
890 }
891
892 //
893 // Get the requied varstore information
894 // Add varstore by Guid and Name in ConfigHdr
895 // Make sure Offset is in varstore size and varstoreid
896 //
897 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
898 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
899 if (VarStoreName == NULL) {
900 Status = EFI_OUT_OF_RESOURCES;
901 goto Done;
902 }
903 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);
904
905 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);
906 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
907 LengthString = StrLen (GuidStr);
908 LengthString = LengthString + StrLen (NameStr) + 1;
909 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
910 if (TempStr == NULL) {
911 FreePool (GuidStr);
912 FreePool (NameStr);
913 FreePool (VarStoreName);
914 Status = EFI_OUT_OF_RESOURCES;
915 goto Done;
916 }
917 StrCpy (TempStr, GuidStr);
918 StrCat (TempStr, NameStr);
919 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
920 //
921 // Find the matched VarStore
922 //
923 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
924 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;
925 VarStorageData->Size = IfrVarStore->Size;
926 VarStorageData->Name = VarStoreName;
927 } else {
928 //
929 // No found, free the allocated memory
930 //
931 FreePool (VarStoreName);
932 }
933 //
934 // Free alllocated temp string.
935 //
936 FreePool (GuidStr);
937 FreePool (NameStr);
938 FreePool (TempStr);
939 break;
940
941 case EFI_IFR_DEFAULTSTORE_OP:
942 //
943 // Add new the map between default id and default name.
944 //
945 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
946 if (DefaultData == NULL) {
947 Status = EFI_OUT_OF_RESOURCES;
948 goto Done;
949 }
950 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
951 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;
952 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);
953 DefaultData = NULL;
954 break;
955
956 case EFI_IFR_FORM_OP:
957 case EFI_IFR_FORM_MAP_OP:
958 //
959 // No matched varstore is found and directly return.
960 //
961 if (VarStorageData->Size == 0) {
962 Status = EFI_SUCCESS;
963 goto Done;
964 }
965 break;
966
967 case EFI_IFR_ONE_OF_OP:
968 case EFI_IFR_NUMERIC_OP:
969 //
970 // Numeric and OneOf has the same opcode structure.
971 //
972
973 //
974 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
975 //
976 if (VarStorageData->Size == 0) {
977 Status = EFI_INVALID_PARAMETER;
978 goto Done;
979 }
980 //
981 // Check whether this question is for the requested varstore.
982 //
983 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
984 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {
985 break;
986 }
987
988 //
989 // Get Offset/Width by Question header and OneOf Flags
990 //
991 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;
992 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
993 //
994 // Check whether this question is in requested block array.
995 //
996 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
997 //
998 // This question is not in the requested string. Skip it.
999 //
1000 break;
1001 }
1002
1003 //
1004 // Check this var question is in the var storage
1005 //
1006 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1007 Status = EFI_INVALID_PARAMETER;
1008 goto Done;
1009 }
1010
1011 //
1012 // Set Block Data
1013 //
1014 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1015 if (BlockData == NULL) {
1016 Status = EFI_OUT_OF_RESOURCES;
1017 goto Done;
1018 }
1019 BlockData->Offset = VarOffset;
1020 BlockData->Width = VarWidth;
1021 BlockData->QuestionId = IfrOneOf->Question.QuestionId;
1022 BlockData->OpCode = IfrOpHdr->OpCode;
1023 BlockData->Scope = IfrOpHdr->Scope;
1024 InitializeListHead (&BlockData->DefaultValueEntry);
1025 //
1026 // Add Block Data into VarStorageData BlockEntry
1027 //
1028 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1029
1030 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
1031 //
1032 // Set this flag to TRUE for the first oneof option.
1033 //
1034 FirstOneOfOption = TRUE;
1035 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
1036 //
1037 // Numeric minimum value will be used as default value when no default is specified.
1038 //
1039
1040 //
1041 // Set standard ID and Get DefaultName String ID
1042 //
1043 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1044 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1045 if (EFI_ERROR (Status)) {
1046 goto Done;
1047 }
1048 //
1049 // Prepare new DefaultValue
1050 //
1051 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1052 if (DefaultData == NULL) {
1053 Status = EFI_OUT_OF_RESOURCES;
1054 goto Done;
1055 }
1056 DefaultData->OpCode = IfrOpHdr->OpCode;
1057 DefaultData->DefaultId = VarDefaultId;
1058 DefaultData->DefaultName = VarDefaultName;
1059
1060 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
1061 case EFI_IFR_NUMERIC_SIZE_1:
1062 DefaultData->Value = (UINT64) IfrOneOf->data.u8.MinValue;
1063 break;
1064
1065 case EFI_IFR_NUMERIC_SIZE_2:
1066 CopyMem (&DefaultData->Value, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
1067 break;
1068
1069 case EFI_IFR_NUMERIC_SIZE_4:
1070 CopyMem (&DefaultData->Value, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
1071 break;
1072
1073 case EFI_IFR_NUMERIC_SIZE_8:
1074 CopyMem (&DefaultData->Value, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
1075 break;
1076 }
1077 //
1078 // Add DefaultValue into current BlockData
1079 //
1080 InsertDefaultValue (BlockData, DefaultData);
1081 }
1082 break;
1083
1084 case EFI_IFR_ORDERED_LIST_OP:
1085 //
1086 // offset by question header
1087 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1088 // no default value and default id, how to define its default value?
1089 //
1090
1091 //
1092 // OrderedList question is not in IFR Form. This IFR form is not valid.
1093 //
1094 if (VarStorageData->Size == 0) {
1095 Status = EFI_INVALID_PARAMETER;
1096 goto Done;
1097 }
1098 //
1099 // Check whether this question is for the requested varstore.
1100 //
1101 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
1102 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {
1103 BlockData = NULL;
1104 break;
1105 }
1106
1107 //
1108 // Get Offset/Width by Question header and OneOf Flags
1109 //
1110 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;
1111 VarWidth = IfrOrderedList->MaxContainers;
1112
1113 //
1114 // Set Block Data
1115 //
1116 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1117 if (BlockData == NULL) {
1118 Status = EFI_OUT_OF_RESOURCES;
1119 goto Done;
1120 }
1121 BlockData->Offset = VarOffset;
1122 BlockData->Width = VarWidth;
1123 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;
1124 BlockData->OpCode = IfrOpHdr->OpCode;
1125 BlockData->Scope = IfrOpHdr->Scope;
1126 InitializeListHead (&BlockData->DefaultValueEntry);
1127 break;
1128
1129 case EFI_IFR_CHECKBOX_OP:
1130 //
1131 // EFI_IFR_DEFAULT_OP
1132 // offset by question header
1133 // width is 1 sizeof (BOOLEAN)
1134 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1135 // value by DefaultOption
1136 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1137 //
1138
1139 //
1140 // CheckBox question is not in IFR Form. This IFR form is not valid.
1141 //
1142 if (VarStorageData->Size == 0) {
1143 Status = EFI_INVALID_PARAMETER;
1144 goto Done;
1145 }
1146 //
1147 // Check whether this question is for the requested varstore.
1148 //
1149 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
1150 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {
1151 break;
1152 }
1153
1154 //
1155 // Get Offset/Width by Question header and OneOf Flags
1156 //
1157 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
1158 VarWidth = (UINT16) sizeof (BOOLEAN);
1159
1160 //
1161 // Check whether this question is in requested block array.
1162 //
1163 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1164 //
1165 // This question is not in the requested string. Skip it.
1166 //
1167 break;
1168 }
1169
1170 //
1171 // Check this var question is in the var storage
1172 //
1173 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1174 Status = EFI_INVALID_PARAMETER;
1175 goto Done;
1176 }
1177
1178 //
1179 // Set Block Data
1180 //
1181 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1182 if (BlockData == NULL) {
1183 Status = EFI_OUT_OF_RESOURCES;
1184 goto Done;
1185 }
1186 BlockData->Offset = VarOffset;
1187 BlockData->Width = VarWidth;
1188 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;
1189 BlockData->OpCode = IfrOpHdr->OpCode;
1190 BlockData->Scope = IfrOpHdr->Scope;
1191 InitializeListHead (&BlockData->DefaultValueEntry);
1192 //
1193 // Add Block Data into VarStorageData BlockEntry
1194 //
1195 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1196
1197 //
1198 // Add default value by CheckBox Flags
1199 //
1200 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
1201 //
1202 // Set standard ID to Manufacture ID and Get DefaultName String ID
1203 //
1204 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1205 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1206 if (EFI_ERROR (Status)) {
1207 goto Done;
1208 }
1209 //
1210 // Prepare new DefaultValue
1211 //
1212 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1213 if (DefaultData == NULL) {
1214 Status = EFI_OUT_OF_RESOURCES;
1215 goto Done;
1216 }
1217 DefaultData->OpCode = IfrOpHdr->OpCode;
1218 DefaultData->DefaultId = VarDefaultId;
1219 DefaultData->DefaultName = VarDefaultName;
1220 DefaultData->Value = 1;
1221 //
1222 // Add DefaultValue into current BlockData
1223 //
1224 InsertDefaultValue (BlockData, DefaultData);
1225 }
1226
1227 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
1228 //
1229 // Set standard ID to Manufacture ID and Get DefaultName String ID
1230 //
1231 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1232 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1233 if (EFI_ERROR (Status)) {
1234 goto Done;
1235 }
1236 //
1237 // Prepare new DefaultValue
1238 //
1239 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1240 if (DefaultData == NULL) {
1241 Status = EFI_OUT_OF_RESOURCES;
1242 goto Done;
1243 }
1244 DefaultData->OpCode = IfrOpHdr->OpCode;
1245 DefaultData->DefaultId = VarDefaultId;
1246 DefaultData->DefaultName = VarDefaultName;
1247 DefaultData->Value = 1;
1248 //
1249 // Add DefaultValue into current BlockData
1250 //
1251 InsertDefaultValue (BlockData, DefaultData);
1252 }
1253 break;
1254
1255 case EFI_IFR_STRING_OP:
1256 //
1257 // offset by question header
1258 // width MaxSize * sizeof (CHAR16)
1259 // no default value, only block array
1260 //
1261
1262 //
1263 // String question is not in IFR Form. This IFR form is not valid.
1264 //
1265 if (VarStorageData->Size == 0) {
1266 Status = EFI_INVALID_PARAMETER;
1267 goto Done;
1268 }
1269 //
1270 // Check whether this question is for the requested varstore.
1271 //
1272 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
1273 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {
1274 break;
1275 }
1276
1277 //
1278 // Get Offset/Width by Question header and OneOf Flags
1279 //
1280 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;
1281 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
1282
1283 //
1284 // Check whether this question is in requested block array.
1285 //
1286 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1287 //
1288 // This question is not in the requested string. Skip it.
1289 //
1290 break;
1291 }
1292
1293 //
1294 // Check this var question is in the var storage
1295 //
1296 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1297 Status = EFI_INVALID_PARAMETER;
1298 goto Done;
1299 }
1300
1301 //
1302 // Set Block Data
1303 //
1304 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1305 if (BlockData == NULL) {
1306 Status = EFI_OUT_OF_RESOURCES;
1307 goto Done;
1308 }
1309 BlockData->Offset = VarOffset;
1310 BlockData->Width = VarWidth;
1311 BlockData->QuestionId = IfrString->Question.QuestionId;
1312 BlockData->OpCode = IfrOpHdr->OpCode;
1313 InitializeListHead (&BlockData->DefaultValueEntry);
1314
1315 //
1316 // Add Block Data into VarStorageData BlockEntry
1317 //
1318 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1319
1320 //
1321 // No default value for string.
1322 //
1323 BlockData = NULL;
1324 break;
1325
1326 case EFI_IFR_PASSWORD_OP:
1327 //
1328 // offset by question header
1329 // width MaxSize * sizeof (CHAR16)
1330 // no default value, only block array
1331 //
1332
1333 //
1334 // Password question is not in IFR Form. This IFR form is not valid.
1335 //
1336 if (VarStorageData->Size == 0) {
1337 Status = EFI_INVALID_PARAMETER;
1338 goto Done;
1339 }
1340 //
1341 // Check whether this question is for the requested varstore.
1342 //
1343 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
1344 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {
1345 break;
1346 }
1347
1348 //
1349 // Get Offset/Width by Question header and OneOf Flags
1350 //
1351 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;
1352 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
1353
1354 //
1355 // Check whether this question is in requested block array.
1356 //
1357 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1358 //
1359 // This question is not in the requested string. Skip it.
1360 //
1361 break;
1362 }
1363
1364 //
1365 // Check this var question is in the var storage
1366 //
1367 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1368 Status = EFI_INVALID_PARAMETER;
1369 goto Done;
1370 }
1371
1372 //
1373 // Set Block Data
1374 //
1375 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1376 if (BlockData == NULL) {
1377 Status = EFI_OUT_OF_RESOURCES;
1378 goto Done;
1379 }
1380 BlockData->Offset = VarOffset;
1381 BlockData->Width = VarWidth;
1382 BlockData->QuestionId = IfrPassword->Question.QuestionId;
1383 BlockData->OpCode = IfrOpHdr->OpCode;
1384 InitializeListHead (&BlockData->DefaultValueEntry);
1385
1386 //
1387 // Add Block Data into VarStorageData BlockEntry
1388 //
1389 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1390
1391 //
1392 // No default value for string.
1393 //
1394 BlockData = NULL;
1395 break;
1396
1397 case EFI_IFR_ONE_OF_OPTION_OP:
1398 //
1399 // No matched block data is ignored.
1400 //
1401 if (BlockData == NULL || BlockData->Scope == 0) {
1402 break;
1403 }
1404
1405 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
1406 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1407 //
1408 // Get ordered list option data type.
1409 //
1410 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
1411 VarWidth = 1;
1412 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1413 VarWidth = 2;
1414 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1415 VarWidth = 4;
1416 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1417 VarWidth = 8;
1418 } else {
1419 //
1420 // Invalid ordered list option data type.
1421 //
1422 Status = EFI_INVALID_PARAMETER;
1423 FreePool (BlockData);
1424 goto Done;
1425 }
1426
1427 //
1428 // Calculate Ordered list QuestionId width.
1429 //
1430 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
1431 //
1432 // Check whether this question is in requested block array.
1433 //
1434 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width)) {
1435 //
1436 // This question is not in the requested string. Skip it.
1437 //
1438 FreePool (BlockData);
1439 BlockData = NULL;
1440 break;
1441 }
1442 //
1443 // Check this var question is in the var storage
1444 //
1445 if ((BlockData->Offset + BlockData->Width) > VarStorageData->Size) {
1446 Status = EFI_INVALID_PARAMETER;
1447 FreePool (BlockData);
1448 goto Done;
1449 }
1450 //
1451 // Add Block Data into VarStorageData BlockEntry
1452 //
1453 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1454 //
1455 // No default data for OrderedList.
1456 //
1457 BlockData = NULL;
1458 break;
1459 }
1460
1461 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
1462 (BlockData->OpCode == EFI_IFR_ONE_OF_OP && FirstOneOfOption)) {
1463 //
1464 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1465 // The first oneof option value will be used as default value when no default value is specified.
1466 //
1467 FirstOneOfOption = FALSE;
1468 //
1469 // Set standard ID to Manufacture ID and Get DefaultName String ID
1470 //
1471 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1472 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1473 if (EFI_ERROR (Status)) {
1474 goto Done;
1475 }
1476 //
1477 // Prepare new DefaultValue
1478 //
1479 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1480 if (DefaultData == NULL) {
1481 Status = EFI_OUT_OF_RESOURCES;
1482 goto Done;
1483 }
1484 DefaultData->OpCode = IfrOpHdr->OpCode;
1485 DefaultData->DefaultId = VarDefaultId;
1486 DefaultData->DefaultName = VarDefaultName;
1487 DefaultData->Value = IfrOneOfOption->Value.u64;
1488 //
1489 // Add DefaultValue into current BlockData
1490 //
1491 InsertDefaultValue (BlockData, DefaultData);
1492 }
1493
1494 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
1495 //
1496 // Set default ID to Manufacture ID and Get DefaultName String ID
1497 //
1498 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1499 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1500 if (EFI_ERROR (Status)) {
1501 goto Done;
1502 }
1503 //
1504 // Prepare new DefaultValue
1505 //
1506 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1507 if (DefaultData == NULL) {
1508 Status = EFI_OUT_OF_RESOURCES;
1509 goto Done;
1510 }
1511 DefaultData->OpCode = IfrOpHdr->OpCode;
1512 DefaultData->DefaultId = VarDefaultId;
1513 DefaultData->DefaultName = VarDefaultName;
1514 DefaultData->Value = IfrOneOfOption->Value.u64;
1515 //
1516 // Add DefaultValue into current BlockData
1517 //
1518 InsertDefaultValue (BlockData, DefaultData);
1519 }
1520 break;
1521
1522 case EFI_IFR_DEFAULT_OP:
1523 //
1524 // Update Current BlockData to the default value.
1525 //
1526 if (BlockData == NULL || BlockData->Scope == 0) {
1527 //
1528 // No matched block data is ignored.
1529 //
1530 break;
1531 }
1532
1533 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1534 //
1535 // OrderedList Opcode is no default value.
1536 //
1537 break;
1538 }
1539 //
1540 // Get the DefaultId and DefaultName String ID
1541 //
1542 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
1543 VarDefaultId = IfrDefault->DefaultId;
1544 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1545 if (EFI_ERROR (Status)) {
1546 goto Done;
1547 }
1548 //
1549 // Prepare new DefaultValue
1550 //
1551 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1552 if (DefaultData == NULL) {
1553 Status = EFI_OUT_OF_RESOURCES;
1554 goto Done;
1555 }
1556 DefaultData->OpCode = IfrOpHdr->OpCode;
1557 DefaultData->DefaultId = VarDefaultId;
1558 DefaultData->DefaultName = VarDefaultName;
1559 DefaultData->Value = IfrDefault->Value.u64;
1560 //
1561 // Add DefaultValue into current BlockData
1562 //
1563 InsertDefaultValue (BlockData, DefaultData);
1564 break;
1565 case EFI_IFR_END_OP:
1566 //
1567 // End Opcode is for Var question.
1568 //
1569 if (BlockData != NULL && BlockData->Scope > 0) {
1570 BlockData->Scope--;
1571 }
1572 break;
1573 default:
1574 if (BlockData != NULL && BlockData->Scope > 0) {
1575 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
1576 }
1577 break;
1578 }
1579
1580 IfrOffset += IfrOpHdr->Length;
1581 }
1582
1583 Done:
1584 return Status;
1585 }
1586
1587 /**
1588 This function gets the full request string and full default value string by
1589 parsing IFR data in HII form packages.
1590
1591 When Request points to NULL string, the request string and default value string
1592 for each varstore in form package will return.
1593
1594 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1595 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1596 @param Request Pointer to a null-terminated Unicode string in
1597 <ConfigRequest> format. When it doesn't contain
1598 any RequestElement, it will be updated to return
1599 the full RequestElement retrieved from IFR data.
1600 If it points to NULL, the request string for the first
1601 varstore in form package will be merged into a
1602 <MultiConfigRequest> format string and return.
1603 @param AltCfgResp Pointer to a null-terminated Unicode string in
1604 <ConfigAltResp> format. When the pointer is to NULL,
1605 the full default value string retrieved from IFR data
1606 will return. When the pinter is to a string, the
1607 full default value string retrieved from IFR data
1608 will be merged into the input string and return.
1609 When Request points to NULL, the default value string
1610 for each varstore in form package will be merged into
1611 a <MultiConfigAltResp> format string and return.
1612 @param PointerProgress Optional parameter, it can be be NULL.
1613 When it is not NULL, if Request is NULL, it returns NULL.
1614 On return, points to a character in the Request
1615 string. Points to the string's null terminator if
1616 request was successful. Points to the most recent
1617 & before the first failing name / value pair (or
1618 the beginning of the string if the failure is in
1619 the first name / value pair) if the request was
1620 not successful.
1621 @retval EFI_SUCCESS The Results string is set to the full request string.
1622 And AltCfgResp contains all default value string.
1623 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1624 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1625 can't be found in Form package.
1626 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1627 @retval EFI_INVALID_PARAMETER Request points to NULL.
1628
1629 **/
1630 EFI_STATUS
1631 EFIAPI
1632 GetFullStringFromHiiFormPackages (
1633 IN HII_DATABASE_RECORD *DataBaseRecord,
1634 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1635 IN OUT EFI_STRING *Request,
1636 IN OUT EFI_STRING *AltCfgResp,
1637 OUT EFI_STRING *PointerProgress OPTIONAL
1638 )
1639 {
1640 EFI_STATUS Status;
1641 UINT8 *HiiFormPackage;
1642 UINTN PackageSize;
1643 UINTN ResultSize;
1644 IFR_BLOCK_DATA *RequestBlockArray;
1645 IFR_BLOCK_DATA *BlockData;
1646 IFR_BLOCK_DATA *NextBlockData;
1647 IFR_DEFAULT_DATA *DefaultValueData;
1648 IFR_DEFAULT_DATA *DefaultId;
1649 IFR_DEFAULT_DATA *DefaultIdArray;
1650 IFR_VARSTORAGE_DATA *VarStorageData;
1651 EFI_STRING DefaultAltCfgResp;
1652 EFI_STRING FullConfigRequest;
1653 EFI_STRING ConfigHdr;
1654 EFI_STRING GuidStr;
1655 EFI_STRING NameStr;
1656 EFI_STRING PathStr;
1657 EFI_STRING StringPtr;
1658 EFI_STRING Progress;
1659 UINTN Length;
1660 UINT8 *TmpBuffer;
1661 UINT16 Offset;
1662 UINT16 Width;
1663 LIST_ENTRY *Link;
1664 LIST_ENTRY *LinkData;
1665 LIST_ENTRY *LinkDefault;
1666 BOOLEAN DataExist;
1667
1668 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
1669 return EFI_INVALID_PARAMETER;
1670 }
1671
1672 //
1673 // Initialize the local variables.
1674 //
1675 RequestBlockArray = NULL;
1676 DefaultIdArray = NULL;
1677 VarStorageData = NULL;
1678 DefaultAltCfgResp = NULL;
1679 FullConfigRequest = NULL;
1680 ConfigHdr = NULL;
1681 GuidStr = NULL;
1682 NameStr = NULL;
1683 PathStr = NULL;
1684 HiiFormPackage = NULL;
1685 ResultSize = 0;
1686 PackageSize = 0;
1687 DataExist = FALSE;
1688 Progress = *Request;
1689
1690 //
1691 // 0. Get Hii Form Package by HiiHandle
1692 //
1693 Status = ExportFormPackages (
1694 &mPrivate,
1695 DataBaseRecord->Handle,
1696 DataBaseRecord->PackageList,
1697 0,
1698 PackageSize,
1699 HiiFormPackage,
1700 &ResultSize
1701 );
1702 if (EFI_ERROR (Status)) {
1703 return Status;
1704 }
1705
1706 HiiFormPackage = AllocatePool (ResultSize);
1707 if (HiiFormPackage == NULL) {
1708 Status = EFI_OUT_OF_RESOURCES;
1709 goto Done;
1710 }
1711
1712 //
1713 // Get HiiFormPackage by HiiHandle
1714 //
1715 PackageSize = ResultSize;
1716 ResultSize = 0;
1717 Status = ExportFormPackages (
1718 &mPrivate,
1719 DataBaseRecord->Handle,
1720 DataBaseRecord->PackageList,
1721 0,
1722 PackageSize,
1723 HiiFormPackage,
1724 &ResultSize
1725 );
1726 if (EFI_ERROR (Status)) {
1727 goto Done;
1728 }
1729
1730 //
1731 // 1. Get the request block array by Request String when Request string containts the block array.
1732 //
1733 StringPtr = NULL;
1734 if (*Request != NULL) {
1735 StringPtr = *Request;
1736 //
1737 // Jump <ConfigHdr>
1738 //
1739 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
1740 Status = EFI_INVALID_PARAMETER;
1741 goto Done;
1742 }
1743 StringPtr += StrLen (L"GUID=");
1744 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
1745 StringPtr++;
1746 }
1747 if (*StringPtr == L'\0') {
1748 Status = EFI_INVALID_PARAMETER;
1749 goto Done;
1750 }
1751 StringPtr += StrLen (L"&NAME=");
1752 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
1753 StringPtr++;
1754 }
1755 if (*StringPtr == L'\0') {
1756 Status = EFI_INVALID_PARAMETER;
1757 goto Done;
1758 }
1759 StringPtr += StrLen (L"&PATH=");
1760 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1761 StringPtr ++;
1762 }
1763 //
1764 // Check the following string &OFFSET=
1765 //
1766 if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
1767 Progress = StringPtr;
1768 Status = EFI_INVALID_PARAMETER;
1769 goto Done;
1770 } else if (*StringPtr == L'\0') {
1771 //
1772 // No request block is found.
1773 //
1774 StringPtr = NULL;
1775 }
1776 }
1777 if (StringPtr != NULL) {
1778 //
1779 // Init RequestBlockArray
1780 //
1781 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1782 if (RequestBlockArray == NULL) {
1783 Status = EFI_OUT_OF_RESOURCES;
1784 goto Done;
1785 }
1786 InitializeListHead (&RequestBlockArray->Entry);
1787
1788 //
1789 // Get the request Block array from the request string
1790 // Offset and Width
1791 //
1792
1793 //
1794 // Parse each <RequestElement> if exists
1795 // Only <BlockName> format is supported by this help function.
1796 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1797 //
1798 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
1799 //
1800 // Skip the OFFSET string
1801 //
1802 Progress = StringPtr;
1803 StringPtr += StrLen (L"&OFFSET=");
1804 //
1805 // Get Offset
1806 //
1807 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1808 if (EFI_ERROR (Status)) {
1809 goto Done;
1810 }
1811 Offset = 0;
1812 CopyMem (
1813 &Offset,
1814 TmpBuffer,
1815 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1816 );
1817 FreePool (TmpBuffer);
1818
1819 StringPtr += Length;
1820 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
1821 Status = EFI_INVALID_PARAMETER;
1822 goto Done;
1823 }
1824 StringPtr += StrLen (L"&WIDTH=");
1825
1826 //
1827 // Get Width
1828 //
1829 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1830 if (EFI_ERROR (Status)) {
1831 goto Done;
1832 }
1833 Width = 0;
1834 CopyMem (
1835 &Width,
1836 TmpBuffer,
1837 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1838 );
1839 FreePool (TmpBuffer);
1840
1841 StringPtr += Length;
1842 if (*StringPtr != 0 && *StringPtr != L'&') {
1843 Status = EFI_INVALID_PARAMETER;
1844 goto Done;
1845 }
1846
1847 //
1848 // Set Block Data
1849 //
1850 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1851 if (BlockData == NULL) {
1852 Status = EFI_OUT_OF_RESOURCES;
1853 goto Done;
1854 }
1855 BlockData->Offset = Offset;
1856 BlockData->Width = Width;
1857 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
1858
1859 //
1860 // Skip &VALUE string if &VALUE does exists.
1861 //
1862 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
1863 StringPtr += StrLen (L"&VALUE=");
1864
1865 //
1866 // Get Value
1867 //
1868 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1869 if (EFI_ERROR (Status)) {
1870 Status = EFI_INVALID_PARAMETER;
1871 goto Done;
1872 }
1873
1874 StringPtr += Length;
1875 if (*StringPtr != 0 && *StringPtr != L'&') {
1876 Status = EFI_INVALID_PARAMETER;
1877 goto Done;
1878 }
1879 }
1880 //
1881 // If '\0', parsing is finished.
1882 //
1883 if (*StringPtr == 0) {
1884 break;
1885 }
1886 }
1887
1888 //
1889 // Merge the requested block data.
1890 //
1891 Link = RequestBlockArray->Entry.ForwardLink;
1892 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
1893 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1894 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
1895 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
1896 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
1897 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
1898 }
1899 RemoveEntryList (Link->ForwardLink);
1900 FreePool (NextBlockData);
1901 continue;
1902 }
1903 Link = Link->ForwardLink;
1904 }
1905 }
1906
1907 //
1908 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1909 //
1910
1911 //
1912 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1913 //
1914 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1915 if (DefaultIdArray == NULL) {
1916 Status = EFI_OUT_OF_RESOURCES;
1917 goto Done;
1918 }
1919 InitializeListHead (&DefaultIdArray->Entry);
1920
1921 //
1922 // Initialize VarStorageData to store the var store Block and Default value information.
1923 //
1924 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
1925 if (VarStorageData == NULL) {
1926 Status = EFI_OUT_OF_RESOURCES;
1927 goto Done;
1928 }
1929 InitializeListHead (&VarStorageData->Entry);
1930 InitializeListHead (&VarStorageData->BlockEntry);
1931
1932 //
1933 // Parse the opcode in form pacakge to get the default setting.
1934 //
1935 Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);
1936 if (EFI_ERROR (Status)) {
1937 goto Done;
1938 }
1939
1940 //
1941 // No requested varstore in IFR data and directly return
1942 //
1943 if (VarStorageData->Size == 0) {
1944 Status = EFI_SUCCESS;
1945 goto Done;
1946 }
1947
1948 //
1949 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1950 //
1951
1952 //
1953 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1954 //
1955 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
1956 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
1957 GenerateSubStr (
1958 L"PATH=",
1959 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
1960 (VOID *) DevicePath,
1961 1,
1962 &PathStr
1963 );
1964 Length = StrLen (GuidStr);
1965 Length = Length + StrLen (NameStr);
1966 Length = Length + StrLen (PathStr) + 1;
1967 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
1968 if (ConfigHdr == NULL) {
1969 Status = EFI_OUT_OF_RESOURCES;
1970 goto Done;
1971 }
1972 StrCpy (ConfigHdr, GuidStr);
1973 StrCat (ConfigHdr, NameStr);
1974 StrCat (ConfigHdr, PathStr);
1975
1976 //
1977 // Remove the last character L'&'
1978 //
1979 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';
1980
1981 if (RequestBlockArray == NULL) {
1982 //
1983 // Append VarStorageData BlockEntry into *Request string
1984 // Now support only one varstore in a form package.
1985 //
1986
1987 //
1988 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1989 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1990 //
1991
1992 //
1993 // Compute the length of the entire request starting with <ConfigHdr> and a
1994 // Null-terminator
1995 //
1996 DataExist = FALSE;
1997 Length = StrLen (ConfigHdr) + 1;
1998
1999 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2000 //
2001 // Add <BlockName> length for each Offset/Width pair
2002 //
2003 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2004 // | 8 | 4 | 7 | 4 |
2005 //
2006 DataExist = TRUE;
2007 Length = Length + (8 + 4 + 7 + 4);
2008 }
2009
2010 //
2011 // No any request block data is found. The request string can't be constructed.
2012 //
2013 if (!DataExist) {
2014 Status = EFI_SUCCESS;
2015 goto Done;
2016 }
2017
2018 //
2019 // Allocate buffer for the entire <ConfigRequest>
2020 //
2021 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
2022 if (FullConfigRequest == NULL) {
2023 Status = EFI_OUT_OF_RESOURCES;
2024 goto Done;
2025 }
2026 StringPtr = FullConfigRequest;
2027
2028 //
2029 // Start with <ConfigHdr>
2030 //
2031 StrCpy (StringPtr, ConfigHdr);
2032 StringPtr += StrLen (StringPtr);
2033
2034 //
2035 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2036 //
2037 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2038 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2039 //
2040 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2041 //
2042 UnicodeSPrint (
2043 StringPtr,
2044 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
2045 L"&OFFSET=%04X&WIDTH=%04X",
2046 BlockData->Offset,
2047 BlockData->Width
2048 );
2049 StringPtr += StrLen (StringPtr);
2050 }
2051 //
2052 // Set to the got full request string.
2053 //
2054 HiiToLower (FullConfigRequest);
2055 if (*Request != NULL) {
2056 FreePool (*Request);
2057 }
2058 *Request = FullConfigRequest;
2059 }
2060
2061 //
2062 // 4. Construct Default Value string in AltResp according to request element.
2063 // Go through all VarStorageData Entry and get the DefaultId array for each one
2064 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2065 //
2066 DataExist = FALSE;
2067 //
2068 // Add length for <ConfigHdr> + '\0'
2069 //
2070 Length = StrLen (ConfigHdr) + 1;
2071
2072 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2073 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2074 //
2075 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2076 // |1| StrLen (ConfigHdr) | 8 | 4 |
2077 //
2078 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
2079
2080 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2081 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2082 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
2083 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2084 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
2085 //
2086 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2087 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2088 //
2089 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
2090 DataExist = TRUE;
2091 }
2092 }
2093 }
2094 }
2095
2096 //
2097 // No default value is found. The default string doesn't exist.
2098 //
2099 if (!DataExist) {
2100 Status = EFI_SUCCESS;
2101 goto Done;
2102 }
2103
2104 //
2105 // Allocate buffer for the entire <DefaultAltCfgResp>
2106 //
2107 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
2108 if (DefaultAltCfgResp == NULL) {
2109 Status = EFI_OUT_OF_RESOURCES;
2110 goto Done;
2111 }
2112 StringPtr = DefaultAltCfgResp;
2113
2114 //
2115 // Start with <ConfigHdr>
2116 //
2117 StrCpy (StringPtr, ConfigHdr);
2118 StringPtr += StrLen (StringPtr);
2119
2120 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2121 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2122 //
2123 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2124 // |1| StrLen (ConfigHdr) | 8 | 4 |
2125 //
2126 UnicodeSPrint (
2127 StringPtr,
2128 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
2129 L"&%s&ALTCFG=%04X",
2130 ConfigHdr,
2131 DefaultId->DefaultName
2132 );
2133 StringPtr += StrLen (StringPtr);
2134
2135 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2136 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2137 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
2138 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2139 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
2140 //
2141 // Add <BlockConfig>
2142 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2143 //
2144 UnicodeSPrint (
2145 StringPtr,
2146 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
2147 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2148 BlockData->Offset,
2149 BlockData->Width
2150 );
2151 StringPtr += StrLen (StringPtr);
2152
2153 //
2154 // Convert Value to a hex string in "%x" format
2155 // NOTE: This is in the opposite byte that GUID and PATH use
2156 //
2157 Width = BlockData->Width;
2158 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
2159 for (; Width > 0; Width--) {
2160 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
2161 }
2162 }
2163 }
2164 }
2165 }
2166 HiiToLower (DefaultAltCfgResp);
2167
2168 //
2169 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2170 //
2171 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
2172 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
2173 FreePool (DefaultAltCfgResp);
2174 } else if (*AltCfgResp == NULL) {
2175 *AltCfgResp = DefaultAltCfgResp;
2176 }
2177
2178 Done:
2179 if (RequestBlockArray != NULL) {
2180 //
2181 // Free Link Array RequestBlockArray
2182 //
2183 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2184 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2185 RemoveEntryList (&BlockData->Entry);
2186 FreePool (BlockData);
2187 }
2188
2189 FreePool (RequestBlockArray);
2190 }
2191
2192 if (VarStorageData != NULL) {
2193 //
2194 // Free link array VarStorageData
2195 //
2196 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
2197 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
2198 RemoveEntryList (&BlockData->Entry);
2199 //
2200 // Free default value link array
2201 //
2202 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
2203 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
2204 RemoveEntryList (&DefaultValueData->Entry);
2205 FreePool (DefaultValueData);
2206 }
2207 FreePool (BlockData);
2208 }
2209 FreePool (VarStorageData);
2210 }
2211
2212 if (DefaultIdArray != NULL) {
2213 //
2214 // Free DefaultId Array
2215 //
2216 while (!IsListEmpty (&DefaultIdArray->Entry)) {
2217 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
2218 RemoveEntryList (&DefaultId->Entry);
2219 FreePool (DefaultId);
2220 }
2221 FreePool (DefaultIdArray);
2222 }
2223
2224 //
2225 // Free the allocated string
2226 //
2227 if (GuidStr != NULL) {
2228 FreePool (GuidStr);
2229 }
2230 if (NameStr != NULL) {
2231 FreePool (NameStr);
2232 }
2233 if (PathStr != NULL) {
2234 FreePool (PathStr);
2235 }
2236 if (ConfigHdr != NULL) {
2237 FreePool (ConfigHdr);
2238 }
2239
2240 //
2241 // Free Pacakge data
2242 //
2243 if (HiiFormPackage != NULL) {
2244 FreePool (HiiFormPackage);
2245 }
2246
2247 if (PointerProgress != NULL) {
2248 if (*Request == NULL) {
2249 *PointerProgress = NULL;
2250 } else if (EFI_ERROR (Status)) {
2251 *PointerProgress = Progress;
2252 } else {
2253 *PointerProgress = *Request + StrLen (*Request);
2254 }
2255 }
2256
2257 return Status;
2258 }
2259
2260 /**
2261 This function allows a caller to extract the current configuration
2262 for one or more named elements from one or more drivers.
2263
2264 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2265 instance.
2266 @param Request A null-terminated Unicode string in
2267 <MultiConfigRequest> format.
2268 @param Progress On return, points to a character in the Request
2269 string. Points to the string's null terminator if
2270 request was successful. Points to the most recent
2271 & before the first failing name / value pair (or
2272 the beginning of the string if the failure is in
2273 the first name / value pair) if the request was
2274 not successful.
2275 @param Results Null-terminated Unicode string in
2276 <MultiConfigAltResp> format which has all values
2277 filled in for the names in the Request string.
2278 String to be allocated by the called function.
2279
2280 @retval EFI_SUCCESS The Results string is filled with the values
2281 corresponding to all requested names.
2282 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2283 results that must be stored awaiting possible
2284 future protocols.
2285 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2286 Progress set to the "G" in "GUID" of the routing
2287 header that doesn't match. Note: There is no
2288 requirement that all routing data be validated
2289 before any configuration extraction.
2290 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2291 parameter would result in this type of error. The
2292 Progress parameter is set to NULL.
2293 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2294 before the error or the beginning of the string.
2295 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2296 name in question.
2297
2298 **/
2299 EFI_STATUS
2300 EFIAPI
2301 HiiConfigRoutingExtractConfig (
2302 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2303 IN CONST EFI_STRING Request,
2304 OUT EFI_STRING *Progress,
2305 OUT EFI_STRING *Results
2306 )
2307 {
2308 HII_DATABASE_PRIVATE_DATA *Private;
2309 EFI_STRING StringPtr;
2310 EFI_STRING ConfigRequest;
2311 UINTN Length;
2312 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2313 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
2314 EFI_STATUS Status;
2315 LIST_ENTRY *Link;
2316 HII_DATABASE_RECORD *Database;
2317 UINT8 *DevicePathPkg;
2318 UINT8 *CurrentDevicePath;
2319 EFI_HANDLE DriverHandle;
2320 EFI_HII_HANDLE HiiHandle;
2321 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2322 EFI_STRING AccessProgress;
2323 EFI_STRING AccessResults;
2324 EFI_STRING DefaultResults;
2325 BOOLEAN FirstElement;
2326 BOOLEAN IfrDataParsedFlag;
2327
2328 if (This == NULL || Progress == NULL || Results == NULL) {
2329 return EFI_INVALID_PARAMETER;
2330 }
2331
2332 if (Request == NULL) {
2333 *Progress = NULL;
2334 return EFI_INVALID_PARAMETER;
2335 }
2336
2337 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2338 StringPtr = Request;
2339 *Progress = StringPtr;
2340 DefaultResults = NULL;
2341 ConfigRequest = NULL;
2342 Status = EFI_SUCCESS;
2343 AccessResults = NULL;
2344 DevicePath = NULL;
2345 IfrDataParsedFlag = FALSE;
2346
2347 //
2348 // The first element of <MultiConfigRequest> should be
2349 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2350 //
2351 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2352 return EFI_INVALID_PARAMETER;
2353 }
2354
2355 FirstElement = TRUE;
2356
2357 //
2358 // Allocate a fix length of memory to store Results. Reallocate memory for
2359 // Results if this fix length is insufficient.
2360 //
2361 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2362 if (*Results == NULL) {
2363 return EFI_OUT_OF_RESOURCES;
2364 }
2365
2366 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
2367 //
2368 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2369 // or most recent & before the error.
2370 //
2371 if (StringPtr == Request) {
2372 *Progress = StringPtr;
2373 } else {
2374 *Progress = StringPtr - 1;
2375 }
2376
2377 //
2378 // Process each <ConfigRequest> of <MultiConfigRequest>
2379 //
2380 Length = CalculateConfigStringLen (StringPtr);
2381 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
2382 if (ConfigRequest == NULL) {
2383 Status = EFI_OUT_OF_RESOURCES;
2384 goto Done;
2385 }
2386 *(ConfigRequest + Length) = 0;
2387
2388 //
2389 // Get the UEFI device path
2390 //
2391 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
2392 if (EFI_ERROR (Status)) {
2393 goto Done;
2394 }
2395
2396 //
2397 // Find driver which matches the routing data.
2398 //
2399 DriverHandle = NULL;
2400 HiiHandle = NULL;
2401 Database = NULL;
2402 for (Link = Private->DatabaseList.ForwardLink;
2403 Link != &Private->DatabaseList;
2404 Link = Link->ForwardLink
2405 ) {
2406 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2407 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2408 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2409 if (CompareMem (
2410 DevicePath,
2411 CurrentDevicePath,
2412 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
2413 ) == 0) {
2414 DriverHandle = Database->DriverHandle;
2415 HiiHandle = Database->Handle;
2416 break;
2417 }
2418 }
2419 }
2420
2421 //
2422 // Try to find driver handle by device path.
2423 //
2424 if (DriverHandle == NULL) {
2425 TempDevicePath = DevicePath;
2426 Status = gBS->LocateDevicePath (
2427 &gEfiDevicePathProtocolGuid,
2428 &TempDevicePath,
2429 &DriverHandle
2430 );
2431 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
2432 //
2433 // Routing data does not match any known driver.
2434 // Set Progress to the 'G' in "GUID" of the routing header.
2435 //
2436 *Progress = StringPtr;
2437 Status = EFI_NOT_FOUND;
2438 goto Done;
2439 }
2440 }
2441
2442 //
2443 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2444 //
2445 IfrDataParsedFlag = FALSE;
2446 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {
2447 //
2448 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2449 //
2450 IfrDataParsedFlag = TRUE;
2451 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
2452 if (EFI_ERROR (Status)) {
2453 //
2454 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2455 // Map it to the progress on <MultiConfigRequest> then return it.
2456 //
2457 *Progress = StrStr (StringPtr, AccessProgress);
2458 goto Done;
2459 }
2460 //
2461 // Not any request block is found.
2462 //
2463 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {
2464 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
2465 goto NextConfigString;
2466 }
2467 }
2468
2469 //
2470 // Call corresponding ConfigAccess protocol to extract settings
2471 //
2472 Status = gBS->HandleProtocol (
2473 DriverHandle,
2474 &gEfiHiiConfigAccessProtocolGuid,
2475 (VOID **) &ConfigAccess
2476 );
2477 ASSERT_EFI_ERROR (Status);
2478
2479 Status = ConfigAccess->ExtractConfig (
2480 ConfigAccess,
2481 ConfigRequest,
2482 &AccessProgress,
2483 &AccessResults
2484 );
2485 if (EFI_ERROR (Status)) {
2486 //
2487 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2488 // Map it to the progress on <MultiConfigRequest> then return it.
2489 //
2490 *Progress = StrStr (StringPtr, AccessProgress);
2491 goto Done;
2492 }
2493
2494 //
2495 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2496 // which seperates the first <ConfigAltResp> and the following ones.
2497 //
2498 ASSERT (*AccessProgress == 0);
2499
2500 //
2501 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2502 //
2503 if (!IfrDataParsedFlag && HiiHandle != NULL) {
2504 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
2505 ASSERT_EFI_ERROR (Status);
2506 }
2507
2508 FreePool (DevicePath);
2509 DevicePath = NULL;
2510
2511 if (DefaultResults != NULL) {
2512 Status = MergeDefaultString (&AccessResults, DefaultResults);
2513 ASSERT_EFI_ERROR (Status);
2514 FreePool (DefaultResults);
2515 DefaultResults = NULL;
2516 }
2517
2518 NextConfigString:
2519 if (!FirstElement) {
2520 Status = AppendToMultiString (Results, L"&");
2521 ASSERT_EFI_ERROR (Status);
2522 }
2523
2524 Status = AppendToMultiString (Results, AccessResults);
2525 ASSERT_EFI_ERROR (Status);
2526
2527 FirstElement = FALSE;
2528
2529 FreePool (AccessResults);
2530 AccessResults = NULL;
2531 FreePool (ConfigRequest);
2532 ConfigRequest = NULL;
2533
2534 //
2535 // Go to next <ConfigRequest> (skip '&').
2536 //
2537 StringPtr += Length;
2538 if (*StringPtr == 0) {
2539 *Progress = StringPtr;
2540 break;
2541 }
2542
2543 StringPtr++;
2544 }
2545
2546 Done:
2547 if (EFI_ERROR (Status)) {
2548 FreePool (*Results);
2549 *Results = NULL;
2550 }
2551
2552 if (ConfigRequest != NULL) {
2553 FreePool (ConfigRequest);
2554 }
2555
2556 if (AccessResults != NULL) {
2557 FreePool (AccessResults);
2558 }
2559
2560 if (DefaultResults != NULL) {
2561 FreePool (DefaultResults);
2562 }
2563
2564 if (DevicePath != NULL) {
2565 FreePool (DevicePath);
2566 }
2567
2568 return Status;
2569 }
2570
2571
2572 /**
2573 This function allows the caller to request the current configuration for the
2574 entirety of the current HII database and returns the data in a
2575 null-terminated Unicode string.
2576
2577 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2578 instance.
2579 @param Results Null-terminated Unicode string in
2580 <MultiConfigAltResp> format which has all values
2581 filled in for the names in the Request string.
2582 String to be allocated by the called function.
2583 De-allocation is up to the caller.
2584
2585 @retval EFI_SUCCESS The Results string is filled with the values
2586 corresponding to all requested names.
2587 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2588 results that must be stored awaiting possible
2589 future protocols.
2590 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2591 parameter would result in this type of error.
2592
2593 **/
2594 EFI_STATUS
2595 EFIAPI
2596 HiiConfigRoutingExportConfig (
2597 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2598 OUT EFI_STRING *Results
2599 )
2600 {
2601 EFI_STATUS Status;
2602 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2603 EFI_STRING AccessResults;
2604 EFI_STRING Progress;
2605 EFI_STRING StringPtr;
2606 EFI_STRING ConfigRequest;
2607 UINTN Index;
2608 EFI_HANDLE *ConfigAccessHandles;
2609 UINTN NumberConfigAccessHandles;
2610 BOOLEAN FirstElement;
2611 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2612 EFI_HII_HANDLE HiiHandle;
2613 EFI_STRING DefaultResults;
2614 HII_DATABASE_PRIVATE_DATA *Private;
2615 LIST_ENTRY *Link;
2616 HII_DATABASE_RECORD *Database;
2617 UINT8 *DevicePathPkg;
2618 UINT8 *CurrentDevicePath;
2619 BOOLEAN IfrDataParsedFlag;
2620
2621 if (This == NULL || Results == NULL) {
2622 return EFI_INVALID_PARAMETER;
2623 }
2624
2625 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2626
2627 //
2628 // Allocate a fix length of memory to store Results. Reallocate memory for
2629 // Results if this fix length is insufficient.
2630 //
2631 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2632 if (*Results == NULL) {
2633 return EFI_OUT_OF_RESOURCES;
2634 }
2635
2636 NumberConfigAccessHandles = 0;
2637 Status = gBS->LocateHandleBuffer (
2638 ByProtocol,
2639 &gEfiHiiConfigAccessProtocolGuid,
2640 NULL,
2641 &NumberConfigAccessHandles,
2642 &ConfigAccessHandles
2643 );
2644 if (EFI_ERROR (Status)) {
2645 return Status;
2646 }
2647
2648 FirstElement = TRUE;
2649
2650 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
2651 Status = gBS->HandleProtocol (
2652 ConfigAccessHandles[Index],
2653 &gEfiHiiConfigAccessProtocolGuid,
2654 (VOID **) &ConfigAccess
2655 );
2656 if (EFI_ERROR (Status)) {
2657 continue;
2658 }
2659
2660 //
2661 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2662 //
2663 IfrDataParsedFlag = FALSE;
2664 Progress = NULL;
2665 HiiHandle = NULL;
2666 DefaultResults = NULL;
2667 Database = NULL;
2668 ConfigRequest = NULL;
2669 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
2670 if (DevicePath != NULL) {
2671 for (Link = Private->DatabaseList.ForwardLink;
2672 Link != &Private->DatabaseList;
2673 Link = Link->ForwardLink
2674 ) {
2675 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2676 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2677 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2678 if (CompareMem (
2679 DevicePath,
2680 CurrentDevicePath,
2681 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
2682 ) == 0) {
2683 HiiHandle = Database->Handle;
2684 break;
2685 }
2686 }
2687 }
2688 }
2689
2690 Status = ConfigAccess->ExtractConfig (
2691 ConfigAccess,
2692 NULL,
2693 &Progress,
2694 &AccessResults
2695 );
2696 if (EFI_ERROR (Status)) {
2697 //
2698 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2699 //
2700 if (HiiHandle != NULL && DevicePath != NULL) {
2701 IfrDataParsedFlag = TRUE;
2702 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
2703 //
2704 // Get the full request string to get the Current setting again.
2705 //
2706 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
2707 Status = ConfigAccess->ExtractConfig (
2708 ConfigAccess,
2709 ConfigRequest,
2710 &Progress,
2711 &AccessResults
2712 );
2713 FreePool (ConfigRequest);
2714 } else {
2715 Status = EFI_NOT_FOUND;
2716 }
2717 }
2718 }
2719
2720 if (!EFI_ERROR (Status)) {
2721 //
2722 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2723 //
2724 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
2725 StringPtr = StrStr (AccessResults, L"&GUID=");
2726 if (StringPtr != NULL) {
2727 *StringPtr = 0;
2728 }
2729 if (StrStr (AccessResults, L"&OFFSET=") != NULL) {
2730 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
2731 ASSERT_EFI_ERROR (Status);
2732 }
2733 if (StringPtr != NULL) {
2734 *StringPtr = L'&';
2735 }
2736 }
2737 //
2738 // Merge the default sting from IFR code into the got setting from driver.
2739 //
2740 if (DefaultResults != NULL) {
2741 Status = MergeDefaultString (&AccessResults, DefaultResults);
2742 ASSERT_EFI_ERROR (Status);
2743 FreePool (DefaultResults);
2744 DefaultResults = NULL;
2745 }
2746
2747 //
2748 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2749 // which seperates the first <ConfigAltResp> and the following ones.
2750 //
2751 if (!FirstElement) {
2752 Status = AppendToMultiString (Results, L"&");
2753 ASSERT_EFI_ERROR (Status);
2754 }
2755
2756 Status = AppendToMultiString (Results, AccessResults);
2757 ASSERT_EFI_ERROR (Status);
2758
2759 FirstElement = FALSE;
2760
2761 FreePool (AccessResults);
2762 AccessResults = NULL;
2763 }
2764 }
2765 FreePool (ConfigAccessHandles);
2766
2767 return EFI_SUCCESS;
2768 }
2769
2770
2771 /**
2772 This function processes the results of processing forms and routes it to the
2773 appropriate handlers or storage.
2774
2775 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2776 instance.
2777 @param Configuration A null-terminated Unicode string in
2778 <MulltiConfigResp> format.
2779 @param Progress A pointer to a string filled in with the offset of
2780 the most recent & before the first failing name /
2781 value pair (or the beginning of the string if the
2782 failure is in the first name / value pair) or the
2783 terminating NULL if all was successful.
2784
2785 @retval EFI_SUCCESS The results have been distributed or are awaiting
2786 distribution.
2787 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2788 results that must be stored awaiting possible
2789 future protocols.
2790 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2791 would result in this type of error.
2792 @retval EFI_NOT_FOUND Target for the specified routing data was not
2793 found.
2794
2795 **/
2796 EFI_STATUS
2797 EFIAPI
2798 HiiConfigRoutingRouteConfig (
2799 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2800 IN CONST EFI_STRING Configuration,
2801 OUT EFI_STRING *Progress
2802 )
2803 {
2804 HII_DATABASE_PRIVATE_DATA *Private;
2805 EFI_STRING StringPtr;
2806 EFI_STRING ConfigResp;
2807 UINTN Length;
2808 EFI_STATUS Status;
2809 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2810 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
2811 LIST_ENTRY *Link;
2812 HII_DATABASE_RECORD *Database;
2813 UINT8 *DevicePathPkg;
2814 UINT8 *CurrentDevicePath;
2815 EFI_HANDLE DriverHandle;
2816 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2817 EFI_STRING AccessProgress;
2818
2819 if (This == NULL || Progress == NULL) {
2820 return EFI_INVALID_PARAMETER;
2821 }
2822
2823 if (Configuration == NULL) {
2824 *Progress = NULL;
2825 return EFI_INVALID_PARAMETER;
2826 }
2827
2828 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2829 StringPtr = Configuration;
2830 *Progress = StringPtr;
2831
2832 //
2833 // The first element of <MultiConfigResp> should be
2834 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2835 //
2836 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2837 return EFI_INVALID_PARAMETER;
2838 }
2839
2840 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
2841 //
2842 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2843 // or most recent & before the error.
2844 //
2845 if (StringPtr == Configuration) {
2846 *Progress = StringPtr;
2847 } else {
2848 *Progress = StringPtr - 1;
2849 }
2850
2851 //
2852 // Process each <ConfigResp> of <MultiConfigResp>
2853 //
2854 Length = CalculateConfigStringLen (StringPtr);
2855 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
2856 if (ConfigResp == NULL) {
2857 return EFI_OUT_OF_RESOURCES;
2858 }
2859 //
2860 // Append '\0' to the end of ConfigRequest
2861 //
2862 *(ConfigResp + Length) = 0;
2863
2864 //
2865 // Get the UEFI device path
2866 //
2867 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
2868 if (EFI_ERROR (Status)) {
2869 FreePool (ConfigResp);
2870 return Status;
2871 }
2872
2873 //
2874 // Find driver which matches the routing data.
2875 //
2876 DriverHandle = NULL;
2877 for (Link = Private->DatabaseList.ForwardLink;
2878 Link != &Private->DatabaseList;
2879 Link = Link->ForwardLink
2880 ) {
2881 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2882
2883 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2884 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2885 if (CompareMem (
2886 DevicePath,
2887 CurrentDevicePath,
2888 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
2889 ) == 0) {
2890 DriverHandle = Database->DriverHandle;
2891 break;
2892 }
2893 }
2894 }
2895
2896 //
2897 // Try to find driver handle by device path.
2898 //
2899 if (DriverHandle == NULL) {
2900 TempDevicePath = DevicePath;
2901 Status = gBS->LocateDevicePath (
2902 &gEfiDevicePathProtocolGuid,
2903 &TempDevicePath,
2904 &DriverHandle
2905 );
2906 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
2907 //
2908 // Routing data does not match any known driver.
2909 // Set Progress to the 'G' in "GUID" of the routing header.
2910 //
2911 FreePool (DevicePath);
2912 *Progress = StringPtr;
2913 FreePool (ConfigResp);
2914 return EFI_NOT_FOUND;
2915 }
2916 }
2917
2918 FreePool (DevicePath);
2919
2920 //
2921 // Call corresponding ConfigAccess protocol to route settings
2922 //
2923 Status = gBS->HandleProtocol (
2924 DriverHandle,
2925 &gEfiHiiConfigAccessProtocolGuid,
2926 (VOID **) &ConfigAccess
2927 );
2928 ASSERT_EFI_ERROR (Status);
2929
2930 Status = ConfigAccess->RouteConfig (
2931 ConfigAccess,
2932 ConfigResp,
2933 &AccessProgress
2934 );
2935
2936 if (EFI_ERROR (Status)) {
2937 //
2938 // AccessProgress indicates the parsing progress on <ConfigResp>.
2939 // Map it to the progress on <MultiConfigResp> then return it.
2940 //
2941 *Progress = StrStr (StringPtr, AccessProgress);
2942
2943 FreePool (ConfigResp);
2944 return Status;
2945 }
2946
2947 FreePool (ConfigResp);
2948 ConfigResp = NULL;
2949
2950 //
2951 // Go to next <ConfigResp> (skip '&').
2952 //
2953 StringPtr += Length;
2954 if (*StringPtr == 0) {
2955 *Progress = StringPtr;
2956 break;
2957 }
2958
2959 StringPtr++;
2960
2961 }
2962
2963 return EFI_SUCCESS;
2964 }
2965
2966
2967 /**
2968 This helper function is to be called by drivers to map configuration data
2969 stored in byte array ("block") formats such as UEFI Variables into current
2970 configuration strings.
2971
2972 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2973 instance.
2974 @param ConfigRequest A null-terminated Unicode string in
2975 <ConfigRequest> format.
2976 @param Block Array of bytes defining the block's configuration.
2977 @param BlockSize Length in bytes of Block.
2978 @param Config Filled-in configuration string. String allocated
2979 by the function. Returned only if call is
2980 successful. It is <ConfigResp> string format.
2981 @param Progress A pointer to a string filled in with the offset of
2982 the most recent & before the first failing
2983 name/value pair (or the beginning of the string if
2984 the failure is in the first name / value pair) or
2985 the terminating NULL if all was successful.
2986
2987 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2988 terminator at the end of the ConfigRequest
2989 string.
2990 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2991 points to the first character of ConfigRequest.
2992 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2993 Block parameter would result in this type of
2994 error. Progress points to the first character of
2995 ConfigRequest.
2996 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2997 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2998 Block is left updated and Progress points at
2999 the "&" preceding the first non-<BlockName>.
3000
3001 **/
3002 EFI_STATUS
3003 EFIAPI
3004 HiiBlockToConfig (
3005 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3006 IN CONST EFI_STRING ConfigRequest,
3007 IN CONST UINT8 *Block,
3008 IN CONST UINTN BlockSize,
3009 OUT EFI_STRING *Config,
3010 OUT EFI_STRING *Progress
3011 )
3012 {
3013 HII_DATABASE_PRIVATE_DATA *Private;
3014 EFI_STRING StringPtr;
3015 UINTN Length;
3016 EFI_STATUS Status;
3017 EFI_STRING TmpPtr;
3018 UINT8 *TmpBuffer;
3019 UINTN Offset;
3020 UINTN Width;
3021 UINT8 *Value;
3022 EFI_STRING ValueStr;
3023 EFI_STRING ConfigElement;
3024 UINTN Index;
3025 UINT8 *TemBuffer;
3026 CHAR16 *TemString;
3027
3028 if (This == NULL || Progress == NULL || Config == NULL) {
3029 return EFI_INVALID_PARAMETER;
3030 }
3031
3032 if (Block == NULL || ConfigRequest == NULL) {
3033 *Progress = ConfigRequest;
3034 return EFI_INVALID_PARAMETER;
3035 }
3036
3037
3038 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3039 ASSERT (Private != NULL);
3040
3041 StringPtr = ConfigRequest;
3042 ValueStr = NULL;
3043 Value = NULL;
3044 ConfigElement = NULL;
3045
3046 //
3047 // Allocate a fix length of memory to store Results. Reallocate memory for
3048 // Results if this fix length is insufficient.
3049 //
3050 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
3051 if (*Config == NULL) {
3052 return EFI_OUT_OF_RESOURCES;
3053 }
3054
3055 //
3056 // Jump <ConfigHdr>
3057 //
3058 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3059 *Progress = StringPtr;
3060 Status = EFI_INVALID_PARAMETER;
3061 goto Exit;
3062 }
3063 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
3064 StringPtr++;
3065 }
3066 if (*StringPtr == 0) {
3067 *Progress = StringPtr - 1;
3068 Status = EFI_INVALID_PARAMETER;
3069 goto Exit;
3070 }
3071
3072 while (*StringPtr != L'&' && *StringPtr != 0) {
3073 StringPtr++;
3074 }
3075 if (*StringPtr == 0) {
3076 *Progress = StringPtr - 1;
3077 Status = EFI_INVALID_PARAMETER;
3078 goto Exit;
3079 }
3080 //
3081 // Skip '&'
3082 //
3083 StringPtr++;
3084
3085 //
3086 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3087 //
3088 Length = StringPtr - ConfigRequest;
3089 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));
3090
3091 //
3092 // Parse each <RequestElement> if exists
3093 // Only <BlockName> format is supported by this help function.
3094 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3095 //
3096 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
3097 //
3098 // Back up the header of one <BlockName>
3099 //
3100 TmpPtr = StringPtr;
3101
3102 StringPtr += StrLen (L"OFFSET=");
3103 //
3104 // Get Offset
3105 //
3106 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3107 if (EFI_ERROR (Status)) {
3108 *Progress = ConfigRequest;
3109 goto Exit;
3110 }
3111 Offset = 0;
3112 CopyMem (
3113 &Offset,
3114 TmpBuffer,
3115 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3116 );
3117 FreePool (TmpBuffer);
3118
3119 StringPtr += Length;
3120 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3121 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
3122 Status = EFI_INVALID_PARAMETER;
3123 goto Exit;
3124 }
3125 StringPtr += StrLen (L"&WIDTH=");
3126
3127 //
3128 // Get Width
3129 //
3130 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3131 if (EFI_ERROR (Status)) {
3132 *Progress = ConfigRequest;
3133 goto Exit;
3134 }
3135 Width = 0;
3136 CopyMem (
3137 &Width,
3138 TmpBuffer,
3139 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3140 );
3141 FreePool (TmpBuffer);
3142
3143 StringPtr += Length;
3144 if (*StringPtr != 0 && *StringPtr != L'&') {
3145 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
3146 Status = EFI_INVALID_PARAMETER;
3147 goto Exit;
3148 }
3149
3150 //
3151 // Calculate Value and convert it to hex string.
3152 //
3153 if (Offset + Width > BlockSize) {
3154 *Progress = StringPtr;
3155 Status = EFI_DEVICE_ERROR;
3156 goto Exit;
3157 }
3158
3159 Value = (UINT8 *) AllocateZeroPool (Width);
3160 if (Value == NULL) {
3161 *Progress = ConfigRequest;
3162 Status = EFI_OUT_OF_RESOURCES;
3163 goto Exit;
3164 }
3165
3166 CopyMem (Value, (UINT8 *) Block + Offset, Width);
3167
3168 Length = Width * 2 + 1;
3169 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
3170 if (ValueStr == NULL) {
3171 *Progress = ConfigRequest;
3172 Status = EFI_OUT_OF_RESOURCES;
3173 goto Exit;
3174 }
3175
3176 TemString = ValueStr;
3177 TemBuffer = Value + Width - 1;
3178 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
3179 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
3180 }
3181
3182 FreePool (Value);
3183 Value = NULL;
3184
3185 //
3186 // Build a ConfigElement
3187 //
3188 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
3189 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
3190 if (ConfigElement == NULL) {
3191 Status = EFI_OUT_OF_RESOURCES;
3192 goto Exit;
3193 }
3194 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
3195 if (*StringPtr == 0) {
3196 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
3197 }
3198 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
3199 StrCat (ConfigElement, L"VALUE=");
3200 StrCat (ConfigElement, ValueStr);
3201
3202 AppendToMultiString (Config, ConfigElement);
3203
3204 FreePool (ConfigElement);
3205 FreePool (ValueStr);
3206 ConfigElement = NULL;
3207 ValueStr = NULL;
3208
3209 //
3210 // If '\0', parsing is finished. Otherwise skip '&' to continue
3211 //
3212 if (*StringPtr == 0) {
3213 break;
3214 }
3215 AppendToMultiString (Config, L"&");
3216 StringPtr++;
3217
3218 }
3219
3220 if (*StringPtr != 0) {
3221 *Progress = StringPtr - 1;
3222 Status = EFI_INVALID_PARAMETER;
3223 goto Exit;
3224 }
3225
3226 HiiToLower (*Config);
3227 *Progress = StringPtr;
3228 return EFI_SUCCESS;
3229
3230 Exit:
3231 if (*Config != NULL) {
3232 FreePool (*Config);
3233 *Config = NULL;
3234 }
3235 if (ValueStr != NULL) {
3236 FreePool (ValueStr);
3237 }
3238 if (Value != NULL) {
3239 FreePool (Value);
3240 }
3241 if (ConfigElement != NULL) {
3242 FreePool (ConfigElement);
3243 }
3244
3245 return Status;
3246
3247 }
3248
3249
3250 /**
3251 This helper function is to be called by drivers to map configuration strings
3252 to configurations stored in byte array ("block") formats such as UEFI Variables.
3253
3254 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3255 instance.
3256 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3257 format.
3258 @param Block A possibly null array of bytes representing the
3259 current block. Only bytes referenced in the
3260 ConfigResp string in the block are modified. If
3261 this parameter is null or if the *BlockSize
3262 parameter is (on input) shorter than required by
3263 the Configuration string, only the BlockSize
3264 parameter is updated and an appropriate status
3265 (see below) is returned.
3266 @param BlockSize The length of the Block in units of UINT8. On
3267 input, this is the size of the Block. On output,
3268 if successful, contains the index of the last
3269 modified byte in the Block.
3270 @param Progress On return, points to an element of the ConfigResp
3271 string filled in with the offset of the most
3272 recent '&' before the first failing name / value
3273 pair (or the beginning of the string if the
3274 failure is in the first name / value pair) or the
3275 terminating NULL if all was successful.
3276
3277 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3278 terminator at the end of the ConfigResp string.
3279 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3280 points to the first character of ConfigResp.
3281 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3282 Block parameter would result in this type of
3283 error. Progress points to the first character of
3284 ConfigResp.
3285 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3286 value pair. Block is left updated and
3287 Progress points at the '&' preceding the first
3288 non-<BlockName>.
3289 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3290 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3291 Progress points to the "G" in "GUID" of the errant
3292 routing data.
3293
3294 **/
3295 EFI_STATUS
3296 EFIAPI
3297 HiiConfigToBlock (
3298 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3299 IN CONST EFI_STRING ConfigResp,
3300 IN OUT UINT8 *Block,
3301 IN OUT UINTN *BlockSize,
3302 OUT EFI_STRING *Progress
3303 )
3304 {
3305 HII_DATABASE_PRIVATE_DATA *Private;
3306 EFI_STRING StringPtr;
3307 UINTN Length;
3308 EFI_STATUS Status;
3309 UINT8 *TmpBuffer;
3310 UINTN Offset;
3311 UINTN Width;
3312 UINT8 *Value;
3313 UINTN BufferSize;
3314 UINTN MaxBlockSize;
3315
3316 if (This == NULL || BlockSize == NULL || Progress == NULL) {
3317 return EFI_INVALID_PARAMETER;
3318 }
3319
3320 *Progress = ConfigResp;
3321 if (ConfigResp == NULL) {
3322 return EFI_INVALID_PARAMETER;
3323 }
3324
3325 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3326 ASSERT (Private != NULL);
3327
3328 StringPtr = ConfigResp;
3329 BufferSize = *BlockSize;
3330 Value = NULL;
3331 MaxBlockSize = 0;
3332
3333 //
3334 // Jump <ConfigHdr>
3335 //
3336 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3337 *Progress = StringPtr;
3338 Status = EFI_INVALID_PARAMETER;
3339 goto Exit;
3340 }
3341 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
3342 StringPtr++;
3343 }
3344 if (*StringPtr == 0) {
3345 *Progress = StringPtr;
3346 Status = EFI_INVALID_PARAMETER;
3347 goto Exit;
3348 }
3349
3350 while (*StringPtr != L'&' && *StringPtr != 0) {
3351 StringPtr++;
3352 }
3353 if (*StringPtr == 0) {
3354 *Progress = StringPtr;
3355 Status = EFI_INVALID_PARAMETER;
3356 goto Exit;
3357 }
3358 //
3359 // Skip '&'
3360 //
3361 StringPtr++;
3362
3363 //
3364 // Parse each <ConfigElement> if exists
3365 // Only <BlockConfig> format is supported by this help function.
3366 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3367 //
3368 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
3369 StringPtr += StrLen (L"OFFSET=");
3370 //
3371 // Get Offset
3372 //
3373 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3374 if (EFI_ERROR (Status)) {
3375 *Progress = ConfigResp;
3376 goto Exit;
3377 }
3378 Offset = 0;
3379 CopyMem (
3380 &Offset,
3381 TmpBuffer,
3382 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3383 );
3384 FreePool (TmpBuffer);
3385
3386 StringPtr += Length;
3387 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3388 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
3389 Status = EFI_INVALID_PARAMETER;
3390 goto Exit;
3391 }
3392 StringPtr += StrLen (L"&WIDTH=");
3393
3394 //
3395 // Get Width
3396 //
3397 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3398 if (EFI_ERROR (Status)) {
3399 *Progress = ConfigResp;
3400 goto Exit;
3401 }
3402 Width = 0;
3403 CopyMem (
3404 &Width,
3405 TmpBuffer,
3406 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3407 );
3408 FreePool (TmpBuffer);
3409
3410 StringPtr += Length;
3411 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
3412 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
3413 Status = EFI_INVALID_PARAMETER;
3414 goto Exit;
3415 }
3416 StringPtr += StrLen (L"&VALUE=");
3417
3418 //
3419 // Get Value
3420 //
3421 Status = GetValueOfNumber (StringPtr, &Value, &Length);
3422 if (EFI_ERROR (Status)) {
3423 *Progress = ConfigResp;
3424 goto Exit;
3425 }
3426
3427 StringPtr += Length;
3428 if (*StringPtr != 0 && *StringPtr != L'&') {
3429 *Progress = StringPtr - Length - 7;
3430 Status = EFI_INVALID_PARAMETER;
3431 goto Exit;
3432 }
3433
3434 //
3435 // Update the Block with configuration info
3436 //
3437 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
3438 CopyMem (Block + Offset, Value, Width);
3439 }
3440 if (Offset + Width > MaxBlockSize) {
3441 MaxBlockSize = Offset + Width;
3442 }
3443
3444 FreePool (Value);
3445 Value = NULL;
3446
3447 //
3448 // If '\0', parsing is finished. Otherwise skip '&' to continue
3449 //
3450 if (*StringPtr == 0) {
3451 break;
3452 }
3453
3454 StringPtr++;
3455 }
3456
3457 //
3458 // The input string is ConfigAltResp format.
3459 //
3460 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {
3461 *Progress = StringPtr - 1;
3462 Status = EFI_INVALID_PARAMETER;
3463 goto Exit;
3464 }
3465
3466 *Progress = StringPtr + StrLen (StringPtr);
3467 *BlockSize = MaxBlockSize - 1;
3468
3469 if (MaxBlockSize > BufferSize) {
3470 *BlockSize = MaxBlockSize;
3471 if (Block != NULL) {
3472 return EFI_DEVICE_ERROR;
3473 }
3474 }
3475
3476 if (Block == NULL) {
3477 *Progress = ConfigResp;
3478 return EFI_INVALID_PARAMETER;
3479 }
3480
3481 return EFI_SUCCESS;
3482
3483 Exit:
3484
3485 if (Value != NULL) {
3486 FreePool (Value);
3487 }
3488 return Status;
3489 }
3490
3491
3492 /**
3493 This helper function is to be called by drivers to extract portions of
3494 a larger configuration string.
3495
3496 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3497 instance.
3498 @param Configuration A null-terminated Unicode string in
3499 <MultiConfigAltResp> format.
3500 @param Guid A pointer to the GUID value to search for in the
3501 routing portion of the ConfigResp string when
3502 retrieving the requested data. If Guid is NULL,
3503 then all GUID values will be searched for.
3504 @param Name A pointer to the NAME value to search for in the
3505 routing portion of the ConfigResp string when
3506 retrieving the requested data. If Name is NULL,
3507 then all Name values will be searched for.
3508 @param DevicePath A pointer to the PATH value to search for in the
3509 routing portion of the ConfigResp string when
3510 retrieving the requested data. If DevicePath is
3511 NULL, then all DevicePath values will be searched
3512 for.
3513 @param AltCfgId A pointer to the ALTCFG value to search for in the
3514 routing portion of the ConfigResp string when
3515 retrieving the requested data. If this parameter
3516 is NULL, then the current setting will be
3517 retrieved.
3518 @param AltCfgResp A pointer to a buffer which will be allocated by
3519 the function which contains the retrieved string
3520 as requested. This buffer is only allocated if
3521 the call was successful. It is <ConfigResp> format.
3522
3523 @retval EFI_SUCCESS The request succeeded. The requested data was
3524 extracted and placed in the newly allocated
3525 AltCfgResp buffer.
3526 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3527 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3528 @retval EFI_NOT_FOUND Target for the specified routing data was not
3529 found.
3530
3531 **/
3532 EFI_STATUS
3533 EFIAPI
3534 HiiGetAltCfg (
3535 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3536 IN CONST EFI_STRING Configuration,
3537 IN CONST EFI_GUID *Guid,
3538 IN CONST EFI_STRING Name,
3539 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3540 IN CONST UINT16 *AltCfgId,
3541 OUT EFI_STRING *AltCfgResp
3542 )
3543 {
3544 EFI_STATUS Status;
3545 EFI_STRING StringPtr;
3546 EFI_STRING HdrStart;
3547 EFI_STRING HdrEnd;
3548 EFI_STRING TmpPtr;
3549 UINTN Length;
3550 EFI_STRING GuidStr;
3551 EFI_STRING NameStr;
3552 EFI_STRING PathStr;
3553 EFI_STRING AltIdStr;
3554 EFI_STRING Result;
3555 BOOLEAN GuidFlag;
3556 BOOLEAN NameFlag;
3557 BOOLEAN PathFlag;
3558
3559 HdrStart = NULL;
3560 HdrEnd = NULL;
3561 GuidStr = NULL;
3562 NameStr = NULL;
3563 PathStr = NULL;
3564 AltIdStr = NULL;
3565 Result = NULL;
3566 GuidFlag = FALSE;
3567 NameFlag = FALSE;
3568 PathFlag = FALSE;
3569
3570 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
3571 return EFI_INVALID_PARAMETER;
3572 }
3573
3574 StringPtr = Configuration;
3575 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3576 return EFI_INVALID_PARAMETER;
3577 }
3578
3579 //
3580 // Generate the sub string for later matching.
3581 //
3582 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
3583 GenerateSubStr (
3584 L"PATH=",
3585 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3586 (VOID *) DevicePath,
3587 1,
3588 &PathStr
3589 );
3590 if (AltCfgId != NULL) {
3591 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
3592 }
3593 if (Name != NULL) {
3594 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
3595 } else {
3596 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3597 }
3598
3599 while (*StringPtr != 0) {
3600 //
3601 // Try to match the GUID
3602 //
3603 if (!GuidFlag) {
3604 TmpPtr = StrStr (StringPtr, GuidStr);
3605 if (TmpPtr == NULL) {
3606 Status = EFI_NOT_FOUND;
3607 goto Exit;
3608 }
3609 HdrStart = TmpPtr;
3610
3611 //
3612 // Jump to <NameHdr>
3613 //
3614 if (Guid != NULL) {
3615 StringPtr = TmpPtr + StrLen (GuidStr);
3616 } else {
3617 StringPtr = StrStr (TmpPtr, L"NAME=");
3618 if (StringPtr == NULL) {
3619 Status = EFI_NOT_FOUND;
3620 goto Exit;
3621 }
3622 }
3623 GuidFlag = TRUE;
3624 }
3625
3626 //
3627 // Try to match the NAME
3628 //
3629 if (GuidFlag && !NameFlag) {
3630 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
3631 GuidFlag = FALSE;
3632 } else {
3633 //
3634 // Jump to <PathHdr>
3635 //
3636 if (Name != NULL) {
3637 StringPtr += StrLen (NameStr);
3638 } else {
3639 StringPtr = StrStr (StringPtr, L"PATH=");
3640 if (StringPtr == NULL) {
3641 Status = EFI_NOT_FOUND;
3642 goto Exit;
3643 }
3644 }
3645 NameFlag = TRUE;
3646 }
3647 }
3648
3649 //
3650 // Try to match the DevicePath
3651 //
3652 if (GuidFlag && NameFlag && !PathFlag) {
3653 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
3654 GuidFlag = FALSE;
3655 NameFlag = FALSE;
3656 } else {
3657 //
3658 // Jump to '&' before <DescHdr> or <ConfigBody>
3659 //
3660 if (DevicePath != NULL) {
3661 StringPtr += StrLen (PathStr);
3662 } else {
3663 StringPtr = StrStr (StringPtr, L"&");
3664 if (StringPtr == NULL) {
3665 Status = EFI_NOT_FOUND;
3666 goto Exit;
3667 }
3668 StringPtr ++;
3669 }
3670 PathFlag = TRUE;
3671 HdrEnd = StringPtr;
3672 }
3673 }
3674
3675 //
3676 // Try to match the AltCfgId
3677 //
3678 if (GuidFlag && NameFlag && PathFlag) {
3679 if (AltCfgId == NULL) {
3680 //
3681 // Return Current Setting when AltCfgId is NULL.
3682 //
3683 Status = OutputConfigBody (StringPtr, &Result);
3684 goto Exit;
3685 }
3686 //
3687 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3688 //
3689 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
3690 GuidFlag = FALSE;
3691 NameFlag = FALSE;
3692 PathFlag = FALSE;
3693 } else {
3694 //
3695 // Skip AltIdStr and &
3696 //
3697 StringPtr = StringPtr + StrLen (AltIdStr);
3698 Status = OutputConfigBody (StringPtr, &Result);
3699 goto Exit;
3700 }
3701 }
3702 }
3703
3704 Status = EFI_NOT_FOUND;
3705
3706 Exit:
3707 *AltCfgResp = NULL;
3708 if (!EFI_ERROR (Status) && (Result != NULL)) {
3709 //
3710 // Copy the <ConfigHdr> and <ConfigBody>
3711 //
3712 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
3713 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3714 if (*AltCfgResp == NULL) {
3715 Status = EFI_OUT_OF_RESOURCES;
3716 } else {
3717 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
3718 StrCat (*AltCfgResp, Result);
3719 Status = EFI_SUCCESS;
3720 }
3721 }
3722
3723 if (GuidStr != NULL) {
3724 FreePool (GuidStr);
3725 }
3726 if (NameStr != NULL) {
3727 FreePool (NameStr);
3728 }
3729 if (PathStr != NULL) {
3730 FreePool (PathStr);
3731 }
3732 if (AltIdStr != NULL) {
3733 FreePool (AltIdStr);
3734 }
3735 if (Result != NULL) {
3736 FreePool (Result);
3737 }
3738
3739 return Status;
3740
3741 }
3742
3743