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"
21 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
24 Draw a dialog and return the selected key.
26 @param NumberOfLines The number of lines for the dialog box
27 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
28 @param String Pointer to the first string in the list
29 @param ... A series of (quantity == NumberOfLines - 1) text
30 strings which will be used to construct the dialog
33 @retval EFI_SUCCESS Displayed dialog and received user interaction
34 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
40 IN UINTN NumberOfLines
,
41 OUT EFI_INPUT_KEY
*KeyValue
,
54 UINTN DimensionsWidth
;
55 UINTN DimensionsHeight
;
64 EFI_EVENT WaitList
[2];
65 UINTN CurrentAttribute
;
66 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
69 String
= VA_ARG (Marker
, CHAR16
*);
71 if ((KeyValue
== NULL
) || (String
== NULL
)) {
72 return EFI_INVALID_PARAMETER
;
81 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &RightColumn
, &BottomRow
);
83 DimensionsWidth
= RightColumn
- LeftColumn
;
84 DimensionsHeight
= BottomRow
- TopRow
;
86 CurrentAttribute
= ConOut
->Mode
->Attribute
;
88 LineBuffer
= AllocateZeroPool (DimensionsWidth
* sizeof (CHAR16
));
89 ASSERT (LineBuffer
!= NULL
);
92 // Determine the largest string in the dialog box
93 // Notice we are starting with 1 since String is the first string
95 StringArray
= AllocateZeroPool (NumberOfLines
* sizeof (CHAR16
*));
96 LargestString
= StrLen (String
);
97 StringArray
[0] = String
;
99 for (Index
= 1; Index
< NumberOfLines
; Index
++) {
100 StackString
= VA_ARG (Marker
, CHAR16
*);
102 if (StackString
== NULL
) {
103 return EFI_INVALID_PARAMETER
;
106 StringArray
[Index
] = StackString
;
107 StringLen
= StrLen (StackString
);
108 if (StringLen
> LargestString
) {
109 LargestString
= StringLen
;
113 if ((LargestString
+ 2) > DimensionsWidth
) {
114 LargestString
= DimensionsWidth
- 2;
118 // Subtract the PopUp width from total Columns, allow for one space extra on
119 // each end plus a border.
121 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + LeftColumn
+ 1;
123 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + TopRow
- 1;
128 ConOut
->EnableCursor (ConOut
, FALSE
);
129 ConOut
->SetAttribute (ConOut
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
131 StringPtr
= &LineBuffer
[0];
132 *StringPtr
++ = BOXDRAW_DOWN_RIGHT
;
133 for (Index
= 0; Index
< LargestString
; Index
++) {
134 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
136 *StringPtr
++ = BOXDRAW_DOWN_LEFT
;
139 ConOut
->SetCursorPosition (ConOut
, Start
, Top
);
140 ConOut
->OutputString (ConOut
, LineBuffer
);
142 for (Index
= 0; Index
< NumberOfLines
; Index
++) {
143 StringPtr
= &LineBuffer
[0];
144 *StringPtr
++ = BOXDRAW_VERTICAL
;
146 for (Count
= 0; Count
< LargestString
; Count
++) {
147 StringPtr
[Count
] = L
' ';
150 StringLen
= StrLen (StringArray
[Index
]);
151 if (StringLen
> LargestString
) {
152 StringLen
= LargestString
;
155 StringPtr
+ ((LargestString
- StringLen
) / 2),
157 StringLen
* sizeof (CHAR16
)
159 StringPtr
+= LargestString
;
161 *StringPtr
++ = BOXDRAW_VERTICAL
;
164 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ 1 + Index
);
165 ConOut
->OutputString (ConOut
, LineBuffer
);
168 StringPtr
= &LineBuffer
[0];
169 *StringPtr
++ = BOXDRAW_UP_RIGHT
;
170 for (Index
= 0; Index
< LargestString
; Index
++) {
171 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
173 *StringPtr
++ = BOXDRAW_UP_LEFT
;
176 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ NumberOfLines
+ 1);
177 ConOut
->OutputString (ConOut
, LineBuffer
);
180 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
183 // Set a timer event of 1 second expiration
192 // Wait for the keystroke event or the timer
194 WaitList
[0] = gST
->ConIn
->WaitForKey
;
195 WaitList
[1] = TimerEvent
;
196 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
199 // Check for the timer expiration
201 if (!EFI_ERROR (Status
) && Index
== 1) {
202 Status
= EFI_TIMEOUT
;
205 gBS
->CloseEvent (TimerEvent
);
206 } while (Status
== EFI_TIMEOUT
);
208 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
209 CopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
211 ConOut
->SetAttribute (ConOut
, CurrentAttribute
);
212 ConOut
->EnableCursor (ConOut
, TRUE
);
218 Draw a dialog and return the selected key.
220 @param NumberOfLines The number of lines for the dialog box
221 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
222 @param String Pointer to the first string in the list
223 @param ... A series of (quantity == NumberOfLines - 1) text
224 strings which will be used to construct the dialog
227 @retval EFI_SUCCESS Displayed dialog and received user interaction
228 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
234 IN UINTN NumberOfLines
,
235 OUT EFI_INPUT_KEY
*KeyValue
,
243 VA_START (Marker
, KeyValue
);
245 Status
= IfrLibCreatePopUp2 (NumberOfLines
, KeyValue
, Marker
);
253 Swap bytes in the buffer. This is a internal function.
255 @param Buffer Binary buffer.
256 @param BufferSize Size of the buffer in bytes.
263 IN OUT UINT8
*Buffer
,
271 SwapCount
= BufferSize
/ 2;
272 for (Index
= 0; Index
< SwapCount
; Index
++) {
273 Temp
= Buffer
[Index
];
274 Buffer
[Index
] = Buffer
[BufferSize
- 1 - Index
];
275 Buffer
[BufferSize
- 1 - Index
] = Temp
;
280 Converts the unicode character of the string from uppercase to lowercase.
281 This is a internal function.
283 @param Str String to be converted
294 for (Ptr
= Str
; *Ptr
!= L
'\0'; Ptr
++) {
295 if (*Ptr
>= L
'A' && *Ptr
<= L
'Z') {
296 *Ptr
= (CHAR16
) (*Ptr
- L
'A' + L
'a');
303 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
305 @param Str String for output
306 @param Buffer Binary buffer.
307 @param BufferSize Size of the buffer in bytes.
309 @retval EFI_SUCCESS The function completed successfully.
324 NewBuffer
= AllocateCopyPool (BufferSize
, Buffer
);
325 SwapBuffer (NewBuffer
, BufferSize
);
327 StrBufferLen
= BufferSize
* sizeof (CHAR16
) + 1;
328 Status
= BufToHexString (Str
, &StrBufferLen
, NewBuffer
, BufferSize
);
330 FreePool (NewBuffer
);
332 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
341 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
343 @param Buffer Pointer to buffer that receives the data.
344 @param BufferSize Length in bytes of the buffer to hold converted
345 data. If routine return with EFI_SUCCESS,
346 containing length of converted data. If routine
347 return with EFI_BUFFER_TOO_SMALL, containg length
349 @param Str String to be converted from.
351 @retval EFI_SUCCESS The function completed successfully.
357 IN OUT UINT8
*Buffer
,
358 IN OUT UINTN
*BufferSize
,
363 UINTN ConvertedStrLen
;
366 Status
= HexStringToBuf (Buffer
, BufferSize
, Str
, &ConvertedStrLen
);
367 if (!EFI_ERROR (Status
)) {
368 SwapBuffer (Buffer
, ConvertedStrLen
);
375 Convert binary representation Config string (e.g. "0041004200430044") to the
376 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
377 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
379 @param UnicodeString Original Unicode string.
380 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
381 Includes tailing '\0' character.
383 If return EFI_SUCCESS, containing length of Unicode string buffer.
384 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
385 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
387 @retval EFI_SUCCESS Routine success.
388 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
393 ConfigStringToUnicode (
394 IN OUT CHAR16
*UnicodeString
,
395 IN OUT UINTN
*StrBufferLen
,
396 IN CHAR16
*ConfigString
404 Len
= StrLen (ConfigString
) / 4;
405 BufferSize
= (Len
+ 1) * sizeof (CHAR16
);
407 if (*StrBufferLen
< BufferSize
) {
408 *StrBufferLen
= BufferSize
;
409 return EFI_BUFFER_TOO_SMALL
;
412 *StrBufferLen
= BufferSize
;
414 for (Index
= 0; Index
< Len
; Index
++) {
415 BackupChar
= ConfigString
[4];
416 ConfigString
[4] = L
'\0';
418 HexStringToBuf ((UINT8
*) UnicodeString
, &BufferSize
, ConfigString
, NULL
);
420 ConfigString
[4] = BackupChar
;
427 // Add tailing '\0' character
429 *UnicodeString
= L
'\0';
435 Convert Unicode string to binary representation Config string, e.g.
436 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
437 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
439 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
440 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
441 Includes tailing '\0' character.
443 If return EFI_SUCCESS, containing length of Unicode string buffer.
444 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
445 @param UnicodeString Original Unicode string.
447 @retval EFI_SUCCESS Routine success.
448 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
453 UnicodeToConfigString (
454 IN OUT CHAR16
*ConfigString
,
455 IN OUT UINTN
*StrBufferLen
,
456 IN CHAR16
*UnicodeString
464 Len
= StrLen (UnicodeString
);
465 BufferSize
= (Len
* 4 + 1) * sizeof (CHAR16
);
467 if (*StrBufferLen
< BufferSize
) {
468 *StrBufferLen
= BufferSize
;
469 return EFI_BUFFER_TOO_SMALL
;
472 *StrBufferLen
= BufferSize
;
473 String
= ConfigString
;
475 for (Index
= 0; Index
< Len
; Index
++) {
476 BufToHexString (ConfigString
, &BufferSize
, (UINT8
*) UnicodeString
, 2);
483 // Add tailing '\0' character
485 *ConfigString
= L
'\0';
488 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
495 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
497 @param ConfigHdr Pointer to the ConfigHdr string.
498 @param StrBufferLen On input: Length in bytes of buffer to hold the
499 ConfigHdr string. Includes tailing '\0' character.
500 On output: If return EFI_SUCCESS, containing
501 length of ConfigHdr string buffer. If return
502 EFI_BUFFER_TOO_SMALL, containg length of string
504 @param Guid Routing information: GUID.
505 @param Name Routing information: NAME.
506 @param DriverHandle Driver handle which contains the routing
509 @retval EFI_SUCCESS Routine success.
510 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
516 IN OUT CHAR16
*ConfigHdr
,
517 IN OUT UINTN
*StrBufferLen
,
519 IN CHAR16
*Name
, OPTIONAL
520 IN EFI_HANDLE
*DriverHandle
525 UINTN DevicePathSize
;
528 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
532 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
537 // For buffer storage
539 NameStrLen
= StrLen (Name
);
543 // Retrieve DevicePath Protocol associated with this HiiPackageList
545 Status
= gBS
->HandleProtocol (
547 &gEfiDevicePathProtocolGuid
,
548 (VOID
**) &DevicePath
550 if (EFI_ERROR (Status
)) {
554 DevicePathSize
= GetDevicePathSize (DevicePath
);
557 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
558 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
560 BufferSize
= (5 + 32 + 6 + NameStrLen
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
561 if (*StrBufferLen
< BufferSize
) {
562 *StrBufferLen
= BufferSize
;
563 return EFI_BUFFER_TOO_SMALL
;
566 *StrBufferLen
= BufferSize
;
570 StrCpy (StrPtr
, L
"GUID=");
572 BufferToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
576 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
578 StrCpy (StrPtr
, L
"&NAME=");
581 BufferSize
= (NameStrLen
* 4 + 1) * sizeof (CHAR16
);
582 UnicodeToConfigString (StrPtr
, &BufferSize
, Name
);
583 StrPtr
+= (NameStrLen
* 4);
586 StrCpy (StrPtr
, L
"&PATH=");
588 BufferToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
595 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
597 @param String The string to be searched in.
598 @param Offset Offset in BlockName.
599 @param Width Width in BlockName.
601 @retval TRUE Block name found.
602 @retval FALSE Block name not found.
608 IN OUT CHAR16
*String
,
616 UINTN ConvertedStrLen
;
618 while ((String
= StrStr (String
, L
"&OFFSET=")) != NULL
) {
625 BufferSize
= sizeof (UINTN
);
626 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
627 if (EFI_ERROR (Status
)) {
630 String
= String
+ ConvertedStrLen
;
632 if (Data
!= Offset
) {
636 if (StrnCmp (String
, L
"&WIDTH=", 7) != 0) {
642 BufferSize
= sizeof (UINTN
);
643 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
644 if (EFI_ERROR (Status
)) {
651 String
= String
+ ConvertedStrLen
;
659 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
661 @param VariableGuid An optional field to indicate the target variable
663 @param VariableName An optional field to indicate the target
664 human-readable variable name.
665 @param BufferSize On input: Length in bytes of buffer to hold
666 retrived data. On output: If return
667 EFI_BUFFER_TOO_SMALL, containg length of buffer
669 @param Buffer Buffer to hold retrived data.
671 @retval EFI_SUCCESS Routine success.
672 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
678 EFI_GUID
*VariableGuid
, OPTIONAL
679 CHAR16
*VariableName
, OPTIONAL
685 CONST CHAR16
*ConfigHdr
;
691 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
692 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
695 // Locate protocols for use
697 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
698 if (EFI_ERROR (Status
)) {
702 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
703 if (EFI_ERROR (Status
)) {
708 // Retrive formset storage data from Form Browser
710 ConfigHdr
= mFakeConfigHdr
;
711 HeaderLen
= StrLen (ConfigHdr
);
714 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
716 StringPtr
= ConfigResp
+ HeaderLen
;
720 Status
= FormBrowser2
->BrowserCallback (
728 if (Status
== EFI_BUFFER_TOO_SMALL
) {
729 FreePool (ConfigResp
);
730 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
732 StringPtr
= ConfigResp
+ HeaderLen
;
736 Status
= FormBrowser2
->BrowserCallback (
745 if (EFI_ERROR (Status
)) {
746 FreePool (ConfigResp
);
749 CopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
752 // Convert <ConfigResp> to buffer data
754 Status
= HiiConfigRouting
->ConfigToBlock (
761 FreePool (ConfigResp
);
768 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
770 @param VariableGuid An optional field to indicate the target variable
772 @param VariableName An optional field to indicate the target
773 human-readable variable name.
774 @param BufferSize Length in bytes of buffer to hold retrived data.
775 @param Buffer Buffer to hold retrived data.
776 @param RequestElement An optional field to specify which part of the
777 buffer data will be send back to Browser. If NULL,
778 the whole buffer of data will be committed to
779 Browser. <RequestElement> ::=
780 &OFFSET=<Number>&WIDTH=<Number>*
782 @retval EFI_SUCCESS Routine success.
783 @retval Other Updating Browser uncommitted data failed.
789 EFI_GUID
*VariableGuid
, OPTIONAL
790 CHAR16
*VariableName
, OPTIONAL
793 CHAR16
*RequestElement OPTIONAL
797 CONST CHAR16
*ConfigHdr
;
803 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
804 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
805 CHAR16 BlockName
[33];
806 CHAR16
*ConfigRequest
;
810 // Locate protocols for use
812 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
813 if (EFI_ERROR (Status
)) {
817 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
818 if (EFI_ERROR (Status
)) {
823 // Prepare <ConfigRequest>
825 ConfigHdr
= mFakeConfigHdr
;
826 HeaderLen
= StrLen (ConfigHdr
);
828 if (RequestElement
== NULL
) {
830 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
832 BlockName
[0] = L
'\0';
833 StrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
836 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
838 StringPtr
= BlockName
+ 16;
839 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
840 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
844 Request
= RequestElement
;
847 BufferLen
= HeaderLen
* sizeof (CHAR16
) + StrSize (Request
);
848 ConfigRequest
= AllocateZeroPool (BufferLen
);
850 CopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
851 StringPtr
= ConfigRequest
+ HeaderLen
;
852 StrCpy (StringPtr
, Request
);
855 // Convert buffer to <ConfigResp>
857 Status
= HiiConfigRouting
->BlockToConfig (
865 if (EFI_ERROR (Status
)) {
866 FreePool (ConfigResp
);
871 // Skip <ConfigHdr> and '&'
873 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
876 // Change uncommitted data in Browser
878 Status
= FormBrowser2
->BrowserCallback (
886 FreePool (ConfigResp
);