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