2 Utility functions which helps in opcode creation, HII configuration string manipulations,
3 pop up window creations, setup browser persistence data set and get.
5 Copyright (c) 2007- 2008, 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
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.
16 #include "UefiIfrLibraryInternal.h"
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'};
25 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
28 This function locate FormBrowser2 protocols for later usage.
30 @return Status the status to locate protocol.
33 LocateFormBrowser2Protocols (
39 // Locate protocols for later usage
41 if (mFormBrowser2
== NULL
) {
42 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mFormBrowser2
);
43 if (EFI_ERROR (Status
)) {
48 if (mIfrSupportLibHiiConfigRouting
== NULL
) {
49 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &mIfrSupportLibHiiConfigRouting
);
50 if (EFI_ERROR (Status
)) {
59 Draw a dialog and return the selected key.
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
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.
76 IN UINTN NumberOfLines
,
77 OUT EFI_INPUT_KEY
*KeyValue
,
91 UINTN DimensionsWidth
;
92 UINTN DimensionsHeight
;
100 EFI_EVENT TimerEvent
;
101 EFI_EVENT WaitList
[2];
102 UINTN CurrentAttribute
;
103 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
105 if ((KeyValue
== NULL
) || (String
== NULL
)) {
106 return EFI_INVALID_PARAMETER
;
114 ConOut
= gST
->ConOut
;
115 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &RightColumn
, &BottomRow
);
117 DimensionsWidth
= RightColumn
- LeftColumn
;
118 DimensionsHeight
= BottomRow
- TopRow
;
120 CurrentAttribute
= ConOut
->Mode
->Attribute
;
122 LineBuffer
= AllocateZeroPool (DimensionsWidth
* sizeof (CHAR16
));
123 if (LineBuffer
== NULL
) {
124 return EFI_OUT_OF_RESOURCES
;
128 // Determine the largest string in the dialog box
129 // Notice we are starting with 1 since String is the first string
131 StringArray
= AllocateZeroPool (NumberOfLines
* sizeof (CHAR16
*));
132 if (StringArray
== NULL
) {
133 FreePool (LineBuffer
);
134 return EFI_OUT_OF_RESOURCES
;
136 LargestString
= StrLen (String
);
137 StringArray
[0] = String
;
139 for (Index
= 1; Index
< NumberOfLines
; Index
++) {
140 StackString
= VA_ARG (Marker
, CHAR16
*);
142 if (StackString
== NULL
) {
143 FreePool (LineBuffer
);
144 FreePool (StringArray
);
145 return EFI_INVALID_PARAMETER
;
148 StringArray
[Index
] = StackString
;
149 StringLen
= StrLen (StackString
);
150 if (StringLen
> LargestString
) {
151 LargestString
= StringLen
;
155 if ((LargestString
+ 2) > DimensionsWidth
) {
156 LargestString
= DimensionsWidth
- 2;
160 // Subtract the PopUp width from total Columns, allow for one space extra on
161 // each end plus a border.
163 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + LeftColumn
+ 1;
165 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + TopRow
- 1;
170 ConOut
->EnableCursor (ConOut
, FALSE
);
171 ConOut
->SetAttribute (ConOut
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
173 StringPtr
= &LineBuffer
[0];
174 *StringPtr
++ = BOXDRAW_DOWN_RIGHT
;
175 for (Index
= 0; Index
< LargestString
; Index
++) {
176 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
178 *StringPtr
++ = BOXDRAW_DOWN_LEFT
;
181 ConOut
->SetCursorPosition (ConOut
, Start
, Top
);
182 ConOut
->OutputString (ConOut
, LineBuffer
);
184 for (Index
= 0; Index
< NumberOfLines
; Index
++) {
185 StringPtr
= &LineBuffer
[0];
186 *StringPtr
++ = BOXDRAW_VERTICAL
;
188 for (Count
= 0; Count
< LargestString
; Count
++) {
189 StringPtr
[Count
] = L
' ';
192 StringLen
= StrLen (StringArray
[Index
]);
193 if (StringLen
> LargestString
) {
194 StringLen
= LargestString
;
197 StringPtr
+ ((LargestString
- StringLen
) / 2),
199 StringLen
* sizeof (CHAR16
)
201 StringPtr
+= LargestString
;
203 *StringPtr
++ = BOXDRAW_VERTICAL
;
206 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ 1 + Index
);
207 ConOut
->OutputString (ConOut
, LineBuffer
);
210 StringPtr
= &LineBuffer
[0];
211 *StringPtr
++ = BOXDRAW_UP_RIGHT
;
212 for (Index
= 0; Index
< LargestString
; Index
++) {
213 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
215 *StringPtr
++ = BOXDRAW_UP_LEFT
;
218 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ NumberOfLines
+ 1);
219 ConOut
->OutputString (ConOut
, LineBuffer
);
222 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
225 // Set a timer event of 1 second expiration
234 // Wait for the keystroke event or the timer
236 WaitList
[0] = gST
->ConIn
->WaitForKey
;
237 WaitList
[1] = TimerEvent
;
238 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
241 // Check for the timer expiration
243 if (!EFI_ERROR (Status
) && Index
== 1) {
244 Status
= EFI_TIMEOUT
;
247 gBS
->CloseEvent (TimerEvent
);
248 } while (Status
== EFI_TIMEOUT
);
250 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
251 CopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
253 ConOut
->SetAttribute (ConOut
, CurrentAttribute
);
254 ConOut
->EnableCursor (ConOut
, TRUE
);
256 FreePool (LineBuffer
);
257 FreePool (StringArray
);
264 Draw a dialog and return the selected key.
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
273 @retval EFI_SUCCESS Displayed dialog and received user interaction
274 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
280 IN UINTN NumberOfLines
,
281 OUT EFI_INPUT_KEY
*KeyValue
,
289 VA_START (Marker
, String
);
291 Status
= IfrLibCreatePopUp2 (NumberOfLines
, KeyValue
, String
, Marker
);
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
309 @param Buffer Array generated by VFR compiler.
310 @param BlockName The returned <BlockName>
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.
320 OUT CHAR16
**BlockName
326 UINT32 BlockNameNumber
;
327 UINTN HexStringBufferLen
;
330 if ((Buffer
== NULL
) || (BlockName
== NULL
)) {
331 return EFI_INVALID_PARAMETER
;
335 // Calculate number of Offset/Width pair
337 CopyMem (&Length
, Buffer
, sizeof (UINT32
));
338 BlockNameNumber
= (Length
- sizeof (UINT32
)) / (sizeof (UINT16
) * 2);
341 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
344 StringPtr
= AllocateZeroPool ((BlockNameNumber
* (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16
));
345 *BlockName
= StringPtr
;
346 if (StringPtr
== NULL
) {
347 return EFI_OUT_OF_RESOURCES
;
350 Buffer
+= sizeof (UINT32
);
351 for (Index
= 0; Index
< BlockNameNumber
; Index
++) {
352 StrCpy (StringPtr
, L
"&OFFSET=");
355 HexStringBufferLen
= 5;
356 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
357 Buffer
+= sizeof (UINT16
);
360 StrCpy (StringPtr
, L
"&WIDTH=");
363 HexStringBufferLen
= 5;
364 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
365 Buffer
+= sizeof (UINT16
);
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".
377 @param Buffer - Array generated by VFR compiler.
378 @param BlockConfig - The returned <BlockConfig>
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.
388 OUT CHAR16
**BlockConfig
393 UINTN HexStringBufferLen
;
399 if ((Buffer
== NULL
) || (BlockConfig
== NULL
)) {
400 return EFI_INVALID_PARAMETER
;
404 // Calculate length of AltResp string
405 // Format of Default value array is:
406 // Array length | 4-bytes
409 // Value | Variable length
412 // Value | Variable length
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
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
;
427 StringEnd
= StringPtr
+ (Length
* 7);
429 Buffer
+= sizeof (UINT32
);
430 while (Buffer
< BufferEnd
) {
431 StrCpy (StringPtr
, L
"&OFFSET=");
434 HexStringBufferLen
= 5;
435 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
436 Buffer
+= sizeof (UINT16
);
439 StrCpy (StringPtr
, L
"&WIDTH=");
442 HexStringBufferLen
= 5;
443 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
444 CopyMem (&Width
, Buffer
, sizeof (UINT16
));
445 Buffer
+= sizeof (UINT16
);
448 StrCpy (StringPtr
, L
"&VALUE=");
451 HexStringBufferLen
= StringEnd
- StringPtr
;
452 Status
= BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, Width
);
453 if (EFI_ERROR (Status
)) {
457 StringPtr
+= (Width
* 2);
464 Construct <ConfigAltResp> for a buffer storage.
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>.
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.
488 ConstructConfigAltResp (
489 IN EFI_STRING ConfigRequest
, OPTIONAL
490 OUT EFI_STRING
*Progress
,
491 OUT EFI_STRING
*ConfigAltResp
,
494 IN EFI_HANDLE
*DriverHandle
,
495 IN VOID
*BufferStorage
,
496 IN UINTN BufferStorageSize
,
497 IN VOID
*BlockNameArray
, OPTIONAL
498 IN UINTN NumberAltCfg
,
500 //IN UINT16 AltCfgId,
501 //IN VOID *DefaultValueArray,
511 VOID
*DefaultValueArray
;
513 EFI_STRING ConfigResp
;
518 BOOLEAN NeedFreeConfigRequest
;
519 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
522 if (ConfigAltResp
== NULL
) {
523 return EFI_INVALID_PARAMETER
;
527 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
531 Status
= ConstructConfigHdr (
538 if (Status
== EFI_BUFFER_TOO_SMALL
) {
539 ConfigHdr
= AllocateZeroPool (StrBufferLen
);
540 Status
= ConstructConfigHdr (
549 if (EFI_ERROR (Status
)) {
554 // Construct <ConfigResp>
556 NeedFreeConfigRequest
= FALSE
;
557 if (ConfigRequest
== NULL
) {
559 // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray
561 Status
= ExtractBlockName (BlockNameArray
, &BlockName
);
562 if (EFI_ERROR (Status
)) {
566 Len
= StrSize (ConfigHdr
);
567 ConfigRequest
= AllocateZeroPool (Len
+ StrSize (BlockName
) - sizeof (CHAR16
));
568 StrCpy (ConfigRequest
, ConfigHdr
);
569 StrCat (ConfigRequest
, BlockName
);
570 NeedFreeConfigRequest
= TRUE
;
573 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
574 if (EFI_ERROR (Status
)) {
578 Status
= HiiConfigRouting
->BlockToConfig (
584 (Progress
== NULL
) ? &TempStr
: Progress
586 if (EFI_ERROR (Status
)) {
591 // Construct <AltResp>
593 DescHdr
= AllocateZeroPool (NumberAltCfg
* 16 * sizeof (CHAR16
));
595 AltCfg
= AllocateZeroPool (NumberAltCfg
* sizeof (CHAR16
*));
597 VA_START (Args
, NumberAltCfg
);
598 for (Index
= 0; Index
< NumberAltCfg
; Index
++) {
599 AltCfgId
= (UINT16
) VA_ARG (Args
, UINT16
);
600 DefaultValueArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
605 AltRespLen
+= (StrLen (ConfigHdr
) + 1);
607 StringPtr
= DescHdr
+ Index
* 16;
608 StrCpy (StringPtr
, L
"&ALTCFG=");
609 AltRespLen
+= (8 + sizeof (UINT16
) * 2);
612 BufToHexString (StringPtr
+ 8, &StrBufferLen
, (UINT8
*) &AltCfgId
, sizeof (UINT16
));
613 Status
= ExtractBlockConfig (DefaultValueArray
, &AltCfg
[Index
]);
614 if (EFI_ERROR (Status
)) {
617 AltRespLen
+= StrLen (AltCfg
[Index
]);
622 // Generate the final <ConfigAltResp>
624 StrBufferLen
= (StrLen ((CHAR16
*) ConfigResp
) + AltRespLen
+ 1) * sizeof (CHAR16
);
625 TempStr
= AllocateZeroPool (StrBufferLen
);
626 *ConfigAltResp
= TempStr
;
627 if (TempStr
== NULL
) {
628 return EFI_OUT_OF_RESOURCES
;
632 // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*
634 StrCpy (TempStr
, ConfigResp
);
635 for (Index
= 0; Index
< NumberAltCfg
; Index
++) {
636 StrCat (TempStr
, L
"&");
637 StrCat (TempStr
, ConfigHdr
);
638 StrCat (TempStr
, DescHdr
+ Index
* 16);
639 StrCat (TempStr
, AltCfg
[Index
]);
641 FreePool (AltCfg
[Index
]);
644 if (NeedFreeConfigRequest
) {
645 FreePool (ConfigRequest
);
647 FreePool (ConfigHdr
);
648 FreePool (ConfigResp
);
656 Swap bytes in the buffer. This is a internal function.
658 @param Buffer Binary buffer.
659 @param BufferSize Size of the buffer in bytes.
666 IN OUT UINT8
*Buffer
,
674 SwapCount
= BufferSize
/ 2;
675 for (Index
= 0; Index
< SwapCount
; Index
++) {
676 Temp
= Buffer
[Index
];
677 Buffer
[Index
] = Buffer
[BufferSize
- 1 - Index
];
678 Buffer
[BufferSize
- 1 - Index
] = Temp
;
683 Converts the unicode character of the string from uppercase to lowercase.
684 This is a internal function.
686 @param Str String to be converted
697 for (Ptr
= Str
; *Ptr
!= L
'\0'; Ptr
++) {
698 if (*Ptr
>= L
'A' && *Ptr
<= L
'Z') {
699 *Ptr
= (CHAR16
) (*Ptr
- L
'A' + L
'a');
706 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
708 @param Str String for output
709 @param Buffer Binary buffer.
710 @param BufferSize Size of the buffer in bytes.
712 @retval EFI_SUCCESS The function completed successfully.
713 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
718 BufInReverseOrderToHexString (
728 NewBuffer
= AllocateCopyPool (BufferSize
, Buffer
);
729 if (NewBuffer
== NULL
) {
730 return EFI_OUT_OF_RESOURCES
;
732 SwapBuffer (NewBuffer
, BufferSize
);
734 StrBufferLen
= BufferSize
* sizeof (CHAR16
) + 1;
735 Status
= BufToHexString (Str
, &StrBufferLen
, NewBuffer
, BufferSize
);
737 FreePool (NewBuffer
);
739 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
748 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
750 @param Buffer Pointer to buffer that receives the data.
751 @param BufferSize Length in bytes of the buffer to hold converted
752 data. If routine return with EFI_SUCCESS,
753 containing length of converted data. If routine
754 return with EFI_BUFFER_TOO_SMALL, containg length
756 @param Str String to be converted from.
758 @retval EFI_SUCCESS The function completed successfully.
759 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
760 will be updated to the size required for the converstion.
765 HexStringToBufInReverseOrder (
766 IN OUT UINT8
*Buffer
,
767 IN OUT UINTN
*BufferSize
,
772 UINTN ConvertedStrLen
;
775 Status
= HexStringToBuf (Buffer
, BufferSize
, Str
, &ConvertedStrLen
);
776 if (!EFI_ERROR (Status
)) {
777 SwapBuffer (Buffer
, (ConvertedStrLen
+ 1) / 2);
784 Convert binary representation Config string (e.g. "0041004200430044") to the
785 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
786 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
788 @param UnicodeString Original Unicode string.
789 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
790 Includes tailing '\0' character.
792 If return EFI_SUCCESS, containing length of Unicode string buffer.
793 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
794 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
796 @retval EFI_SUCCESS Operation completes successfully.
797 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
802 ConfigStringToUnicode (
803 IN OUT CHAR16
*UnicodeString
,
804 IN OUT UINTN
*StrBufferLen
,
805 IN CHAR16
*ConfigString
813 Len
= StrLen (ConfigString
) / 4;
814 BufferSize
= (Len
+ 1) * sizeof (CHAR16
);
816 if (*StrBufferLen
< BufferSize
) {
817 *StrBufferLen
= BufferSize
;
818 return EFI_BUFFER_TOO_SMALL
;
821 *StrBufferLen
= BufferSize
;
823 for (Index
= 0; Index
< Len
; Index
++) {
824 BackupChar
= ConfigString
[4];
825 ConfigString
[4] = L
'\0';
827 HexStringToBuf ((UINT8
*) UnicodeString
, &BufferSize
, ConfigString
, NULL
);
829 ConfigString
[4] = BackupChar
;
836 // Add tailing '\0' character
838 *UnicodeString
= L
'\0';
844 Convert Unicode string to binary representation Config string, e.g.
845 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
846 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
848 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
849 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
850 Includes tailing '\0' character.
852 If return EFI_SUCCESS, containing length of Unicode string buffer.
853 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
854 @param UnicodeString Original Unicode string.
856 @retval EFI_SUCCESS Operation completes successfully.
857 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
862 UnicodeToConfigString (
863 IN OUT CHAR16
*ConfigString
,
864 IN OUT UINTN
*StrBufferLen
,
865 IN CHAR16
*UnicodeString
873 Len
= StrLen (UnicodeString
);
874 BufferSize
= (Len
* 4 + 1) * sizeof (CHAR16
);
876 if (*StrBufferLen
< BufferSize
) {
877 *StrBufferLen
= BufferSize
;
878 return EFI_BUFFER_TOO_SMALL
;
881 *StrBufferLen
= BufferSize
;
882 String
= ConfigString
;
884 for (Index
= 0; Index
< Len
; Index
++) {
885 BufToHexString (ConfigString
, &BufferSize
, (UINT8
*) UnicodeString
, 2);
892 // Add tailing '\0' character
894 *ConfigString
= L
'\0';
897 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
904 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
906 @param ConfigHdr Pointer to the ConfigHdr string.
907 @param StrBufferLen On input: Length in bytes of buffer to hold the
908 ConfigHdr string. Includes tailing '\0' character.
909 On output: If return EFI_SUCCESS, containing
910 length of ConfigHdr string buffer. If return
911 EFI_BUFFER_TOO_SMALL, containg length of string
913 @param Guid Routing information: GUID.
914 @param Name Routing information: NAME.
915 @param DriverHandle Driver handle which contains the routing
918 @retval EFI_SUCCESS Operation completes successfully.
919 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
925 IN OUT CHAR16
*ConfigHdr
,
926 IN OUT UINTN
*StrBufferLen
,
927 IN CONST EFI_GUID
*Guid
,
928 IN CHAR16
*Name
, OPTIONAL
929 IN EFI_HANDLE
*DriverHandle
934 UINTN DevicePathSize
;
937 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
941 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
946 // For buffer storage
948 NameStrLen
= StrLen (Name
);
952 // Retrieve DevicePath Protocol associated with this HiiPackageList
954 Status
= gBS
->HandleProtocol (
956 &gEfiDevicePathProtocolGuid
,
957 (VOID
**) &DevicePath
959 if (EFI_ERROR (Status
)) {
963 DevicePathSize
= GetDevicePathSize (DevicePath
);
966 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
967 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
969 BufferSize
= (5 + 32 + 6 + NameStrLen
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
970 if (*StrBufferLen
< BufferSize
) {
971 *StrBufferLen
= BufferSize
;
972 return EFI_BUFFER_TOO_SMALL
;
975 *StrBufferLen
= BufferSize
;
979 StrCpy (StrPtr
, L
"GUID=");
981 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
985 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
987 StrCpy (StrPtr
, L
"&NAME=");
990 BufferSize
= (NameStrLen
* 4 + 1) * sizeof (CHAR16
);
991 UnicodeToConfigString (StrPtr
, &BufferSize
, Name
);
992 StrPtr
+= (NameStrLen
* 4);
995 StrCpy (StrPtr
, L
"&PATH=");
997 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
1003 Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.
1005 @param ConfigString Either <ConfigRequest> or <ConfigResp>.
1006 @param StorageGuid GUID of the storage.
1007 @param StorageName Name of the stoarge.
1009 @retval TRUE Routing information is correct in ConfigString.
1010 @retval FALSE Routing information is incorrect in ConfigString.
1015 IN EFI_STRING ConfigString
,
1016 IN EFI_GUID
*StorageGuid
, OPTIONAL
1017 IN CHAR16
*StorageName OPTIONAL
1029 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1030 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1032 if (StrLen (ConfigString
) <= (5 + 32 + 6)) {
1039 if (StorageGuid
!= NULL
) {
1041 StrPtr
= ConfigString
+ 5 + 32;
1042 if (*StrPtr
!= L
'&') {
1047 BufferSize
= sizeof (EFI_GUID
);
1048 Status
= HexStringToBufInReverseOrder (
1055 if (EFI_ERROR (Status
)) {
1059 if (!CompareGuid (&Guid
, StorageGuid
)) {
1068 if (StorageName
!= NULL
) {
1069 StrPtr
= ConfigString
+ 5 + 32 + 6;
1070 while (*StrPtr
!= L
'\0' && *StrPtr
!= L
'&') {
1073 if (*StrPtr
!= L
'&') {
1078 BufferSize
= (((UINTN
) StrPtr
) - ((UINTN
) &ConfigString
[5 + 32 + 6])) / 4 + sizeof (CHAR16
);
1079 Name
= AllocatePool (BufferSize
);
1080 ASSERT (Name
!= NULL
);
1081 Status
= ConfigStringToUnicode (
1084 ConfigString
+ 5 + 32 + 6
1088 if (EFI_ERROR (Status
) || (StrCmp (Name
, StorageName
) != 0)) {
1098 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
1100 @param String The string to be searched in.
1101 @param Offset Offset in BlockName.
1102 @param Width Width in BlockName.
1104 @retval TRUE Block name found.
1105 @retval FALSE Block name not found.
1111 IN OUT CHAR16
*String
,
1119 UINTN ConvertedStrLen
;
1121 while ((String
= StrStr (String
, L
"&OFFSET=")) != NULL
) {
1125 String
= String
+ 8;
1128 BufferSize
= sizeof (UINTN
);
1129 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1130 if (EFI_ERROR (Status
)) {
1133 String
= String
+ ConvertedStrLen
;
1135 if (Data
!= Offset
) {
1139 if (StrnCmp (String
, L
"&WIDTH=", 7) != 0) {
1142 String
= String
+ 7;
1145 BufferSize
= sizeof (UINTN
);
1146 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1147 if (EFI_ERROR (Status
)) {
1150 if (Data
== Width
) {
1154 String
= String
+ ConvertedStrLen
;
1162 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
1164 @param VariableGuid An optional field to indicate the target variable
1166 @param VariableName An optional field to indicate the target
1167 human-readable variable name.
1168 @param BufferSize On input: Length in bytes of buffer to hold
1169 retrived data. On output: If return
1170 EFI_BUFFER_TOO_SMALL, containg length of buffer
1172 @param Buffer Buffer to hold retrived data.
1174 @retval EFI_SUCCESS Operation completes successfully.
1175 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
1176 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1182 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1183 IN CONST CHAR16
*VariableName
, OPTIONAL
1184 IN OUT UINTN
*BufferSize
,
1185 IN OUT UINT8
*Buffer
1189 CONST CHAR16
*ConfigHdr
;
1197 // Locate protocols for use
1199 Status
= LocateFormBrowser2Protocols ();
1200 if (EFI_ERROR (Status
)) {
1205 // Retrive formset storage data from Form Browser
1207 ConfigHdr
= mFakeConfigHdr
;
1208 HeaderLen
= StrLen (ConfigHdr
);
1211 // First try allocate 0x4000 buffer for the formet storage data.
1214 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1215 if (ConfigResp
== NULL
) {
1219 StringPtr
= ConfigResp
+ HeaderLen
;
1223 Status
= mFormBrowser2
->BrowserCallback (
1231 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1232 if (ConfigResp
!= NULL
) {
1233 FreePool (ConfigResp
);
1236 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1237 if (ConfigResp
== NULL
) {
1238 return EFI_OUT_OF_RESOURCES
;
1241 StringPtr
= ConfigResp
+ HeaderLen
;
1245 Status
= mFormBrowser2
->BrowserCallback (
1254 if (EFI_ERROR (Status
)) {
1255 FreePool (ConfigResp
);
1258 CopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
1261 // Convert <ConfigResp> to buffer data
1263 Status
= mIfrSupportLibHiiConfigRouting
->ConfigToBlock (
1264 mIfrSupportLibHiiConfigRouting
,
1270 FreePool (ConfigResp
);
1277 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
1279 @param VariableGuid An optional field to indicate the target variable
1281 @param VariableName An optional field to indicate the target
1282 human-readable variable name.
1283 @param BufferSize Length in bytes of buffer to hold retrived data.
1284 @param Buffer Buffer to hold retrived data.
1285 @param RequestElement An optional field to specify which part of the
1286 buffer data will be send back to Browser. If NULL,
1287 the whole buffer of data will be committed to
1288 Browser. <RequestElement> ::=
1289 &OFFSET=<Number>&WIDTH=<Number>*
1291 @retval EFI_SUCCESS Operation completes successfully.
1292 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1293 @retval Other Updating Browser uncommitted data failed.
1299 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1300 IN CONST CHAR16
*VariableName
, OPTIONAL
1301 IN UINTN BufferSize
,
1302 IN CONST UINT8
*Buffer
,
1303 IN CONST CHAR16
*RequestElement OPTIONAL
1307 CONST CHAR16
*ConfigHdr
;
1313 CHAR16 BlockName
[33];
1314 CHAR16
*ConfigRequest
;
1315 CONST CHAR16
*Request
;
1318 // Locate protocols for use
1320 Status
= LocateFormBrowser2Protocols ();
1321 if (EFI_ERROR (Status
)) {
1326 // Prepare <ConfigRequest>
1328 ConfigHdr
= mFakeConfigHdr
;
1329 HeaderLen
= StrLen (ConfigHdr
);
1331 if (RequestElement
== NULL
) {
1333 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
1335 BlockName
[0] = L
'\0';
1336 StrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
1339 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
1341 StringPtr
= BlockName
+ 16;
1342 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
1343 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
1345 Request
= BlockName
;
1347 Request
= RequestElement
;
1350 BufferLen
= HeaderLen
* sizeof (CHAR16
) + StrSize (Request
);
1351 ConfigRequest
= AllocateZeroPool (BufferLen
);
1352 if (ConfigRequest
== NULL
) {
1353 return EFI_OUT_OF_RESOURCES
;
1356 CopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
1357 StringPtr
= ConfigRequest
+ HeaderLen
;
1358 StrCpy (StringPtr
, Request
);
1361 // Convert buffer to <ConfigResp>
1363 Status
= mIfrSupportLibHiiConfigRouting
->BlockToConfig (
1364 mIfrSupportLibHiiConfigRouting
,
1371 if (EFI_ERROR (Status
)) {
1372 FreePool (ConfigRequest
);
1377 // Skip <ConfigHdr> and '&'
1379 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
1382 // Change uncommitted data in Browser
1384 Status
= mFormBrowser2
->BrowserCallback (
1392 FreePool (ConfigRequest
);
1397 Test if a Unicode character is a hexadecimal digit. If true, the input
1398 Unicode character is converted to a byte.
1400 This function tests if a Unicode character is a hexadecimal digit. If true, the input
1401 Unicode character is converted to a byte. For example, Unicode character
1402 L'A' will be converted to 0x0A.
1404 If Digit is NULL, then ASSERT.
1406 @param Digit The output hexadecimal digit.
1408 @param Char The input Unicode character.
1410 @retval TRUE Char is in the range of Hexadecimal number. Digit is updated
1411 to the byte value of the number.
1412 @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep
1423 ASSERT (Digit
!= NULL
);
1425 if ((Char
>= L
'0') && (Char
<= L
'9')) {
1426 *Digit
= (UINT8
) (Char
- L
'0');
1430 if ((Char
>= L
'A') && (Char
<= L
'F')) {
1431 *Digit
= (UINT8
) (Char
- L
'A' + 0x0A);
1435 if ((Char
>= L
'a') && (Char
<= L
'f')) {
1436 *Digit
= (UINT8
) (Char
- L
'a' + 0x0A);
1444 Convert binary buffer to a Unicode String in a specified sequence.
1446 This function converts bytes in the memory block pointed by Buffer to a Unicode String Str.
1447 Each byte will be represented by two Unicode characters. For example, byte 0xA1 will
1448 be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character
1449 for the Most Significant Nibble will be put before the Unicode Character for the Least Significant
1450 Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1".
1451 For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the
1452 the last character in the output string. The one next to first byte will be put into the
1453 character before the last character. This rules applies to the rest of the bytes. The Unicode
1454 character by the last byte will be put into the first character in the output string. For example,
1455 the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to
1456 a Unicode string equal to L"12345678abcdef1234".
1458 @param String On input, String is pointed to the buffer allocated for the convertion.
1459 @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.
1460 The StringLen required to convert a N bytes Buffer will be a least equal to or greater
1462 @param Buffer The pointer to a input buffer.
1463 @param BufferSizeInBytes Length in bytes of the input buffer.
1466 @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding
1467 Unicode character and placed into the right place in String.
1468 @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to
1469 complete the convertion.
1474 IN OUT CHAR16
*String
,
1475 IN OUT UINTN
*StringLen
,
1476 IN CONST UINT8
*Buffer
,
1477 IN UINTN BufferSizeInBytes
1485 // Make sure string is either passed or allocate enough.
1486 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
1487 // Plus the Unicode termination character.
1489 StrLen
= BufferSizeInBytes
* 2;
1490 if (StrLen
> ((*StringLen
) - 1)) {
1491 *StringLen
= StrLen
+ 1;
1492 return RETURN_BUFFER_TOO_SMALL
;
1495 *StringLen
= StrLen
+ 1;
1499 String
[StrLen
] = L
'\0';
1501 for (Idx
= 0; Idx
< BufferSizeInBytes
; Idx
++) {
1503 String
[StrLen
- 1 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
& 0xF];
1504 String
[StrLen
- 2 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
>> 4];
1507 return RETURN_SUCCESS
;
1512 Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.
1514 This function converts a Unicode string consisting of characters in the range of Hexadecimal
1515 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
1516 at the first non-hexadecimal character or the NULL character. The convertion process can be
1517 simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be
1518 converted into one byte. The first Unicode character represents the Most Significant Nibble and the
1519 second Unicode character represents the Least Significant Nibble in the output byte.
1520 The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode
1521 characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes.
1522 The last pair represent the first byte in the output buffer.
1524 For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes
1525 (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".
1527 If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least
1528 N/2 (if N is even) or (N+1)/2 (if N if odd) bytes.
1530 @param Buffer The output buffer allocated by the caller.
1531 @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to
1532 contain the size of the Buffer which is actually used for the converstion.
1533 For Unicode string with 2*N hexadecimal characters (not including the
1534 tailing NULL character), N bytes of Buffer will be used for the output.
1535 @param String The input hexadecimal string.
1536 @param ConvertedStrLen The number of hexadecimal characters used to produce content in output
1539 @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes
1540 will be updated to the size required for the converstion.
1541 @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String
1542 is hexadecimal. If ConvertedStrLen is not NULL, it is updated
1543 to the number of hexadecimal character used for the converstion.
1549 IN OUT UINTN
*BufferSizeInBytes
,
1550 IN CONST CHAR16
*String
,
1551 OUT UINTN
*ConvertedStrLen OPTIONAL
1561 // Find out how many hex characters the string has.
1563 for (Idx
= 0, HexCnt
= 0; IsHexDigit (&Digit
, String
[Idx
]); Idx
++, HexCnt
++);
1566 *ConvertedStrLen
= 0;
1567 return RETURN_SUCCESS
;
1570 // Two Unicode characters make up 1 buffer byte. Round up.
1572 BufferLength
= (HexCnt
+ 1) / 2;
1575 // Test if buffer is passed enough.
1577 if (BufferLength
> (*BufferSizeInBytes
)) {
1578 *BufferSizeInBytes
= BufferLength
;
1579 return RETURN_BUFFER_TOO_SMALL
;
1582 *BufferSizeInBytes
= BufferLength
;
1584 for (Idx
= 0; Idx
< HexCnt
; Idx
++) {
1586 IsHexDigit (&Digit
, String
[HexCnt
- 1 - Idx
]);
1589 // For odd charaters, write the lower nibble for each buffer byte,
1590 // and for even characters, the upper nibble.
1592 if ((Idx
& 1) == 0) {
1595 Byte
= Buffer
[Idx
/ 2];
1597 Byte
= (UINT8
) (Byte
| Digit
<< 4);
1600 Buffer
[Idx
/ 2] = Byte
;
1603 if (ConvertedStrLen
!= NULL
) {
1604 *ConvertedStrLen
= HexCnt
;
1607 return RETURN_SUCCESS
;