]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c
Fix various 'EFIAPI' inconsistencies found while building MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Library / UefiIfrSupportLib / UefiIfrForm.c
1 /** @file
2 Utility functions which helps in opcode creation, HII configuration string manipulations,
3 pop up window creations, setup browser persistence data set and get.
4
5 Copyright (c) 2007- 2009, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "UefiIfrLibraryInternal.h"
17
18 CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;
19 CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mIfrSupportLibHiiConfigRouting = NULL;
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mIfrSupportLibHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
21
22 //
23 // Fake <ConfigHdr>
24 //
25 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
26
27 /**
28 This function locate FormBrowser2 protocols for later usage.
29
30 @return Status the status to locate protocol.
31 **/
32 EFI_STATUS
33 LocateFormBrowser2Protocols (
34 VOID
35 )
36 {
37 EFI_STATUS Status;
38 //
39 // Locate protocols for later usage
40 //
41 if (mFormBrowser2 == NULL) {
42 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2);
43 if (EFI_ERROR (Status)) {
44 return Status;
45 }
46 }
47
48 if (mIfrSupportLibHiiConfigRouting == NULL) {
49 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mIfrSupportLibHiiConfigRouting);
50 if (EFI_ERROR (Status)) {
51 return Status;
52 }
53 }
54
55 return EFI_SUCCESS;
56 }
57
58 /**
59 Draw a dialog and return the selected key.
60
61 @param NumberOfLines The number of lines for the dialog box
62 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
63 @param String The first String to be displayed in the Pop-Up.
64 @param Marker A series of (quantity == NumberOfLines - 1) text
65 strings which will be used to construct the dialog
66 box
67
68 @retval EFI_SUCCESS Displayed dialog and received user interaction
69 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
70 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
71
72 **/
73 EFI_STATUS
74 EFIAPI
75 IfrLibCreatePopUp2 (
76 IN UINTN NumberOfLines,
77 OUT EFI_INPUT_KEY *KeyValue,
78 IN CHAR16 *String,
79 IN VA_LIST Marker
80 )
81 {
82 UINTN Index;
83 UINTN Count;
84 UINTN Start;
85 UINTN Top;
86 CHAR16 *StringPtr;
87 UINTN LeftColumn;
88 UINTN RightColumn;
89 UINTN TopRow;
90 UINTN BottomRow;
91 UINTN DimensionsWidth;
92 UINTN DimensionsHeight;
93 EFI_INPUT_KEY Key;
94 UINTN LargestString;
95 CHAR16 *StackString;
96 EFI_STATUS Status;
97 UINTN StringLen;
98 CHAR16 *LineBuffer;
99 CHAR16 **StringArray;
100 EFI_EVENT TimerEvent;
101 EFI_EVENT WaitList[2];
102 UINTN CurrentAttribute;
103 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
104
105 if ((KeyValue == NULL) || (String == NULL)) {
106 return EFI_INVALID_PARAMETER;
107 }
108
109 TopRow = 0;
110 BottomRow = 0;
111 LeftColumn = 0;
112 RightColumn = 0;
113
114 ConOut = gST->ConOut;
115 ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
116
117 DimensionsWidth = RightColumn - LeftColumn;
118 DimensionsHeight = BottomRow - TopRow;
119
120 CurrentAttribute = ConOut->Mode->Attribute;
121
122 LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
123 if (LineBuffer == NULL) {
124 return EFI_OUT_OF_RESOURCES;
125 }
126
127 //
128 // Determine the largest string in the dialog box
129 // Notice we are starting with 1 since String is the first string
130 //
131 StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
132 if (StringArray == NULL) {
133 FreePool (LineBuffer);
134 return EFI_OUT_OF_RESOURCES;
135 }
136 LargestString = StrLen (String);
137 StringArray[0] = String;
138
139 for (Index = 1; Index < NumberOfLines; Index++) {
140 StackString = VA_ARG (Marker, CHAR16 *);
141
142 if (StackString == NULL) {
143 FreePool (LineBuffer);
144 FreePool (StringArray);
145 return EFI_INVALID_PARAMETER;
146 }
147
148 StringArray[Index] = StackString;
149 StringLen = StrLen (StackString);
150 if (StringLen > LargestString) {
151 LargestString = StringLen;
152 }
153 }
154
155 if ((LargestString + 2) > DimensionsWidth) {
156 LargestString = DimensionsWidth - 2;
157 }
158
159 //
160 // Subtract the PopUp width from total Columns, allow for one space extra on
161 // each end plus a border.
162 //
163 Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
164
165 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
166
167 //
168 // Disable cursor
169 //
170 ConOut->EnableCursor (ConOut, FALSE);
171 ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
172
173 StringPtr = &LineBuffer[0];
174 *StringPtr++ = BOXDRAW_DOWN_RIGHT;
175 for (Index = 0; Index < LargestString; Index++) {
176 *StringPtr++ = BOXDRAW_HORIZONTAL;
177 }
178 *StringPtr++ = BOXDRAW_DOWN_LEFT;
179 *StringPtr = L'\0';
180
181 ConOut->SetCursorPosition (ConOut, Start, Top);
182 ConOut->OutputString (ConOut, LineBuffer);
183
184 for (Index = 0; Index < NumberOfLines; Index++) {
185 StringPtr = &LineBuffer[0];
186 *StringPtr++ = BOXDRAW_VERTICAL;
187
188 for (Count = 0; Count < LargestString; Count++) {
189 StringPtr[Count] = L' ';
190 }
191
192 StringLen = StrLen (StringArray[Index]);
193 if (StringLen > LargestString) {
194 StringLen = LargestString;
195 }
196 CopyMem (
197 StringPtr + ((LargestString - StringLen) / 2),
198 StringArray[Index],
199 StringLen * sizeof (CHAR16)
200 );
201 StringPtr += LargestString;
202
203 *StringPtr++ = BOXDRAW_VERTICAL;
204 *StringPtr = L'\0';
205
206 ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
207 ConOut->OutputString (ConOut, LineBuffer);
208 }
209
210 StringPtr = &LineBuffer[0];
211 *StringPtr++ = BOXDRAW_UP_RIGHT;
212 for (Index = 0; Index < LargestString; Index++) {
213 *StringPtr++ = BOXDRAW_HORIZONTAL;
214 }
215 *StringPtr++ = BOXDRAW_UP_LEFT;
216 *StringPtr = L'\0';
217
218 ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
219 ConOut->OutputString (ConOut, LineBuffer);
220
221 do {
222 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
223
224 //
225 // Set a timer event of 1 second expiration
226 //
227 gBS->SetTimer (
228 TimerEvent,
229 TimerRelative,
230 10000000
231 );
232
233 //
234 // Wait for the keystroke event or the timer
235 //
236 WaitList[0] = gST->ConIn->WaitForKey;
237 WaitList[1] = TimerEvent;
238 Status = gBS->WaitForEvent (2, WaitList, &Index);
239
240 //
241 // Check for the timer expiration
242 //
243 if (!EFI_ERROR (Status) && Index == 1) {
244 Status = EFI_TIMEOUT;
245 }
246
247 gBS->CloseEvent (TimerEvent);
248 } while (Status == EFI_TIMEOUT);
249
250 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
251 CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
252
253 ConOut->SetAttribute (ConOut, CurrentAttribute);
254 ConOut->EnableCursor (ConOut, TRUE);
255
256 FreePool (LineBuffer);
257 FreePool (StringArray);
258
259 return Status;
260 }
261
262
263 /**
264 Draw a dialog and return the selected key.
265
266 @param NumberOfLines The number of lines for the dialog box
267 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
268 @param String Pointer to the first string in the list
269 @param ... A series of (quantity == NumberOfLines - 1) text
270 strings which will be used to construct the dialog
271 box
272
273 @retval EFI_SUCCESS Displayed dialog and received user interaction
274 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
275
276 **/
277 EFI_STATUS
278 EFIAPI
279 IfrLibCreatePopUp (
280 IN UINTN NumberOfLines,
281 OUT EFI_INPUT_KEY *KeyValue,
282 IN CHAR16 *String,
283 ...
284 )
285 {
286 EFI_STATUS Status;
287 VA_LIST Marker;
288
289 VA_START (Marker, String);
290
291 Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, String, Marker);
292
293 VA_END (Marker);
294
295 return Status;
296 }
297
298 /**
299 Extract block name from the array generated by VFR compiler. The name of
300 this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".
301 Format of this array is:
302 Array length | 4-bytes
303 Offset | 2-bytes
304 Width | 2-bytes
305 Offset | 2-bytes
306 Width | 2-bytes
307 ... ...
308
309 @param Buffer Array generated by VFR compiler.
310 @param BlockName The returned <BlockName>
311
312 @retval EFI_OUT_OF_RESOURCES Run out of memory resource.
313 @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL.
314 @retval EFI_SUCCESS Operation successful.
315
316 **/
317 EFI_STATUS
318 ExtractBlockName (
319 IN UINT8 *Buffer,
320 OUT CHAR16 **BlockName
321 )
322
323 {
324 UINTN Index;
325 UINT32 Length;
326 UINT32 BlockNameNumber;
327 UINTN HexStringBufferLen;
328 CHAR16 *StringPtr;
329
330 if ((Buffer == NULL) || (BlockName == NULL)) {
331 return EFI_INVALID_PARAMETER;
332 }
333
334 //
335 // Calculate number of Offset/Width pair
336 //
337 CopyMem (&Length, Buffer, sizeof (UINT32));
338 BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2);
339
340 //
341 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
342 // | 8 | 4 | 7 | 4 |
343 //
344 StringPtr = AllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));
345 if (StringPtr == NULL) {
346 return EFI_OUT_OF_RESOURCES;
347 }
348 *BlockName = StringPtr;
349
350 Buffer += sizeof (UINT32);
351 for (Index = 0; Index < BlockNameNumber; Index++) {
352 StrCpy (StringPtr, L"&OFFSET=");
353 StringPtr += 8;
354
355 HexStringBufferLen = 5;
356 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
357 Buffer += sizeof (UINT16);
358 StringPtr += 4;
359
360 StrCpy (StringPtr, L"&WIDTH=");
361 StringPtr += 7;
362
363 HexStringBufferLen = 5;
364 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
365 Buffer += sizeof (UINT16);
366 StringPtr += 4;
367 }
368
369 return EFI_SUCCESS;
370 }
371
372 /**
373
374 Extract block config from the array generated by VFR compiler. The name of
375 this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".
376
377 @param Buffer - Array generated by VFR compiler.
378 @param BlockConfig - The returned <BlockConfig>
379
380 @retval EFI_OUT_OF_RESOURCES - Run out of memory resource.
381 @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.
382 @retval EFI_SUCCESS - Operation successful.
383
384 **/
385 EFI_STATUS
386 ExtractBlockConfig (
387 IN UINT8 *Buffer,
388 OUT CHAR16 **BlockConfig
389 )
390 {
391 UINT32 Length;
392 UINT16 Width;
393 UINTN HexStringBufferLen;
394 CHAR16 *StringPtr;
395 UINT8 *BufferEnd;
396 CHAR16 *StringEnd;
397 EFI_STATUS Status;
398
399 if ((Buffer == NULL) || (BlockConfig == NULL)) {
400 return EFI_INVALID_PARAMETER;
401 }
402
403 //
404 // Calculate length of AltResp string
405 // Format of Default value array is:
406 // Array length | 4-bytes
407 // Offset | 2-bytes
408 // Width | 2-bytes
409 // Value | Variable length
410 // Offset | 2-bytes
411 // Width | 2-bytes
412 // Value | Variable length
413 // ... ...
414 // When value is 1 byte in length, overhead of AltResp string will be maximum,
415 // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+
416 // | 8 | 4 | 7 | 4 | 7 |2|
417 // so the maximum length of BlockConfig could be calculated as:
418 // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7
419 //
420 CopyMem (&Length, Buffer, sizeof (UINT32));
421 BufferEnd = Buffer + Length;
422 StringPtr = AllocatePool (Length * 7 * sizeof (CHAR16));
423 *BlockConfig = StringPtr;
424 if (StringPtr == NULL) {
425 return EFI_OUT_OF_RESOURCES;
426 }
427 StringEnd = StringPtr + (Length * 7);
428
429 Buffer += sizeof (UINT32);
430 while (Buffer < BufferEnd) {
431 StrCpy (StringPtr, L"&OFFSET=");
432 StringPtr += 8;
433
434 HexStringBufferLen = 5;
435 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
436 Buffer += sizeof (UINT16);
437 StringPtr += 4;
438
439 StrCpy (StringPtr, L"&WIDTH=");
440 StringPtr += 7;
441
442 HexStringBufferLen = 5;
443 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
444 CopyMem (&Width, Buffer, sizeof (UINT16));
445 Buffer += sizeof (UINT16);
446 StringPtr += 4;
447
448 StrCpy (StringPtr, L"&VALUE=");
449 StringPtr += 7;
450
451 HexStringBufferLen = StringEnd - StringPtr;
452 Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width);
453 if (EFI_ERROR (Status)) {
454 return Status;
455 }
456 Buffer += Width;
457 StringPtr += (Width * 2);
458 }
459
460 return EFI_SUCCESS;
461 }
462
463 /**
464 Construct <ConfigAltResp> for a buffer storage.
465
466 @param ConfigRequest The Config request string. If set to NULL, all the
467 configurable elements will be extracted from BlockNameArray.
468 @param ConfigAltResp The returned <ConfigAltResp>.
469 @param Progress On return, points to a character in the Request.
470 @param Guid GUID of the buffer storage.
471 @param Name Name of the buffer storage.
472 @param DriverHandle The DriverHandle which is used to invoke HiiDatabase
473 protocol interface NewPackageList().
474 @param BufferStorage Content of the buffer storage.
475 @param BufferStorageSize Length in bytes of the buffer storage.
476 @param BlockNameArray Array generated by VFR compiler.
477 @param NumberAltCfg Number of Default value array generated by VFR compiler.
478 The sequential input parameters will be number of
479 AltCfgId and DefaultValueArray pairs. When set to 0,
480 there will be no <AltResp>.
481
482 retval EFI_OUT_OF_RESOURCES Run out of memory resource.
483 retval EFI_INVALID_PARAMETER ConfigAltResp is NULL.
484 retval EFI_SUCCESS Operation successful.
485
486 **/
487 EFI_STATUS
488 ConstructConfigAltResp (
489 IN EFI_STRING ConfigRequest, OPTIONAL
490 OUT EFI_STRING *Progress,
491 OUT EFI_STRING *ConfigAltResp,
492 IN EFI_GUID *Guid,
493 IN CHAR16 *Name,
494 IN EFI_HANDLE *DriverHandle,
495 IN VOID *BufferStorage,
496 IN UINTN BufferStorageSize,
497 IN VOID *BlockNameArray, OPTIONAL
498 IN UINTN NumberAltCfg,
499 ...
500 //IN UINT16 AltCfgId,
501 //IN VOID *DefaultValueArray,
502 )
503 {
504 EFI_STATUS Status;
505 CHAR16 *ConfigHdr;
506 CHAR16 *BlockName;
507 CHAR16 *DescHdr;
508 CHAR16 *StringPtr;
509 CHAR16 **AltCfg;
510 UINT16 AltCfgId;
511 VOID *DefaultValueArray;
512 UINTN StrBufferLen;
513 EFI_STRING ConfigResp;
514 EFI_STRING TempStr;
515 VA_LIST Args;
516 UINTN AltRespLen;
517 UINTN Index;
518 BOOLEAN NeedFreeConfigRequest;
519 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
520 UINTN Len;
521
522 if (ConfigAltResp == NULL) {
523 return EFI_INVALID_PARAMETER;
524 }
525
526 DescHdr = NULL;
527 StringPtr = NULL;
528 AltCfg = NULL;
529 ConfigResp = NULL;
530 BlockName = NULL;
531 NeedFreeConfigRequest = FALSE;
532
533 //
534 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
535 //
536 ConfigHdr = NULL;
537 StrBufferLen = 0;
538 Status = ConstructConfigHdr (
539 ConfigHdr,
540 &StrBufferLen,
541 Guid,
542 Name,
543 DriverHandle
544 );
545 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
546 ConfigHdr = AllocateZeroPool (StrBufferLen);
547 if (ConfigHdr == NULL) {
548 Status = EFI_OUT_OF_RESOURCES;
549 goto Exit;
550 }
551 Status = ConstructConfigHdr (
552 ConfigHdr,
553 &StrBufferLen,
554 Guid,
555 Name,
556 DriverHandle
557 );
558
559 if (EFI_ERROR (Status)) {
560 goto Exit;
561 }
562
563 //
564 // Construct <ConfigResp>
565 //
566 if (ConfigRequest == NULL) {
567 //
568 // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray
569 //
570 Status = ExtractBlockName (BlockNameArray, &BlockName);
571 if (EFI_ERROR (Status)) {
572 goto Exit;
573 }
574
575 Len = StrSize (ConfigHdr);
576 ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16));
577 if (ConfigRequest == NULL) {
578 Status = EFI_OUT_OF_RESOURCES;
579 goto Exit;
580 }
581
582 StrCpy (ConfigRequest, ConfigHdr);
583 StrCat (ConfigRequest, BlockName);
584 NeedFreeConfigRequest = TRUE;
585
586 }
587
588 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
589 if (EFI_ERROR (Status)) {
590 return Status;
591 }
592
593 Status = HiiConfigRouting->BlockToConfig (
594 HiiConfigRouting,
595 ConfigRequest,
596 BufferStorage,
597 BufferStorageSize,
598 &ConfigResp,
599 (Progress == NULL) ? &TempStr : Progress
600 );
601 if (EFI_ERROR (Status)) {
602 return Status;
603 }
604
605 AltRespLen = 0;
606 //
607 // Construct <AltResp>
608 //
609 if (NumberAltCfg > 0) {
610 DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));
611 if (DescHdr == NULL) {
612 Status = EFI_OUT_OF_RESOURCES;
613 goto Exit;
614 }
615
616 StringPtr = DescHdr;
617 AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));
618 if (AltCfg == NULL) {
619 Status = EFI_OUT_OF_RESOURCES;
620 goto Exit;
621 }
622
623 VA_START (Args, NumberAltCfg);
624 for (Index = 0; Index < NumberAltCfg; Index++) {
625 AltCfgId = (UINT16) VA_ARG (Args, UINT16);
626 DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);
627
628 //
629 // '&' <ConfigHdr>
630 //
631 AltRespLen += (StrLen (ConfigHdr) + 1);
632
633 StringPtr = DescHdr + Index * 16;
634 StrCpy (StringPtr, L"&ALTCFG=");
635 AltRespLen += (8 + sizeof (UINT16) * 2);
636
637 StrBufferLen = 5;
638 BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));
639 Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);
640 if (EFI_ERROR (Status)) {
641 goto Exit;
642 }
643 AltRespLen += StrLen (AltCfg[Index]);
644 }
645 VA_END (Args);
646 }
647
648 //
649 // Generate the final <ConfigAltResp>
650 //
651 StrBufferLen = (StrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16);
652 TempStr = AllocateZeroPool (StrBufferLen);
653 *ConfigAltResp = TempStr;
654 if (TempStr == NULL) {
655 goto Exit;
656 }
657
658 //
659 // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*
660 //
661 StrCpy (TempStr, ConfigResp);
662 for (Index = 0; Index < NumberAltCfg; Index++) {
663 StrCat (TempStr, L"&");
664 StrCat (TempStr, ConfigHdr);
665 StrCat (TempStr, DescHdr + Index * 16);
666 StrCat (TempStr, AltCfg[Index]);
667
668 FreePool (AltCfg[Index]);
669 }
670
671 Exit:
672 if (NeedFreeConfigRequest) {
673 FreePool (ConfigRequest);
674 }
675 FreePool (ConfigHdr);
676 if (ConfigResp != NULL) {
677 FreePool (ConfigResp);
678 }
679
680 if (BlockName != NULL) {
681 FreePool (BlockName);
682 }
683
684 if (NumberAltCfg > 0) {
685 FreePool (DescHdr);
686 FreePool (AltCfg);
687 }
688
689 return EFI_SUCCESS;
690 }
691
692 /**
693 Swap bytes in the buffer. This is a internal function.
694
695 @param Buffer Binary buffer.
696 @param BufferSize Size of the buffer in bytes.
697
698 @return None.
699
700 **/
701 VOID
702 SwapBuffer (
703 IN OUT UINT8 *Buffer,
704 IN UINTN BufferSize
705 )
706 {
707 UINTN Index;
708 UINT8 Temp;
709 UINTN SwapCount;
710
711 SwapCount = BufferSize / 2;
712 for (Index = 0; Index < SwapCount; Index++) {
713 Temp = Buffer[Index];
714 Buffer[Index] = Buffer[BufferSize - 1 - Index];
715 Buffer[BufferSize - 1 - Index] = Temp;
716 }
717 }
718
719 /**
720 Converts the unicode character of the string from uppercase to lowercase.
721 This is a internal function.
722
723 @param Str String to be converted
724
725 **/
726 VOID
727 EFIAPI
728 ToLower (
729 IN OUT CHAR16 *Str
730 )
731 {
732 CHAR16 *Ptr;
733
734 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
735 if (*Ptr >= L'A' && *Ptr <= L'Z') {
736 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
737 }
738 }
739 }
740
741
742 /**
743 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
744
745 @param Str String for output
746 @param Buffer Binary buffer.
747 @param BufferSize Size of the buffer in bytes.
748
749 @retval EFI_SUCCESS The function completed successfully.
750 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
751
752 **/
753 EFI_STATUS
754 EFIAPI
755 BufInReverseOrderToHexString (
756 IN OUT CHAR16 *Str,
757 IN UINT8 *Buffer,
758 IN UINTN BufferSize
759 )
760 {
761 EFI_STATUS Status;
762 UINT8 *NewBuffer;
763 UINTN StrBufferLen;
764
765 NewBuffer = AllocateCopyPool (BufferSize, Buffer);
766 if (NewBuffer == NULL) {
767 return EFI_OUT_OF_RESOURCES;
768 }
769 SwapBuffer (NewBuffer, BufferSize);
770
771 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
772 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
773
774 FreePool (NewBuffer);
775 //
776 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
777 //
778 ToLower (Str);
779
780 return Status;
781 }
782
783
784 /**
785 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
786
787 @param Buffer Pointer to buffer that receives the data.
788 @param BufferSize Length in bytes of the buffer to hold converted
789 data. If routine return with EFI_SUCCESS,
790 containing length of converted data. If routine
791 return with EFI_BUFFER_TOO_SMALL, containg length
792 of buffer desired.
793 @param Str String to be converted from.
794
795 @retval EFI_SUCCESS The function completed successfully.
796 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
797 will be updated to the size required for the converstion.
798
799 **/
800 EFI_STATUS
801 EFIAPI
802 HexStringToBufInReverseOrder (
803 IN OUT UINT8 *Buffer,
804 IN OUT UINTN *BufferSize,
805 IN CHAR16 *Str
806 )
807 {
808 EFI_STATUS Status;
809 UINTN ConvertedStrLen;
810
811 ConvertedStrLen = 0;
812 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
813 if (!EFI_ERROR (Status)) {
814 SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2);
815 }
816
817 return Status;
818 }
819
820 /**
821 Convert binary representation Config string (e.g. "0041004200430044") to the
822 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
823 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
824
825 @param UnicodeString Original Unicode string.
826 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
827 Includes tailing '\0' character.
828 On output:
829 If return EFI_SUCCESS, containing length of Unicode string buffer.
830 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
831 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
832
833 @retval EFI_SUCCESS Operation completes successfully.
834 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
835
836 **/
837 EFI_STATUS
838 EFIAPI
839 ConfigStringToUnicode (
840 IN OUT CHAR16 *UnicodeString,
841 IN OUT UINTN *StrBufferLen,
842 IN CHAR16 *ConfigString
843 )
844 {
845 UINTN Index;
846 UINTN Len;
847 UINTN BufferSize;
848 CHAR16 BackupChar;
849
850 Len = StrLen (ConfigString) / 4;
851 BufferSize = (Len + 1) * sizeof (CHAR16);
852
853 if (*StrBufferLen < BufferSize) {
854 *StrBufferLen = BufferSize;
855 return EFI_BUFFER_TOO_SMALL;
856 }
857
858 *StrBufferLen = BufferSize;
859
860 for (Index = 0; Index < Len; Index++) {
861 BackupChar = ConfigString[4];
862 ConfigString[4] = L'\0';
863
864 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
865
866 ConfigString[4] = BackupChar;
867
868 ConfigString += 4;
869 UnicodeString += 1;
870 }
871
872 //
873 // Add tailing '\0' character
874 //
875 *UnicodeString = L'\0';
876
877 return EFI_SUCCESS;
878 }
879
880 /**
881 Convert Unicode string to binary representation Config string, e.g.
882 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
883 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
884
885 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
886 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
887 Includes tailing '\0' character.
888 On output:
889 If return EFI_SUCCESS, containing length of Unicode string buffer.
890 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
891 @param UnicodeString Original Unicode string.
892
893 @retval EFI_SUCCESS Operation completes successfully.
894 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
895
896 **/
897 EFI_STATUS
898 EFIAPI
899 UnicodeToConfigString (
900 IN OUT CHAR16 *ConfigString,
901 IN OUT UINTN *StrBufferLen,
902 IN CHAR16 *UnicodeString
903 )
904 {
905 UINTN Index;
906 UINTN Len;
907 UINTN BufferSize;
908 CHAR16 *String;
909
910 Len = StrLen (UnicodeString);
911 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
912
913 if (*StrBufferLen < BufferSize) {
914 *StrBufferLen = BufferSize;
915 return EFI_BUFFER_TOO_SMALL;
916 }
917
918 *StrBufferLen = BufferSize;
919 String = ConfigString;
920
921 for (Index = 0; Index < Len; Index++) {
922 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
923
924 ConfigString += 4;
925 UnicodeString += 1;
926 }
927
928 //
929 // Add tailing '\0' character
930 //
931 *ConfigString = L'\0';
932
933 //
934 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
935 //
936 ToLower (String);
937 return EFI_SUCCESS;
938 }
939
940 /**
941 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
942
943 @param ConfigHdr Pointer to the ConfigHdr string.
944 @param StrBufferLen On input: Length in bytes of buffer to hold the
945 ConfigHdr string. Includes tailing '\0' character.
946 On output: If return EFI_SUCCESS, containing
947 length of ConfigHdr string buffer. If return
948 EFI_BUFFER_TOO_SMALL, containg length of string
949 buffer desired.
950 @param Guid Routing information: GUID.
951 @param Name Routing information: NAME.
952 @param DriverHandle Driver handle which contains the routing
953 information: PATH.
954
955 @retval EFI_SUCCESS Operation completes successfully.
956 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
957
958 **/
959 EFI_STATUS
960 EFIAPI
961 ConstructConfigHdr (
962 IN OUT CHAR16 *ConfigHdr,
963 IN OUT UINTN *StrBufferLen,
964 IN CONST EFI_GUID *Guid,
965 IN CHAR16 *Name, OPTIONAL
966 IN EFI_HANDLE *DriverHandle
967 )
968 {
969 EFI_STATUS Status;
970 UINTN NameStrLen;
971 UINTN DevicePathSize;
972 UINTN BufferSize;
973 CHAR16 *StrPtr;
974 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
975
976 //
977 // Make sure when ConfigHdr is NULL, StrBufferlen must be 0
978 //
979 ASSERT (!(ConfigHdr == NULL && *StrBufferLen != 0));
980
981 if (Name == NULL) {
982 //
983 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
984 //
985 NameStrLen = 0;
986 } else {
987 //
988 // For buffer storage
989 //
990 NameStrLen = StrLen (Name);
991 }
992
993 //
994 // Retrieve DevicePath Protocol associated with this HiiPackageList
995 //
996 Status = gBS->HandleProtocol (
997 DriverHandle,
998 &gEfiDevicePathProtocolGuid,
999 (VOID **) &DevicePath
1000 );
1001 if (EFI_ERROR (Status)) {
1002 return Status;
1003 }
1004
1005 DevicePathSize = GetDevicePathSize (DevicePath);
1006
1007 //
1008 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1009 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1010 //
1011 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
1012 if ((*StrBufferLen == 0) || *StrBufferLen < BufferSize) {
1013 *StrBufferLen = BufferSize;
1014 return EFI_BUFFER_TOO_SMALL;
1015 }
1016
1017 *StrBufferLen = BufferSize;
1018
1019 StrPtr = ConfigHdr;
1020
1021 StrCpy (StrPtr, L"GUID=");
1022 StrPtr += 5;
1023 BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
1024 StrPtr += 32;
1025
1026 //
1027 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
1028 //
1029 StrCpy (StrPtr, L"&NAME=");
1030 StrPtr += 6;
1031 if (Name != NULL) {
1032 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
1033 UnicodeToConfigString (StrPtr, &BufferSize, Name);
1034 StrPtr += (NameStrLen * 4);
1035 }
1036
1037 StrCpy (StrPtr, L"&PATH=");
1038 StrPtr += 6;
1039 BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
1040
1041 return EFI_SUCCESS;
1042 }
1043
1044 /**
1045 Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.
1046
1047 @param ConfigString Either <ConfigRequest> or <ConfigResp>.
1048 @param StorageGuid GUID of the storage.
1049 @param StorageName Name of the stoarge.
1050
1051 @retval TRUE Routing information is correct in ConfigString.
1052 @retval FALSE Routing information is incorrect in ConfigString.
1053
1054 **/
1055 BOOLEAN
1056 EFIAPI
1057 IsConfigHdrMatch (
1058 IN EFI_STRING ConfigString,
1059 IN EFI_GUID *StorageGuid, OPTIONAL
1060 IN CHAR16 *StorageName OPTIONAL
1061 )
1062 {
1063 EFI_STATUS Status;
1064 BOOLEAN Match;
1065 EFI_GUID Guid;
1066 CHAR16 *Name;
1067 CHAR16 *StrPtr;
1068 UINTN BufferSize;
1069
1070 //
1071 // <ConfigHdr> ::=
1072 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1073 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1074 //
1075 if (StrLen (ConfigString) <= (5 + 32 + 6)) {
1076 return FALSE;
1077 }
1078
1079 //
1080 // Compare GUID
1081 //
1082 if (StorageGuid != NULL) {
1083
1084 StrPtr = ConfigString + 5 + 32;
1085 if (*StrPtr != L'&') {
1086 return FALSE;
1087 }
1088 *StrPtr = L'\0';
1089
1090 BufferSize = sizeof (EFI_GUID);
1091 Status = HexStringToBufInReverseOrder (
1092 (UINT8 *) &Guid,
1093 &BufferSize,
1094 ConfigString + 5
1095 );
1096 *StrPtr = L'&';
1097
1098 if (EFI_ERROR (Status)) {
1099 return FALSE;
1100 }
1101
1102 if (!CompareGuid (&Guid, StorageGuid)) {
1103 return FALSE;
1104 }
1105 }
1106
1107 //
1108 // Compare Name
1109 //
1110 Match = TRUE;
1111 if (StorageName != NULL) {
1112 StrPtr = ConfigString + 5 + 32 + 6;
1113 while (*StrPtr != L'\0' && *StrPtr != L'&') {
1114 StrPtr++;
1115 }
1116 if (*StrPtr != L'&') {
1117 return FALSE;
1118 }
1119
1120 *StrPtr = L'\0';
1121 BufferSize = (((UINTN) StrPtr) - ((UINTN) &ConfigString[5 + 32 + 6])) / 4 + sizeof (CHAR16);
1122 Name = AllocatePool (BufferSize);
1123 ASSERT (Name != NULL);
1124 Status = ConfigStringToUnicode (
1125 Name,
1126 &BufferSize,
1127 ConfigString + 5 + 32 + 6
1128 );
1129 *StrPtr = L'&';
1130
1131 if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) {
1132 Match = FALSE;
1133 }
1134 FreePool (Name);
1135 }
1136
1137 return Match;
1138 }
1139
1140 /**
1141 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
1142
1143 @param String The string to be searched in.
1144 @param Offset Offset in BlockName.
1145 @param Width Width in BlockName.
1146
1147 @retval TRUE Block name found.
1148 @retval FALSE Block name not found.
1149
1150 **/
1151 BOOLEAN
1152 EFIAPI
1153 FindBlockName (
1154 IN OUT CHAR16 *String,
1155 IN UINTN Offset,
1156 IN UINTN Width
1157 )
1158 {
1159 EFI_STATUS Status;
1160 UINTN Data;
1161 UINTN BufferSize;
1162 UINTN ConvertedStrLen;
1163
1164 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
1165 //
1166 // Skip '&OFFSET='
1167 //
1168 String = String + 8;
1169
1170 Data = 0;
1171 BufferSize = sizeof (UINTN);
1172 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
1173 if (EFI_ERROR (Status)) {
1174 return FALSE;
1175 }
1176 String = String + ConvertedStrLen;
1177
1178 if (Data != Offset) {
1179 continue;
1180 }
1181
1182 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
1183 return FALSE;
1184 }
1185 String = String + 7;
1186
1187 Data = 0;
1188 BufferSize = sizeof (UINTN);
1189 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
1190 if (EFI_ERROR (Status)) {
1191 return FALSE;
1192 }
1193 if (Data == Width) {
1194 return TRUE;
1195 }
1196
1197 String = String + ConvertedStrLen;
1198 }
1199
1200 return FALSE;
1201 }
1202
1203
1204 /**
1205 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
1206
1207 @param VariableGuid An optional field to indicate the target variable
1208 GUID name to use.
1209 @param VariableName An optional field to indicate the target
1210 human-readable variable name.
1211 @param BufferSize On input: Length in bytes of buffer to hold
1212 retrived data. On output: If return
1213 EFI_BUFFER_TOO_SMALL, containg length of buffer
1214 desired.
1215 @param Buffer Buffer to hold retrived data.
1216
1217 @retval EFI_SUCCESS Operation completes successfully.
1218 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
1219 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1220
1221 **/
1222 EFI_STATUS
1223 EFIAPI
1224 GetBrowserData (
1225 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1226 IN CONST CHAR16 *VariableName, OPTIONAL
1227 IN OUT UINTN *BufferSize,
1228 IN OUT UINT8 *Buffer
1229 )
1230 {
1231 EFI_STATUS Status;
1232 CONST CHAR16 *ConfigHdr;
1233 CHAR16 *ConfigResp;
1234 CHAR16 *StringPtr;
1235 UINTN HeaderLen;
1236 UINTN BufferLen;
1237 CHAR16 *Progress;
1238
1239 //
1240 // Locate protocols for use
1241 //
1242 Status = LocateFormBrowser2Protocols ();
1243 if (EFI_ERROR (Status)) {
1244 return Status;
1245 }
1246
1247 //
1248 // Retrive formset storage data from Form Browser
1249 //
1250 ConfigHdr = mFakeConfigHdr;
1251 HeaderLen = StrLen (ConfigHdr);
1252
1253 //
1254 // First try allocate 0x4000 buffer for the formet storage data.
1255 //
1256 BufferLen = 0x4000;
1257 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
1258 if (ConfigResp == NULL) {
1259 return EFI_OUT_OF_RESOURCES;
1260 }
1261
1262 StringPtr = ConfigResp + HeaderLen;
1263 *StringPtr = L'&';
1264 StringPtr++;
1265
1266 Status = mFormBrowser2->BrowserCallback (
1267 mFormBrowser2,
1268 &BufferLen,
1269 StringPtr,
1270 TRUE,
1271 VariableGuid,
1272 VariableName
1273 );
1274 if (Status == EFI_BUFFER_TOO_SMALL) {
1275 FreePool (ConfigResp);
1276
1277 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
1278 if (ConfigResp == NULL) {
1279 return EFI_OUT_OF_RESOURCES;
1280 }
1281
1282 StringPtr = ConfigResp + HeaderLen;
1283 *StringPtr = L'&';
1284 StringPtr++;
1285
1286 Status = mFormBrowser2->BrowserCallback (
1287 mFormBrowser2,
1288 &BufferLen,
1289 StringPtr,
1290 TRUE,
1291 VariableGuid,
1292 VariableName
1293 );
1294 }
1295 if (EFI_ERROR (Status)) {
1296 FreePool (ConfigResp);
1297 return Status;
1298 }
1299 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
1300
1301 //
1302 // Convert <ConfigResp> to buffer data
1303 //
1304 Status = mIfrSupportLibHiiConfigRouting->ConfigToBlock (
1305 mIfrSupportLibHiiConfigRouting,
1306 ConfigResp,
1307 Buffer,
1308 BufferSize,
1309 &Progress
1310 );
1311 FreePool (ConfigResp);
1312
1313 return Status;
1314 }
1315
1316
1317 /**
1318 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
1319
1320 @param VariableGuid An optional field to indicate the target variable
1321 GUID name to use.
1322 @param VariableName An optional field to indicate the target
1323 human-readable variable name.
1324 @param BufferSize Length in bytes of buffer to hold retrived data.
1325 @param Buffer Buffer to hold retrived data.
1326 @param RequestElement An optional field to specify which part of the
1327 buffer data will be send back to Browser. If NULL,
1328 the whole buffer of data will be committed to
1329 Browser. <RequestElement> ::=
1330 &OFFSET=<Number>&WIDTH=<Number>*
1331
1332 @retval EFI_SUCCESS Operation completes successfully.
1333 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1334 @retval Other Updating Browser uncommitted data failed.
1335
1336 **/
1337 EFI_STATUS
1338 EFIAPI
1339 SetBrowserData (
1340 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1341 IN CONST CHAR16 *VariableName, OPTIONAL
1342 IN UINTN BufferSize,
1343 IN CONST UINT8 *Buffer,
1344 IN CONST CHAR16 *RequestElement OPTIONAL
1345 )
1346 {
1347 EFI_STATUS Status;
1348 CONST CHAR16 *ConfigHdr;
1349 CHAR16 *ConfigResp;
1350 CHAR16 *StringPtr;
1351 UINTN HeaderLen;
1352 UINTN BufferLen;
1353 CHAR16 *Progress;
1354 CHAR16 BlockName[33];
1355 CHAR16 *ConfigRequest;
1356 CONST CHAR16 *Request;
1357
1358 //
1359 // Locate protocols for use
1360 //
1361 Status = LocateFormBrowser2Protocols ();
1362 if (EFI_ERROR (Status)) {
1363 return Status;
1364 }
1365
1366 //
1367 // Prepare <ConfigRequest>
1368 //
1369 ConfigHdr = mFakeConfigHdr;
1370 HeaderLen = StrLen (ConfigHdr);
1371
1372 if (RequestElement == NULL) {
1373 //
1374 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
1375 //
1376 BlockName[0] = L'\0';
1377 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
1378
1379 //
1380 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
1381 //
1382 StringPtr = BlockName + 16;
1383 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
1384 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
1385
1386 Request = BlockName;
1387 } else {
1388 Request = RequestElement;
1389 }
1390
1391 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
1392 ConfigRequest = AllocateZeroPool (BufferLen);
1393 if (ConfigRequest == NULL) {
1394 return EFI_OUT_OF_RESOURCES;
1395 }
1396
1397 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
1398 StringPtr = ConfigRequest + HeaderLen;
1399 StrCpy (StringPtr, Request);
1400
1401 //
1402 // Convert buffer to <ConfigResp>
1403 //
1404 Status = mIfrSupportLibHiiConfigRouting->BlockToConfig (
1405 mIfrSupportLibHiiConfigRouting,
1406 ConfigRequest,
1407 Buffer,
1408 BufferSize,
1409 &ConfigResp,
1410 &Progress
1411 );
1412 if (EFI_ERROR (Status)) {
1413 FreePool (ConfigRequest);
1414 return Status;
1415 }
1416
1417 //
1418 // Skip <ConfigHdr> and '&'
1419 //
1420 StringPtr = ConfigResp + HeaderLen + 1;
1421
1422 //
1423 // Change uncommitted data in Browser
1424 //
1425 Status = mFormBrowser2->BrowserCallback (
1426 mFormBrowser2,
1427 &BufferSize,
1428 StringPtr,
1429 FALSE,
1430 VariableGuid,
1431 VariableName
1432 );
1433 FreePool (ConfigRequest);
1434 return Status;
1435 }
1436
1437 /**
1438 Test if a Unicode character is a hexadecimal digit. If true, the input
1439 Unicode character is converted to a byte.
1440
1441 This function tests if a Unicode character is a hexadecimal digit. If true, the input
1442 Unicode character is converted to a byte. For example, Unicode character
1443 L'A' will be converted to 0x0A.
1444
1445 If Digit is NULL, then ASSERT.
1446
1447 @param Digit The output hexadecimal digit.
1448
1449 @param Char The input Unicode character.
1450
1451 @retval TRUE Char is in the range of Hexadecimal number. Digit is updated
1452 to the byte value of the number.
1453 @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep
1454 intact.
1455
1456 **/
1457 BOOLEAN
1458 EFIAPI
1459 IsHexDigit (
1460 OUT UINT8 *Digit,
1461 IN CHAR16 Char
1462 )
1463 {
1464 ASSERT (Digit != NULL);
1465
1466 if ((Char >= L'0') && (Char <= L'9')) {
1467 *Digit = (UINT8) (Char - L'0');
1468 return TRUE;
1469 }
1470
1471 if ((Char >= L'A') && (Char <= L'F')) {
1472 *Digit = (UINT8) (Char - L'A' + 0x0A);
1473 return TRUE;
1474 }
1475
1476 if ((Char >= L'a') && (Char <= L'f')) {
1477 *Digit = (UINT8) (Char - L'a' + 0x0A);
1478 return TRUE;
1479 }
1480
1481 return FALSE;
1482 }
1483
1484 /**
1485 Convert binary buffer to a Unicode String in a specified sequence.
1486
1487 This function converts bytes in the memory block pointed by Buffer to a Unicode String Str.
1488 Each byte will be represented by two Unicode characters. For example, byte 0xA1 will
1489 be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character
1490 for the Most Significant Nibble will be put before the Unicode Character for the Least Significant
1491 Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1".
1492 For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the
1493 the last character in the output string. The one next to first byte will be put into the
1494 character before the last character. This rules applies to the rest of the bytes. The Unicode
1495 character by the last byte will be put into the first character in the output string. For example,
1496 the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to
1497 a Unicode string equal to L"12345678abcdef1234".
1498
1499 @param String On input, String is pointed to the buffer allocated for the convertion.
1500 @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.
1501 The StringLen required to convert a N bytes Buffer will be a least equal to or greater
1502 than 2*N + 1.
1503 @param Buffer The pointer to a input buffer.
1504 @param BufferSizeInBytes Length in bytes of the input buffer.
1505
1506
1507 @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding
1508 Unicode character and placed into the right place in String.
1509 @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to
1510 complete the convertion.
1511 **/
1512 RETURN_STATUS
1513 EFIAPI
1514 BufToHexString (
1515 IN OUT CHAR16 *String,
1516 IN OUT UINTN *StringLen,
1517 IN CONST UINT8 *Buffer,
1518 IN UINTN BufferSizeInBytes
1519 )
1520 {
1521 UINTN Idx;
1522 UINT8 Byte;
1523 UINTN StrLen;
1524
1525 //
1526 // Make sure string is either passed or allocate enough.
1527 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
1528 // Plus the Unicode termination character.
1529 //
1530 StrLen = BufferSizeInBytes * 2;
1531 if (StrLen > ((*StringLen) - 1)) {
1532 *StringLen = StrLen + 1;
1533 return RETURN_BUFFER_TOO_SMALL;
1534 }
1535
1536 *StringLen = StrLen + 1;
1537 //
1538 // Ends the string.
1539 //
1540 String[StrLen] = L'\0';
1541
1542 for (Idx = 0; Idx < BufferSizeInBytes; Idx++) {
1543 Byte = Buffer[Idx];
1544 String[StrLen - 1 - Idx * 2] = mIfrSupportLibHexStr [Byte & 0xF];
1545 String[StrLen - 2 - Idx * 2] = mIfrSupportLibHexStr [Byte >> 4];
1546 }
1547
1548 return RETURN_SUCCESS;
1549 }
1550
1551
1552 /**
1553 Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.
1554
1555 This function converts a Unicode string consisting of characters in the range of Hexadecimal
1556 character (L'0' to L'9', L'A' to L'F' and L'a' to L'f') to a output byte buffer. The function will stop
1557 at the first non-hexadecimal character or the NULL character. The convertion process can be
1558 simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be
1559 converted into one byte. The first Unicode character represents the Most Significant Nibble and the
1560 second Unicode character represents the Least Significant Nibble in the output byte.
1561 The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode
1562 characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes.
1563 The last pair represent the first byte in the output buffer.
1564
1565 For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes
1566 (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".
1567
1568 If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least
1569 N/2 (if N is even) or (N+1)/2 (if N if odd) bytes.
1570
1571 If either Buffer, BufferSizeInBytes or String is NULL, then ASSERT ().
1572
1573 @param Buffer The output buffer allocated by the caller.
1574 @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to
1575 contain the size of the Buffer which is actually used for the converstion.
1576 For Unicode string with 2*N hexadecimal characters (not including the
1577 tailing NULL character), N bytes of Buffer will be used for the output.
1578 @param String The input hexadecimal string.
1579 @param ConvertedStrLen The number of hexadecimal characters used to produce content in output
1580 buffer Buffer.
1581
1582 @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes
1583 will be updated to the size required for the converstion.
1584 @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String
1585 is hexadecimal. If ConvertedStrLen is not NULL, it is updated
1586 to the number of hexadecimal character used for the converstion.
1587 **/
1588 RETURN_STATUS
1589 EFIAPI
1590 HexStringToBuf (
1591 OUT UINT8 *Buffer,
1592 IN OUT UINTN *BufferSizeInBytes,
1593 IN CONST CHAR16 *String,
1594 OUT UINTN *ConvertedStrLen OPTIONAL
1595 )
1596 {
1597 UINTN HexCnt;
1598 UINTN Idx;
1599 UINTN BufferLength;
1600 UINT8 Digit;
1601 UINT8 Byte;
1602
1603 ASSERT (Buffer != NULL);
1604 ASSERT (BufferSizeInBytes != NULL);
1605 ASSERT (String != NULL);
1606
1607 //
1608 // Find out how many hex characters the string has.
1609 //
1610 for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, String[Idx]); Idx++, HexCnt++);
1611
1612 if (HexCnt == 0) {
1613 *ConvertedStrLen = 0;
1614 return RETURN_SUCCESS;
1615 }
1616 //
1617 // Two Unicode characters make up 1 buffer byte. Round up.
1618 //
1619 BufferLength = (HexCnt + 1) / 2;
1620
1621 //
1622 // Test if buffer is passed enough.
1623 //
1624 if (BufferLength > (*BufferSizeInBytes)) {
1625 *BufferSizeInBytes = BufferLength;
1626 return RETURN_BUFFER_TOO_SMALL;
1627 }
1628
1629 *BufferSizeInBytes = BufferLength;
1630
1631 for (Idx = 0; Idx < HexCnt; Idx++) {
1632
1633 IsHexDigit (&Digit, String[HexCnt - 1 - Idx]);
1634
1635 //
1636 // For odd charaters, write the lower nibble for each buffer byte,
1637 // and for even characters, the upper nibble.
1638 //
1639 if ((Idx & 1) == 0) {
1640 Byte = Digit;
1641 } else {
1642 Byte = Buffer[Idx / 2];
1643 Byte &= 0x0F;
1644 Byte = (UINT8) (Byte | Digit << 4);
1645 }
1646
1647 Buffer[Idx / 2] = Byte;
1648 }
1649
1650 if (ConvertedStrLen != NULL) {
1651 *ConvertedStrLen = HexCnt;
1652 }
1653
1654 return RETURN_SUCCESS;
1655 }