]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg/SetupBrowser: Call submit callback function when no failure
[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 - 2016, 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 StrCpyS (Str, Length, String);
256
257 StringHeader = Str + StrLen (String);
258 TemString = (CHAR16 *) StringHeader;
259
260 switch (Flag) {
261 case 1:
262 //
263 // Convert Buffer to Hex String in reverse order
264 //
265 TemBuffer = ((UINT8 *) Buffer);
266 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
267 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
268 }
269 break;
270 case 2:
271 //
272 // Check buffer is enough
273 //
274 TemName = (CHAR16 *) Buffer;
275 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
276 //
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
278 //
279 for (; *TemName != L'\0'; TemName++) {
280 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
281 }
282 break;
283 case 3:
284 //
285 // Convert Buffer to Hex String
286 //
287 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
288 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
289 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
290 }
291 break;
292 default:
293 break;
294 }
295
296 //
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
298 //
299 StrCatS (Str, Length, L"&");
300 HiiToLower (Str);
301
302 *SubStr = Str;
303 }
304
305
306 /**
307 Retrieve the <ConfigBody> from String then output it.
308
309 This is a internal function.
310
311 @param String A sub string of a configuration string in
312 <MultiConfigAltResp> format.
313 @param ConfigBody Points to the output string. It's caller's
314 responsibility to free this buffer.
315
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
318 @retval EFI_SUCCESS All existing storage is exported.
319
320 **/
321 EFI_STATUS
322 OutputConfigBody (
323 IN EFI_STRING String,
324 OUT EFI_STRING *ConfigBody
325 )
326 {
327 EFI_STRING TmpPtr;
328 EFI_STRING Result;
329 UINTN Length;
330
331 if (String == NULL || ConfigBody == NULL) {
332 return EFI_INVALID_PARAMETER;
333 }
334
335 //
336 // The setting information should start OFFSET, not ALTCFG.
337 //
338 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER;
340 }
341
342 TmpPtr = StrStr (String, L"GUID=");
343 if (TmpPtr == NULL) {
344 //
345 // It is the last <ConfigResp> of the incoming configuration string.
346 //
347 Result = AllocateCopyPool (StrSize (String), String);
348 if (Result == NULL) {
349 return EFI_OUT_OF_RESOURCES;
350 } else {
351 *ConfigBody = Result;
352 return EFI_SUCCESS;
353 }
354 }
355
356 Length = TmpPtr - String;
357 if (Length == 0) {
358 return EFI_NOT_FOUND;
359 }
360 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
361 if (Result == NULL) {
362 return EFI_OUT_OF_RESOURCES;
363 }
364
365 *(Result + Length - 1) = 0;
366 *ConfigBody = Result;
367 return EFI_SUCCESS;
368 }
369
370 /**
371 Append a string to a multi-string format.
372
373 This is a internal function.
374
375 @param MultiString String in <MultiConfigRequest>,
376 <MultiConfigAltResp>, or <MultiConfigResp>. On
377 input, the buffer length of this string is
378 MAX_STRING_LENGTH. On output, the buffer length
379 might be updated.
380 @param AppendString NULL-terminated Unicode string.
381
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
384
385 **/
386 EFI_STATUS
387 AppendToMultiString (
388 IN OUT EFI_STRING *MultiString,
389 IN EFI_STRING AppendString
390 )
391 {
392 UINTN AppendStringSize;
393 UINTN MultiStringSize;
394 UINTN MaxLen;
395
396 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
397 return EFI_INVALID_PARAMETER;
398 }
399
400 AppendStringSize = StrSize (AppendString);
401 MultiStringSize = StrSize (*MultiString);
402 MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
403
404 //
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
406 //
407 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
408 MultiStringSize > MAX_STRING_LENGTH) {
409 *MultiString = (EFI_STRING) ReallocatePool (
410 MultiStringSize,
411 MultiStringSize + AppendStringSize,
412 (VOID *) (*MultiString)
413 );
414 MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
415 ASSERT (*MultiString != NULL);
416 }
417 //
418 // Append the incoming string
419 //
420 StrCatS (*MultiString, MaxLen, AppendString);
421
422 return EFI_SUCCESS;
423 }
424
425
426 /**
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
428 or WIDTH or VALUE.
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
430
431 This is a internal function.
432
433 @param StringPtr String in <BlockConfig> format and points to the
434 first character of <Number>.
435 @param Number The output value. Caller takes the responsibility
436 to free memory.
437 @param Len Length of the <Number>, in characters.
438
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
440 structures.
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 successfully.
443
444 **/
445 EFI_STATUS
446 GetValueOfNumber (
447 IN EFI_STRING StringPtr,
448 OUT UINT8 **Number,
449 OUT UINTN *Len
450 )
451 {
452 EFI_STRING TmpPtr;
453 UINTN Length;
454 EFI_STRING Str;
455 UINT8 *Buf;
456 EFI_STATUS Status;
457 UINT8 DigitUint8;
458 UINTN Index;
459 CHAR16 TemStr[2];
460
461 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
462 return EFI_INVALID_PARAMETER;
463 }
464
465 Buf = NULL;
466
467 TmpPtr = StringPtr;
468 while (*StringPtr != L'\0' && *StringPtr != L'&') {
469 StringPtr++;
470 }
471 *Len = StringPtr - TmpPtr;
472 Length = *Len + 1;
473
474 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
475 if (Str == NULL) {
476 Status = EFI_OUT_OF_RESOURCES;
477 goto Exit;
478 }
479 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
480 *(Str + *Len) = L'\0';
481
482 Length = (Length + 1) / 2;
483 Buf = (UINT8 *) AllocateZeroPool (Length);
484 if (Buf == NULL) {
485 Status = EFI_OUT_OF_RESOURCES;
486 goto Exit;
487 }
488
489 Length = *Len;
490 ZeroMem (TemStr, sizeof (TemStr));
491 for (Index = 0; Index < Length; Index ++) {
492 TemStr[0] = Str[Length - Index - 1];
493 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
494 if ((Index & 1) == 0) {
495 Buf [Index/2] = DigitUint8;
496 } else {
497 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
498 }
499 }
500
501 *Number = Buf;
502 Status = EFI_SUCCESS;
503
504 Exit:
505 if (Str != NULL) {
506 FreePool (Str);
507 }
508
509 return Status;
510 }
511
512 /**
513 To find the BlockName in the string with same value.
514
515 @param String Pointer to a Null-terminated Unicode string.
516 @param BlockName Pointer to a Null-terminated Unicode string to search for.
517 @param Buffer Pointer to the value correspond to the BlockName.
518 @param Found The Block whether has been found.
519 @param BufferLen The length of the buffer.
520
521 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
522 @retval EFI_SUCCESS The function finishes successfully.
523
524 **/
525 EFI_STATUS
526 FindSameBlockElement(
527 IN EFI_STRING String,
528 IN EFI_STRING BlockName,
529 IN UINT8 *Buffer,
530 OUT BOOLEAN *Found,
531 IN UINTN BufferLen
532 )
533 {
534 EFI_STRING BlockPtr;
535 UINTN Length;
536 UINT8 *TempBuffer;
537 EFI_STATUS Status;
538
539 TempBuffer = NULL;
540 *Found = FALSE;
541 BlockPtr = StrStr (String, BlockName);
542
543 while (BlockPtr != NULL) {
544 BlockPtr += StrLen (BlockName);
545 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
546 if (EFI_ERROR (Status)) {
547 return Status;
548 }
549 ASSERT (TempBuffer != NULL);
550 if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
551 *Found = TRUE;
552 return EFI_SUCCESS;
553 } else {
554 FreePool (TempBuffer);
555 TempBuffer = NULL;
556 BlockPtr = StrStr (BlockPtr + 1, BlockName);
557 }
558 }
559 return EFI_SUCCESS;
560 }
561
562 /**
563 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
564 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
565
566 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
567 <MultiConfigAltResp> format. The default value
568 string may contain more than one ConfigAltResp
569 string for the different varstore buffer.
570 @param ConfigAltResp Pointer to a null-terminated Unicode string in
571 <ConfigAltResp> format.
572 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
573 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
574
575 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
576 @retval EFI_SUCCESS The function finishes successfully.
577
578 **/
579 EFI_STATUS
580 CompareBlockElementDefault (
581 IN EFI_STRING DefaultAltCfgResp,
582 IN OUT EFI_STRING *ConfigAltResp,
583 IN EFI_STRING AltConfigHdr,
584 IN OUT BOOLEAN *ConfigAltRespChanged
585 )
586 {
587 EFI_STATUS Status;
588 EFI_STRING BlockPtr;
589 EFI_STRING BlockPtrStart;
590 EFI_STRING StringPtr;
591 EFI_STRING AppendString;
592 EFI_STRING AltConfigHdrPtr;
593 UINT8 *TempBuffer;
594 UINTN OffsetLength;
595 UINTN AppendSize;
596 UINTN TotalSize;
597 BOOLEAN FoundOffset;
598
599 AppendString = NULL;
600 TempBuffer = NULL;
601 //
602 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
603 //
604 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
605 ASSERT (AltConfigHdrPtr != NULL);
606 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
607 //
608 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
609 //
610 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
611 ASSERT (StringPtr != NULL);
612
613 while (BlockPtr != NULL) {
614 //
615 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
616 //
617 BlockPtrStart = BlockPtr;
618 BlockPtr += StrLen (L"&OFFSET=");
619 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
620 if (EFI_ERROR (Status)) {
621 Status = EFI_OUT_OF_RESOURCES;
622 goto Exit;
623 }
624 //
625 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
626 //
627 Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
628 if (TempBuffer != NULL) {
629 FreePool (TempBuffer);
630 TempBuffer = NULL;
631 }
632 if (EFI_ERROR (Status)) {
633 Status = EFI_OUT_OF_RESOURCES;
634 goto Exit;
635 }
636 if (!FoundOffset) {
637 //
638 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
639 // Calculate the size of <BlockConfig>.
640 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
641 //
642 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
643 if (BlockPtr != NULL) {
644 AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
645 } else {
646 AppendSize = StrSize (BlockPtrStart);
647 }
648 //
649 // Copy the <BlockConfig> to AppendString.
650 //
651 if (AppendString == NULL) {
652 AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
653 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
654 } else {
655 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
656 AppendString = (EFI_STRING) ReallocatePool (
657 StrSize (AppendString),
658 TotalSize,
659 AppendString
660 );
661 if (AppendString == NULL) {
662 Status = EFI_OUT_OF_RESOURCES;
663 goto Exit;
664 }
665 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
666 }
667 } else {
668 //
669 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
670 //
671 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
672 }
673 }
674
675 if (AppendString != NULL) {
676 //
677 // Reallocate ConfigAltResp to copy the AppendString.
678 //
679 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
680 *ConfigAltResp = (EFI_STRING) ReallocatePool (
681 StrSize (*ConfigAltResp),
682 TotalSize,
683 *ConfigAltResp
684 );
685 if (*ConfigAltResp == NULL) {
686 Status = EFI_OUT_OF_RESOURCES;
687 goto Exit;
688 }
689 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
690 *ConfigAltRespChanged = TRUE;
691 }
692
693 Status = EFI_SUCCESS;
694
695 Exit:
696 if (AppendString != NULL) {
697 FreePool (AppendString);
698 }
699
700 return Status;
701 }
702
703 /**
704 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
705 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
706
707 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
708 <MultiConfigAltResp> format. The default value
709 string may contain more than one ConfigAltResp
710 string for the different varstore buffer.
711 @param ConfigAltResp Pointer to a null-terminated Unicode string in
712 <ConfigAltResp> format.
713 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
714 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
715
716 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
717 @retval EFI_SUCCESS The function finishes successfully.
718
719 **/
720 EFI_STATUS
721 CompareNameElementDefault (
722 IN EFI_STRING DefaultAltCfgResp,
723 IN OUT EFI_STRING *ConfigAltResp,
724 IN EFI_STRING AltConfigHdr,
725 IN OUT BOOLEAN *ConfigAltRespChanged
726 )
727 {
728 EFI_STATUS Status;
729 EFI_STRING NvConfigPtr;
730 EFI_STRING NvConfigStart;
731 EFI_STRING NvConfigValuePtr;
732 EFI_STRING StringPtr;
733 EFI_STRING NvConfigExist;
734 EFI_STRING AppendString;
735 CHAR16 TempChar;
736 UINTN AppendSize;
737 UINTN TotalSize;
738
739 AppendString = NULL;
740 NvConfigExist = NULL;
741 //
742 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
743 //
744 NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
745 ASSERT (NvConfigPtr != NULL);
746 NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&");
747 //
748 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
749 //
750 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
751 ASSERT (StringPtr != NULL);
752 StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
753 ASSERT (StringPtr != NULL);
754
755 while (NvConfigPtr != NULL) {
756 //
757 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
758 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
759 //
760 NvConfigStart = NvConfigPtr;
761 NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
762 ASSERT (NvConfigValuePtr != NULL);
763 TempChar = *NvConfigValuePtr;
764 *NvConfigValuePtr = L'\0';
765 //
766 // Get the <Label> with AltConfigHdr in ConfigAltResp.
767 //
768 NvConfigExist = StrStr (StringPtr, NvConfigPtr);
769 if (NvConfigExist == NULL) {
770 //
771 // Don't find same <Label> in ConfigAltResp.
772 // Calculate the size of <NvConfig>.
773 //
774 *NvConfigValuePtr = TempChar;
775 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
776 if (NvConfigPtr != NULL) {
777 AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
778 } else {
779 AppendSize = StrSize (NvConfigStart);
780 }
781 //
782 // Copy the <NvConfig> to AppendString.
783 //
784 if (AppendString == NULL) {
785 AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
786 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
787 } else {
788 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
789 AppendString = (EFI_STRING) ReallocatePool (
790 StrSize (AppendString),
791 TotalSize,
792 AppendString
793 );
794 if (AppendString == NULL) {
795 Status = EFI_OUT_OF_RESOURCES;
796 goto Exit;
797 }
798 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
799 }
800 } else {
801 //
802 // To find next <Label> in DefaultAltCfgResp.
803 //
804 *NvConfigValuePtr = TempChar;
805 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
806 }
807 }
808 if (AppendString != NULL) {
809 //
810 // Reallocate ConfigAltResp to copy the AppendString.
811 //
812 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
813 *ConfigAltResp = (EFI_STRING) ReallocatePool (
814 StrSize (*ConfigAltResp),
815 StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
816 *ConfigAltResp
817 );
818 if (*ConfigAltResp == NULL) {
819 Status = EFI_OUT_OF_RESOURCES;
820 goto Exit;
821 }
822 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
823 *ConfigAltRespChanged = TRUE;
824 }
825 Status = EFI_SUCCESS;
826
827 Exit:
828 if (AppendString != NULL) {
829 FreePool (AppendString);
830 }
831 return Status;
832 }
833
834 /**
835 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
836 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
837
838 @param AltCfgResp Pointer to a null-terminated Unicode string in
839 <ConfigAltResp> format.
840 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
841 <MultiConfigAltResp> format. The default value
842 string may contain more than one ConfigAltResp
843 string for the different varstore buffer.
844 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
845
846 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
847 structures.
848 @retval EFI_SUCCESS The function finishes successfully.
849
850 **/
851 EFI_STATUS
852 CompareAndMergeDefaultString (
853 IN OUT EFI_STRING *AltCfgResp,
854 IN EFI_STRING DefaultAltCfgResp,
855 IN EFI_STRING AltConfigHdr
856 )
857 {
858 EFI_STATUS Status;
859 EFI_STRING AltCfgRespBackup;
860 EFI_STRING AltConfigHdrPtr;
861 EFI_STRING AltConfigHdrPtrNext;
862 EFI_STRING ConfigAltResp;
863 EFI_STRING StringPtr;
864 EFI_STRING StringPtrNext;
865 EFI_STRING BlockPtr;
866 UINTN ReallocateSize;
867 CHAR16 TempChar;
868 CHAR16 TempCharA;
869 BOOLEAN ConfigAltRespChanged;
870
871 Status = EFI_OUT_OF_RESOURCES;
872 BlockPtr = NULL;
873 AltConfigHdrPtrNext = NULL;
874 StringPtrNext = NULL;
875 ConfigAltResp = NULL;
876 AltCfgRespBackup = NULL;
877 TempChar = L'\0';
878 TempCharA = L'\0';
879 ConfigAltRespChanged = FALSE;
880
881 //
882 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
883 //
884 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
885 ASSERT (AltConfigHdrPtr != NULL);
886 AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
887 if (AltConfigHdrPtrNext != NULL) {
888 TempChar = *AltConfigHdrPtrNext;
889 *AltConfigHdrPtrNext = L'\0';
890 }
891 //
892 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
893 //
894 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
895 StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
896 if (StringPtrNext != NULL) {
897 TempCharA = *StringPtrNext;
898 *StringPtrNext = L'\0';
899 }
900 //
901 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
902 //
903 ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
904 if (ConfigAltResp == NULL) {
905 goto Exit;
906 }
907 //
908 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
909 //
910 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
911 if (BlockPtr != NULL) {
912 //
913 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
914 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
915 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
916 //
917 Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
918 if (EFI_ERROR(Status)) {
919 goto Exit;
920 }
921 } else {
922 //
923 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
924 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
925 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
926 //
927 Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
928 if (EFI_ERROR(Status)) {
929 goto Exit;
930 }
931 }
932 //
933 // Restore the AltCfgResp.
934 //
935 if (StringPtrNext != NULL) {
936 *StringPtrNext = TempCharA;
937 }
938
939 //
940 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
941 //
942 if (!ConfigAltRespChanged) {
943 Status = EFI_SUCCESS;
944 goto Exit;
945 }
946 //
947 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
948 //
949 if (StringPtrNext != NULL) {
950 ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
951 } else {
952 ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
953 }
954
955 AltCfgRespBackup = (EFI_STRING) AllocateZeroPool (ReallocateSize);
956 if (AltCfgRespBackup == NULL) {
957 goto Exit;
958 }
959
960 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
961 if (StringPtrNext != NULL) {
962 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
963 }
964
965 FreePool (*AltCfgResp);
966 *AltCfgResp = AltCfgRespBackup;
967
968 Status = EFI_SUCCESS;
969
970 Exit:
971 if (ConfigAltResp != NULL) {
972 FreePool(ConfigAltResp);
973 }
974 //
975 // Restore the DefaultAltCfgResp.
976 //
977 if ( AltConfigHdrPtrNext != NULL) {
978 *AltConfigHdrPtrNext = TempChar;
979 AltConfigHdrPtrNext = NULL;
980 }
981
982 return Status;
983 }
984
985 /**
986 This function merges DefaultAltCfgResp string into AltCfgResp string for
987 the missing AltCfgId in AltCfgResq.
988
989 @param AltCfgResp Pointer to a null-terminated Unicode string in
990 <ConfigAltResp> format. The default value string
991 will be merged into it.
992 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
993 <MultiConfigAltResp> format. The default value
994 string may contain more than one ConfigAltResp
995 string for the different varstore buffer.
996
997 @retval EFI_SUCCESS The merged string returns.
998 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
999 **/
1000 EFI_STATUS
1001 EFIAPI
1002 MergeDefaultString (
1003 IN OUT EFI_STRING *AltCfgResp,
1004 IN EFI_STRING DefaultAltCfgResp
1005 )
1006 {
1007 EFI_STRING StringPtrDefault;
1008 EFI_STRING StringPtrEnd;
1009 CHAR16 TempChar;
1010 EFI_STRING StringPtr;
1011 EFI_STRING AltConfigHdr;
1012 UINTN HeaderLength;
1013 UINTN SizeAltCfgResp;
1014 UINTN MaxLen;
1015 UINTN TotalSize;
1016
1017 if (*AltCfgResp == NULL) {
1018 return EFI_INVALID_PARAMETER;
1019 }
1020
1021 //
1022 // Get the requestr ConfigHdr
1023 //
1024 SizeAltCfgResp = 0;
1025 StringPtr = *AltCfgResp;
1026
1027 //
1028 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1029 //
1030 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
1031 return EFI_INVALID_PARAMETER;
1032 }
1033 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
1034 StringPtr++;
1035 }
1036 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
1037 StringPtr++;
1038 }
1039 if (*StringPtr == L'\0') {
1040 return EFI_INVALID_PARAMETER;
1041 }
1042 StringPtr += StrLen (L"&PATH=");
1043 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1044 StringPtr ++;
1045 }
1046 HeaderLength = StringPtr - *AltCfgResp;
1047
1048 //
1049 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1050 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1051 //
1052 MaxLen = 1 + HeaderLength + 8 + 4 + 1;
1053 AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
1054 if (AltConfigHdr == NULL) {
1055 return EFI_OUT_OF_RESOURCES;
1056 }
1057 StrCpyS (AltConfigHdr, MaxLen, L"&");
1058 StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
1059 StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
1060 HeaderLength = StrLen (AltConfigHdr);
1061
1062 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
1063 while (StringPtrDefault != NULL) {
1064 //
1065 // Get AltCfg Name
1066 //
1067 StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
1068 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
1069
1070 //
1071 // Append the found default value string to the input AltCfgResp
1072 //
1073 if (StringPtr == NULL) {
1074 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
1075 SizeAltCfgResp = StrSize (*AltCfgResp);
1076 if (StringPtrEnd == NULL) {
1077 //
1078 // No more default string is found.
1079 //
1080 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1081 *AltCfgResp = (EFI_STRING) ReallocatePool (
1082 SizeAltCfgResp,
1083 TotalSize,
1084 (VOID *) (*AltCfgResp)
1085 );
1086 if (*AltCfgResp == NULL) {
1087 FreePool (AltConfigHdr);
1088 return EFI_OUT_OF_RESOURCES;
1089 }
1090 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1091 break;
1092 } else {
1093 TempChar = *StringPtrEnd;
1094 *StringPtrEnd = L'\0';
1095 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1096 *AltCfgResp = (EFI_STRING) ReallocatePool (
1097 SizeAltCfgResp,
1098 TotalSize,
1099 (VOID *) (*AltCfgResp)
1100 );
1101 if (*AltCfgResp == NULL) {
1102 FreePool (AltConfigHdr);
1103 return EFI_OUT_OF_RESOURCES;
1104 }
1105 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1106 *StringPtrEnd = TempChar;
1107 }
1108 } else {
1109 //
1110 // The AltCfgResp contains <AltCfgResp>.
1111 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1112 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1113 //
1114 CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
1115 }
1116
1117 //
1118 // Find next AltCfg String
1119 //
1120 *(AltConfigHdr + HeaderLength) = L'\0';
1121 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
1122 }
1123
1124 FreePool (AltConfigHdr);
1125 return EFI_SUCCESS;
1126 }
1127
1128 /**
1129 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1130
1131 @param BlockData The BlockData is updated to add new default value.
1132 @param DefaultValueData The DefaultValue is added.
1133
1134 **/
1135 VOID
1136 InsertDefaultValue (
1137 IN IFR_BLOCK_DATA *BlockData,
1138 IN IFR_DEFAULT_DATA *DefaultValueData
1139 )
1140 {
1141 LIST_ENTRY *Link;
1142 IFR_DEFAULT_DATA *DefaultValueArray;
1143 LIST_ENTRY *DefaultLink;
1144
1145 DefaultLink = &BlockData->DefaultValueEntry;
1146
1147 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
1148 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
1149 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
1150 //
1151 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1152 //
1153 if (DefaultValueData->Type > DefaultValueArray->Type) {
1154 //
1155 // Update the default value array in BlockData.
1156 //
1157 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
1158 DefaultValueArray->Type = DefaultValueData->Type;
1159 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
1160 }
1161 return;
1162 }
1163 }
1164
1165 //
1166 // Insert new default value data in tail.
1167 //
1168 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1169 ASSERT (DefaultValueArray != NULL);
1170 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
1171 InsertTailList (Link, &DefaultValueArray->Entry);
1172 }
1173
1174 /**
1175 This function inserts new BlockData into the block link
1176
1177 @param BlockLink The list entry points to block array.
1178 @param BlockData The point to BlockData is added.
1179
1180 **/
1181 VOID
1182 InsertBlockData (
1183 IN LIST_ENTRY *BlockLink,
1184 IN IFR_BLOCK_DATA **BlockData
1185 )
1186 {
1187 LIST_ENTRY *Link;
1188 IFR_BLOCK_DATA *BlockArray;
1189 IFR_BLOCK_DATA *BlockSingleData;
1190
1191 BlockSingleData = *BlockData;
1192
1193 if (BlockSingleData->Name != NULL) {
1194 InsertTailList (BlockLink, &BlockSingleData->Entry);
1195 return;
1196 }
1197
1198 //
1199 // Insert block data in its Offset and Width order.
1200 //
1201 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
1202 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1203 if (BlockArray->Offset == BlockSingleData->Offset) {
1204 if (BlockArray->Width > BlockSingleData->Width) {
1205 //
1206 // Insert this block data in the front of block array
1207 //
1208 InsertTailList (Link, &BlockSingleData->Entry);
1209 return;
1210 }
1211
1212 if (BlockArray->Width == BlockSingleData->Width) {
1213 //
1214 // The same block array has been added.
1215 //
1216 if (BlockSingleData != BlockArray) {
1217 FreePool (BlockSingleData);
1218 *BlockData = BlockArray;
1219 }
1220 return;
1221 }
1222 } else if (BlockArray->Offset > BlockSingleData->Offset) {
1223 //
1224 // Insert new block data in the front of block array
1225 //
1226 InsertTailList (Link, &BlockSingleData->Entry);
1227 return;
1228 }
1229 }
1230
1231 //
1232 // Add new block data into the tail.
1233 //
1234 InsertTailList (Link, &BlockSingleData->Entry);
1235 }
1236
1237 /**
1238 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1239 of languages that an HII handle in the HII Database supports. The returned
1240 string is allocated using AllocatePool(). The caller is responsible for freeing
1241 the returned string using FreePool(). The format of the returned string follows
1242 the language format assumed the HII Database.
1243
1244 If HiiHandle is NULL, then ASSERT().
1245
1246 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1247
1248 @retval NULL HiiHandle is not registered in the HII database
1249 @retval NULL There are not enough resources available to retrieve the suported
1250 languages.
1251 @retval NULL The list of suported languages could not be retrieved.
1252 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1253
1254 **/
1255 CHAR8 *
1256 GetSupportedLanguages (
1257 IN EFI_HII_HANDLE HiiHandle
1258 )
1259 {
1260 EFI_STATUS Status;
1261 UINTN LanguageSize;
1262 CHAR8 TempSupportedLanguages;
1263 CHAR8 *SupportedLanguages;
1264
1265 ASSERT (HiiHandle != NULL);
1266
1267 //
1268 // Retrieve the size required for the supported languages buffer.
1269 //
1270 LanguageSize = 0;
1271 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
1272
1273 //
1274 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1275 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1276 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1277 // in the HII Database
1278 //
1279 if (Status != EFI_BUFFER_TOO_SMALL) {
1280 //
1281 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1282 //
1283 return NULL;
1284 }
1285
1286 //
1287 // Allocate the supported languages buffer.
1288 //
1289 SupportedLanguages = AllocateZeroPool (LanguageSize);
1290 if (SupportedLanguages == NULL) {
1291 //
1292 // Return NULL if allocation fails.
1293 //
1294 return NULL;
1295 }
1296
1297 //
1298 // Retrieve the supported languages string
1299 //
1300 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
1301 if (EFI_ERROR (Status)) {
1302 //
1303 // Free the buffer and return NULL if the supported languages can not be retrieved.
1304 //
1305 FreePool (SupportedLanguages);
1306 return NULL;
1307 }
1308
1309 //
1310 // Return the Null-terminated ASCII string of supported languages
1311 //
1312 return SupportedLanguages;
1313 }
1314
1315 /**
1316 Retrieves a string from a string package.
1317
1318 If HiiHandle is NULL, then ASSERT().
1319 If StringId is 0, then ASSET.
1320
1321 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1322 @param[in] StringId The identifier of the string to retrieved from the string
1323 package associated with HiiHandle.
1324
1325 @retval NULL The string specified by StringId is not present in the string package.
1326 @retval Other The string was returned.
1327
1328 **/
1329 EFI_STRING
1330 InternalGetString (
1331 IN EFI_HII_HANDLE HiiHandle,
1332 IN EFI_STRING_ID StringId
1333 )
1334 {
1335 EFI_STATUS Status;
1336 UINTN StringSize;
1337 CHAR16 TempString;
1338 EFI_STRING String;
1339 CHAR8 *SupportedLanguages;
1340 CHAR8 *PlatformLanguage;
1341 CHAR8 *BestLanguage;
1342 CHAR8 *Language;
1343
1344 ASSERT (HiiHandle != NULL);
1345 ASSERT (StringId != 0);
1346
1347 //
1348 // Initialize all allocated buffers to NULL
1349 //
1350 SupportedLanguages = NULL;
1351 PlatformLanguage = NULL;
1352 BestLanguage = NULL;
1353 String = NULL;
1354 Language = "";
1355
1356 //
1357 // Get the languages that the package specified by HiiHandle supports
1358 //
1359 SupportedLanguages = GetSupportedLanguages (HiiHandle);
1360 if (SupportedLanguages == NULL) {
1361 goto Error;
1362 }
1363
1364 //
1365 // Get the current platform language setting
1366 //
1367 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
1368
1369 //
1370 // Get the best matching language from SupportedLanguages
1371 //
1372 BestLanguage = GetBestLanguage (
1373 SupportedLanguages,
1374 FALSE, // RFC 4646 mode
1375 Language, // Highest priority
1376 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
1377 SupportedLanguages, // Lowest priority
1378 NULL
1379 );
1380 if (BestLanguage == NULL) {
1381 goto Error;
1382 }
1383
1384 //
1385 // Retrieve the size of the string in the string package for the BestLanguage
1386 //
1387 StringSize = 0;
1388 Status = mPrivate.HiiString.GetString (
1389 &mPrivate.HiiString,
1390 BestLanguage,
1391 HiiHandle,
1392 StringId,
1393 &TempString,
1394 &StringSize,
1395 NULL
1396 );
1397 //
1398 // If GetString() returns EFI_SUCCESS for a zero size,
1399 // then there are no supported languages registered for HiiHandle. If GetString()
1400 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1401 // in the HII Database
1402 //
1403 if (Status != EFI_BUFFER_TOO_SMALL) {
1404 goto Error;
1405 }
1406
1407 //
1408 // Allocate a buffer for the return string
1409 //
1410 String = AllocateZeroPool (StringSize);
1411 if (String == NULL) {
1412 goto Error;
1413 }
1414
1415 //
1416 // Retrieve the string from the string package
1417 //
1418 Status = mPrivate.HiiString.GetString (
1419 &mPrivate.HiiString,
1420 BestLanguage,
1421 HiiHandle,
1422 StringId,
1423 String,
1424 &StringSize,
1425 NULL
1426 );
1427 if (EFI_ERROR (Status)) {
1428 //
1429 // Free the buffer and return NULL if the supported languages can not be retrieved.
1430 //
1431 FreePool (String);
1432 String = NULL;
1433 }
1434
1435 Error:
1436 //
1437 // Free allocated buffers
1438 //
1439 if (SupportedLanguages != NULL) {
1440 FreePool (SupportedLanguages);
1441 }
1442 if (PlatformLanguage != NULL) {
1443 FreePool (PlatformLanguage);
1444 }
1445 if (BestLanguage != NULL) {
1446 FreePool (BestLanguage);
1447 }
1448
1449 //
1450 // Return the Null-terminated Unicode string
1451 //
1452 return String;
1453 }
1454
1455 /**
1456 This function checks VarOffset and VarWidth is in the block range.
1457
1458 @param RequestBlockArray The block array is to be checked.
1459 @param VarOffset Offset of var to the structure
1460 @param VarWidth Width of var.
1461 @param IsNameValueType Whether this varstore is name/value varstore or not.
1462 @param HiiHandle Hii handle for this hii package.
1463
1464 @retval TRUE This Var is in the block range.
1465 @retval FALSE This Var is not in the block range.
1466 **/
1467 BOOLEAN
1468 BlockArrayCheck (
1469 IN IFR_BLOCK_DATA *RequestBlockArray,
1470 IN UINT16 VarOffset,
1471 IN UINT16 VarWidth,
1472 IN BOOLEAN IsNameValueType,
1473 IN EFI_HII_HANDLE HiiHandle
1474 )
1475 {
1476 LIST_ENTRY *Link;
1477 IFR_BLOCK_DATA *BlockData;
1478 EFI_STRING Name;
1479
1480 //
1481 // No Request Block array, all vars are got.
1482 //
1483 if (RequestBlockArray == NULL) {
1484 return TRUE;
1485 }
1486
1487 //
1488 // Check the input var is in the request block range.
1489 //
1490 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
1491 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1492
1493 if (IsNameValueType) {
1494 Name = InternalGetString (HiiHandle, VarOffset);
1495 ASSERT (Name != NULL);
1496
1497 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
1498 FreePool (Name);
1499 return TRUE;
1500 }
1501 FreePool (Name);
1502 } else {
1503 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
1504 return TRUE;
1505 }
1506 }
1507 }
1508
1509 return FALSE;
1510 }
1511
1512 /**
1513 Get form package data from data base.
1514
1515 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1516 @param HiiFormPackage The buffer saves the package data.
1517 @param PackageSize The buffer size of the package data.
1518
1519 **/
1520 EFI_STATUS
1521 GetFormPackageData (
1522 IN HII_DATABASE_RECORD *DataBaseRecord,
1523 IN OUT UINT8 **HiiFormPackage,
1524 OUT UINTN *PackageSize
1525 )
1526 {
1527 EFI_STATUS Status;
1528 UINTN Size;
1529 UINTN ResultSize;
1530
1531 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
1532 return EFI_INVALID_PARAMETER;
1533 }
1534
1535 Size = 0;
1536 ResultSize = 0;
1537 //
1538 // 0. Get Hii Form Package by HiiHandle
1539 //
1540 Status = ExportFormPackages (
1541 &mPrivate,
1542 DataBaseRecord->Handle,
1543 DataBaseRecord->PackageList,
1544 0,
1545 Size,
1546 HiiFormPackage,
1547 &ResultSize
1548 );
1549 if (EFI_ERROR (Status)) {
1550 return Status;
1551 }
1552
1553 (*HiiFormPackage) = AllocatePool (ResultSize);
1554 if (*HiiFormPackage == NULL) {
1555 Status = EFI_OUT_OF_RESOURCES;
1556 return Status;
1557 }
1558
1559 //
1560 // Get HiiFormPackage by HiiHandle
1561 //
1562 Size = ResultSize;
1563 ResultSize = 0;
1564 Status = ExportFormPackages (
1565 &mPrivate,
1566 DataBaseRecord->Handle,
1567 DataBaseRecord->PackageList,
1568 0,
1569 Size,
1570 *HiiFormPackage,
1571 &ResultSize
1572 );
1573 if (EFI_ERROR (Status)) {
1574 FreePool (*HiiFormPackage);
1575 }
1576
1577 *PackageSize = Size;
1578
1579 return Status;
1580 }
1581
1582
1583 /**
1584 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1585
1586 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1587 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1588 the first found varstore will be as ConfigHdr.
1589 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1590 @param EfiVarStore The efi varstore info which will return.
1591 **/
1592 EFI_STATUS
1593 GetVarStoreType (
1594 IN HII_DATABASE_RECORD *DataBaseRecord,
1595 IN EFI_STRING ConfigHdr,
1596 OUT BOOLEAN *IsEfiVarstore,
1597 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
1598 )
1599 {
1600 EFI_STATUS Status;
1601 UINTN IfrOffset;
1602 UINTN PackageOffset;
1603 EFI_IFR_OP_HEADER *IfrOpHdr;
1604 CHAR16 *VarStoreName;
1605 EFI_STRING GuidStr;
1606 EFI_STRING NameStr;
1607 EFI_STRING TempStr;
1608 UINTN LengthString;
1609 UINT8 *HiiFormPackage;
1610 UINTN PackageSize;
1611 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1612 EFI_HII_PACKAGE_HEADER *PackageHeader;
1613
1614 HiiFormPackage = NULL;
1615 LengthString = 0;
1616 Status = EFI_SUCCESS;
1617 GuidStr = NULL;
1618 NameStr = NULL;
1619 TempStr = NULL;
1620 *IsEfiVarstore = FALSE;
1621
1622 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1623 if (EFI_ERROR (Status)) {
1624 return Status;
1625 }
1626
1627 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1628 PackageOffset = IfrOffset;
1629 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1630
1631 while (IfrOffset < PackageSize) {
1632 //
1633 // More than one form packages exist.
1634 //
1635 if (PackageOffset >= PackageHeader->Length) {
1636 //
1637 // Process the new form package.
1638 //
1639 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1640 IfrOffset += PackageOffset;
1641 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1642 }
1643
1644 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1645 IfrOffset += IfrOpHdr->Length;
1646 PackageOffset += IfrOpHdr->Length;
1647
1648 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1649 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1650 //
1651 // If the length is small than the structure, this is from old efi
1652 // varstore definition. Old efi varstore get config directly from
1653 // GetVariable function.
1654 //
1655 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1656 continue;
1657 }
1658
1659 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1660 if (VarStoreName == NULL) {
1661 Status = EFI_OUT_OF_RESOURCES;
1662 goto Done;
1663 }
1664 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
1665
1666 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1667 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1668 LengthString = StrLen (GuidStr);
1669 LengthString = LengthString + StrLen (NameStr) + 1;
1670 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1671 if (TempStr == NULL) {
1672 FreePool (GuidStr);
1673 FreePool (NameStr);
1674 FreePool (VarStoreName);
1675 Status = EFI_OUT_OF_RESOURCES;
1676 goto Done;
1677 }
1678 StrCpyS (TempStr, LengthString, GuidStr);
1679 StrCatS (TempStr, LengthString, NameStr);
1680 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1681 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
1682 if (*EfiVarStore == NULL) {
1683 FreePool (VarStoreName);
1684 FreePool (GuidStr);
1685 FreePool (NameStr);
1686 FreePool (TempStr);
1687 Status = EFI_OUT_OF_RESOURCES;
1688 goto Done;
1689 }
1690 *IsEfiVarstore = TRUE;
1691 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1692 }
1693
1694 //
1695 // Free alllocated temp string.
1696 //
1697 FreePool (VarStoreName);
1698 FreePool (GuidStr);
1699 FreePool (NameStr);
1700 FreePool (TempStr);
1701
1702 //
1703 // Already found the varstore, break;
1704 //
1705 if (*IsEfiVarstore) {
1706 break;
1707 }
1708 }
1709 }
1710 Done:
1711 if (HiiFormPackage != NULL) {
1712 FreePool (HiiFormPackage);
1713 }
1714
1715 return Status;
1716 }
1717
1718 /**
1719 Check whether the ConfigRequest string has the request elements.
1720 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1721 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1722
1723 @param ConfigRequest The input config request string.
1724
1725 @retval TRUE The input include config request elements.
1726 @retval FALSE The input string not includes.
1727
1728 **/
1729 BOOLEAN
1730 GetElementsFromRequest (
1731 IN EFI_STRING ConfigRequest
1732 )
1733 {
1734 EFI_STRING TmpRequest;
1735
1736 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1737 ASSERT (TmpRequest != NULL);
1738
1739 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1740 return TRUE;
1741 }
1742
1743 return FALSE;
1744 }
1745
1746 /**
1747 Check whether the this varstore is the request varstore.
1748
1749 @param VarstoreGuid Varstore guid.
1750 @param Name Varstore name.
1751 @param ConfigHdr Current configRequest info.
1752
1753 @retval TRUE This varstore is the requst one.
1754 @retval FALSE This varstore is not the requst one.
1755
1756 **/
1757 BOOLEAN
1758 IsThisVarstore (
1759 IN EFI_GUID *VarstoreGuid,
1760 IN CHAR16 *Name,
1761 IN CHAR16 *ConfigHdr
1762 )
1763 {
1764 EFI_STRING GuidStr;
1765 EFI_STRING NameStr;
1766 EFI_STRING TempStr;
1767 UINTN LengthString;
1768 BOOLEAN RetVal;
1769
1770 RetVal = FALSE;
1771 GuidStr = NULL;
1772 TempStr = NULL;
1773
1774 //
1775 // If ConfigHdr has name field and varstore not has name, return FALSE.
1776 //
1777 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
1778 return FALSE;
1779 }
1780
1781 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1782 if (Name != NULL) {
1783 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
1784 } else {
1785 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1786 }
1787 LengthString = StrLen (GuidStr);
1788 LengthString = LengthString + StrLen (NameStr) + 1;
1789 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1790 if (TempStr == NULL) {
1791 goto Done;
1792 }
1793
1794 StrCpyS (TempStr, LengthString, GuidStr);
1795 StrCatS (TempStr, LengthString, NameStr);
1796
1797 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1798 RetVal = TRUE;
1799 }
1800
1801 Done:
1802 if (GuidStr != NULL) {
1803 FreePool (GuidStr);
1804 }
1805
1806 if (NameStr != NULL) {
1807 FreePool (NameStr);
1808 }
1809
1810 if (TempStr != NULL) {
1811 FreePool (TempStr);
1812 }
1813
1814 return RetVal;
1815 }
1816
1817 /**
1818 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1819
1820 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1821 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1822 the first found varstore will be as ConfigHdr.
1823 @retval TRUE This hii package is the reqeust one.
1824 @retval FALSE This hii package is not the reqeust one.
1825 **/
1826 BOOLEAN
1827 IsThisPackageList (
1828 IN HII_DATABASE_RECORD *DataBaseRecord,
1829 IN EFI_STRING ConfigHdr
1830 )
1831 {
1832 EFI_STATUS Status;
1833 UINTN IfrOffset;
1834 UINTN PackageOffset;
1835 EFI_IFR_OP_HEADER *IfrOpHdr;
1836 CHAR16 *VarStoreName;
1837 UINT8 *HiiFormPackage;
1838 UINTN PackageSize;
1839 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1840 EFI_HII_PACKAGE_HEADER *PackageHeader;
1841 EFI_IFR_VARSTORE *IfrVarStore;
1842 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1843 BOOLEAN FindVarstore;
1844
1845 HiiFormPackage = NULL;
1846 VarStoreName = NULL;
1847 Status = EFI_SUCCESS;
1848 FindVarstore = FALSE;
1849
1850 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1851 if (EFI_ERROR (Status)) {
1852 return FALSE;
1853 }
1854
1855 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1856 PackageOffset = IfrOffset;
1857 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1858
1859 while (IfrOffset < PackageSize) {
1860 //
1861 // More than one form packages exist.
1862 //
1863 if (PackageOffset >= PackageHeader->Length) {
1864 //
1865 // Process the new form package.
1866 //
1867 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1868 IfrOffset += PackageOffset;
1869 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1870 }
1871
1872 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1873 IfrOffset += IfrOpHdr->Length;
1874 PackageOffset += IfrOpHdr->Length;
1875
1876 switch (IfrOpHdr->OpCode) {
1877
1878 case EFI_IFR_VARSTORE_OP:
1879 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1880
1881 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
1882 if (VarStoreName == NULL) {
1883 goto Done;
1884 }
1885 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
1886
1887 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1888 FindVarstore = TRUE;
1889 goto Done;
1890 }
1891 break;
1892
1893 case EFI_IFR_VARSTORE_EFI_OP:
1894 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1895 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1896 if (VarStoreName == NULL) {
1897 goto Done;
1898 }
1899 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
1900
1901 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1902 FindVarstore = TRUE;
1903 goto Done;
1904 }
1905 break;
1906
1907 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1908 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1909
1910 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1911 FindVarstore = TRUE;
1912 goto Done;
1913 }
1914 break;
1915
1916 case EFI_IFR_FORM_OP:
1917 case EFI_IFR_FORM_MAP_OP:
1918 //
1919 // No matched varstore is found and directly return.
1920 //
1921 goto Done;
1922
1923 default:
1924 break;
1925 }
1926 }
1927 Done:
1928 if (HiiFormPackage != NULL) {
1929 FreePool (HiiFormPackage);
1930 }
1931
1932 if (VarStoreName != NULL) {
1933 FreePool (VarStoreName);
1934 }
1935
1936 return FindVarstore;
1937 }
1938
1939 /**
1940 Check whether the this op code is required.
1941
1942 @param RequestBlockArray The array includes all the request info or NULL.
1943 @param HiiHandle The hii handle for this form package.
1944 @param VarStorageData The varstore data strucure.
1945 @param IfrOpHdr Ifr opcode header for this opcode.
1946 @param VarWidth The buffer width for this opcode.
1947 @param ReturnData The data block added for this opcode.
1948
1949 @retval EFI_SUCCESS This opcode is required.
1950 @retval EFI_NOT_FOUND This opcode is not required.
1951 @retval Others Contain some error.
1952
1953 **/
1954 EFI_STATUS
1955 IsThisOpcodeRequired (
1956 IN IFR_BLOCK_DATA *RequestBlockArray,
1957 IN EFI_HII_HANDLE HiiHandle,
1958 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1959 IN EFI_IFR_OP_HEADER *IfrOpHdr,
1960 IN UINT16 VarWidth,
1961 OUT IFR_BLOCK_DATA **ReturnData
1962 )
1963 {
1964 IFR_BLOCK_DATA *BlockData;
1965 UINT16 VarOffset;
1966 EFI_STRING_ID NameId;
1967 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
1968
1969 NameId = 0;
1970 VarOffset = 0;
1971 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
1972
1973 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1974 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
1975
1976 //
1977 // Check whether this question is in requested block array.
1978 //
1979 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
1980 //
1981 // This question is not in the requested string. Skip it.
1982 //
1983 return EFI_NOT_FOUND;
1984 }
1985 } else {
1986 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
1987
1988 //
1989 // Check whether this question is in requested block array.
1990 //
1991 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
1992 //
1993 // This question is not in the requested string. Skip it.
1994 //
1995 return EFI_NOT_FOUND;
1996 }
1997
1998 //
1999 // Check this var question is in the var storage
2000 //
2001 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
2002 return EFI_INVALID_PARAMETER;
2003 }
2004 }
2005
2006 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2007 if (BlockData == NULL) {
2008 return EFI_OUT_OF_RESOURCES;
2009 }
2010
2011 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2012 BlockData->Name = InternalGetString(HiiHandle, NameId);
2013 } else {
2014 BlockData->Offset = VarOffset;
2015 }
2016
2017 BlockData->Width = VarWidth;
2018 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
2019 BlockData->OpCode = IfrOpHdr->OpCode;
2020 BlockData->Scope = IfrOpHdr->Scope;
2021 InitializeListHead (&BlockData->DefaultValueEntry);
2022 //
2023 // Add Block Data into VarStorageData BlockEntry
2024 //
2025 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2026 *ReturnData = BlockData;
2027
2028 return EFI_SUCCESS;
2029 }
2030
2031 /**
2032 This function parses Form Package to get the block array and the default
2033 value array according to the request ConfigHdr.
2034
2035 @param HiiHandle Hii Handle for this hii package.
2036 @param Package Pointer to the form package data.
2037 @param PackageLength Length of the pacakge.
2038 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2039 the first found varstore will be as ConfigHdr.
2040 @param RequestBlockArray The block array is retrieved from the request string.
2041 @param VarStorageData VarStorage structure contains the got block and default value.
2042 @param DefaultIdArray Point to the got default id and default name array.
2043
2044 @retval EFI_SUCCESS The block array and the default value array are got.
2045 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
2046 are conflicted.
2047 @retval EFI_OUT_OF_RESOURCES No enough memory.
2048 **/
2049 EFI_STATUS
2050 EFIAPI
2051 ParseIfrData (
2052 IN EFI_HII_HANDLE HiiHandle,
2053 IN UINT8 *Package,
2054 IN UINT32 PackageLength,
2055 IN EFI_STRING ConfigHdr,
2056 IN IFR_BLOCK_DATA *RequestBlockArray,
2057 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
2058 OUT IFR_DEFAULT_DATA *DefaultIdArray
2059 )
2060 {
2061 EFI_STATUS Status;
2062 UINTN IfrOffset;
2063 UINTN PackageOffset;
2064 EFI_IFR_VARSTORE *IfrVarStore;
2065 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
2066 EFI_IFR_OP_HEADER *IfrOpHdr;
2067 EFI_IFR_ONE_OF *IfrOneOf;
2068 EFI_IFR_REF4 *IfrRef;
2069 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
2070 EFI_IFR_DEFAULT *IfrDefault;
2071 EFI_IFR_ORDERED_LIST *IfrOrderedList;
2072 EFI_IFR_CHECKBOX *IfrCheckBox;
2073 EFI_IFR_PASSWORD *IfrPassword;
2074 EFI_IFR_STRING *IfrString;
2075 EFI_IFR_DATE *IfrDate;
2076 EFI_IFR_TIME *IfrTime;
2077 IFR_DEFAULT_DATA DefaultData;
2078 IFR_DEFAULT_DATA *DefaultDataPtr;
2079 IFR_BLOCK_DATA *BlockData;
2080 CHAR16 *VarStoreName;
2081 UINT16 VarWidth;
2082 UINT16 VarDefaultId;
2083 BOOLEAN FirstOneOfOption;
2084 BOOLEAN FirstOrderedList;
2085 LIST_ENTRY *LinkData;
2086 LIST_ENTRY *LinkDefault;
2087 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
2088 EFI_HII_PACKAGE_HEADER *PackageHeader;
2089 EFI_VARSTORE_ID VarStoreId;
2090
2091 Status = EFI_SUCCESS;
2092 BlockData = NULL;
2093 DefaultDataPtr = NULL;
2094 FirstOneOfOption = FALSE;
2095 VarStoreId = 0;
2096 FirstOrderedList = FALSE;
2097 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
2098
2099 //
2100 // Go through the form package to parse OpCode one by one.
2101 //
2102 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2103 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
2104 IfrOffset = PackageOffset;
2105 while (IfrOffset < PackageLength) {
2106
2107 //
2108 // More than one form package found.
2109 //
2110 if (PackageOffset >= PackageHeader->Length) {
2111 //
2112 // Already found varstore for this request, break;
2113 //
2114 if (VarStoreId != 0) {
2115 VarStoreId = 0;
2116 }
2117
2118 //
2119 // Get next package header info.
2120 //
2121 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
2122 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2123 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
2124 }
2125
2126 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
2127 switch (IfrOpHdr->OpCode) {
2128 case EFI_IFR_VARSTORE_OP:
2129 //
2130 // VarStore is found. Don't need to search any more.
2131 //
2132 if (VarStoreId != 0) {
2133 break;
2134 }
2135
2136 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
2137
2138 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
2139 if (VarStoreName == NULL) {
2140 Status = EFI_OUT_OF_RESOURCES;
2141 goto Done;
2142 }
2143 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
2144
2145 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
2146 //
2147 // Find the matched VarStore
2148 //
2149 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
2150 VarStorageData->Size = IfrVarStore->Size;
2151 VarStorageData->Name = VarStoreName;
2152 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
2153 VarStoreId = IfrVarStore->VarStoreId;
2154 }
2155 break;
2156
2157 case EFI_IFR_VARSTORE_EFI_OP:
2158 //
2159 // VarStore is found. Don't need to search any more.
2160 //
2161 if (VarStoreId != 0) {
2162 break;
2163 }
2164
2165 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
2166
2167 //
2168 // If the length is small than the structure, this is from old efi
2169 // varstore definition. Old efi varstore get config directly from
2170 // GetVariable function.
2171 //
2172 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
2173 break;
2174 }
2175
2176 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
2177 if (VarStoreName == NULL) {
2178 Status = EFI_OUT_OF_RESOURCES;
2179 goto Done;
2180 }
2181 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
2182
2183 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
2184 //
2185 // Find the matched VarStore
2186 //
2187 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
2188 VarStorageData->Size = IfrEfiVarStore->Size;
2189 VarStorageData->Name = VarStoreName;
2190 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
2191 VarStoreId = IfrEfiVarStore->VarStoreId;
2192 }
2193 break;
2194
2195 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
2196 //
2197 // VarStore is found. Don't need to search any more.
2198 //
2199 if (VarStoreId != 0) {
2200 break;
2201 }
2202
2203 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
2204
2205 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
2206 //
2207 // Find the matched VarStore
2208 //
2209 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
2210 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
2211 VarStoreId = IfrNameValueVarStore->VarStoreId;
2212 }
2213 break;
2214
2215 case EFI_IFR_DEFAULTSTORE_OP:
2216 //
2217 // Add new the map between default id and default name.
2218 //
2219 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
2220 if (DefaultDataPtr == NULL) {
2221 Status = EFI_OUT_OF_RESOURCES;
2222 goto Done;
2223 }
2224 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
2225 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
2226 DefaultDataPtr = NULL;
2227 break;
2228
2229 case EFI_IFR_FORM_OP:
2230 case EFI_IFR_FORM_MAP_OP:
2231 //
2232 // No matched varstore is found and directly return.
2233 //
2234 if ( VarStoreId == 0) {
2235 Status = EFI_SUCCESS;
2236 goto Done;
2237 }
2238 break;
2239
2240 case EFI_IFR_REF_OP:
2241 //
2242 // Ref question is not in IFR Form. This IFR form is not valid.
2243 //
2244 if ( VarStoreId == 0) {
2245 Status = EFI_INVALID_PARAMETER;
2246 goto Done;
2247 }
2248 //
2249 // Check whether this question is for the requested varstore.
2250 //
2251 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
2252 if (IfrRef->Question.VarStoreId != VarStoreId) {
2253 break;
2254 }
2255 VarWidth = (UINT16) (sizeof (EFI_HII_REF));
2256
2257 //
2258 // The BlockData may allocate by other opcode,need to clean.
2259 //
2260 if (BlockData != NULL){
2261 BlockData = NULL;
2262 }
2263
2264 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2265 if (EFI_ERROR (Status)) {
2266 if (Status == EFI_NOT_FOUND){
2267 //
2268 //The opcode is not required,exit and parse other opcode.
2269 //
2270 break;
2271 }
2272 goto Done;
2273 }
2274 break;
2275
2276 case EFI_IFR_ONE_OF_OP:
2277 case EFI_IFR_NUMERIC_OP:
2278 //
2279 // Numeric and OneOf has the same opcode structure.
2280 //
2281
2282 //
2283 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2284 //
2285 if (VarStoreId == 0) {
2286 Status = EFI_INVALID_PARAMETER;
2287 goto Done;
2288 }
2289 //
2290 // Check whether this question is for the requested varstore.
2291 //
2292 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
2293 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
2294 break;
2295 }
2296 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
2297
2298 //
2299 // The BlockData may allocate by other opcode,need to clean.
2300 //
2301 if (BlockData != NULL){
2302 BlockData = NULL;
2303 }
2304
2305 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2306 if (EFI_ERROR (Status)) {
2307 if (Status == EFI_NOT_FOUND){
2308 //
2309 //The opcode is not required,exit and parse other opcode.
2310 //
2311 break;
2312 }
2313 goto Done;
2314 }
2315
2316 //
2317 //when go to there,BlockData can't be NULLL.
2318 //
2319 ASSERT (BlockData != NULL);
2320
2321 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
2322 //
2323 // Set this flag to TRUE for the first oneof option.
2324 //
2325 FirstOneOfOption = TRUE;
2326 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
2327 //
2328 // Numeric minimum value will be used as default value when no default is specified.
2329 //
2330 DefaultData.Type = DefaultValueFromDefault;
2331 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
2332 case EFI_IFR_NUMERIC_SIZE_1:
2333 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
2334 break;
2335
2336 case EFI_IFR_NUMERIC_SIZE_2:
2337 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
2338 break;
2339
2340 case EFI_IFR_NUMERIC_SIZE_4:
2341 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
2342 break;
2343
2344 case EFI_IFR_NUMERIC_SIZE_8:
2345 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
2346 break;
2347
2348 default:
2349 Status = EFI_INVALID_PARAMETER;
2350 goto Done;
2351 }
2352 //
2353 // Set default value base on the DefaultId list get from IFR data.
2354 //
2355 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2356 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2357 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2358 InsertDefaultValue (BlockData, &DefaultData);
2359 }
2360 }
2361 break;
2362
2363 case EFI_IFR_ORDERED_LIST_OP:
2364 //
2365 // offset by question header
2366 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2367 //
2368
2369 FirstOrderedList = TRUE;
2370 //
2371 // OrderedList question is not in IFR Form. This IFR form is not valid.
2372 //
2373 if (VarStoreId == 0) {
2374 Status = EFI_INVALID_PARAMETER;
2375 goto Done;
2376 }
2377 //
2378 // Check whether this question is for the requested varstore.
2379 //
2380 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
2381 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
2382 BlockData = NULL;
2383 break;
2384 }
2385 VarWidth = IfrOrderedList->MaxContainers;
2386
2387 //
2388 // The BlockData may allocate by other opcode,need to clean.
2389 //
2390 if (BlockData != NULL){
2391 BlockData = NULL;
2392 }
2393
2394 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2395 if (EFI_ERROR (Status)) {
2396 if (Status == EFI_NOT_FOUND){
2397 //
2398 //The opcode is not required,exit and parse other opcode.
2399 //
2400 break;
2401 }
2402 goto Done;
2403 }
2404 break;
2405
2406 case EFI_IFR_CHECKBOX_OP:
2407 //
2408 // EFI_IFR_DEFAULT_OP
2409 // offset by question header
2410 // width is 1 sizeof (BOOLEAN)
2411 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2412 // value by DefaultOption
2413 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2414 //
2415
2416 //
2417 // CheckBox question is not in IFR Form. This IFR form is not valid.
2418 //
2419 if (VarStoreId == 0) {
2420 Status = EFI_INVALID_PARAMETER;
2421 goto Done;
2422 }
2423 //
2424 // Check whether this question is for the requested varstore.
2425 //
2426 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
2427 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
2428 break;
2429 }
2430 VarWidth = (UINT16) sizeof (BOOLEAN);
2431
2432 //
2433 // The BlockData may allocate by other opcode,need to clean.
2434 //
2435 if (BlockData != NULL){
2436 BlockData = NULL;
2437 }
2438
2439 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2440 if (EFI_ERROR (Status)) {
2441 if (Status == EFI_NOT_FOUND){
2442 //
2443 //The opcode is not required,exit and parse other opcode.
2444 //
2445 break;
2446 }
2447 goto Done;
2448 }
2449
2450 //
2451 //when go to there,BlockData can't be NULLL.
2452 //
2453 ASSERT (BlockData != NULL);
2454
2455 //
2456 // Add default value for standard ID by CheckBox Flag
2457 //
2458 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2459 //
2460 // Prepare new DefaultValue
2461 //
2462 DefaultData.DefaultId = VarDefaultId;
2463 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
2464 //
2465 // When flag is set, defautl value is TRUE.
2466 //
2467 DefaultData.Type = DefaultValueFromFlag;
2468 DefaultData.Value.b = TRUE;
2469 } else {
2470 //
2471 // When flag is not set, defautl value is FASLE.
2472 //
2473 DefaultData.Type = DefaultValueFromDefault;
2474 DefaultData.Value.b = FALSE;
2475 }
2476 //
2477 // Add DefaultValue into current BlockData
2478 //
2479 InsertDefaultValue (BlockData, &DefaultData);
2480
2481 //
2482 // Add default value for Manufacture ID by CheckBox Flag
2483 //
2484 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2485 //
2486 // Prepare new DefaultValue
2487 //
2488 DefaultData.DefaultId = VarDefaultId;
2489 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
2490 //
2491 // When flag is set, defautl value is TRUE.
2492 //
2493 DefaultData.Type = DefaultValueFromFlag;
2494 DefaultData.Value.b = TRUE;
2495 } else {
2496 //
2497 // When flag is not set, defautl value is FASLE.
2498 //
2499 DefaultData.Type = DefaultValueFromDefault;
2500 DefaultData.Value.b = FALSE;
2501 }
2502 //
2503 // Add DefaultValue into current BlockData
2504 //
2505 InsertDefaultValue (BlockData, &DefaultData);
2506 break;
2507
2508 case EFI_IFR_DATE_OP:
2509 //
2510 // offset by question header
2511 // width MaxSize * sizeof (CHAR16)
2512 // no default value, only block array
2513 //
2514
2515 //
2516 // Date question is not in IFR Form. This IFR form is not valid.
2517 //
2518 if (VarStoreId == 0) {
2519 Status = EFI_INVALID_PARAMETER;
2520 goto Done;
2521 }
2522 //
2523 // Check whether this question is for the requested varstore.
2524 //
2525 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
2526 if (IfrDate->Question.VarStoreId != VarStoreId) {
2527 break;
2528 }
2529
2530 //
2531 // The BlockData may allocate by other opcode,need to clean.
2532 //
2533 if (BlockData != NULL){
2534 BlockData = NULL;
2535 }
2536
2537 VarWidth = (UINT16) sizeof (EFI_HII_DATE);
2538 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2539 if (EFI_ERROR (Status)) {
2540 if (Status == EFI_NOT_FOUND){
2541 //
2542 //The opcode is not required,exit and parse other opcode.
2543 //
2544 break;
2545 }
2546 goto Done;
2547 }
2548 break;
2549
2550 case EFI_IFR_TIME_OP:
2551 //
2552 // offset by question header
2553 // width MaxSize * sizeof (CHAR16)
2554 // no default value, only block array
2555 //
2556
2557 //
2558 // Time question is not in IFR Form. This IFR form is not valid.
2559 //
2560 if (VarStoreId == 0) {
2561 Status = EFI_INVALID_PARAMETER;
2562 goto Done;
2563 }
2564 //
2565 // Check whether this question is for the requested varstore.
2566 //
2567 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
2568 if (IfrTime->Question.VarStoreId != VarStoreId) {
2569 break;
2570 }
2571
2572 //
2573 // The BlockData may allocate by other opcode,need to clean.
2574 //
2575 if (BlockData != NULL){
2576 BlockData = NULL;
2577 }
2578
2579 VarWidth = (UINT16) sizeof (EFI_HII_TIME);
2580 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2581 if (EFI_ERROR (Status)) {
2582 if (Status == EFI_NOT_FOUND){
2583 //
2584 //The opcode is not required,exit and parse other opcode.
2585 //
2586 break;
2587 }
2588 goto Done;
2589 }
2590 break;
2591
2592 case EFI_IFR_STRING_OP:
2593 //
2594 // offset by question header
2595 // width MaxSize * sizeof (CHAR16)
2596 // no default value, only block array
2597 //
2598
2599 //
2600 // String question is not in IFR Form. This IFR form is not valid.
2601 //
2602 if (VarStoreId == 0) {
2603 Status = EFI_INVALID_PARAMETER;
2604 goto Done;
2605 }
2606 //
2607 // Check whether this question is for the requested varstore.
2608 //
2609 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
2610 if (IfrString->Question.VarStoreId != VarStoreId) {
2611 break;
2612 }
2613
2614 //
2615 // The BlockData may allocate by other opcode,need to clean.
2616 //
2617 if (BlockData != NULL){
2618 BlockData = NULL;
2619 }
2620
2621 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
2622 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2623 if (EFI_ERROR (Status)) {
2624 if (Status == EFI_NOT_FOUND){
2625 //
2626 //The opcode is not required,exit and parse other opcode.
2627 //
2628 break;
2629 }
2630 goto Done;
2631 }
2632 break;
2633
2634 case EFI_IFR_PASSWORD_OP:
2635 //
2636 // offset by question header
2637 // width MaxSize * sizeof (CHAR16)
2638 // no default value, only block array
2639 //
2640
2641 //
2642 // Password question is not in IFR Form. This IFR form is not valid.
2643 //
2644 if (VarStoreId == 0) {
2645 Status = EFI_INVALID_PARAMETER;
2646 goto Done;
2647 }
2648 //
2649 // Check whether this question is for the requested varstore.
2650 //
2651 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
2652 if (IfrPassword->Question.VarStoreId != VarStoreId) {
2653 break;
2654 }
2655
2656 //
2657 // The BlockData may allocate by other opcode,need to clean.
2658 //
2659 if (BlockData != NULL){
2660 BlockData = NULL;
2661 }
2662
2663 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
2664 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2665 if (EFI_ERROR (Status)) {
2666 if (Status == EFI_NOT_FOUND){
2667 //
2668 //The opcode is not required,exit and parse other opcode.
2669 //
2670 break;
2671 }
2672 goto Done;
2673 }
2674
2675 //
2676 // No default value for string.
2677 //
2678 BlockData = NULL;
2679 break;
2680
2681 case EFI_IFR_ONE_OF_OPTION_OP:
2682 //
2683 // No matched block data is ignored.
2684 //
2685 if (BlockData == NULL || BlockData->Scope == 0) {
2686 break;
2687 }
2688
2689 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
2690 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2691
2692 if (!FirstOrderedList){
2693 break;
2694 }
2695 //
2696 // Get ordered list option data type.
2697 //
2698 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
2699 VarWidth = 1;
2700 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
2701 VarWidth = 2;
2702 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
2703 VarWidth = 4;
2704 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
2705 VarWidth = 8;
2706 } else {
2707 //
2708 // Invalid ordered list option data type.
2709 //
2710 Status = EFI_INVALID_PARAMETER;
2711 if (BlockData->Name != NULL) {
2712 FreePool (BlockData->Name);
2713 }
2714 FreePool (BlockData);
2715 goto Done;
2716 }
2717
2718 //
2719 // Calculate Ordered list QuestionId width.
2720 //
2721 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
2722 //
2723 // Check whether this question is in requested block array.
2724 //
2725 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2726 //
2727 // This question is not in the requested string. Skip it.
2728 //
2729 if (BlockData->Name != NULL) {
2730 FreePool (BlockData->Name);
2731 }
2732 FreePool (BlockData);
2733 BlockData = NULL;
2734 break;
2735 }
2736 //
2737 // Check this var question is in the var storage
2738 //
2739 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2740 Status = EFI_INVALID_PARAMETER;
2741 if (BlockData->Name != NULL) {
2742 FreePool (BlockData->Name);
2743 }
2744 FreePool (BlockData);
2745 goto Done;
2746 }
2747 //
2748 // Add Block Data into VarStorageData BlockEntry
2749 //
2750 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2751
2752 FirstOrderedList = FALSE;
2753
2754 break;
2755 }
2756
2757 //
2758 // 1. Set default value for OneOf option when flag field has default attribute.
2759 //
2760 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2761 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
2762 //
2763 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2764 // The first oneof option value will be used as default value when no default value is specified.
2765 //
2766 FirstOneOfOption = FALSE;
2767
2768 // Prepare new DefaultValue
2769 //
2770 DefaultData.Type = DefaultValueFromFlag;
2771 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2772 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
2773 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2774 InsertDefaultValue (BlockData, &DefaultData);
2775 }
2776 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
2777 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2778 InsertDefaultValue (BlockData, &DefaultData);
2779 }
2780 }
2781
2782 //
2783 // 2. Set as the default value when this is the first option.
2784 // The first oneof option value will be used as default value when no default value is specified.
2785 //
2786 if (FirstOneOfOption) {
2787 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2788 FirstOneOfOption = FALSE;
2789
2790 //
2791 // Prepare new DefaultValue
2792 //
2793 DefaultData.Type = DefaultValueFromDefault;
2794 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2795 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2796 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2797 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2798 InsertDefaultValue (BlockData, &DefaultData);
2799 }
2800 }
2801 break;
2802
2803 case EFI_IFR_DEFAULT_OP:
2804 //
2805 // Update Current BlockData to the default value.
2806 //
2807 if (BlockData == NULL || BlockData->Scope == 0) {
2808 //
2809 // No matched block data is ignored.
2810 //
2811 break;
2812 }
2813
2814 //
2815 // Get the DefaultId
2816 //
2817 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
2818 VarDefaultId = IfrDefault->DefaultId;
2819 //
2820 // Prepare new DefaultValue
2821 //
2822 DefaultData.Type = DefaultValueFromOpcode;
2823 DefaultData.DefaultId = VarDefaultId;
2824 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2825
2826 // If the value field is expression, set the cleaned flag.
2827 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
2828 DefaultData.Cleaned = TRUE;
2829 }
2830 //
2831 // Add DefaultValue into current BlockData
2832 //
2833 InsertDefaultValue (BlockData, &DefaultData);
2834
2835 //
2836 // After insert the default value, reset the cleaned value for next
2837 // time used. If not set here, need to set the value before everytime
2838 // use it.
2839 //
2840 DefaultData.Cleaned = FALSE;
2841 break;
2842
2843 case EFI_IFR_END_OP:
2844 //
2845 // End Opcode is for Var question.
2846 //
2847 if (BlockData != NULL) {
2848 if (BlockData->Scope > 0) {
2849 BlockData->Scope--;
2850 }
2851 if (BlockData->Scope == 0) {
2852 BlockData = NULL;
2853 }
2854 }
2855
2856 break;
2857
2858 default:
2859 if (BlockData != NULL) {
2860 if (BlockData->Scope > 0) {
2861 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
2862 }
2863
2864 if (BlockData->Scope == 0) {
2865 BlockData = NULL;
2866 }
2867 }
2868 break;
2869 }
2870
2871 IfrOffset += IfrOpHdr->Length;
2872 PackageOffset += IfrOpHdr->Length;
2873 }
2874
2875 //
2876 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2877 //so set the Status to EFI_SUCCESS.
2878 //
2879 if (Status == EFI_NOT_FOUND){
2880 Status = EFI_SUCCESS;
2881 }
2882
2883 Done:
2884 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2885 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2886 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
2887 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2888 LinkDefault = LinkDefault->ForwardLink;
2889 if (DefaultDataPtr->Cleaned == TRUE) {
2890 RemoveEntryList (&DefaultDataPtr->Entry);
2891 FreePool (DefaultDataPtr);
2892 }
2893 }
2894 }
2895
2896 return Status;
2897 }
2898
2899 /**
2900 parse the configrequest string, get the elements.
2901
2902 @param ConfigRequest The input configrequest string.
2903 @param Progress Return the progress data.
2904
2905 @retval Block data pointer.
2906 **/
2907 IFR_BLOCK_DATA *
2908 GetBlockElement (
2909 IN EFI_STRING ConfigRequest,
2910 OUT EFI_STRING *Progress
2911 )
2912 {
2913 EFI_STRING StringPtr;
2914 IFR_BLOCK_DATA *BlockData;
2915 IFR_BLOCK_DATA *RequestBlockArray;
2916 EFI_STATUS Status;
2917 UINT8 *TmpBuffer;
2918 UINT16 Offset;
2919 UINT16 Width;
2920 LIST_ENTRY *Link;
2921 IFR_BLOCK_DATA *NextBlockData;
2922 UINTN Length;
2923
2924 TmpBuffer = NULL;
2925
2926 //
2927 // Init RequestBlockArray
2928 //
2929 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2930 if (RequestBlockArray == NULL) {
2931 goto Done;
2932 }
2933 InitializeListHead (&RequestBlockArray->Entry);
2934
2935 //
2936 // Get the request Block array from the request string
2937 // Offset and Width
2938 //
2939
2940 //
2941 // Parse each <RequestElement> if exists
2942 // Only <BlockName> format is supported by this help function.
2943 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2944 //
2945 StringPtr = ConfigRequest;
2946 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
2947 //
2948 // Skip the OFFSET string
2949 //
2950 *Progress = StringPtr;
2951 StringPtr += StrLen (L"&OFFSET=");
2952 //
2953 // Get Offset
2954 //
2955 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2956 if (EFI_ERROR (Status)) {
2957 goto Done;
2958 }
2959 Offset = 0;
2960 CopyMem (
2961 &Offset,
2962 TmpBuffer,
2963 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2964 );
2965 FreePool (TmpBuffer);
2966
2967 StringPtr += Length;
2968 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
2969 goto Done;
2970 }
2971 StringPtr += StrLen (L"&WIDTH=");
2972
2973 //
2974 // Get Width
2975 //
2976 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2977 if (EFI_ERROR (Status)) {
2978 goto Done;
2979 }
2980 Width = 0;
2981 CopyMem (
2982 &Width,
2983 TmpBuffer,
2984 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2985 );
2986 FreePool (TmpBuffer);
2987
2988 StringPtr += Length;
2989 if (*StringPtr != 0 && *StringPtr != L'&') {
2990 goto Done;
2991 }
2992
2993 //
2994 // Set Block Data
2995 //
2996 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2997 if (BlockData == NULL) {
2998 goto Done;
2999 }
3000 BlockData->Offset = Offset;
3001 BlockData->Width = Width;
3002 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3003
3004 //
3005 // Skip &VALUE string if &VALUE does exists.
3006 //
3007 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
3008 StringPtr += StrLen (L"&VALUE=");
3009
3010 //
3011 // Get Value
3012 //
3013 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3014 if (EFI_ERROR (Status)) {
3015 goto Done;
3016 }
3017
3018 StringPtr += Length;
3019 if (*StringPtr != 0 && *StringPtr != L'&') {
3020 goto Done;
3021 }
3022 }
3023 //
3024 // If '\0', parsing is finished.
3025 //
3026 if (*StringPtr == 0) {
3027 break;
3028 }
3029 }
3030
3031 //
3032 // Merge the requested block data.
3033 //
3034 Link = RequestBlockArray->Entry.ForwardLink;
3035 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
3036 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3037 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
3038 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
3039 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
3040 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
3041 }
3042 RemoveEntryList (Link->ForwardLink);
3043 FreePool (NextBlockData);
3044 continue;
3045 }
3046 Link = Link->ForwardLink;
3047 }
3048
3049 return RequestBlockArray;
3050
3051 Done:
3052 if (RequestBlockArray != NULL) {
3053 //
3054 // Free Link Array RequestBlockArray
3055 //
3056 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3057 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3058 RemoveEntryList (&BlockData->Entry);
3059 FreePool (BlockData);
3060 }
3061
3062 FreePool (RequestBlockArray);
3063 }
3064
3065 return NULL;
3066 }
3067
3068 /**
3069 parse the configrequest string, get the elements.
3070
3071 @param ConfigRequest The input config request string.
3072 @param Progress Return the progress data.
3073
3074 @retval return data block array.
3075 **/
3076 IFR_BLOCK_DATA *
3077 GetNameElement (
3078 IN EFI_STRING ConfigRequest,
3079 OUT EFI_STRING *Progress
3080 )
3081 {
3082 EFI_STRING StringPtr;
3083 EFI_STRING NextTag;
3084 IFR_BLOCK_DATA *BlockData;
3085 IFR_BLOCK_DATA *RequestBlockArray;
3086 BOOLEAN HasValue;
3087
3088 StringPtr = ConfigRequest;
3089
3090 //
3091 // Init RequestBlockArray
3092 //
3093 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3094 if (RequestBlockArray == NULL) {
3095 goto Done;
3096 }
3097 InitializeListHead (&RequestBlockArray->Entry);
3098
3099 //
3100 // Get the request Block array from the request string
3101 //
3102
3103 //
3104 // Parse each <RequestElement> if exists
3105 // Only <BlockName> format is supported by this help function.
3106 // <BlockName> ::= &'Name***=***
3107 //
3108 while (StringPtr != NULL && *StringPtr == L'&') {
3109
3110 *Progress = StringPtr;
3111 //
3112 // Skip the L"&" string
3113 //
3114 StringPtr += 1;
3115
3116 HasValue = FALSE;
3117 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
3118 *NextTag = L'\0';
3119 HasValue = TRUE;
3120 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
3121 *NextTag = L'\0';
3122 }
3123
3124 //
3125 // Set Block Data
3126 //
3127 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3128 if (BlockData == NULL) {
3129 goto Done;
3130 }
3131
3132 //
3133 // Get Name
3134 //
3135 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
3136 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3137
3138 if (HasValue) {
3139 //
3140 // If has value, skip the value.
3141 //
3142 StringPtr = NextTag + 1;
3143 *NextTag = L'=';
3144 StringPtr = StrStr (StringPtr, L"&");
3145 } else if (NextTag != NULL) {
3146 //
3147 // restore the '&' text.
3148 //
3149 StringPtr = NextTag;
3150 *NextTag = L'&';
3151 }
3152 }
3153
3154 return RequestBlockArray;
3155
3156 Done:
3157 if (RequestBlockArray != NULL) {
3158 //
3159 // Free Link Array RequestBlockArray
3160 //
3161 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3162 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3163 RemoveEntryList (&BlockData->Entry);
3164 if (BlockData->Name != NULL) {
3165 FreePool (BlockData->Name);
3166 }
3167 FreePool (BlockData);
3168 }
3169
3170 FreePool (RequestBlockArray);
3171 }
3172
3173 return NULL;
3174 }
3175
3176 /**
3177 Generate ConfigRequest string base on the varstore info.
3178
3179 @param ConfigHdr The config header for this varstore.
3180 @param VarStorageData The varstore info.
3181 @param Status Return Status.
3182 @param ConfigRequest The ConfigRequest info may be return.
3183
3184 @retval TRUE Need to continue
3185 @retval Others NO need to continue or error occur.
3186 **/
3187 BOOLEAN
3188 GenerateConfigRequest (
3189 IN CHAR16 *ConfigHdr,
3190 IN IFR_VARSTORAGE_DATA *VarStorageData,
3191 OUT EFI_STATUS *Status,
3192 IN OUT EFI_STRING *ConfigRequest
3193 )
3194 {
3195 BOOLEAN DataExist;
3196 UINTN Length;
3197 LIST_ENTRY *Link;
3198 CHAR16 *FullConfigRequest;
3199 CHAR16 *StringPtr;
3200 IFR_BLOCK_DATA *BlockData;
3201
3202 //
3203 // Append VarStorageData BlockEntry into *Request string
3204 // Now support only one varstore in a form package.
3205 //
3206
3207 //
3208 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3209 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3210 //
3211
3212 //
3213 // Compute the length of the entire request starting with <ConfigHdr> and a
3214 // Null-terminator
3215 //
3216 DataExist = FALSE;
3217 Length = StrLen (ConfigHdr) + 1;
3218
3219 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3220 DataExist = TRUE;
3221 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3222 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3223 //
3224 // Add <BlockName> length for each Name
3225 //
3226 // <BlockName> ::= &Name1&Name2&...
3227 // |1| StrLen(Name1)
3228 //
3229 Length = Length + (1 + StrLen (BlockData->Name));
3230 } else {
3231 //
3232 // Add <BlockName> length for each Offset/Width pair
3233 //
3234 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3235 // | 8 | 4 | 7 | 4 |
3236 //
3237 Length = Length + (8 + 4 + 7 + 4);
3238 }
3239 }
3240 //
3241 // No any request block data is found. The request string can't be constructed.
3242 //
3243 if (!DataExist) {
3244 *Status = EFI_SUCCESS;
3245 return FALSE;
3246 }
3247
3248 //
3249 // Allocate buffer for the entire <ConfigRequest>
3250 //
3251 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
3252 if (FullConfigRequest == NULL) {
3253 *Status = EFI_OUT_OF_RESOURCES;
3254 return FALSE;
3255 }
3256 StringPtr = FullConfigRequest;
3257
3258 //
3259 // Start with <ConfigHdr>
3260 //
3261 StrCpyS (StringPtr, Length, ConfigHdr);
3262 StringPtr += StrLen (StringPtr);
3263
3264 //
3265 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3266 //
3267 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3268 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3269 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3270 //
3271 // Append &Name1\0
3272 //
3273 UnicodeSPrint (
3274 StringPtr,
3275 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
3276 L"&%s",
3277 BlockData->Name
3278 );
3279 } else {
3280 //
3281 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3282 //
3283 UnicodeSPrint (
3284 StringPtr,
3285 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
3286 L"&OFFSET=%04X&WIDTH=%04X",
3287 BlockData->Offset,
3288 BlockData->Width
3289 );
3290 }
3291 StringPtr += StrLen (StringPtr);
3292 }
3293 //
3294 // Set to the got full request string.
3295 //
3296 HiiToLower (FullConfigRequest);
3297
3298 if (*ConfigRequest != NULL) {
3299 FreePool (*ConfigRequest);
3300 }
3301 *ConfigRequest = FullConfigRequest;
3302
3303 return TRUE;
3304 }
3305
3306 /**
3307 Generate ConfigRequest Header base on the varstore info.
3308
3309 @param VarStorageData The varstore info.
3310 @param DevicePath Device path for this varstore.
3311 @param ConfigHdr The config header for this varstore.
3312
3313 @retval EFI_SUCCESS Generate the header success.
3314 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3315 **/
3316 EFI_STATUS
3317 GenerateHdr (
3318 IN IFR_VARSTORAGE_DATA *VarStorageData,
3319 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3320 OUT EFI_STRING *ConfigHdr
3321 )
3322 {
3323 EFI_STRING GuidStr;
3324 EFI_STRING NameStr;
3325 EFI_STRING PathStr;
3326 UINTN Length;
3327 EFI_STATUS Status;
3328
3329 Status = EFI_SUCCESS;
3330 NameStr = NULL;
3331 GuidStr = NULL;
3332 PathStr = NULL;
3333
3334 //
3335 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3336 //
3337 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
3338 if (VarStorageData->Name != NULL) {
3339 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
3340 } else {
3341 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3342 }
3343 GenerateSubStr (
3344 L"PATH=",
3345 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3346 (VOID *) DevicePath,
3347 1,
3348 &PathStr
3349 );
3350 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
3351 if (VarStorageData->Name == NULL) {
3352 Length += 1;
3353 }
3354
3355 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
3356 if (*ConfigHdr == NULL) {
3357 Status = EFI_OUT_OF_RESOURCES;
3358 goto Done;
3359 }
3360 StrCpyS (*ConfigHdr, Length, GuidStr);
3361 StrCatS (*ConfigHdr, Length, NameStr);
3362 if (VarStorageData->Name == NULL) {
3363 StrCatS (*ConfigHdr, Length, L"&");
3364 }
3365 StrCatS (*ConfigHdr, Length, PathStr);
3366
3367 //
3368 // Remove the last character L'&'
3369 //
3370 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
3371
3372 Done:
3373 if (GuidStr != NULL) {
3374 FreePool (GuidStr);
3375 }
3376
3377 if (NameStr != NULL) {
3378 FreePool (NameStr);
3379 }
3380
3381 if (PathStr != NULL) {
3382 FreePool (PathStr);
3383 }
3384
3385 return Status;
3386 }
3387
3388 /**
3389 Get Data buffer size based on data type.
3390
3391 @param ValueType The input data type.
3392
3393 @retval The data buffer size for the input type.
3394 **/
3395 UINT16
3396 GetStorageWidth (
3397 IN UINT8 ValueType
3398 )
3399 {
3400 UINT16 StorageWidth;
3401
3402 switch (ValueType) {
3403 case EFI_IFR_NUMERIC_SIZE_1:
3404 case EFI_IFR_TYPE_BOOLEAN:
3405 StorageWidth = (UINT16) sizeof (UINT8);
3406 break;
3407
3408 case EFI_IFR_NUMERIC_SIZE_2:
3409 StorageWidth = (UINT16) sizeof (UINT16);
3410 break;
3411
3412 case EFI_IFR_NUMERIC_SIZE_4:
3413 StorageWidth = (UINT16) sizeof (UINT32);
3414 break;
3415
3416 case EFI_IFR_NUMERIC_SIZE_8:
3417 StorageWidth = (UINT16) sizeof (UINT64);
3418 break;
3419
3420 case EFI_IFR_TYPE_TIME:
3421 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
3422 break;
3423
3424 case EFI_IFR_TYPE_DATE:
3425 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
3426 break;
3427
3428 default:
3429 StorageWidth = 0;
3430 break;
3431 }
3432
3433 return StorageWidth;
3434 }
3435
3436 /**
3437 Generate ConfigAltResp string base on the varstore info.
3438
3439 @param HiiHandle Hii Handle for this hii package.
3440 @param ConfigHdr The config header for this varstore.
3441 @param VarStorageData The varstore info.
3442 @param DefaultIdArray The Default id array.
3443 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3444
3445 @retval TRUE Need to continue
3446 @retval Others NO need to continue or error occur.
3447 **/
3448 EFI_STATUS
3449 GenerateAltConfigResp (
3450 IN EFI_HII_HANDLE HiiHandle,
3451 IN CHAR16 *ConfigHdr,
3452 IN IFR_VARSTORAGE_DATA *VarStorageData,
3453 IN IFR_DEFAULT_DATA *DefaultIdArray,
3454 IN OUT EFI_STRING *DefaultAltCfgResp
3455 )
3456 {
3457 BOOLEAN DataExist;
3458 UINTN Length;
3459 LIST_ENTRY *Link;
3460 LIST_ENTRY *LinkData;
3461 LIST_ENTRY *LinkDefault;
3462 LIST_ENTRY *ListEntry;
3463 CHAR16 *StringPtr;
3464 IFR_BLOCK_DATA *BlockData;
3465 IFR_DEFAULT_DATA *DefaultId;
3466 IFR_DEFAULT_DATA *DefaultValueData;
3467 UINTN Width;
3468 UINT8 *TmpBuffer;
3469 CHAR16 *DefaultString;
3470
3471 BlockData = NULL;
3472 DataExist = FALSE;
3473 DefaultString = NULL;
3474 //
3475 // Add length for <ConfigHdr> + '\0'
3476 //
3477 Length = StrLen (ConfigHdr) + 1;
3478
3479 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3480 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3481 //
3482 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3483 // |1| StrLen (ConfigHdr) | 8 | 4 |
3484 //
3485 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
3486
3487 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3488 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3489 ListEntry = &BlockData->DefaultValueEntry;
3490 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3491 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3492 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3493 continue;
3494 }
3495 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3496 //
3497 // Add length for "&Name1=zzzzzzzzzzzz"
3498 // |1|Name|1|Value|
3499 //
3500 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
3501 } else {
3502 //
3503 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3504 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3505 //
3506 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
3507 }
3508 DataExist = TRUE;
3509 }
3510 }
3511 }
3512
3513 //
3514 // No default value is found. The default string doesn't exist.
3515 //
3516 if (!DataExist) {
3517 return EFI_SUCCESS;
3518 }
3519
3520 //
3521 // Allocate buffer for the entire <DefaultAltCfgResp>
3522 //
3523 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3524 if (*DefaultAltCfgResp == NULL) {
3525 return EFI_OUT_OF_RESOURCES;
3526 }
3527 StringPtr = *DefaultAltCfgResp;
3528
3529 //
3530 // Start with <ConfigHdr>
3531 //
3532 StrCpyS (StringPtr, Length, ConfigHdr);
3533 StringPtr += StrLen (StringPtr);
3534
3535 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3536 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3537 //
3538 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3539 // |1| StrLen (ConfigHdr) | 8 | 4 |
3540 //
3541 UnicodeSPrint (
3542 StringPtr,
3543 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
3544 L"&%s&ALTCFG=%04X",
3545 ConfigHdr,
3546 DefaultId->DefaultId
3547 );
3548 StringPtr += StrLen (StringPtr);
3549
3550 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3551 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3552 ListEntry = &BlockData->DefaultValueEntry;
3553 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3554 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3555 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3556 continue;
3557 }
3558 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3559 UnicodeSPrint (
3560 StringPtr,
3561 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
3562 L"&%s=",
3563 BlockData->Name
3564 );
3565 StringPtr += StrLen (StringPtr);
3566 } else {
3567 //
3568 // Add <BlockConfig>
3569 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3570 //
3571 UnicodeSPrint (
3572 StringPtr,
3573 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
3574 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3575 BlockData->Offset,
3576 BlockData->Width
3577 );
3578 StringPtr += StrLen (StringPtr);
3579 }
3580 Width = BlockData->Width;
3581 //
3582 // Convert Value to a hex string in "%x" format
3583 // NOTE: This is in the opposite byte that GUID and PATH use
3584 //
3585 if (BlockData->OpCode == EFI_IFR_STRING_OP){
3586 DefaultString = InternalGetString(HiiHandle, DefaultValueData->Value.string);
3587 TmpBuffer = (UINT8 *) DefaultString;
3588 } else {
3589 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
3590 }
3591 for (; Width > 0 && (TmpBuffer != NULL); Width--) {
3592 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
3593 }
3594 if (DefaultString != NULL){
3595 FreePool(DefaultString);
3596 DefaultString = NULL;
3597 }
3598 }
3599 }
3600 }
3601
3602 HiiToLower (*DefaultAltCfgResp);
3603
3604 return EFI_SUCCESS;
3605 }
3606
3607 /**
3608 This function gets the full request string and full default value string by
3609 parsing IFR data in HII form packages.
3610
3611 When Request points to NULL string, the request string and default value string
3612 for each varstore in form package will return.
3613
3614 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3615 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3616 @param Request Pointer to a null-terminated Unicode string in
3617 <ConfigRequest> format. When it doesn't contain
3618 any RequestElement, it will be updated to return
3619 the full RequestElement retrieved from IFR data.
3620 If it points to NULL, the request string for the first
3621 varstore in form package will be merged into a
3622 <MultiConfigRequest> format string and return.
3623 @param AltCfgResp Pointer to a null-terminated Unicode string in
3624 <ConfigAltResp> format. When the pointer is to NULL,
3625 the full default value string retrieved from IFR data
3626 will return. When the pinter is to a string, the
3627 full default value string retrieved from IFR data
3628 will be merged into the input string and return.
3629 When Request points to NULL, the default value string
3630 for each varstore in form package will be merged into
3631 a <MultiConfigAltResp> format string and return.
3632 @param PointerProgress Optional parameter, it can be be NULL.
3633 When it is not NULL, if Request is NULL, it returns NULL.
3634 On return, points to a character in the Request
3635 string. Points to the string's null terminator if
3636 request was successful. Points to the most recent
3637 & before the first failing name / value pair (or
3638 the beginning of the string if the failure is in
3639 the first name / value pair) if the request was
3640 not successful.
3641 @retval EFI_SUCCESS The Results string is set to the full request string.
3642 And AltCfgResp contains all default value string.
3643 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3644 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3645 can't be found in Form package.
3646 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3647 @retval EFI_INVALID_PARAMETER Request points to NULL.
3648
3649 **/
3650 EFI_STATUS
3651 EFIAPI
3652 GetFullStringFromHiiFormPackages (
3653 IN HII_DATABASE_RECORD *DataBaseRecord,
3654 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3655 IN OUT EFI_STRING *Request,
3656 IN OUT EFI_STRING *AltCfgResp,
3657 OUT EFI_STRING *PointerProgress OPTIONAL
3658 )
3659 {
3660 EFI_STATUS Status;
3661 UINT8 *HiiFormPackage;
3662 UINTN PackageSize;
3663 IFR_BLOCK_DATA *RequestBlockArray;
3664 IFR_BLOCK_DATA *BlockData;
3665 IFR_DEFAULT_DATA *DefaultValueData;
3666 IFR_DEFAULT_DATA *DefaultId;
3667 IFR_DEFAULT_DATA *DefaultIdArray;
3668 IFR_VARSTORAGE_DATA *VarStorageData;
3669 EFI_STRING DefaultAltCfgResp;
3670 EFI_STRING ConfigHdr;
3671 EFI_STRING StringPtr;
3672 EFI_STRING Progress;
3673
3674 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
3675 return EFI_INVALID_PARAMETER;
3676 }
3677
3678 //
3679 // Initialize the local variables.
3680 //
3681 RequestBlockArray = NULL;
3682 DefaultIdArray = NULL;
3683 VarStorageData = NULL;
3684 DefaultAltCfgResp = NULL;
3685 ConfigHdr = NULL;
3686 HiiFormPackage = NULL;
3687 PackageSize = 0;
3688 Progress = *Request;
3689
3690 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
3691 if (EFI_ERROR (Status)) {
3692 goto Done;
3693 }
3694
3695 //
3696 // 1. Get the request block array by Request String when Request string containts the block array.
3697 //
3698 StringPtr = NULL;
3699 if (*Request != NULL) {
3700 StringPtr = *Request;
3701 //
3702 // Jump <ConfigHdr>
3703 //
3704 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3705 Status = EFI_INVALID_PARAMETER;
3706 goto Done;
3707 }
3708 StringPtr += StrLen (L"GUID=");
3709 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3710 StringPtr++;
3711 }
3712 if (*StringPtr == L'\0') {
3713 Status = EFI_INVALID_PARAMETER;
3714 goto Done;
3715 }
3716 StringPtr += StrLen (L"&NAME=");
3717 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3718 StringPtr++;
3719 }
3720 if (*StringPtr == L'\0') {
3721 Status = EFI_INVALID_PARAMETER;
3722 goto Done;
3723 }
3724 StringPtr += StrLen (L"&PATH=");
3725 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3726 StringPtr ++;
3727 }
3728
3729 if (*StringPtr == L'\0') {
3730 //
3731 // No request block is found.
3732 //
3733 StringPtr = NULL;
3734 }
3735 }
3736
3737 //
3738 // If StringPtr != NULL, get the request elements.
3739 //
3740 if (StringPtr != NULL) {
3741 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
3742 RequestBlockArray = GetBlockElement(StringPtr, &Progress);
3743 } else {
3744 RequestBlockArray = GetNameElement(StringPtr, &Progress);
3745 }
3746
3747 if (RequestBlockArray == NULL) {
3748 Status = EFI_INVALID_PARAMETER;
3749 goto Done;
3750 }
3751 }
3752
3753 //
3754 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3755 //
3756 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
3757 if (DefaultIdArray == NULL) {
3758 Status = EFI_OUT_OF_RESOURCES;
3759 goto Done;
3760 }
3761 InitializeListHead (&DefaultIdArray->Entry);
3762
3763 //
3764 // Initialize VarStorageData to store the var store Block and Default value information.
3765 //
3766 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
3767 if (VarStorageData == NULL) {
3768 Status = EFI_OUT_OF_RESOURCES;
3769 goto Done;
3770 }
3771 InitializeListHead (&VarStorageData->Entry);
3772 InitializeListHead (&VarStorageData->BlockEntry);
3773
3774 //
3775 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3776 //
3777
3778 //
3779 // Parse the opcode in form pacakge to get the default setting.
3780 //
3781 Status = ParseIfrData (DataBaseRecord->Handle,
3782 HiiFormPackage,
3783 (UINT32) PackageSize,
3784 *Request,
3785 RequestBlockArray,
3786 VarStorageData,
3787 DefaultIdArray);
3788 if (EFI_ERROR (Status)) {
3789 goto Done;
3790 }
3791
3792 //
3793 // No requested varstore in IFR data and directly return
3794 //
3795 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
3796 Status = EFI_SUCCESS;
3797 goto Done;
3798 }
3799
3800 //
3801 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3802 //
3803 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
3804 if (EFI_ERROR (Status)) {
3805 goto Done;
3806 }
3807
3808 if (RequestBlockArray == NULL) {
3809 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
3810 goto Done;
3811 }
3812 }
3813
3814 //
3815 // 4. Construct Default Value string in AltResp according to request element.
3816 // Go through all VarStorageData Entry and get the DefaultId array for each one
3817 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3818 //
3819 Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
3820 if (EFI_ERROR (Status)) {
3821 goto Done;
3822 }
3823
3824 //
3825 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3826 //
3827 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
3828 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
3829 FreePool (DefaultAltCfgResp);
3830 } else if (*AltCfgResp == NULL) {
3831 *AltCfgResp = DefaultAltCfgResp;
3832 }
3833
3834 Done:
3835 if (RequestBlockArray != NULL) {
3836 //
3837 // Free Link Array RequestBlockArray
3838 //
3839 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3840 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3841 RemoveEntryList (&BlockData->Entry);
3842 if (BlockData->Name != NULL) {
3843 FreePool (BlockData->Name);
3844 }
3845 FreePool (BlockData);
3846 }
3847
3848 FreePool (RequestBlockArray);
3849 }
3850
3851 if (VarStorageData != NULL) {
3852 //
3853 // Free link array VarStorageData
3854 //
3855 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
3856 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
3857 RemoveEntryList (&BlockData->Entry);
3858 if (BlockData->Name != NULL) {
3859 FreePool (BlockData->Name);
3860 }
3861 //
3862 // Free default value link array
3863 //
3864 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
3865 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3866 RemoveEntryList (&DefaultValueData->Entry);
3867 FreePool (DefaultValueData);
3868 }
3869 FreePool (BlockData);
3870 }
3871 FreePool (VarStorageData);
3872 }
3873
3874 if (DefaultIdArray != NULL) {
3875 //
3876 // Free DefaultId Array
3877 //
3878 while (!IsListEmpty (&DefaultIdArray->Entry)) {
3879 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3880 RemoveEntryList (&DefaultId->Entry);
3881 FreePool (DefaultId);
3882 }
3883 FreePool (DefaultIdArray);
3884 }
3885
3886 //
3887 // Free the allocated string
3888 //
3889 if (ConfigHdr != NULL) {
3890 FreePool (ConfigHdr);
3891 }
3892
3893 //
3894 // Free Pacakge data
3895 //
3896 if (HiiFormPackage != NULL) {
3897 FreePool (HiiFormPackage);
3898 }
3899
3900 if (PointerProgress != NULL) {
3901 if (*Request == NULL) {
3902 *PointerProgress = NULL;
3903 } else if (EFI_ERROR (Status)) {
3904 *PointerProgress = *Request;
3905 } else {
3906 *PointerProgress = *Request + StrLen (*Request);
3907 }
3908 }
3909
3910 return Status;
3911 }
3912
3913 /**
3914 This function gets the full request resp string by
3915 parsing IFR data in HII form packages.
3916
3917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3918 instance.
3919 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3920 varstore data structure.
3921 @param Request Pointer to a null-terminated Unicode string in
3922 <ConfigRequest> format.
3923 @param RequestResp Pointer to a null-terminated Unicode string in
3924 <ConfigResp> format.
3925 @param AccessProgress On return, points to a character in the Request
3926 string. Points to the string's null terminator if
3927 request was successful. Points to the most recent
3928 & before the first failing name / value pair (or
3929 the beginning of the string if the failure is in
3930 the first name / value pair) if the request was
3931 not successful.
3932
3933 @retval EFI_SUCCESS The Results string is set to the full request string.
3934 And AltCfgResp contains all default value string.
3935 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3936 @retval EFI_INVALID_PARAMETER Request points to NULL.
3937
3938 **/
3939 EFI_STATUS
3940 GetConfigRespFromEfiVarStore (
3941 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3942 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3943 IN EFI_STRING Request,
3944 OUT EFI_STRING *RequestResp,
3945 OUT EFI_STRING *AccessProgress
3946 )
3947 {
3948 EFI_STATUS Status;
3949 EFI_STRING VarStoreName;
3950 UINT8 *VarStore;
3951 UINTN BufferSize;
3952
3953 Status = EFI_SUCCESS;
3954 BufferSize = 0;
3955 VarStore = NULL;
3956 VarStoreName = NULL;
3957 *AccessProgress = Request;
3958
3959 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
3960 if (VarStoreName == NULL) {
3961 Status = EFI_OUT_OF_RESOURCES;
3962 goto Done;
3963 }
3964 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
3965
3966
3967 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3968 if (Status != EFI_BUFFER_TOO_SMALL) {
3969 goto Done;
3970 }
3971
3972 VarStore = AllocateZeroPool (BufferSize);
3973 ASSERT (VarStore != NULL);
3974 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
3975 if (EFI_ERROR (Status)) {
3976 goto Done;
3977 }
3978
3979 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
3980 if (EFI_ERROR (Status)) {
3981 goto Done;
3982 }
3983
3984 Done:
3985 if (VarStoreName != NULL) {
3986 FreePool (VarStoreName);
3987 }
3988
3989 if (VarStore != NULL) {
3990 FreePool (VarStore);
3991 }
3992
3993 return Status;
3994 }
3995
3996
3997 /**
3998 This function route the full request resp string for efi varstore.
3999
4000 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4001 instance.
4002 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4003 varstore data structure.
4004 @param RequestResp Pointer to a null-terminated Unicode string in
4005 <ConfigResp> format.
4006 @param Result Pointer to a null-terminated Unicode string in
4007 <ConfigResp> format.
4008
4009 @retval EFI_SUCCESS The Results string is set to the full request string.
4010 And AltCfgResp contains all default value string.
4011 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4012 @retval EFI_INVALID_PARAMETER Request points to NULL.
4013
4014 **/
4015 EFI_STATUS
4016 RouteConfigRespForEfiVarStore (
4017 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4018 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4019 IN EFI_STRING RequestResp,
4020 OUT EFI_STRING *Result
4021 )
4022 {
4023 EFI_STATUS Status;
4024 EFI_STRING VarStoreName;
4025 UINT8 *VarStore;
4026 UINTN BufferSize;
4027 UINTN BlockSize;
4028
4029 Status = EFI_SUCCESS;
4030 BufferSize = 0;
4031 VarStore = NULL;
4032 VarStoreName = NULL;
4033
4034 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
4035 if (VarStoreName == NULL) {
4036 Status = EFI_OUT_OF_RESOURCES;
4037 goto Done;
4038 }
4039 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
4040
4041 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4042 if (Status != EFI_BUFFER_TOO_SMALL) {
4043 goto Done;
4044 }
4045
4046 BlockSize = BufferSize;
4047 VarStore = AllocateZeroPool (BufferSize);
4048 ASSERT (VarStore != NULL);
4049 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4050 if (EFI_ERROR (Status)) {
4051 goto Done;
4052 }
4053
4054 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
4055 if (EFI_ERROR (Status)) {
4056 goto Done;
4057 }
4058
4059 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
4060 if (EFI_ERROR (Status)) {
4061 goto Done;
4062 }
4063
4064 Done:
4065 if (VarStoreName != NULL) {
4066 FreePool (VarStoreName);
4067 }
4068
4069 if (VarStore != NULL) {
4070 FreePool (VarStore);
4071 }
4072
4073 return Status;
4074 }
4075
4076 /**
4077 Validate the config request elements.
4078
4079 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4080 without configHdr field.
4081
4082 @retval CHAR16 * THE first Name/value pair not correct.
4083 @retval NULL Success parse the name/value pair
4084 **/
4085 CHAR16 *
4086 OffsetWidthValidate (
4087 CHAR16 *ConfigElements
4088 )
4089 {
4090 CHAR16 *StringPtr;
4091 CHAR16 *RetVal;
4092
4093 StringPtr = ConfigElements;
4094
4095 while (1) {
4096 RetVal = StringPtr;
4097 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4098 return RetVal;
4099 }
4100
4101 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4102 StringPtr++;
4103 }
4104 if (*StringPtr == L'\0') {
4105 return RetVal;
4106 }
4107
4108 StringPtr += StrLen (L"&WIDTH=");
4109 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4110 StringPtr ++;
4111 }
4112
4113 if (*StringPtr == L'\0') {
4114 return NULL;
4115 }
4116 }
4117 }
4118
4119 /**
4120 Validate the config request elements.
4121
4122 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4123 without configHdr field.
4124
4125 @retval CHAR16 * THE first Name/value pair not correct.
4126 @retval NULL Success parse the name/value pair
4127
4128 **/
4129 CHAR16 *
4130 NameValueValidate (
4131 CHAR16 *ConfigElements
4132 )
4133 {
4134 CHAR16 *StringPtr;
4135 CHAR16 *RetVal;
4136
4137 StringPtr = ConfigElements;
4138
4139 while (1) {
4140 RetVal = StringPtr;
4141 if (*StringPtr != L'&') {
4142 return RetVal;
4143 }
4144 StringPtr += 1;
4145
4146 StringPtr = StrStr (StringPtr, L"&");
4147
4148 if (StringPtr == NULL) {
4149 return NULL;
4150 }
4151 }
4152 }
4153
4154 /**
4155 Validate the config request string.
4156
4157 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4158
4159 @retval CHAR16 * THE first element not correct.
4160 @retval NULL Success parse the name/value pair
4161
4162 **/
4163 CHAR16 *
4164 ConfigRequestValidate (
4165 CHAR16 *ConfigRequest
4166 )
4167 {
4168 BOOLEAN HasNameField;
4169 CHAR16 *StringPtr;
4170
4171 HasNameField = TRUE;
4172 StringPtr = ConfigRequest;
4173
4174 //
4175 // Check <ConfigHdr>
4176 //
4177 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4178 return ConfigRequest;
4179 }
4180 StringPtr += StrLen (L"GUID=");
4181 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
4182 StringPtr++;
4183 }
4184 if (*StringPtr == L'\0') {
4185 return ConfigRequest;
4186 }
4187 StringPtr += StrLen (L"&NAME=");
4188 if (*StringPtr == L'&') {
4189 HasNameField = FALSE;
4190 }
4191 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
4192 StringPtr++;
4193 }
4194 if (*StringPtr == L'\0') {
4195 return ConfigRequest;
4196 }
4197 StringPtr += StrLen (L"&PATH=");
4198 while (*StringPtr != L'\0' && *StringPtr != L'&') {
4199 StringPtr ++;
4200 }
4201
4202 if (*StringPtr == L'\0') {
4203 return NULL;
4204 }
4205
4206 if (HasNameField) {
4207 //
4208 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4209 //
4210 return OffsetWidthValidate(StringPtr);
4211 } else {
4212 //
4213 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4214 //
4215 return NameValueValidate(StringPtr);
4216 }
4217 }
4218
4219 /**
4220 This function allows a caller to extract the current configuration
4221 for one or more named elements from one or more drivers.
4222
4223 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4224 instance.
4225 @param Request A null-terminated Unicode string in
4226 <MultiConfigRequest> format.
4227 @param Progress On return, points to a character in the Request
4228 string. Points to the string's null terminator if
4229 request was successful. Points to the most recent
4230 & before the first failing name / value pair (or
4231 the beginning of the string if the failure is in
4232 the first name / value pair) if the request was
4233 not successful.
4234 @param Results Null-terminated Unicode string in
4235 <MultiConfigAltResp> format which has all values
4236 filled in for the names in the Request string.
4237 String to be allocated by the called function.
4238
4239 @retval EFI_SUCCESS The Results string is filled with the values
4240 corresponding to all requested names.
4241 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4242 results that must be stored awaiting possible
4243 future protocols.
4244 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4245 Progress set to the "G" in "GUID" of the routing
4246 header that doesn't match. Note: There is no
4247 requirement that all routing data be validated
4248 before any configuration extraction.
4249 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4250 parameter would result in this type of error. The
4251 Progress parameter is set to NULL.
4252 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4253 before the error or the beginning of the string.
4254 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4255 Configuration Access Protocol returned
4256 EFI_INVALID_PARAMETER. Progress set to most recent
4257 & before the error or the beginning of the string.
4258
4259 **/
4260 EFI_STATUS
4261 EFIAPI
4262 HiiConfigRoutingExtractConfig (
4263 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4264 IN CONST EFI_STRING Request,
4265 OUT EFI_STRING *Progress,
4266 OUT EFI_STRING *Results
4267 )
4268 {
4269 HII_DATABASE_PRIVATE_DATA *Private;
4270 EFI_STRING StringPtr;
4271 EFI_STRING ConfigRequest;
4272 UINTN Length;
4273 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4274 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4275 EFI_STATUS Status;
4276 LIST_ENTRY *Link;
4277 HII_DATABASE_RECORD *Database;
4278 UINT8 *DevicePathPkg;
4279 UINT8 *CurrentDevicePath;
4280 EFI_HANDLE DriverHandle;
4281 EFI_HII_HANDLE HiiHandle;
4282 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4283 EFI_STRING AccessProgress;
4284 EFI_STRING AccessResults;
4285 EFI_STRING AccessProgressBackup;
4286 EFI_STRING AccessResultsBackup;
4287 EFI_STRING DefaultResults;
4288 BOOLEAN FirstElement;
4289 BOOLEAN IfrDataParsedFlag;
4290 BOOLEAN IsEfiVarStore;
4291 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4292 EFI_STRING ErrorPtr;
4293 UINTN DevicePathSize;
4294 UINTN ConigStringSize;
4295 UINTN ConigStringSizeNewsize;
4296 EFI_STRING ConfigStringPtr;
4297
4298 if (This == NULL || Progress == NULL || Results == NULL) {
4299 return EFI_INVALID_PARAMETER;
4300 }
4301
4302 if (Request == NULL) {
4303 *Progress = NULL;
4304 return EFI_INVALID_PARAMETER;
4305 }
4306
4307 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4308 StringPtr = Request;
4309 *Progress = StringPtr;
4310 DefaultResults = NULL;
4311 ConfigRequest = NULL;
4312 Status = EFI_SUCCESS;
4313 AccessResults = NULL;
4314 AccessProgress = NULL;
4315 AccessResultsBackup = NULL;
4316 AccessProgressBackup = NULL;
4317 DevicePath = NULL;
4318 IfrDataParsedFlag = FALSE;
4319 IsEfiVarStore = FALSE;
4320 EfiVarStoreInfo = NULL;
4321
4322 //
4323 // The first element of <MultiConfigRequest> should be
4324 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4325 //
4326 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4327 return EFI_INVALID_PARAMETER;
4328 }
4329
4330 FirstElement = TRUE;
4331
4332 //
4333 // Allocate a fix length of memory to store Results. Reallocate memory for
4334 // Results if this fix length is insufficient.
4335 //
4336 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4337 if (*Results == NULL) {
4338 return EFI_OUT_OF_RESOURCES;
4339 }
4340
4341 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4342 //
4343 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4344 // or most recent & before the error.
4345 //
4346 if (StringPtr == Request) {
4347 *Progress = StringPtr;
4348 } else {
4349 *Progress = StringPtr - 1;
4350 }
4351
4352 //
4353 // Process each <ConfigRequest> of <MultiConfigRequest>
4354 //
4355 Length = CalculateConfigStringLen (StringPtr);
4356 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4357 if (ConfigRequest == NULL) {
4358 Status = EFI_OUT_OF_RESOURCES;
4359 goto Done;
4360 }
4361 *(ConfigRequest + Length) = 0;
4362
4363 //
4364 // Get the UEFI device path
4365 //
4366 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
4367 if (EFI_ERROR (Status)) {
4368 goto Done;
4369 }
4370
4371 //
4372 // Find driver which matches the routing data.
4373 //
4374 DriverHandle = NULL;
4375 HiiHandle = NULL;
4376 Database = NULL;
4377 for (Link = Private->DatabaseList.ForwardLink;
4378 Link != &Private->DatabaseList;
4379 Link = Link->ForwardLink
4380 ) {
4381 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4382 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4383 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4384 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4385 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
4386 DriverHandle = Database->DriverHandle;
4387 HiiHandle = Database->Handle;
4388 break;
4389 }
4390 }
4391 }
4392
4393 //
4394 // Try to find driver handle by device path.
4395 //
4396 if (DriverHandle == NULL) {
4397 TempDevicePath = DevicePath;
4398 Status = gBS->LocateDevicePath (
4399 &gEfiDevicePathProtocolGuid,
4400 &TempDevicePath,
4401 &DriverHandle
4402 );
4403 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4404 //
4405 // Routing data does not match any known driver.
4406 // Set Progress to the 'G' in "GUID" of the routing header.
4407 //
4408 *Progress = StringPtr;
4409 Status = EFI_NOT_FOUND;
4410 goto Done;
4411 }
4412 }
4413
4414 //
4415 // Validate ConfigRequest String.
4416 //
4417 ErrorPtr = ConfigRequestValidate(ConfigRequest);
4418 if (ErrorPtr != NULL) {
4419 *Progress = StrStr (StringPtr, ErrorPtr);
4420 Status = EFI_INVALID_PARAMETER;
4421 goto Done;
4422 }
4423
4424 //
4425 // Check whether ConfigRequest contains request string.
4426 //
4427 IfrDataParsedFlag = FALSE;
4428 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
4429 //
4430 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4431 //
4432 IfrDataParsedFlag = TRUE;
4433 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
4434 if (EFI_ERROR (Status)) {
4435 //
4436 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4437 // Map it to the progress on <MultiConfigRequest> then return it.
4438 //
4439 ASSERT (AccessProgress != NULL);
4440 *Progress = StrStr (StringPtr, AccessProgress);
4441 goto Done;
4442 }
4443 //
4444 // Not any request block is found.
4445 //
4446 if (!GetElementsFromRequest(ConfigRequest)) {
4447 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
4448 goto NextConfigString;
4449 }
4450 }
4451
4452 //
4453 // Check whether this ConfigRequest is search from Efi varstore type storage.
4454 //
4455 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
4456 if (EFI_ERROR (Status)) {
4457 goto Done;
4458 }
4459
4460 if (IsEfiVarStore) {
4461 //
4462 // Call the GetVariable function to extract settings.
4463 //
4464 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
4465 FreePool (EfiVarStoreInfo);
4466 if (EFI_ERROR (Status)) {
4467 //
4468 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4469 // Map it to the progress on <MultiConfigRequest> then return it.
4470 //
4471 *Progress = StrStr (StringPtr, AccessProgress);
4472 goto Done;
4473 }
4474
4475 //
4476 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4477 //
4478 Status = gBS->HandleProtocol (
4479 DriverHandle,
4480 &gEfiHiiConfigAccessProtocolGuid,
4481 (VOID **) &ConfigAccess
4482 );
4483 if (EFI_ERROR (Status)) {
4484 //
4485 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4486 // So ignore the error status in this case.
4487 //
4488 Status = EFI_SUCCESS;
4489 } else {
4490 Status = ConfigAccess->ExtractConfig (
4491 ConfigAccess,
4492 ConfigRequest,
4493 &AccessProgressBackup,
4494 &AccessResultsBackup
4495 );
4496 if (!EFI_ERROR(Status)) {
4497 //
4498 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4499 //
4500 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
4501 ConigStringSize = StrSize (AccessResults);
4502 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
4503 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
4504 AccessResults = (EFI_STRING) ReallocatePool (
4505 ConigStringSize,
4506 ConigStringSizeNewsize,
4507 AccessResults);
4508 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
4509 }
4510 } else {
4511 //
4512 // In the ExtractConfig function of some driver may not support EfiVarStore,
4513 // may return error status, just ignore the error status in this case.
4514 //
4515 Status = EFI_SUCCESS;
4516 }
4517 if (AccessResultsBackup != NULL) {
4518 FreePool (AccessResultsBackup);
4519 AccessResultsBackup = NULL;
4520 }
4521 }
4522 } else {
4523 //
4524 // Call corresponding ConfigAccess protocol to extract settings
4525 //
4526 Status = gBS->HandleProtocol (
4527 DriverHandle,
4528 &gEfiHiiConfigAccessProtocolGuid,
4529 (VOID **) &ConfigAccess
4530 );
4531 if (EFI_ERROR (Status)) {
4532 goto Done;
4533 }
4534
4535 Status = ConfigAccess->ExtractConfig (
4536 ConfigAccess,
4537 ConfigRequest,
4538 &AccessProgress,
4539 &AccessResults
4540 );
4541 }
4542 if (EFI_ERROR (Status)) {
4543 //
4544 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4545 // Map it to the progress on <MultiConfigRequest> then return it.
4546 //
4547 *Progress = StrStr (StringPtr, AccessProgress);
4548 goto Done;
4549 }
4550
4551 //
4552 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4553 // which seperates the first <ConfigAltResp> and the following ones.
4554 //
4555 ASSERT (*AccessProgress == 0);
4556
4557 //
4558 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4559 //
4560 if (!IfrDataParsedFlag && HiiHandle != NULL) {
4561 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4562 ASSERT_EFI_ERROR (Status);
4563 }
4564
4565 FreePool (DevicePath);
4566 DevicePath = NULL;
4567
4568 if (DefaultResults != NULL) {
4569 Status = MergeDefaultString (&AccessResults, DefaultResults);
4570 ASSERT_EFI_ERROR (Status);
4571 FreePool (DefaultResults);
4572 DefaultResults = NULL;
4573 }
4574
4575 NextConfigString:
4576 if (!FirstElement) {
4577 Status = AppendToMultiString (Results, L"&");
4578 ASSERT_EFI_ERROR (Status);
4579 }
4580
4581 Status = AppendToMultiString (Results, AccessResults);
4582 ASSERT_EFI_ERROR (Status);
4583
4584 FirstElement = FALSE;
4585
4586 FreePool (AccessResults);
4587 AccessResults = NULL;
4588 FreePool (ConfigRequest);
4589 ConfigRequest = NULL;
4590
4591 //
4592 // Go to next <ConfigRequest> (skip '&').
4593 //
4594 StringPtr += Length;
4595 if (*StringPtr == 0) {
4596 *Progress = StringPtr;
4597 break;
4598 }
4599
4600 StringPtr++;
4601 }
4602
4603 Done:
4604 if (EFI_ERROR (Status)) {
4605 FreePool (*Results);
4606 *Results = NULL;
4607 }
4608
4609 if (ConfigRequest != NULL) {
4610 FreePool (ConfigRequest);
4611 }
4612
4613 if (AccessResults != NULL) {
4614 FreePool (AccessResults);
4615 }
4616
4617 if (DefaultResults != NULL) {
4618 FreePool (DefaultResults);
4619 }
4620
4621 if (DevicePath != NULL) {
4622 FreePool (DevicePath);
4623 }
4624
4625 return Status;
4626 }
4627
4628
4629 /**
4630 This function allows the caller to request the current configuration for the
4631 entirety of the current HII database and returns the data in a
4632 null-terminated Unicode string.
4633
4634 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4635 instance.
4636 @param Results Null-terminated Unicode string in
4637 <MultiConfigAltResp> format which has all values
4638 filled in for the entirety of the current HII
4639 database. String to be allocated by the called
4640 function. De-allocation is up to the caller.
4641
4642 @retval EFI_SUCCESS The Results string is filled with the values
4643 corresponding to all requested names.
4644 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4645 results that must be stored awaiting possible
4646 future protocols.
4647 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4648 parameter would result in this type of error.
4649
4650 **/
4651 EFI_STATUS
4652 EFIAPI
4653 HiiConfigRoutingExportConfig (
4654 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4655 OUT EFI_STRING *Results
4656 )
4657 {
4658 EFI_STATUS Status;
4659 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4660 EFI_STRING AccessResults;
4661 EFI_STRING Progress;
4662 EFI_STRING StringPtr;
4663 EFI_STRING ConfigRequest;
4664 UINTN Index;
4665 EFI_HANDLE *ConfigAccessHandles;
4666 UINTN NumberConfigAccessHandles;
4667 BOOLEAN FirstElement;
4668 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4669 EFI_HII_HANDLE HiiHandle;
4670 EFI_STRING DefaultResults;
4671 HII_DATABASE_PRIVATE_DATA *Private;
4672 LIST_ENTRY *Link;
4673 HII_DATABASE_RECORD *Database;
4674 UINT8 *DevicePathPkg;
4675 UINT8 *CurrentDevicePath;
4676 BOOLEAN IfrDataParsedFlag;
4677
4678 if (This == NULL || Results == NULL) {
4679 return EFI_INVALID_PARAMETER;
4680 }
4681
4682 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4683
4684 //
4685 // Allocate a fix length of memory to store Results. Reallocate memory for
4686 // Results if this fix length is insufficient.
4687 //
4688 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4689 if (*Results == NULL) {
4690 return EFI_OUT_OF_RESOURCES;
4691 }
4692
4693 NumberConfigAccessHandles = 0;
4694 Status = gBS->LocateHandleBuffer (
4695 ByProtocol,
4696 &gEfiHiiConfigAccessProtocolGuid,
4697 NULL,
4698 &NumberConfigAccessHandles,
4699 &ConfigAccessHandles
4700 );
4701 if (EFI_ERROR (Status)) {
4702 return Status;
4703 }
4704
4705 FirstElement = TRUE;
4706
4707 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
4708 Status = gBS->HandleProtocol (
4709 ConfigAccessHandles[Index],
4710 &gEfiHiiConfigAccessProtocolGuid,
4711 (VOID **) &ConfigAccess
4712 );
4713 if (EFI_ERROR (Status)) {
4714 continue;
4715 }
4716
4717 //
4718 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4719 //
4720 IfrDataParsedFlag = FALSE;
4721 Progress = NULL;
4722 HiiHandle = NULL;
4723 DefaultResults = NULL;
4724 Database = NULL;
4725 ConfigRequest = NULL;
4726 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
4727 if (DevicePath != NULL) {
4728 for (Link = Private->DatabaseList.ForwardLink;
4729 Link != &Private->DatabaseList;
4730 Link = Link->ForwardLink
4731 ) {
4732 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4733 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4734 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4735 if (CompareMem (
4736 DevicePath,
4737 CurrentDevicePath,
4738 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
4739 ) == 0) {
4740 HiiHandle = Database->Handle;
4741 break;
4742 }
4743 }
4744 }
4745 }
4746
4747 Status = ConfigAccess->ExtractConfig (
4748 ConfigAccess,
4749 NULL,
4750 &Progress,
4751 &AccessResults
4752 );
4753 if (EFI_ERROR (Status)) {
4754 //
4755 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4756 //
4757 if (HiiHandle != NULL && DevicePath != NULL) {
4758 IfrDataParsedFlag = TRUE;
4759 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4760 //
4761 // Get the full request string to get the Current setting again.
4762 //
4763 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
4764 Status = ConfigAccess->ExtractConfig (
4765 ConfigAccess,
4766 ConfigRequest,
4767 &Progress,
4768 &AccessResults
4769 );
4770 FreePool (ConfigRequest);
4771 } else {
4772 Status = EFI_NOT_FOUND;
4773 }
4774 }
4775 }
4776
4777 if (!EFI_ERROR (Status)) {
4778 //
4779 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4780 //
4781 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
4782 StringPtr = StrStr (AccessResults, L"&GUID=");
4783 if (StringPtr != NULL) {
4784 *StringPtr = 0;
4785 }
4786 if (GetElementsFromRequest (AccessResults)) {
4787 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
4788 ASSERT_EFI_ERROR (Status);
4789 }
4790 if (StringPtr != NULL) {
4791 *StringPtr = L'&';
4792 }
4793 }
4794 //
4795 // Merge the default sting from IFR code into the got setting from driver.
4796 //
4797 if (DefaultResults != NULL) {
4798 Status = MergeDefaultString (&AccessResults, DefaultResults);
4799 ASSERT_EFI_ERROR (Status);
4800 FreePool (DefaultResults);
4801 DefaultResults = NULL;
4802 }
4803
4804 //
4805 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4806 // which seperates the first <ConfigAltResp> and the following ones.
4807 //
4808 if (!FirstElement) {
4809 Status = AppendToMultiString (Results, L"&");
4810 ASSERT_EFI_ERROR (Status);
4811 }
4812
4813 Status = AppendToMultiString (Results, AccessResults);
4814 ASSERT_EFI_ERROR (Status);
4815
4816 FirstElement = FALSE;
4817
4818 FreePool (AccessResults);
4819 AccessResults = NULL;
4820 }
4821 }
4822 FreePool (ConfigAccessHandles);
4823
4824 return EFI_SUCCESS;
4825 }
4826
4827
4828 /**
4829 This function processes the results of processing forms and routes it to the
4830 appropriate handlers or storage.
4831
4832 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4833 instance.
4834 @param Configuration A null-terminated Unicode string in
4835 <MulltiConfigResp> format.
4836 @param Progress A pointer to a string filled in with the offset of
4837 the most recent & before the first failing name /
4838 value pair (or the beginning of the string if the
4839 failure is in the first name / value pair) or the
4840 terminating NULL if all was successful.
4841
4842 @retval EFI_SUCCESS The results have been distributed or are awaiting
4843 distribution.
4844 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4845 results that must be stored awaiting possible
4846 future protocols.
4847 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4848 would result in this type of error.
4849 @retval EFI_NOT_FOUND Target for the specified routing data was not
4850 found.
4851
4852 **/
4853 EFI_STATUS
4854 EFIAPI
4855 HiiConfigRoutingRouteConfig (
4856 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4857 IN CONST EFI_STRING Configuration,
4858 OUT EFI_STRING *Progress
4859 )
4860 {
4861 HII_DATABASE_PRIVATE_DATA *Private;
4862 EFI_STRING StringPtr;
4863 EFI_STRING ConfigResp;
4864 UINTN Length;
4865 EFI_STATUS Status;
4866 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4867 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4868 LIST_ENTRY *Link;
4869 HII_DATABASE_RECORD *Database;
4870 UINT8 *DevicePathPkg;
4871 UINT8 *CurrentDevicePath;
4872 EFI_HANDLE DriverHandle;
4873 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4874 EFI_STRING AccessProgress;
4875 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4876 BOOLEAN IsEfiVarstore;
4877 UINTN DevicePathSize;
4878
4879 if (This == NULL || Progress == NULL) {
4880 return EFI_INVALID_PARAMETER;
4881 }
4882
4883 if (Configuration == NULL) {
4884 *Progress = NULL;
4885 return EFI_INVALID_PARAMETER;
4886 }
4887
4888 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4889 StringPtr = Configuration;
4890 *Progress = StringPtr;
4891 Database = NULL;
4892 AccessProgress = NULL;
4893 EfiVarStoreInfo= NULL;
4894 IsEfiVarstore = FALSE;
4895
4896 //
4897 // The first element of <MultiConfigResp> should be
4898 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4899 //
4900 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4901 return EFI_INVALID_PARAMETER;
4902 }
4903
4904 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4905 //
4906 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4907 // or most recent & before the error.
4908 //
4909 if (StringPtr == Configuration) {
4910 *Progress = StringPtr;
4911 } else {
4912 *Progress = StringPtr - 1;
4913 }
4914
4915 //
4916 // Process each <ConfigResp> of <MultiConfigResp>
4917 //
4918 Length = CalculateConfigStringLen (StringPtr);
4919 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4920 if (ConfigResp == NULL) {
4921 return EFI_OUT_OF_RESOURCES;
4922 }
4923 //
4924 // Append '\0' to the end of ConfigRequest
4925 //
4926 *(ConfigResp + Length) = 0;
4927
4928 //
4929 // Get the UEFI device path
4930 //
4931 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
4932 if (EFI_ERROR (Status)) {
4933 FreePool (ConfigResp);
4934 return Status;
4935 }
4936
4937 //
4938 // Find driver which matches the routing data.
4939 //
4940 DriverHandle = NULL;
4941 for (Link = Private->DatabaseList.ForwardLink;
4942 Link != &Private->DatabaseList;
4943 Link = Link->ForwardLink
4944 ) {
4945 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4946
4947 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4948 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4949 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4950 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
4951 DriverHandle = Database->DriverHandle;
4952 break;
4953 }
4954 }
4955 }
4956
4957 //
4958 // Try to find driver handle by device path.
4959 //
4960 if (DriverHandle == NULL) {
4961 TempDevicePath = DevicePath;
4962 Status = gBS->LocateDevicePath (
4963 &gEfiDevicePathProtocolGuid,
4964 &TempDevicePath,
4965 &DriverHandle
4966 );
4967 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4968 //
4969 // Routing data does not match any known driver.
4970 // Set Progress to the 'G' in "GUID" of the routing header.
4971 //
4972 FreePool (DevicePath);
4973 *Progress = StringPtr;
4974 FreePool (ConfigResp);
4975 return EFI_NOT_FOUND;
4976 }
4977 }
4978
4979 FreePool (DevicePath);
4980
4981 //
4982 // Check whether this ConfigRequest is search from Efi varstore type storage.
4983 //
4984 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
4985 if (EFI_ERROR (Status)) {
4986 return Status;
4987 }
4988
4989 if (IsEfiVarstore) {
4990 //
4991 // Call the SetVariable function to route settings.
4992 //
4993 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
4994 FreePool (EfiVarStoreInfo);
4995 } else {
4996 //
4997 // Call corresponding ConfigAccess protocol to route settings
4998 //
4999 Status = gBS->HandleProtocol (
5000 DriverHandle,
5001 &gEfiHiiConfigAccessProtocolGuid,
5002 (VOID **) &ConfigAccess
5003 );
5004 if (EFI_ERROR (Status)) {
5005 *Progress = StringPtr;
5006 FreePool (ConfigResp);
5007 return EFI_NOT_FOUND;
5008 }
5009
5010 Status = ConfigAccess->RouteConfig (
5011 ConfigAccess,
5012 ConfigResp,
5013 &AccessProgress
5014 );
5015 }
5016 if (EFI_ERROR (Status)) {
5017 ASSERT (AccessProgress != NULL);
5018 //
5019 // AccessProgress indicates the parsing progress on <ConfigResp>.
5020 // Map it to the progress on <MultiConfigResp> then return it.
5021 //
5022 *Progress = StrStr (StringPtr, AccessProgress);
5023
5024 FreePool (ConfigResp);
5025 return Status;
5026 }
5027
5028 FreePool (ConfigResp);
5029 ConfigResp = NULL;
5030
5031 //
5032 // Go to next <ConfigResp> (skip '&').
5033 //
5034 StringPtr += Length;
5035 if (*StringPtr == 0) {
5036 *Progress = StringPtr;
5037 break;
5038 }
5039
5040 StringPtr++;
5041
5042 }
5043
5044 return EFI_SUCCESS;
5045 }
5046
5047
5048 /**
5049 This helper function is to be called by drivers to map configuration data
5050 stored in byte array ("block") formats such as UEFI Variables into current
5051 configuration strings.
5052
5053 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5054 instance.
5055 @param ConfigRequest A null-terminated Unicode string in
5056 <ConfigRequest> format.
5057 @param Block Array of bytes defining the block's configuration.
5058 @param BlockSize Length in bytes of Block.
5059 @param Config Filled-in configuration string. String allocated
5060 by the function. Returned only if call is
5061 successful. It is <ConfigResp> string format.
5062 @param Progress A pointer to a string filled in with the offset of
5063 the most recent & before the first failing
5064 name/value pair (or the beginning of the string if
5065 the failure is in the first name / value pair) or
5066 the terminating NULL if all was successful.
5067
5068 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5069 terminator at the end of the ConfigRequest
5070 string.
5071 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5072 points to the first character of ConfigRequest.
5073 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5074 Block parameter would result in this type of
5075 error. Progress points to the first character of
5076 ConfigRequest.
5077 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5078 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5079 Block is left updated and Progress points at
5080 the "&" preceding the first non-<BlockName>.
5081
5082 **/
5083 EFI_STATUS
5084 EFIAPI
5085 HiiBlockToConfig (
5086 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5087 IN CONST EFI_STRING ConfigRequest,
5088 IN CONST UINT8 *Block,
5089 IN CONST UINTN BlockSize,
5090 OUT EFI_STRING *Config,
5091 OUT EFI_STRING *Progress
5092 )
5093 {
5094 HII_DATABASE_PRIVATE_DATA *Private;
5095 EFI_STRING StringPtr;
5096 UINTN Length;
5097 EFI_STATUS Status;
5098 EFI_STRING TmpPtr;
5099 UINT8 *TmpBuffer;
5100 UINTN Offset;
5101 UINTN Width;
5102 UINT8 *Value;
5103 EFI_STRING ValueStr;
5104 EFI_STRING ConfigElement;
5105 UINTN Index;
5106 UINT8 *TemBuffer;
5107 CHAR16 *TemString;
5108 CHAR16 TemChar;
5109
5110 TmpBuffer = NULL;
5111
5112 if (This == NULL || Progress == NULL || Config == NULL) {
5113 return EFI_INVALID_PARAMETER;
5114 }
5115
5116 if (Block == NULL || ConfigRequest == NULL) {
5117 *Progress = ConfigRequest;
5118 return EFI_INVALID_PARAMETER;
5119 }
5120
5121
5122 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5123 ASSERT (Private != NULL);
5124
5125 StringPtr = ConfigRequest;
5126 ValueStr = NULL;
5127 Value = NULL;
5128 ConfigElement = NULL;
5129
5130 //
5131 // Allocate a fix length of memory to store Results. Reallocate memory for
5132 // Results if this fix length is insufficient.
5133 //
5134 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
5135 if (*Config == NULL) {
5136 return EFI_OUT_OF_RESOURCES;
5137 }
5138
5139 //
5140 // Jump <ConfigHdr>
5141 //
5142 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5143 *Progress = StringPtr;
5144 Status = EFI_INVALID_PARAMETER;
5145 goto Exit;
5146 }
5147 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5148 StringPtr++;
5149 }
5150 if (*StringPtr == 0) {
5151 *Progress = StringPtr - 1;
5152 Status = EFI_INVALID_PARAMETER;
5153 goto Exit;
5154 }
5155
5156 while (*StringPtr != L'&' && *StringPtr != 0) {
5157 StringPtr++;
5158 }
5159 if (*StringPtr == 0) {
5160 *Progress = StringPtr;
5161
5162 AppendToMultiString(Config, ConfigRequest);
5163 HiiToLower (*Config);
5164
5165 return EFI_SUCCESS;
5166 }
5167 //
5168 // Skip '&'
5169 //
5170 StringPtr++;
5171
5172 //
5173 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5174 //
5175 TemChar = *StringPtr;
5176 *StringPtr = '\0';
5177 AppendToMultiString(Config, ConfigRequest);
5178 *StringPtr = TemChar;
5179
5180 //
5181 // Parse each <RequestElement> if exists
5182 // Only <BlockName> format is supported by this help function.
5183 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5184 //
5185 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
5186 //
5187 // Back up the header of one <BlockName>
5188 //
5189 TmpPtr = StringPtr;
5190
5191 StringPtr += StrLen (L"OFFSET=");
5192 //
5193 // Get Offset
5194 //
5195 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5196 if (EFI_ERROR (Status)) {
5197 *Progress = TmpPtr - 1;
5198 goto Exit;
5199 }
5200 Offset = 0;
5201 CopyMem (
5202 &Offset,
5203 TmpBuffer,
5204 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5205 );
5206 FreePool (TmpBuffer);
5207
5208 StringPtr += Length;
5209 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5210 *Progress = TmpPtr - 1;
5211 Status = EFI_INVALID_PARAMETER;
5212 goto Exit;
5213 }
5214 StringPtr += StrLen (L"&WIDTH=");
5215
5216 //
5217 // Get Width
5218 //
5219 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5220 if (EFI_ERROR (Status)) {
5221 *Progress = TmpPtr - 1;
5222 goto Exit;
5223 }
5224 Width = 0;
5225 CopyMem (
5226 &Width,
5227 TmpBuffer,
5228 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5229 );
5230 FreePool (TmpBuffer);
5231
5232 StringPtr += Length;
5233 if (*StringPtr != 0 && *StringPtr != L'&') {
5234 *Progress = TmpPtr - 1;
5235 Status = EFI_INVALID_PARAMETER;
5236 goto Exit;
5237 }
5238
5239 //
5240 // Calculate Value and convert it to hex string.
5241 //
5242 if (Offset + Width > BlockSize) {
5243 *Progress = StringPtr;
5244 Status = EFI_DEVICE_ERROR;
5245 goto Exit;
5246 }
5247
5248 Value = (UINT8 *) AllocateZeroPool (Width);
5249 if (Value == NULL) {
5250 *Progress = ConfigRequest;
5251 Status = EFI_OUT_OF_RESOURCES;
5252 goto Exit;
5253 }
5254
5255 CopyMem (Value, (UINT8 *) Block + Offset, Width);
5256
5257 Length = Width * 2 + 1;
5258 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5259 if (ValueStr == NULL) {
5260 *Progress = ConfigRequest;
5261 Status = EFI_OUT_OF_RESOURCES;
5262 goto Exit;
5263 }
5264
5265 TemString = ValueStr;
5266 TemBuffer = Value + Width - 1;
5267 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
5268 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
5269 }
5270
5271 FreePool (Value);
5272 Value = NULL;
5273
5274 //
5275 // Build a ConfigElement
5276 //
5277 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
5278 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5279 if (ConfigElement == NULL) {
5280 Status = EFI_OUT_OF_RESOURCES;
5281 goto Exit;
5282 }
5283 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
5284 if (*StringPtr == 0) {
5285 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
5286 }
5287 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
5288 StrCatS (ConfigElement, Length, L"VALUE=");
5289 StrCatS (ConfigElement, Length, ValueStr);
5290
5291 AppendToMultiString (Config, ConfigElement);
5292
5293 FreePool (ConfigElement);
5294 FreePool (ValueStr);
5295 ConfigElement = NULL;
5296 ValueStr = NULL;
5297
5298 //
5299 // If '\0', parsing is finished. Otherwise skip '&' to continue
5300 //
5301 if (*StringPtr == 0) {
5302 break;
5303 }
5304 AppendToMultiString (Config, L"&");
5305 StringPtr++;
5306
5307 }
5308
5309 if (*StringPtr != 0) {
5310 *Progress = StringPtr - 1;
5311 Status = EFI_INVALID_PARAMETER;
5312 goto Exit;
5313 }
5314
5315 HiiToLower (*Config);
5316 *Progress = StringPtr;
5317 return EFI_SUCCESS;
5318
5319 Exit:
5320 if (*Config != NULL) {
5321 FreePool (*Config);
5322 *Config = NULL;
5323 }
5324 if (ValueStr != NULL) {
5325 FreePool (ValueStr);
5326 }
5327 if (Value != NULL) {
5328 FreePool (Value);
5329 }
5330 if (ConfigElement != NULL) {
5331 FreePool (ConfigElement);
5332 }
5333
5334 return Status;
5335
5336 }
5337
5338
5339 /**
5340 This helper function is to be called by drivers to map configuration strings
5341 to configurations stored in byte array ("block") formats such as UEFI Variables.
5342
5343 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5344 instance.
5345 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5346 format.
5347 @param Block A possibly null array of bytes representing the
5348 current block. Only bytes referenced in the
5349 ConfigResp string in the block are modified. If
5350 this parameter is null or if the *BlockSize
5351 parameter is (on input) shorter than required by
5352 the Configuration string, only the BlockSize
5353 parameter is updated and an appropriate status
5354 (see below) is returned.
5355 @param BlockSize The length of the Block in units of UINT8. On
5356 input, this is the size of the Block. On output,
5357 if successful, contains the largest index of the
5358 modified byte in the Block, or the required buffer
5359 size if the Block is not large enough.
5360 @param Progress On return, points to an element of the ConfigResp
5361 string filled in with the offset of the most
5362 recent '&' before the first failing name / value
5363 pair (or the beginning of the string if the
5364 failure is in the first name / value pair) or the
5365 terminating NULL if all was successful.
5366
5367 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5368 terminator at the end of the ConfigResp string.
5369 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5370 points to the first character of ConfigResp.
5371 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5372 Block parameter would result in this type of
5373 error. Progress points to the first character of
5374 ConfigResp.
5375 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5376 value pair. Block is left updated and
5377 Progress points at the '&' preceding the first
5378 non-<BlockName>.
5379 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5380 BlockSize is updated with the required buffer size.
5381 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5382 Progress points to the "G" in "GUID" of the errant
5383 routing data.
5384
5385 **/
5386 EFI_STATUS
5387 EFIAPI
5388 HiiConfigToBlock (
5389 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5390 IN CONST EFI_STRING ConfigResp,
5391 IN OUT UINT8 *Block,
5392 IN OUT UINTN *BlockSize,
5393 OUT EFI_STRING *Progress
5394 )
5395 {
5396 HII_DATABASE_PRIVATE_DATA *Private;
5397 EFI_STRING StringPtr;
5398 EFI_STRING TmpPtr;
5399 UINTN Length;
5400 EFI_STATUS Status;
5401 UINT8 *TmpBuffer;
5402 UINTN Offset;
5403 UINTN Width;
5404 UINT8 *Value;
5405 UINTN BufferSize;
5406 UINTN MaxBlockSize;
5407
5408 TmpBuffer = NULL;
5409
5410 if (This == NULL || BlockSize == NULL || Progress == NULL) {
5411 return EFI_INVALID_PARAMETER;
5412 }
5413
5414 *Progress = ConfigResp;
5415 if (ConfigResp == NULL) {
5416 return EFI_INVALID_PARAMETER;
5417 }
5418
5419 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5420 ASSERT (Private != NULL);
5421
5422 StringPtr = ConfigResp;
5423 BufferSize = *BlockSize;
5424 Value = NULL;
5425 MaxBlockSize = 0;
5426
5427 //
5428 // Jump <ConfigHdr>
5429 //
5430 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5431 *Progress = StringPtr;
5432 Status = EFI_INVALID_PARAMETER;
5433 goto Exit;
5434 }
5435 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5436 StringPtr++;
5437 }
5438 if (*StringPtr == 0) {
5439 *Progress = StringPtr;
5440 Status = EFI_INVALID_PARAMETER;
5441 goto Exit;
5442 }
5443
5444 while (*StringPtr != L'&' && *StringPtr != 0) {
5445 StringPtr++;
5446 }
5447 if (*StringPtr == 0) {
5448 *Progress = StringPtr;
5449 Status = EFI_INVALID_PARAMETER;
5450 goto Exit;
5451 }
5452
5453 //
5454 // Parse each <ConfigElement> if exists
5455 // Only '&'<BlockConfig> format is supported by this help function.
5456 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5457 //
5458 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
5459 TmpPtr = StringPtr;
5460 StringPtr += StrLen (L"&OFFSET=");
5461 //
5462 // Get Offset
5463 //
5464 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5465 if (EFI_ERROR (Status)) {
5466 *Progress = TmpPtr;
5467 goto Exit;
5468 }
5469 Offset = 0;
5470 CopyMem (
5471 &Offset,
5472 TmpBuffer,
5473 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5474 );
5475 FreePool (TmpBuffer);
5476
5477 StringPtr += Length;
5478 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5479 *Progress = TmpPtr;
5480 Status = EFI_INVALID_PARAMETER;
5481 goto Exit;
5482 }
5483 StringPtr += StrLen (L"&WIDTH=");
5484
5485 //
5486 // Get Width
5487 //
5488 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5489 if (EFI_ERROR (Status)) {
5490 *Progress = TmpPtr;
5491 goto Exit;
5492 }
5493 Width = 0;
5494 CopyMem (
5495 &Width,
5496 TmpBuffer,
5497 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5498 );
5499 FreePool (TmpBuffer);
5500
5501 StringPtr += Length;
5502 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
5503 *Progress = TmpPtr;
5504 Status = EFI_INVALID_PARAMETER;
5505 goto Exit;
5506 }
5507 StringPtr += StrLen (L"&VALUE=");
5508
5509 //
5510 // Get Value
5511 //
5512 Status = GetValueOfNumber (StringPtr, &Value, &Length);
5513 if (EFI_ERROR (Status)) {
5514 *Progress = TmpPtr;
5515 goto Exit;
5516 }
5517
5518 StringPtr += Length;
5519 if (*StringPtr != 0 && *StringPtr != L'&') {
5520 *Progress = TmpPtr;
5521 Status = EFI_INVALID_PARAMETER;
5522 goto Exit;
5523 }
5524
5525 //
5526 // Update the Block with configuration info
5527 //
5528 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
5529 CopyMem (Block + Offset, Value, Width);
5530 }
5531 if (Offset + Width > MaxBlockSize) {
5532 MaxBlockSize = Offset + Width;
5533 }
5534
5535 FreePool (Value);
5536 Value = NULL;
5537
5538 //
5539 // If '\0', parsing is finished.
5540 //
5541 if (*StringPtr == 0) {
5542 break;
5543 }
5544 }
5545
5546 //
5547 // The input string is not ConfigResp format, return error.
5548 //
5549 if (*StringPtr != 0) {
5550 *Progress = StringPtr;
5551 Status = EFI_INVALID_PARAMETER;
5552 goto Exit;
5553 }
5554
5555 *Progress = StringPtr + StrLen (StringPtr);
5556 *BlockSize = MaxBlockSize - 1;
5557
5558 if (MaxBlockSize > BufferSize) {
5559 *BlockSize = MaxBlockSize;
5560 if (Block != NULL) {
5561 return EFI_BUFFER_TOO_SMALL;
5562 }
5563 }
5564
5565 if (Block == NULL) {
5566 *Progress = ConfigResp;
5567 return EFI_INVALID_PARAMETER;
5568 }
5569
5570 return EFI_SUCCESS;
5571
5572 Exit:
5573
5574 if (Value != NULL) {
5575 FreePool (Value);
5576 }
5577 return Status;
5578 }
5579
5580
5581 /**
5582 This helper function is to be called by drivers to extract portions of
5583 a larger configuration string.
5584
5585 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5586 instance.
5587 @param Configuration A null-terminated Unicode string in
5588 <MultiConfigAltResp> format.
5589 @param Guid A pointer to the GUID value to search for in the
5590 routing portion of the ConfigResp string when
5591 retrieving the requested data. If Guid is NULL,
5592 then all GUID values will be searched for.
5593 @param Name A pointer to the NAME value to search for in the
5594 routing portion of the ConfigResp string when
5595 retrieving the requested data. If Name is NULL,
5596 then all Name values will be searched for.
5597 @param DevicePath A pointer to the PATH value to search for in the
5598 routing portion of the ConfigResp string when
5599 retrieving the requested data. If DevicePath is
5600 NULL, then all DevicePath values will be searched
5601 for.
5602 @param AltCfgId A pointer to the ALTCFG value to search for in the
5603 routing portion of the ConfigResp string when
5604 retrieving the requested data. If this parameter
5605 is NULL, then the current setting will be
5606 retrieved.
5607 @param AltCfgResp A pointer to a buffer which will be allocated by
5608 the function which contains the retrieved string
5609 as requested. This buffer is only allocated if
5610 the call was successful. It is <ConfigResp> format.
5611
5612 @retval EFI_SUCCESS The request succeeded. The requested data was
5613 extracted and placed in the newly allocated
5614 AltCfgResp buffer.
5615 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5616 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5617 @retval EFI_NOT_FOUND Target for the specified routing data was not
5618 found.
5619
5620 **/
5621 EFI_STATUS
5622 EFIAPI
5623 HiiGetAltCfg (
5624 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5625 IN CONST EFI_STRING Configuration,
5626 IN CONST EFI_GUID *Guid,
5627 IN CONST EFI_STRING Name,
5628 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
5629 IN CONST UINT16 *AltCfgId,
5630 OUT EFI_STRING *AltCfgResp
5631 )
5632 {
5633 EFI_STATUS Status;
5634 EFI_STRING StringPtr;
5635 EFI_STRING HdrStart;
5636 EFI_STRING HdrEnd;
5637 EFI_STRING TmpPtr;
5638 UINTN Length;
5639 EFI_STRING GuidStr;
5640 EFI_STRING NameStr;
5641 EFI_STRING PathStr;
5642 EFI_STRING AltIdStr;
5643 EFI_STRING Result;
5644 BOOLEAN GuidFlag;
5645 BOOLEAN NameFlag;
5646 BOOLEAN PathFlag;
5647
5648 HdrStart = NULL;
5649 HdrEnd = NULL;
5650 GuidStr = NULL;
5651 NameStr = NULL;
5652 PathStr = NULL;
5653 AltIdStr = NULL;
5654 Result = NULL;
5655 GuidFlag = FALSE;
5656 NameFlag = FALSE;
5657 PathFlag = FALSE;
5658
5659 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
5660 return EFI_INVALID_PARAMETER;
5661 }
5662
5663 StringPtr = Configuration;
5664 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5665 return EFI_INVALID_PARAMETER;
5666 }
5667
5668 //
5669 // Generate the sub string for later matching.
5670 //
5671 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
5672 GenerateSubStr (
5673 L"PATH=",
5674 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
5675 (VOID *) DevicePath,
5676 1,
5677 &PathStr
5678 );
5679 if (AltCfgId != NULL) {
5680 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
5681 }
5682 if (Name != NULL) {
5683 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
5684 } else {
5685 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
5686 }
5687
5688 while (*StringPtr != 0) {
5689 //
5690 // Try to match the GUID
5691 //
5692 if (!GuidFlag) {
5693 TmpPtr = StrStr (StringPtr, GuidStr);
5694 if (TmpPtr == NULL) {
5695 Status = EFI_NOT_FOUND;
5696 goto Exit;
5697 }
5698 HdrStart = TmpPtr;
5699
5700 //
5701 // Jump to <NameHdr>
5702 //
5703 if (Guid != NULL) {
5704 StringPtr = TmpPtr + StrLen (GuidStr);
5705 } else {
5706 StringPtr = StrStr (TmpPtr, L"NAME=");
5707 if (StringPtr == NULL) {
5708 Status = EFI_NOT_FOUND;
5709 goto Exit;
5710 }
5711 }
5712 GuidFlag = TRUE;
5713 }
5714
5715 //
5716 // Try to match the NAME
5717 //
5718 if (GuidFlag && !NameFlag) {
5719 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
5720 GuidFlag = FALSE;
5721 } else {
5722 //
5723 // Jump to <PathHdr>
5724 //
5725 if (Name != NULL) {
5726 StringPtr += StrLen (NameStr);
5727 } else {
5728 StringPtr = StrStr (StringPtr, L"PATH=");
5729 if (StringPtr == NULL) {
5730 Status = EFI_NOT_FOUND;
5731 goto Exit;
5732 }
5733 }
5734 NameFlag = TRUE;
5735 }
5736 }
5737
5738 //
5739 // Try to match the DevicePath
5740 //
5741 if (GuidFlag && NameFlag && !PathFlag) {
5742 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
5743 GuidFlag = FALSE;
5744 NameFlag = FALSE;
5745 } else {
5746 //
5747 // Jump to '&' before <DescHdr> or <ConfigBody>
5748 //
5749 if (DevicePath != NULL) {
5750 StringPtr += StrLen (PathStr);
5751 } else {
5752 StringPtr = StrStr (StringPtr, L"&");
5753 if (StringPtr == NULL) {
5754 Status = EFI_NOT_FOUND;
5755 goto Exit;
5756 }
5757 StringPtr ++;
5758 }
5759 PathFlag = TRUE;
5760 HdrEnd = StringPtr;
5761 }
5762 }
5763
5764 //
5765 // Try to match the AltCfgId
5766 //
5767 if (GuidFlag && NameFlag && PathFlag) {
5768 if (AltCfgId == NULL) {
5769 //
5770 // Return Current Setting when AltCfgId is NULL.
5771 //
5772 Status = OutputConfigBody (StringPtr, &Result);
5773 goto Exit;
5774 }
5775 //
5776 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5777 //
5778 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
5779 GuidFlag = FALSE;
5780 NameFlag = FALSE;
5781 PathFlag = FALSE;
5782 } else {
5783 //
5784 // Skip AltIdStr and &
5785 //
5786 StringPtr = StringPtr + StrLen (AltIdStr);
5787 Status = OutputConfigBody (StringPtr, &Result);
5788 goto Exit;
5789 }
5790 }
5791 }
5792
5793 Status = EFI_NOT_FOUND;
5794
5795 Exit:
5796 *AltCfgResp = NULL;
5797 if (!EFI_ERROR (Status) && (Result != NULL)) {
5798 //
5799 // Copy the <ConfigHdr> and <ConfigBody>
5800 //
5801 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
5802 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
5803 if (*AltCfgResp == NULL) {
5804 Status = EFI_OUT_OF_RESOURCES;
5805 } else {
5806 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
5807 StrCatS (*AltCfgResp, Length, Result);
5808 Status = EFI_SUCCESS;
5809 }
5810 }
5811
5812 if (GuidStr != NULL) {
5813 FreePool (GuidStr);
5814 }
5815 if (NameStr != NULL) {
5816 FreePool (NameStr);
5817 }
5818 if (PathStr != NULL) {
5819 FreePool (PathStr);
5820 }
5821 if (AltIdStr != NULL) {
5822 FreePool (AltIdStr);
5823 }
5824 if (Result != NULL) {
5825 FreePool (Result);
5826 }
5827
5828 return Status;
5829
5830 }
5831
5832