]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/IfrSupportLib/UefiIfrForm.c
d0da744240bdd493c39b1974194cd129d96d0094
[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 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) 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
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
214 return Status;
215 }
216
217
218 /**
219 Swap bytes in the buffer. This is a internal function.
220
221 @param Buffer Binary buffer.
222 @param BufferSize Size of the buffer in bytes.
223
224 @return None.
225
226 **/
227 VOID
228 SwapBuffer (
229 IN OUT UINT8 *Buffer,
230 IN UINTN BufferSize
231 )
232 {
233 UINTN Index;
234 UINT8 Temp;
235 UINTN SwapCount;
236
237 SwapCount = BufferSize / 2;
238 for (Index = 0; Index < SwapCount; Index++) {
239 Temp = Buffer[Index];
240 Buffer[Index] = Buffer[BufferSize - 1 - Index];
241 Buffer[BufferSize - 1 - Index] = Temp;
242 }
243 }
244
245 /**
246 Converts the unicode character of the string from uppercase to lowercase.
247 This is a internal function.
248
249 @param Str String to be converted
250
251 **/
252 VOID
253 ToLower (
254 IN OUT CHAR16 *Str
255 )
256 {
257 CHAR16 *Ptr;
258
259 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
260 if (*Ptr >= L'A' && *Ptr <= L'Z') {
261 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
262 }
263 }
264 }
265
266
267 /**
268 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
269
270 @param Str String for output
271 @param Buffer Binary buffer.
272 @param BufferSize Size of the buffer in bytes.
273
274 @retval EFI_SUCCESS The function completed successfully.
275
276 **/
277 EFI_STATUS
278 EFIAPI
279 BufferToHexString (
280 IN OUT CHAR16 *Str,
281 IN UINT8 *Buffer,
282 IN UINTN BufferSize
283 )
284 {
285 EFI_STATUS Status;
286 UINT8 *NewBuffer;
287 UINTN StrBufferLen;
288
289 NewBuffer = AllocateCopyPool (BufferSize, Buffer);
290 SwapBuffer (NewBuffer, BufferSize);
291
292 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
293 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
294
295 gBS->FreePool (NewBuffer);
296 //
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
298 //
299 ToLower (Str);
300
301 return Status;
302 }
303
304
305 /**
306 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
307
308 @param Buffer Pointer to buffer that receives the data.
309 @param BufferSize Length in bytes of the buffer to hold converted
310 data. If routine return with EFI_SUCCESS,
311 containing length of converted data. If routine
312 return with EFI_BUFFER_TOO_SMALL, containg length
313 of buffer desired.
314 @param Str String to be converted from.
315
316 @retval EFI_SUCCESS The function completed successfully.
317
318 **/
319 EFI_STATUS
320 EFIAPI
321 HexStringToBuffer (
322 IN OUT UINT8 *Buffer,
323 IN OUT UINTN *BufferSize,
324 IN CHAR16 *Str
325 )
326 {
327 EFI_STATUS Status;
328 UINTN ConvertedStrLen;
329
330 ConvertedStrLen = 0;
331 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
332 if (!EFI_ERROR (Status)) {
333 SwapBuffer (Buffer, ConvertedStrLen);
334 }
335
336 return Status;
337 }
338
339 /**
340 Convert binary representation Config string (e.g. "0041004200430044") to the
341 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
342 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
343
344 @param UnicodeString Original Unicode string.
345 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
346 Includes tailing '\0' character.
347 On output:
348 If return EFI_SUCCESS, containing length of Unicode string buffer.
349 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
350 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
351
352 @retval EFI_SUCCESS Routine success.
353 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
354
355 **/
356 EFI_STATUS
357 ConfigStringToUnicode (
358 IN OUT CHAR16 *UnicodeString,
359 IN OUT UINTN *StrBufferLen,
360 IN CHAR16 *ConfigString
361 )
362 {
363 UINTN Index;
364 UINTN Len;
365 UINTN BufferSize;
366 CHAR16 BackupChar;
367
368 Len = StrLen (ConfigString) / 4;
369 BufferSize = (Len + 1) * sizeof (CHAR16);
370
371 if (*StrBufferLen < BufferSize) {
372 *StrBufferLen = BufferSize;
373 return EFI_BUFFER_TOO_SMALL;
374 }
375
376 *StrBufferLen = BufferSize;
377
378 for (Index = 0; Index < Len; Index++) {
379 BackupChar = ConfigString[4];
380 ConfigString[4] = L'\0';
381
382 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
383
384 ConfigString[4] = BackupChar;
385
386 ConfigString += 4;
387 UnicodeString += 1;
388 }
389
390 //
391 // Add tailing '\0' character
392 //
393 *UnicodeString = L'\0';
394
395 return EFI_SUCCESS;
396 }
397
398 /**
399 Convert Unicode string to binary representation Config string, e.g.
400 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
401 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
402
403 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
404 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
405 Includes tailing '\0' character.
406 On output:
407 If return EFI_SUCCESS, containing length of Unicode string buffer.
408 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
409 @param UnicodeString Original Unicode string.
410
411 @retval EFI_SUCCESS Routine success.
412 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
413
414 **/
415 EFI_STATUS
416 UnicodeToConfigString (
417 IN OUT CHAR16 *ConfigString,
418 IN OUT UINTN *StrBufferLen,
419 IN CHAR16 *UnicodeString
420 )
421 {
422 UINTN Index;
423 UINTN Len;
424 UINTN BufferSize;
425 CHAR16 *String;
426
427 Len = StrLen (UnicodeString);
428 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
429
430 if (*StrBufferLen < BufferSize) {
431 *StrBufferLen = BufferSize;
432 return EFI_BUFFER_TOO_SMALL;
433 }
434
435 *StrBufferLen = BufferSize;
436 String = ConfigString;
437
438 for (Index = 0; Index < Len; Index++) {
439 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
440
441 ConfigString += 4;
442 UnicodeString += 1;
443 }
444
445 //
446 // Add tailing '\0' character
447 //
448 *ConfigString = L'\0';
449
450 //
451 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
452 //
453 ToLower (String);
454 return EFI_SUCCESS;
455 }
456
457 /**
458 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
459
460 @param ConfigHdr Pointer to the ConfigHdr string.
461 @param StrBufferLen On input: Length in bytes of buffer to hold the
462 ConfigHdr string. Includes tailing '\0' character.
463 On output: If return EFI_SUCCESS, containing
464 length of ConfigHdr string buffer. If return
465 EFI_BUFFER_TOO_SMALL, containg length of string
466 buffer desired.
467 @param Guid Routing information: GUID.
468 @param Name Routing information: NAME.
469 @param DriverHandle Driver handle which contains the routing
470 information: PATH.
471
472 @retval EFI_SUCCESS Routine success.
473 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
474
475 **/
476 EFI_STATUS
477 EFIAPI
478 ConstructConfigHdr (
479 IN OUT CHAR16 *ConfigHdr,
480 IN OUT UINTN *StrBufferLen,
481 IN EFI_GUID *Guid,
482 IN CHAR16 *Name, OPTIONAL
483 IN EFI_HANDLE *DriverHandle
484 )
485 {
486 EFI_STATUS Status;
487 UINTN NameStrLen;
488 UINTN DevicePathSize;
489 UINTN BufferSize;
490 CHAR16 *StrPtr;
491 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
492
493 if (Name == NULL) {
494 //
495 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
496 //
497 NameStrLen = 0;
498 } else {
499 //
500 // For buffer storage
501 //
502 NameStrLen = StrLen (Name);
503 }
504
505 //
506 // Retrieve DevicePath Protocol associated with this HiiPackageList
507 //
508 Status = gBS->HandleProtocol (
509 DriverHandle,
510 &gEfiDevicePathProtocolGuid,
511 (VOID **) &DevicePath
512 );
513 if (EFI_ERROR (Status)) {
514 return Status;
515 }
516
517 DevicePathSize = GetDevicePathSize (DevicePath);
518
519 //
520 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
521 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
522 //
523 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
524 if (*StrBufferLen < BufferSize) {
525 *StrBufferLen = BufferSize;
526 return EFI_BUFFER_TOO_SMALL;
527 }
528
529 *StrBufferLen = BufferSize;
530
531 StrPtr = ConfigHdr;
532
533 StrCpy (StrPtr, L"GUID=");
534 StrPtr += 5;
535 BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
536 StrPtr += 32;
537
538 //
539 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
540 //
541 StrCpy (StrPtr, L"&NAME=");
542 StrPtr += 6;
543 if (Name != NULL) {
544 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
545 UnicodeToConfigString (StrPtr, &BufferSize, Name);
546 StrPtr += (NameStrLen * 4);
547 }
548
549 StrCpy (StrPtr, L"&PATH=");
550 StrPtr += 6;
551 BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
552
553 return EFI_SUCCESS;
554 }
555
556
557 /**
558 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
559
560 @param String The string to be searched in.
561 @param Offset Offset in BlockName.
562 @param Width Width in BlockName.
563
564 @retval TRUE Block name found.
565 @retval FALSE Block name not found.
566
567 **/
568 BOOLEAN
569 FindBlockName (
570 IN OUT CHAR16 *String,
571 UINTN Offset,
572 UINTN Width
573 )
574 {
575 EFI_STATUS Status;
576 UINTN Data;
577 UINTN BufferSize;
578 UINTN ConvertedStrLen;
579
580 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
581 //
582 // Skip '&OFFSET='
583 //
584 String = String + 8;
585
586 Data = 0;
587 BufferSize = sizeof (UINTN);
588 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
589 if (EFI_ERROR (Status)) {
590 return FALSE;
591 }
592 String = String + ConvertedStrLen;
593
594 if (Data != Offset) {
595 continue;
596 }
597
598 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
599 return FALSE;
600 }
601 String = String + 7;
602
603 Data = 0;
604 BufferSize = sizeof (UINTN);
605 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
606 if (EFI_ERROR (Status)) {
607 return FALSE;
608 }
609 if (Data == Width) {
610 return TRUE;
611 }
612
613 String = String + ConvertedStrLen;
614 }
615
616 return FALSE;
617 }
618
619
620 /**
621 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
622
623 @param VariableGuid An optional field to indicate the target variable
624 GUID name to use.
625 @param VariableName An optional field to indicate the target
626 human-readable variable name.
627 @param BufferSize On input: Length in bytes of buffer to hold
628 retrived data. On output: If return
629 EFI_BUFFER_TOO_SMALL, containg length of buffer
630 desired.
631 @param Buffer Buffer to hold retrived data.
632
633 @retval EFI_SUCCESS Routine success.
634 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
635
636 **/
637 EFI_STATUS
638 EFIAPI
639 GetBrowserData (
640 EFI_GUID *VariableGuid, OPTIONAL
641 CHAR16 *VariableName, OPTIONAL
642 UINTN *BufferSize,
643 UINT8 *Buffer
644 )
645 {
646 EFI_STATUS Status;
647 CHAR16 *ConfigHdr;
648 CHAR16 *ConfigResp;
649 CHAR16 *StringPtr;
650 UINTN HeaderLen;
651 UINTN BufferLen;
652 CHAR16 *Progress;
653 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
654 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
655
656 //
657 // Locate protocols for use
658 //
659 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
660 if (EFI_ERROR (Status)) {
661 return Status;
662 }
663
664 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
665 if (EFI_ERROR (Status)) {
666 return Status;
667 }
668
669 //
670 // Retrive formset storage data from Form Browser
671 //
672 ConfigHdr = mFakeConfigHdr;
673 HeaderLen = StrLen (ConfigHdr);
674
675 BufferLen = 0x4000;
676 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
677
678 StringPtr = ConfigResp + HeaderLen;
679 *StringPtr = L'&';
680 StringPtr++;
681
682 Status = FormBrowser2->BrowserCallback (
683 FormBrowser2,
684 &BufferLen,
685 StringPtr,
686 TRUE,
687 VariableGuid,
688 VariableName
689 );
690 if (Status == EFI_BUFFER_TOO_SMALL) {
691 gBS->FreePool (ConfigResp);
692 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
693
694 StringPtr = ConfigResp + HeaderLen;
695 *StringPtr = L'&';
696 StringPtr++;
697
698 Status = FormBrowser2->BrowserCallback (
699 FormBrowser2,
700 &BufferLen,
701 StringPtr,
702 TRUE,
703 VariableGuid,
704 VariableName
705 );
706 }
707 if (EFI_ERROR (Status)) {
708 gBS->FreePool (ConfigResp);
709 return Status;
710 }
711 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
712
713 //
714 // Convert <ConfigResp> to buffer data
715 //
716 Status = HiiConfigRouting->ConfigToBlock (
717 HiiConfigRouting,
718 ConfigResp,
719 Buffer,
720 BufferSize,
721 &Progress
722 );
723 gBS->FreePool (ConfigResp);
724
725 return Status;
726 }
727
728
729 /**
730 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
731
732 @param VariableGuid An optional field to indicate the target variable
733 GUID name to use.
734 @param VariableName An optional field to indicate the target
735 human-readable variable name.
736 @param BufferSize Length in bytes of buffer to hold retrived data.
737 @param Buffer Buffer to hold retrived data.
738 @param RequestElement An optional field to specify which part of the
739 buffer data will be send back to Browser. If NULL,
740 the whole buffer of data will be committed to
741 Browser. <RequestElement> ::=
742 &OFFSET=<Number>&WIDTH=<Number>*
743
744 @retval EFI_SUCCESS Routine success.
745 @retval Other Updating Browser uncommitted data failed.
746
747 **/
748 EFI_STATUS
749 EFIAPI
750 SetBrowserData (
751 EFI_GUID *VariableGuid, OPTIONAL
752 CHAR16 *VariableName, OPTIONAL
753 UINTN BufferSize,
754 UINT8 *Buffer,
755 CHAR16 *RequestElement OPTIONAL
756 )
757 {
758 EFI_STATUS Status;
759 CHAR16 *ConfigHdr;
760 CHAR16 *ConfigResp;
761 CHAR16 *StringPtr;
762 UINTN HeaderLen;
763 UINTN BufferLen;
764 CHAR16 *Progress;
765 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
766 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
767 CHAR16 BlockName[33];
768 CHAR16 *ConfigRequest;
769 CHAR16 *Request;
770
771 //
772 // Locate protocols for use
773 //
774 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
775 if (EFI_ERROR (Status)) {
776 return Status;
777 }
778
779 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
780 if (EFI_ERROR (Status)) {
781 return Status;
782 }
783
784 //
785 // Prepare <ConfigRequest>
786 //
787 ConfigHdr = mFakeConfigHdr;
788 HeaderLen = StrLen (ConfigHdr);
789
790 if (RequestElement == NULL) {
791 //
792 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
793 //
794 BlockName[0] = L'\0';
795 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
796
797 //
798 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
799 //
800 StringPtr = BlockName + 16;
801 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
802 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
803
804 Request = BlockName;
805 } else {
806 Request = RequestElement;
807 }
808
809 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
810 ConfigRequest = AllocateZeroPool (BufferLen);
811
812 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
813 StringPtr = ConfigRequest + HeaderLen;
814 StrCpy (StringPtr, Request);
815
816 //
817 // Convert buffer to <ConfigResp>
818 //
819 Status = HiiConfigRouting->BlockToConfig (
820 HiiConfigRouting,
821 ConfigRequest,
822 Buffer,
823 BufferSize,
824 &ConfigResp,
825 &Progress
826 );
827 if (EFI_ERROR (Status)) {
828 gBS->FreePool (ConfigResp);
829 return Status;
830 }
831
832 //
833 // Skip <ConfigHdr> and '&'
834 //
835 StringPtr = ConfigResp + HeaderLen + 1;
836
837 //
838 // Change uncommitted data in Browser
839 //
840 Status = FormBrowser2->BrowserCallback (
841 FormBrowser2,
842 &BufferSize,
843 StringPtr,
844 FALSE,
845 NULL,
846 NULL
847 );
848 gBS->FreePool (ConfigResp);
849 return Status;
850 }