]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/IfrSupportLib/UefiIfrForm.c
Add IfrLibCreatePopUp2 and HiiLibExportPackageLists.
[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
18//
19// Fake <ConfigHdr>
20//
1db1f6ad 21GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
e52c5a9f 22
e52c5a9f 23/**
24 Draw a dialog and return the selected key.
25
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
1db1f6ad 29 @param ... A series of (quantity == NumberOfLines - 1) text
e52c5a9f 30 strings which will be used to construct the dialog
31 box
32
33 @retval EFI_SUCCESS Displayed dialog and received user interaction
34 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
35
36**/
37EFI_STATUS
38EFIAPI
55a9663b 39IfrLibCreatePopUp2 (
e52c5a9f 40 IN UINTN NumberOfLines,
41 OUT EFI_INPUT_KEY *KeyValue,
55a9663b 42 IN VA_LIST Marker
e52c5a9f 43 )
44{
45 UINTN Index;
46 UINTN Count;
47 UINTN Start;
48 UINTN Top;
49 CHAR16 *StringPtr;
50 UINTN LeftColumn;
51 UINTN RightColumn;
52 UINTN TopRow;
53 UINTN BottomRow;
54 UINTN DimensionsWidth;
55 UINTN DimensionsHeight;
e52c5a9f 56 EFI_INPUT_KEY Key;
57 UINTN LargestString;
58 CHAR16 *StackString;
59 EFI_STATUS Status;
60 UINTN StringLen;
61 CHAR16 *LineBuffer;
62 CHAR16 **StringArray;
63 EFI_EVENT TimerEvent;
64 EFI_EVENT WaitList[2];
65 UINTN CurrentAttribute;
66 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
55a9663b 67 CHAR16 *String;
e52c5a9f 68
55a9663b 69 String = VA_ARG (Marker, CHAR16 *);
70
e52c5a9f 71 if ((KeyValue == NULL) || (String == NULL)) {
72 return EFI_INVALID_PARAMETER;
73 }
74
75 TopRow = 0;
76 BottomRow = 0;
77 LeftColumn = 0;
78 RightColumn = 0;
79
80 ConOut = gST->ConOut;
81 ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
82
83 DimensionsWidth = RightColumn - LeftColumn;
84 DimensionsHeight = BottomRow - TopRow;
85
86 CurrentAttribute = ConOut->Mode->Attribute;
87
88 LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
89 ASSERT (LineBuffer != NULL);
90
91 //
92 // Determine the largest string in the dialog box
93 // Notice we are starting with 1 since String is the first string
94 //
95 StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
96 LargestString = StrLen (String);
97 StringArray[0] = String;
98
e52c5a9f 99 for (Index = 1; Index < NumberOfLines; Index++) {
100 StackString = VA_ARG (Marker, CHAR16 *);
101
102 if (StackString == NULL) {
103 return EFI_INVALID_PARAMETER;
104 }
105
106 StringArray[Index] = StackString;
107 StringLen = StrLen (StackString);
108 if (StringLen > LargestString) {
109 LargestString = StringLen;
110 }
111 }
112
113 if ((LargestString + 2) > DimensionsWidth) {
114 LargestString = DimensionsWidth - 2;
115 }
116
117 //
118 // Subtract the PopUp width from total Columns, allow for one space extra on
119 // each end plus a border.
120 //
121 Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
122
123 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
124
125 //
126 // Disable cursor
127 //
128 ConOut->EnableCursor (ConOut, FALSE);
129 ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
130
131 StringPtr = &LineBuffer[0];
132 *StringPtr++ = BOXDRAW_DOWN_RIGHT;
133 for (Index = 0; Index < LargestString; Index++) {
134 *StringPtr++ = BOXDRAW_HORIZONTAL;
135 }
136 *StringPtr++ = BOXDRAW_DOWN_LEFT;
137 *StringPtr = L'\0';
138
139 ConOut->SetCursorPosition (ConOut, Start, Top);
140 ConOut->OutputString (ConOut, LineBuffer);
141
142 for (Index = 0; Index < NumberOfLines; Index++) {
143 StringPtr = &LineBuffer[0];
144 *StringPtr++ = BOXDRAW_VERTICAL;
145
146 for (Count = 0; Count < LargestString; Count++) {
147 StringPtr[Count] = L' ';
148 }
149
150 StringLen = StrLen (StringArray[Index]);
151 if (StringLen > LargestString) {
152 StringLen = LargestString;
153 }
154 CopyMem (
155 StringPtr + ((LargestString - StringLen) / 2),
156 StringArray[Index],
157 StringLen * sizeof (CHAR16)
158 );
159 StringPtr += LargestString;
160
161 *StringPtr++ = BOXDRAW_VERTICAL;
162 *StringPtr = L'\0';
163
164 ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
165 ConOut->OutputString (ConOut, LineBuffer);
166 }
167
168 StringPtr = &LineBuffer[0];
169 *StringPtr++ = BOXDRAW_UP_RIGHT;
170 for (Index = 0; Index < LargestString; Index++) {
171 *StringPtr++ = BOXDRAW_HORIZONTAL;
172 }
173 *StringPtr++ = BOXDRAW_UP_LEFT;
174 *StringPtr = L'\0';
175
176 ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
177 ConOut->OutputString (ConOut, LineBuffer);
178
179 do {
180 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
181
182 //
183 // Set a timer event of 1 second expiration
184 //
185 gBS->SetTimer (
186 TimerEvent,
187 TimerRelative,
188 10000000
189 );
190
191 //
192 // Wait for the keystroke event or the timer
193 //
194 WaitList[0] = gST->ConIn->WaitForKey;
195 WaitList[1] = TimerEvent;
196 Status = gBS->WaitForEvent (2, WaitList, &Index);
197
198 //
199 // Check for the timer expiration
200 //
201 if (!EFI_ERROR (Status) && Index == 1) {
202 Status = EFI_TIMEOUT;
203 }
204
205 gBS->CloseEvent (TimerEvent);
206 } while (Status == EFI_TIMEOUT);
207
208 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
209 CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
210
211 ConOut->SetAttribute (ConOut, CurrentAttribute);
212 ConOut->EnableCursor (ConOut, TRUE);
213
55a9663b 214 return Status;}
215
216
217/**
218 Draw a dialog and return the selected key.
219
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
225 box
226
227 @retval EFI_SUCCESS Displayed dialog and received user interaction
228 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
229
230**/
231EFI_STATUS
232EFIAPI
233IfrLibCreatePopUp (
234 IN UINTN NumberOfLines,
235 OUT EFI_INPUT_KEY *KeyValue,
236 IN CHAR16 *String,
237 ...
238 )
239{
240 EFI_STATUS Status;
241 VA_LIST Marker;
242
243 VA_START (Marker, KeyValue);
244
245 Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, Marker);
246
247 VA_END (Marker);
248
e52c5a9f 249 return Status;
250}
251
e52c5a9f 252/**
ad1b3619 253 Swap bytes in the buffer. This is a internal function.
e52c5a9f 254
255 @param Buffer Binary buffer.
256 @param BufferSize Size of the buffer in bytes.
257
258 @return None.
259
260**/
e52c5a9f 261VOID
262SwapBuffer (
263 IN OUT UINT8 *Buffer,
264 IN UINTN BufferSize
265 )
266{
267 UINTN Index;
268 UINT8 Temp;
269 UINTN SwapCount;
270
54cf8780 271 SwapCount = BufferSize / 2;
e52c5a9f 272 for (Index = 0; Index < SwapCount; Index++) {
273 Temp = Buffer[Index];
274 Buffer[Index] = Buffer[BufferSize - 1 - Index];
275 Buffer[BufferSize - 1 - Index] = Temp;
276 }
277}
278
54cf8780 279/**
280 Converts the unicode character of the string from uppercase to lowercase.
ad1b3619 281 This is a internal function.
54cf8780 282
283 @param Str String to be converted
284
54cf8780 285**/
286VOID
1db1f6ad 287EFIAPI
54cf8780 288ToLower (
289 IN OUT CHAR16 *Str
290 )
291{
292 CHAR16 *Ptr;
293
294 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
295 if (*Ptr >= L'A' && *Ptr <= L'Z') {
296 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
297 }
298 }
299}
300
e52c5a9f 301
302/**
d9e5c1ff 303 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
e52c5a9f 304
305 @param Str String for output
306 @param Buffer Binary buffer.
307 @param BufferSize Size of the buffer in bytes.
308
309 @retval EFI_SUCCESS The function completed successfully.
310
311**/
312EFI_STATUS
313EFIAPI
314BufferToHexString (
315 IN OUT CHAR16 *Str,
316 IN UINT8 *Buffer,
317 IN UINTN BufferSize
318 )
319{
320 EFI_STATUS Status;
321 UINT8 *NewBuffer;
322 UINTN StrBufferLen;
323
324 NewBuffer = AllocateCopyPool (BufferSize, Buffer);
325 SwapBuffer (NewBuffer, BufferSize);
326
54cf8780 327 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
d9e5c1ff 328 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
e52c5a9f 329
1db1f6ad 330 FreePool (NewBuffer);
54cf8780 331 //
332 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
333 //
334 ToLower (Str);
e52c5a9f 335
336 return Status;
337}
338
339
340/**
d9e5c1ff 341 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
e52c5a9f 342
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
348 of buffer desired.
349 @param Str String to be converted from.
350
351 @retval EFI_SUCCESS The function completed successfully.
352
353**/
354EFI_STATUS
355EFIAPI
356HexStringToBuffer (
357 IN OUT UINT8 *Buffer,
358 IN OUT UINTN *BufferSize,
359 IN CHAR16 *Str
360 )
361{
362 EFI_STATUS Status;
363 UINTN ConvertedStrLen;
364
365 ConvertedStrLen = 0;
d9e5c1ff 366 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
e52c5a9f 367 if (!EFI_ERROR (Status)) {
368 SwapBuffer (Buffer, ConvertedStrLen);
369 }
370
371 return Status;
372}
373
54cf8780 374/**
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>").
378
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.
382 On output:
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)+
386
387 @retval EFI_SUCCESS Routine success.
388 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
389
390**/
391EFI_STATUS
1db1f6ad 392EFIAPI
54cf8780 393ConfigStringToUnicode (
394 IN OUT CHAR16 *UnicodeString,
395 IN OUT UINTN *StrBufferLen,
396 IN CHAR16 *ConfigString
397 )
398{
399 UINTN Index;
400 UINTN Len;
401 UINTN BufferSize;
402 CHAR16 BackupChar;
403
404 Len = StrLen (ConfigString) / 4;
405 BufferSize = (Len + 1) * sizeof (CHAR16);
406
407 if (*StrBufferLen < BufferSize) {
408 *StrBufferLen = BufferSize;
409 return EFI_BUFFER_TOO_SMALL;
410 }
411
412 *StrBufferLen = BufferSize;
413
414 for (Index = 0; Index < Len; Index++) {
415 BackupChar = ConfigString[4];
416 ConfigString[4] = L'\0';
417
418 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
419
420 ConfigString[4] = BackupChar;
421
422 ConfigString += 4;
423 UnicodeString += 1;
424 }
425
426 //
427 // Add tailing '\0' character
428 //
429 *UnicodeString = L'\0';
430
431 return EFI_SUCCESS;
432}
433
434/**
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>").
438
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.
442 On output:
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.
446
447 @retval EFI_SUCCESS Routine success.
448 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
449
450**/
451EFI_STATUS
1db1f6ad 452EFIAPI
54cf8780 453UnicodeToConfigString (
454 IN OUT CHAR16 *ConfigString,
455 IN OUT UINTN *StrBufferLen,
456 IN CHAR16 *UnicodeString
457 )
458{
459 UINTN Index;
460 UINTN Len;
461 UINTN BufferSize;
462 CHAR16 *String;
463
464 Len = StrLen (UnicodeString);
465 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
466
467 if (*StrBufferLen < BufferSize) {
468 *StrBufferLen = BufferSize;
469 return EFI_BUFFER_TOO_SMALL;
470 }
471
472 *StrBufferLen = BufferSize;
473 String = ConfigString;
474
475 for (Index = 0; Index < Len; Index++) {
476 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
477
478 ConfigString += 4;
479 UnicodeString += 1;
480 }
481
482 //
483 // Add tailing '\0' character
484 //
485 *ConfigString = L'\0';
486
487 //
488 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
489 //
490 ToLower (String);
491 return EFI_SUCCESS;
492}
e52c5a9f 493
494/**
495 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
496
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
503 buffer desired.
504 @param Guid Routing information: GUID.
505 @param Name Routing information: NAME.
506 @param DriverHandle Driver handle which contains the routing
507 information: PATH.
508
509 @retval EFI_SUCCESS Routine success.
510 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
511
512**/
513EFI_STATUS
514EFIAPI
515ConstructConfigHdr (
516 IN OUT CHAR16 *ConfigHdr,
517 IN OUT UINTN *StrBufferLen,
518 IN EFI_GUID *Guid,
519 IN CHAR16 *Name, OPTIONAL
520 IN EFI_HANDLE *DriverHandle
521 )
522{
523 EFI_STATUS Status;
524 UINTN NameStrLen;
525 UINTN DevicePathSize;
526 UINTN BufferSize;
527 CHAR16 *StrPtr;
528 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
529
530 if (Name == NULL) {
531 //
532 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
533 //
534 NameStrLen = 0;
535 } else {
536 //
537 // For buffer storage
538 //
539 NameStrLen = StrLen (Name);
540 }
541
542 //
543 // Retrieve DevicePath Protocol associated with this HiiPackageList
544 //
545 Status = gBS->HandleProtocol (
546 DriverHandle,
547 &gEfiDevicePathProtocolGuid,
548 (VOID **) &DevicePath
549 );
550 if (EFI_ERROR (Status)) {
551 return Status;
552 }
553
554 DevicePathSize = GetDevicePathSize (DevicePath);
555
556 //
54cf8780 557 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
558 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
e52c5a9f 559 //
54cf8780 560 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
e52c5a9f 561 if (*StrBufferLen < BufferSize) {
562 *StrBufferLen = BufferSize;
563 return EFI_BUFFER_TOO_SMALL;
564 }
565
566 *StrBufferLen = BufferSize;
567
568 StrPtr = ConfigHdr;
569
570 StrCpy (StrPtr, L"GUID=");
571 StrPtr += 5;
572 BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
573 StrPtr += 32;
574
54cf8780 575 //
576 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
577 //
e52c5a9f 578 StrCpy (StrPtr, L"&NAME=");
579 StrPtr += 6;
580 if (Name != NULL) {
54cf8780 581 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
582 UnicodeToConfigString (StrPtr, &BufferSize, Name);
583 StrPtr += (NameStrLen * 4);
e52c5a9f 584 }
585
586 StrCpy (StrPtr, L"&PATH=");
587 StrPtr += 6;
588 BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
589
590 return EFI_SUCCESS;
591}
592
593
594/**
595 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
596
597 @param String The string to be searched in.
598 @param Offset Offset in BlockName.
599 @param Width Width in BlockName.
600
601 @retval TRUE Block name found.
602 @retval FALSE Block name not found.
603
604**/
605BOOLEAN
1db1f6ad 606EFIAPI
e52c5a9f 607FindBlockName (
608 IN OUT CHAR16 *String,
609 UINTN Offset,
610 UINTN Width
611 )
612{
613 EFI_STATUS Status;
614 UINTN Data;
615 UINTN BufferSize;
616 UINTN ConvertedStrLen;
617
618 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
619 //
620 // Skip '&OFFSET='
621 //
622 String = String + 8;
623
624 Data = 0;
625 BufferSize = sizeof (UINTN);
d9e5c1ff 626 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
e52c5a9f 627 if (EFI_ERROR (Status)) {
628 return FALSE;
629 }
630 String = String + ConvertedStrLen;
631
632 if (Data != Offset) {
633 continue;
634 }
635
636 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
637 return FALSE;
638 }
639 String = String + 7;
640
641 Data = 0;
642 BufferSize = sizeof (UINTN);
d9e5c1ff 643 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
e52c5a9f 644 if (EFI_ERROR (Status)) {
645 return FALSE;
646 }
647 if (Data == Width) {
648 return TRUE;
649 }
650
651 String = String + ConvertedStrLen;
652 }
653
654 return FALSE;
655}
656
657
658/**
659 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
660
661 @param VariableGuid An optional field to indicate the target variable
662 GUID name to use.
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
668 desired.
669 @param Buffer Buffer to hold retrived data.
670
671 @retval EFI_SUCCESS Routine success.
672 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
673
674**/
675EFI_STATUS
676EFIAPI
677GetBrowserData (
678 EFI_GUID *VariableGuid, OPTIONAL
679 CHAR16 *VariableName, OPTIONAL
680 UINTN *BufferSize,
681 UINT8 *Buffer
682 )
683{
684 EFI_STATUS Status;
1db1f6ad 685 CONST CHAR16 *ConfigHdr;
e52c5a9f 686 CHAR16 *ConfigResp;
687 CHAR16 *StringPtr;
688 UINTN HeaderLen;
689 UINTN BufferLen;
690 CHAR16 *Progress;
691 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
692 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
693
694 //
695 // Locate protocols for use
696 //
697 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
698 if (EFI_ERROR (Status)) {
699 return Status;
700 }
701
702 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
703 if (EFI_ERROR (Status)) {
704 return Status;
705 }
706
707 //
708 // Retrive formset storage data from Form Browser
709 //
710 ConfigHdr = mFakeConfigHdr;
711 HeaderLen = StrLen (ConfigHdr);
712
713 BufferLen = 0x4000;
714 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
715
716 StringPtr = ConfigResp + HeaderLen;
717 *StringPtr = L'&';
718 StringPtr++;
719
720 Status = FormBrowser2->BrowserCallback (
721 FormBrowser2,
722 &BufferLen,
723 StringPtr,
724 TRUE,
725 VariableGuid,
726 VariableName
727 );
728 if (Status == EFI_BUFFER_TOO_SMALL) {
1db1f6ad 729 FreePool (ConfigResp);
e52c5a9f 730 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
731
732 StringPtr = ConfigResp + HeaderLen;
733 *StringPtr = L'&';
734 StringPtr++;
735
736 Status = FormBrowser2->BrowserCallback (
737 FormBrowser2,
738 &BufferLen,
739 StringPtr,
740 TRUE,
741 VariableGuid,
742 VariableName
743 );
744 }
745 if (EFI_ERROR (Status)) {
1db1f6ad 746 FreePool (ConfigResp);
e52c5a9f 747 return Status;
748 }
749 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
750
751 //
752 // Convert <ConfigResp> to buffer data
753 //
754 Status = HiiConfigRouting->ConfigToBlock (
755 HiiConfigRouting,
756 ConfigResp,
757 Buffer,
758 BufferSize,
759 &Progress
760 );
1db1f6ad 761 FreePool (ConfigResp);
e52c5a9f 762
763 return Status;
764}
765
766
767/**
768 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
769
770 @param VariableGuid An optional field to indicate the target variable
771 GUID name to use.
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>*
781
782 @retval EFI_SUCCESS Routine success.
783 @retval Other Updating Browser uncommitted data failed.
784
785**/
786EFI_STATUS
787EFIAPI
788SetBrowserData (
789 EFI_GUID *VariableGuid, OPTIONAL
790 CHAR16 *VariableName, OPTIONAL
791 UINTN BufferSize,
792 UINT8 *Buffer,
793 CHAR16 *RequestElement OPTIONAL
794 )
795{
796 EFI_STATUS Status;
1db1f6ad 797 CONST CHAR16 *ConfigHdr;
e52c5a9f 798 CHAR16 *ConfigResp;
799 CHAR16 *StringPtr;
800 UINTN HeaderLen;
801 UINTN BufferLen;
802 CHAR16 *Progress;
803 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
804 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
805 CHAR16 BlockName[33];
806 CHAR16 *ConfigRequest;
807 CHAR16 *Request;
808
809 //
810 // Locate protocols for use
811 //
812 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
813 if (EFI_ERROR (Status)) {
814 return Status;
815 }
816
817 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
818 if (EFI_ERROR (Status)) {
819 return Status;
820 }
821
822 //
823 // Prepare <ConfigRequest>
824 //
825 ConfigHdr = mFakeConfigHdr;
826 HeaderLen = StrLen (ConfigHdr);
827
828 if (RequestElement == NULL) {
829 //
830 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
831 //
832 BlockName[0] = L'\0';
833 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
834
835 //
836 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
837 //
838 StringPtr = BlockName + 16;
839 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
d9e5c1ff 840 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
e52c5a9f 841
842 Request = BlockName;
843 } else {
844 Request = RequestElement;
845 }
846
847 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
848 ConfigRequest = AllocateZeroPool (BufferLen);
849
850 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
851 StringPtr = ConfigRequest + HeaderLen;
852 StrCpy (StringPtr, Request);
853
854 //
855 // Convert buffer to <ConfigResp>
856 //
857 Status = HiiConfigRouting->BlockToConfig (
858 HiiConfigRouting,
859 ConfigRequest,
860 Buffer,
861 BufferSize,
862 &ConfigResp,
863 &Progress
864 );
865 if (EFI_ERROR (Status)) {
1db1f6ad 866 FreePool (ConfigResp);
e52c5a9f 867 return Status;
868 }
869
870 //
871 // Skip <ConfigHdr> and '&'
872 //
873 StringPtr = ConfigResp + HeaderLen + 1;
874
875 //
876 // Change uncommitted data in Browser
877 //
878 Status = FormBrowser2->BrowserCallback (
879 FormBrowser2,
880 &BufferSize,
881 StringPtr,
882 FALSE,
883 NULL,
884 NULL
885 );
1db1f6ad 886 FreePool (ConfigResp);
e52c5a9f 887 return Status;
888}