]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/IfrSupportLib/UefiIfrForm.c
Fix ECC issue.
[mirror_edk2.git] / MdePkg / Library / IfrSupportLib / UefiIfrForm.c
CommitLineData
e52c5a9f 1/** @file
ad1b3619 2Utility functions which helps in opcode creation, HII configuration string manipulations,
3pop up window creations, setup browser persistence data set and get.
e52c5a9f 4
54cf8780 5Copyright (c) 2007- 2008, Intel Corporation
e52c5a9f 6All rights reserved. This program and the accompanying materials
7are licensed and made available under the terms and conditions of the BSD License
8which accompanies this distribution. The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
e52c5a9f 14**/
15
16#include "UefiIfrLibraryInternal.h"
17
b911d09f
LG
18STATIC CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;
19STATIC CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;
20
55f298c3 21/**
22 This function locate FormBrowser2 protocols for later usage.
23
24 @return Status the status to locate protocol.
25**/
26EFI_STATUS
27LocateFormBrowser2Protocols (
28 VOID
29 )
b911d09f
LG
30{
31 EFI_STATUS Status;
32 //
33 // Locate protocols for later usage
34 //
35 if (mFormBrowser2 == NULL) {
36 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2);
37 if (EFI_ERROR (Status)) {
38 return Status;
39 }
40 }
41
42 if (mHiiConfigRouting == NULL) {
43 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mHiiConfigRouting);
44 if (EFI_ERROR (Status)) {
45 return Status;
46 }
47 }
48
49 return EFI_SUCCESS;
50}
51
e52c5a9f 52//
53// Fake <ConfigHdr>
54//
1db1f6ad 55GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
e52c5a9f 56
e52c5a9f 57/**
58 Draw a dialog and return the selected key.
59
60 @param NumberOfLines The number of lines for the dialog box
61 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
f81656f7 62 @param Marker A series of (quantity == NumberOfLines - 1) text
e52c5a9f 63 strings which will be used to construct the dialog
64 box
65
66 @retval EFI_SUCCESS Displayed dialog and received user interaction
67 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
b911d09f 68 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
e52c5a9f 69
70**/
71EFI_STATUS
72EFIAPI
55a9663b 73IfrLibCreatePopUp2 (
e52c5a9f 74 IN UINTN NumberOfLines,
75 OUT EFI_INPUT_KEY *KeyValue,
55a9663b 76 IN VA_LIST Marker
e52c5a9f 77 )
78{
79 UINTN Index;
80 UINTN Count;
81 UINTN Start;
82 UINTN Top;
83 CHAR16 *StringPtr;
84 UINTN LeftColumn;
85 UINTN RightColumn;
86 UINTN TopRow;
87 UINTN BottomRow;
88 UINTN DimensionsWidth;
89 UINTN DimensionsHeight;
e52c5a9f 90 EFI_INPUT_KEY Key;
91 UINTN LargestString;
92 CHAR16 *StackString;
93 EFI_STATUS Status;
94 UINTN StringLen;
95 CHAR16 *LineBuffer;
96 CHAR16 **StringArray;
97 EFI_EVENT TimerEvent;
98 EFI_EVENT WaitList[2];
99 UINTN CurrentAttribute;
100 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
55a9663b 101 CHAR16 *String;
e52c5a9f 102
55a9663b 103 String = VA_ARG (Marker, CHAR16 *);
104
e52c5a9f 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));
b911d09f
LG
123 if (LineBuffer == NULL) {
124 return EFI_OUT_OF_RESOURCES;
125 }
e52c5a9f 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 *));
b911d09f
LG
132 if (StringArray == NULL) {
133 FreePool (LineBuffer);
134 return EFI_OUT_OF_RESOURCES;
135 }
e52c5a9f 136 LargestString = StrLen (String);
137 StringArray[0] = String;
138
e52c5a9f 139 for (Index = 1; Index < NumberOfLines; Index++) {
140 StackString = VA_ARG (Marker, CHAR16 *);
141
142 if (StackString == NULL) {
b911d09f
LG
143 FreePool (LineBuffer);
144 FreePool (StringArray);
e52c5a9f 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
b911d09f
LG
256 FreePool (LineBuffer);
257 FreePool (StringArray);
258
259 return Status;
260}
55a9663b 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**/
277EFI_STATUS
278EFIAPI
279IfrLibCreatePopUp (
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, KeyValue);
290
291 Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, Marker);
292
293 VA_END (Marker);
294
e52c5a9f 295 return Status;
296}
297
e52c5a9f 298/**
ad1b3619 299 Swap bytes in the buffer. This is a internal function.
e52c5a9f 300
301 @param Buffer Binary buffer.
302 @param BufferSize Size of the buffer in bytes.
303
304 @return None.
305
306**/
e52c5a9f 307VOID
308SwapBuffer (
309 IN OUT UINT8 *Buffer,
310 IN UINTN BufferSize
311 )
312{
313 UINTN Index;
314 UINT8 Temp;
315 UINTN SwapCount;
316
54cf8780 317 SwapCount = BufferSize / 2;
e52c5a9f 318 for (Index = 0; Index < SwapCount; Index++) {
319 Temp = Buffer[Index];
320 Buffer[Index] = Buffer[BufferSize - 1 - Index];
321 Buffer[BufferSize - 1 - Index] = Temp;
322 }
323}
324
54cf8780 325/**
326 Converts the unicode character of the string from uppercase to lowercase.
ad1b3619 327 This is a internal function.
54cf8780 328
329 @param Str String to be converted
330
54cf8780 331**/
332VOID
1db1f6ad 333EFIAPI
54cf8780 334ToLower (
335 IN OUT CHAR16 *Str
336 )
337{
338 CHAR16 *Ptr;
339
340 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
341 if (*Ptr >= L'A' && *Ptr <= L'Z') {
342 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
343 }
344 }
345}
346
e52c5a9f 347
348/**
d9e5c1ff 349 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
e52c5a9f 350
351 @param Str String for output
352 @param Buffer Binary buffer.
353 @param BufferSize Size of the buffer in bytes.
354
355 @retval EFI_SUCCESS The function completed successfully.
b911d09f 356 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
e52c5a9f 357
358**/
359EFI_STATUS
360EFIAPI
f4e8509b 361BufInReverseOrderToHexString (
e52c5a9f 362 IN OUT CHAR16 *Str,
363 IN UINT8 *Buffer,
364 IN UINTN BufferSize
365 )
366{
367 EFI_STATUS Status;
368 UINT8 *NewBuffer;
369 UINTN StrBufferLen;
370
371 NewBuffer = AllocateCopyPool (BufferSize, Buffer);
b911d09f
LG
372 if (NewBuffer == NULL) {
373 return EFI_OUT_OF_RESOURCES;
374 }
e52c5a9f 375 SwapBuffer (NewBuffer, BufferSize);
376
54cf8780 377 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
d9e5c1ff 378 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
e52c5a9f 379
1db1f6ad 380 FreePool (NewBuffer);
54cf8780 381 //
382 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
383 //
384 ToLower (Str);
e52c5a9f 385
386 return Status;
387}
388
389
390/**
d9e5c1ff 391 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
e52c5a9f 392
393 @param Buffer Pointer to buffer that receives the data.
394 @param BufferSize Length in bytes of the buffer to hold converted
395 data. If routine return with EFI_SUCCESS,
396 containing length of converted data. If routine
397 return with EFI_BUFFER_TOO_SMALL, containg length
398 of buffer desired.
399 @param Str String to be converted from.
400
401 @retval EFI_SUCCESS The function completed successfully.
f4e8509b 402 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
403 will be updated to the size required for the converstion.
e52c5a9f 404
405**/
406EFI_STATUS
407EFIAPI
f4e8509b 408HexStringToBufInReverseOrder (
e52c5a9f 409 IN OUT UINT8 *Buffer,
410 IN OUT UINTN *BufferSize,
411 IN CHAR16 *Str
412 )
413{
414 EFI_STATUS Status;
415 UINTN ConvertedStrLen;
416
417 ConvertedStrLen = 0;
d9e5c1ff 418 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
e52c5a9f 419 if (!EFI_ERROR (Status)) {
420 SwapBuffer (Buffer, ConvertedStrLen);
421 }
422
423 return Status;
424}
425
54cf8780 426/**
427 Convert binary representation Config string (e.g. "0041004200430044") to the
428 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
429 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
430
431 @param UnicodeString Original Unicode string.
432 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
433 Includes tailing '\0' character.
434 On output:
435 If return EFI_SUCCESS, containing length of Unicode string buffer.
436 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
437 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
438
f4e8509b 439 @retval EFI_SUCCESS Operation completes successfully.
54cf8780 440 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
441
442**/
443EFI_STATUS
1db1f6ad 444EFIAPI
54cf8780 445ConfigStringToUnicode (
446 IN OUT CHAR16 *UnicodeString,
447 IN OUT UINTN *StrBufferLen,
448 IN CHAR16 *ConfigString
449 )
450{
451 UINTN Index;
452 UINTN Len;
453 UINTN BufferSize;
454 CHAR16 BackupChar;
455
456 Len = StrLen (ConfigString) / 4;
457 BufferSize = (Len + 1) * sizeof (CHAR16);
458
459 if (*StrBufferLen < BufferSize) {
460 *StrBufferLen = BufferSize;
461 return EFI_BUFFER_TOO_SMALL;
462 }
463
464 *StrBufferLen = BufferSize;
465
466 for (Index = 0; Index < Len; Index++) {
467 BackupChar = ConfigString[4];
468 ConfigString[4] = L'\0';
469
470 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
471
472 ConfigString[4] = BackupChar;
473
474 ConfigString += 4;
475 UnicodeString += 1;
476 }
477
478 //
479 // Add tailing '\0' character
480 //
481 *UnicodeString = L'\0';
482
483 return EFI_SUCCESS;
484}
485
486/**
487 Convert Unicode string to binary representation Config string, e.g.
488 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
489 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
490
491 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
492 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
493 Includes tailing '\0' character.
494 On output:
495 If return EFI_SUCCESS, containing length of Unicode string buffer.
496 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
497 @param UnicodeString Original Unicode string.
498
f4e8509b 499 @retval EFI_SUCCESS Operation completes successfully.
54cf8780 500 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
501
502**/
503EFI_STATUS
1db1f6ad 504EFIAPI
54cf8780 505UnicodeToConfigString (
506 IN OUT CHAR16 *ConfigString,
507 IN OUT UINTN *StrBufferLen,
508 IN CHAR16 *UnicodeString
509 )
510{
511 UINTN Index;
512 UINTN Len;
513 UINTN BufferSize;
514 CHAR16 *String;
515
516 Len = StrLen (UnicodeString);
517 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
518
519 if (*StrBufferLen < BufferSize) {
520 *StrBufferLen = BufferSize;
521 return EFI_BUFFER_TOO_SMALL;
522 }
523
524 *StrBufferLen = BufferSize;
525 String = ConfigString;
526
527 for (Index = 0; Index < Len; Index++) {
528 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
529
530 ConfigString += 4;
531 UnicodeString += 1;
532 }
533
534 //
535 // Add tailing '\0' character
536 //
537 *ConfigString = L'\0';
538
539 //
540 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
541 //
542 ToLower (String);
543 return EFI_SUCCESS;
544}
e52c5a9f 545
546/**
547 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
548
549 @param ConfigHdr Pointer to the ConfigHdr string.
550 @param StrBufferLen On input: Length in bytes of buffer to hold the
551 ConfigHdr string. Includes tailing '\0' character.
552 On output: If return EFI_SUCCESS, containing
553 length of ConfigHdr string buffer. If return
554 EFI_BUFFER_TOO_SMALL, containg length of string
555 buffer desired.
556 @param Guid Routing information: GUID.
557 @param Name Routing information: NAME.
558 @param DriverHandle Driver handle which contains the routing
559 information: PATH.
560
f4e8509b 561 @retval EFI_SUCCESS Operation completes successfully.
e52c5a9f 562 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
563
564**/
565EFI_STATUS
566EFIAPI
567ConstructConfigHdr (
568 IN OUT CHAR16 *ConfigHdr,
569 IN OUT UINTN *StrBufferLen,
55f298c3 570 IN CONST EFI_GUID *Guid,
e52c5a9f 571 IN CHAR16 *Name, OPTIONAL
572 IN EFI_HANDLE *DriverHandle
573 )
574{
575 EFI_STATUS Status;
576 UINTN NameStrLen;
577 UINTN DevicePathSize;
578 UINTN BufferSize;
579 CHAR16 *StrPtr;
580 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
581
582 if (Name == NULL) {
583 //
584 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
585 //
586 NameStrLen = 0;
587 } else {
588 //
589 // For buffer storage
590 //
591 NameStrLen = StrLen (Name);
592 }
593
594 //
595 // Retrieve DevicePath Protocol associated with this HiiPackageList
596 //
597 Status = gBS->HandleProtocol (
598 DriverHandle,
599 &gEfiDevicePathProtocolGuid,
600 (VOID **) &DevicePath
601 );
602 if (EFI_ERROR (Status)) {
603 return Status;
604 }
605
606 DevicePathSize = GetDevicePathSize (DevicePath);
607
608 //
54cf8780 609 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
610 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
e52c5a9f 611 //
54cf8780 612 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
e52c5a9f 613 if (*StrBufferLen < BufferSize) {
614 *StrBufferLen = BufferSize;
615 return EFI_BUFFER_TOO_SMALL;
616 }
617
618 *StrBufferLen = BufferSize;
619
620 StrPtr = ConfigHdr;
621
622 StrCpy (StrPtr, L"GUID=");
623 StrPtr += 5;
f4e8509b 624 BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
e52c5a9f 625 StrPtr += 32;
626
54cf8780 627 //
628 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
629 //
e52c5a9f 630 StrCpy (StrPtr, L"&NAME=");
631 StrPtr += 6;
632 if (Name != NULL) {
54cf8780 633 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
634 UnicodeToConfigString (StrPtr, &BufferSize, Name);
635 StrPtr += (NameStrLen * 4);
e52c5a9f 636 }
637
638 StrCpy (StrPtr, L"&PATH=");
639 StrPtr += 6;
f4e8509b 640 BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
e52c5a9f 641
642 return EFI_SUCCESS;
643}
644
645
646/**
647 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
648
649 @param String The string to be searched in.
650 @param Offset Offset in BlockName.
651 @param Width Width in BlockName.
652
653 @retval TRUE Block name found.
654 @retval FALSE Block name not found.
655
656**/
657BOOLEAN
1db1f6ad 658EFIAPI
e52c5a9f 659FindBlockName (
660 IN OUT CHAR16 *String,
55f298c3 661 IN UINTN Offset,
662 IN UINTN Width
e52c5a9f 663 )
664{
665 EFI_STATUS Status;
666 UINTN Data;
667 UINTN BufferSize;
668 UINTN ConvertedStrLen;
669
670 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
671 //
672 // Skip '&OFFSET='
673 //
674 String = String + 8;
675
676 Data = 0;
677 BufferSize = sizeof (UINTN);
d9e5c1ff 678 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
e52c5a9f 679 if (EFI_ERROR (Status)) {
680 return FALSE;
681 }
682 String = String + ConvertedStrLen;
683
684 if (Data != Offset) {
685 continue;
686 }
687
688 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
689 return FALSE;
690 }
691 String = String + 7;
692
693 Data = 0;
694 BufferSize = sizeof (UINTN);
d9e5c1ff 695 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
e52c5a9f 696 if (EFI_ERROR (Status)) {
697 return FALSE;
698 }
699 if (Data == Width) {
700 return TRUE;
701 }
702
703 String = String + ConvertedStrLen;
704 }
705
706 return FALSE;
707}
708
709
710/**
711 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
712
713 @param VariableGuid An optional field to indicate the target variable
714 GUID name to use.
715 @param VariableName An optional field to indicate the target
716 human-readable variable name.
717 @param BufferSize On input: Length in bytes of buffer to hold
718 retrived data. On output: If return
719 EFI_BUFFER_TOO_SMALL, containg length of buffer
720 desired.
721 @param Buffer Buffer to hold retrived data.
722
f4e8509b 723 @retval EFI_SUCCESS Operation completes successfully.
e52c5a9f 724 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
b911d09f 725 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
e52c5a9f 726
727**/
728EFI_STATUS
729EFIAPI
730GetBrowserData (
55f298c3 731 IN CONST EFI_GUID *VariableGuid, OPTIONAL
732 IN CONST CHAR16 *VariableName, OPTIONAL
733 IN OUT UINTN *BufferSize,
734 IN OUT UINT8 *Buffer
e52c5a9f 735 )
736{
737 EFI_STATUS Status;
1db1f6ad 738 CONST CHAR16 *ConfigHdr;
e52c5a9f 739 CHAR16 *ConfigResp;
740 CHAR16 *StringPtr;
741 UINTN HeaderLen;
742 UINTN BufferLen;
743 CHAR16 *Progress;
e52c5a9f 744
745 //
746 // Locate protocols for use
747 //
b911d09f 748 Status = LocateFormBrowser2Protocols ();
e52c5a9f 749 if (EFI_ERROR (Status)) {
750 return Status;
751 }
752
753 //
754 // Retrive formset storage data from Form Browser
755 //
756 ConfigHdr = mFakeConfigHdr;
757 HeaderLen = StrLen (ConfigHdr);
b911d09f
LG
758
759 //
760 // First try allocate 0x4000 buffer for the formet storage data.
761 //
e52c5a9f 762 BufferLen = 0x4000;
763 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
b911d09f
LG
764 if (ConfigResp == NULL) {
765 BufferLen = 0;
766 }
e52c5a9f 767
768 StringPtr = ConfigResp + HeaderLen;
769 *StringPtr = L'&';
770 StringPtr++;
771
b911d09f
LG
772 Status = mFormBrowser2->BrowserCallback (
773 mFormBrowser2,
e52c5a9f 774 &BufferLen,
775 StringPtr,
776 TRUE,
777 VariableGuid,
778 VariableName
779 );
780 if (Status == EFI_BUFFER_TOO_SMALL) {
b911d09f
LG
781 if (ConfigResp != NULL) {
782 FreePool (ConfigResp);
783 }
784
e52c5a9f 785 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
b911d09f
LG
786 if (ConfigResp == NULL) {
787 return EFI_OUT_OF_RESOURCES;
788 }
e52c5a9f 789
790 StringPtr = ConfigResp + HeaderLen;
791 *StringPtr = L'&';
792 StringPtr++;
793
b911d09f
LG
794 Status = mFormBrowser2->BrowserCallback (
795 mFormBrowser2,
e52c5a9f 796 &BufferLen,
797 StringPtr,
798 TRUE,
799 VariableGuid,
800 VariableName
801 );
802 }
803 if (EFI_ERROR (Status)) {
1db1f6ad 804 FreePool (ConfigResp);
e52c5a9f 805 return Status;
806 }
807 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
808
809 //
810 // Convert <ConfigResp> to buffer data
811 //
b911d09f
LG
812 Status = mHiiConfigRouting->ConfigToBlock (
813 mHiiConfigRouting,
e52c5a9f 814 ConfigResp,
815 Buffer,
816 BufferSize,
817 &Progress
818 );
1db1f6ad 819 FreePool (ConfigResp);
e52c5a9f 820
821 return Status;
822}
823
824
825/**
826 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
827
828 @param VariableGuid An optional field to indicate the target variable
829 GUID name to use.
830 @param VariableName An optional field to indicate the target
831 human-readable variable name.
832 @param BufferSize Length in bytes of buffer to hold retrived data.
833 @param Buffer Buffer to hold retrived data.
834 @param RequestElement An optional field to specify which part of the
835 buffer data will be send back to Browser. If NULL,
836 the whole buffer of data will be committed to
837 Browser. <RequestElement> ::=
838 &OFFSET=<Number>&WIDTH=<Number>*
839
f4e8509b 840 @retval EFI_SUCCESS Operation completes successfully.
b911d09f 841 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
e52c5a9f 842 @retval Other Updating Browser uncommitted data failed.
843
844**/
845EFI_STATUS
846EFIAPI
847SetBrowserData (
55f298c3 848 IN CONST EFI_GUID *VariableGuid, OPTIONAL
849 IN CONST CHAR16 *VariableName, OPTIONAL
850 IN UINTN BufferSize,
851 IN CONST UINT8 *Buffer,
852 IN CONST CHAR16 *RequestElement OPTIONAL
e52c5a9f 853 )
854{
855 EFI_STATUS Status;
1db1f6ad 856 CONST CHAR16 *ConfigHdr;
e52c5a9f 857 CHAR16 *ConfigResp;
858 CHAR16 *StringPtr;
859 UINTN HeaderLen;
860 UINTN BufferLen;
861 CHAR16 *Progress;
e52c5a9f 862 CHAR16 BlockName[33];
863 CHAR16 *ConfigRequest;
55f298c3 864 CONST CHAR16 *Request;
e52c5a9f 865
866 //
867 // Locate protocols for use
868 //
b911d09f 869 Status = LocateFormBrowser2Protocols ();
e52c5a9f 870 if (EFI_ERROR (Status)) {
871 return Status;
872 }
873
874 //
875 // Prepare <ConfigRequest>
876 //
877 ConfigHdr = mFakeConfigHdr;
878 HeaderLen = StrLen (ConfigHdr);
879
880 if (RequestElement == NULL) {
881 //
882 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
883 //
884 BlockName[0] = L'\0';
885 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
886
887 //
888 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
889 //
890 StringPtr = BlockName + 16;
891 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
d9e5c1ff 892 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
e52c5a9f 893
894 Request = BlockName;
895 } else {
896 Request = RequestElement;
897 }
898
899 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
900 ConfigRequest = AllocateZeroPool (BufferLen);
b911d09f
LG
901 if (ConfigRequest == NULL) {
902 return EFI_OUT_OF_RESOURCES;
903 }
e52c5a9f 904
905 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
906 StringPtr = ConfigRequest + HeaderLen;
907 StrCpy (StringPtr, Request);
908
909 //
910 // Convert buffer to <ConfigResp>
911 //
b911d09f
LG
912 Status = mHiiConfigRouting->BlockToConfig (
913 mHiiConfigRouting,
e52c5a9f 914 ConfigRequest,
915 Buffer,
916 BufferSize,
917 &ConfigResp,
918 &Progress
919 );
920 if (EFI_ERROR (Status)) {
b911d09f 921 FreePool (ConfigRequest);
e52c5a9f 922 return Status;
923 }
924
925 //
926 // Skip <ConfigHdr> and '&'
927 //
928 StringPtr = ConfigResp + HeaderLen + 1;
929
930 //
931 // Change uncommitted data in Browser
932 //
b911d09f
LG
933 Status = mFormBrowser2->BrowserCallback (
934 mFormBrowser2,
e52c5a9f 935 &BufferSize,
936 StringPtr,
937 FALSE,
938 NULL,
939 NULL
940 );
b911d09f 941 FreePool (ConfigRequest);
e52c5a9f 942 return Status;
943}