]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/IfrSupportLib/UefiIfrForm.c
Fix ECC issue.
[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 STATIC CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;
19 STATIC CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;
20
21 /**
22 This function locate FormBrowser2 protocols for later usage.
23
24 @return Status the status to locate protocol.
25 **/
26 EFI_STATUS
27 LocateFormBrowser2Protocols (
28 VOID
29 )
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
52 //
53 // Fake <ConfigHdr>
54 //
55 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
56
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..
62 @param Marker A series of (quantity == NumberOfLines - 1) text
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.
68 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
69
70 **/
71 EFI_STATUS
72 EFIAPI
73 IfrLibCreatePopUp2 (
74 IN UINTN NumberOfLines,
75 OUT EFI_INPUT_KEY *KeyValue,
76 IN VA_LIST Marker
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;
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;
101 CHAR16 *String;
102
103 String = VA_ARG (Marker, CHAR16 *);
104
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));
123 if (LineBuffer == NULL) {
124 return EFI_OUT_OF_RESOURCES;
125 }
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 *));
132 if (StringArray == NULL) {
133 FreePool (LineBuffer);
134 return EFI_OUT_OF_RESOURCES;
135 }
136 LargestString = StrLen (String);
137 StringArray[0] = String;
138
139 for (Index = 1; Index < NumberOfLines; Index++) {
140 StackString = VA_ARG (Marker, CHAR16 *);
141
142 if (StackString == NULL) {
143 FreePool (LineBuffer);
144 FreePool (StringArray);
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
256 FreePool (LineBuffer);
257 FreePool (StringArray);
258
259 return Status;
260 }
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 **/
277 EFI_STATUS
278 EFIAPI
279 IfrLibCreatePopUp (
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
295 return Status;
296 }
297
298 /**
299 Swap bytes in the buffer. This is a internal function.
300
301 @param Buffer Binary buffer.
302 @param BufferSize Size of the buffer in bytes.
303
304 @return None.
305
306 **/
307 VOID
308 SwapBuffer (
309 IN OUT UINT8 *Buffer,
310 IN UINTN BufferSize
311 )
312 {
313 UINTN Index;
314 UINT8 Temp;
315 UINTN SwapCount;
316
317 SwapCount = BufferSize / 2;
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
325 /**
326 Converts the unicode character of the string from uppercase to lowercase.
327 This is a internal function.
328
329 @param Str String to be converted
330
331 **/
332 VOID
333 EFIAPI
334 ToLower (
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
347
348 /**
349 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
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.
356 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
357
358 **/
359 EFI_STATUS
360 EFIAPI
361 BufInReverseOrderToHexString (
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);
372 if (NewBuffer == NULL) {
373 return EFI_OUT_OF_RESOURCES;
374 }
375 SwapBuffer (NewBuffer, BufferSize);
376
377 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
378 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
379
380 FreePool (NewBuffer);
381 //
382 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
383 //
384 ToLower (Str);
385
386 return Status;
387 }
388
389
390 /**
391 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
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.
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.
404
405 **/
406 EFI_STATUS
407 EFIAPI
408 HexStringToBufInReverseOrder (
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;
418 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
419 if (!EFI_ERROR (Status)) {
420 SwapBuffer (Buffer, ConvertedStrLen);
421 }
422
423 return Status;
424 }
425
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
439 @retval EFI_SUCCESS Operation completes successfully.
440 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
441
442 **/
443 EFI_STATUS
444 EFIAPI
445 ConfigStringToUnicode (
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
499 @retval EFI_SUCCESS Operation completes successfully.
500 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
501
502 **/
503 EFI_STATUS
504 EFIAPI
505 UnicodeToConfigString (
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 }
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
561 @retval EFI_SUCCESS Operation completes successfully.
562 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
563
564 **/
565 EFI_STATUS
566 EFIAPI
567 ConstructConfigHdr (
568 IN OUT CHAR16 *ConfigHdr,
569 IN OUT UINTN *StrBufferLen,
570 IN CONST EFI_GUID *Guid,
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 //
609 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
610 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
611 //
612 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
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;
624 BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
625 StrPtr += 32;
626
627 //
628 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
629 //
630 StrCpy (StrPtr, L"&NAME=");
631 StrPtr += 6;
632 if (Name != NULL) {
633 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
634 UnicodeToConfigString (StrPtr, &BufferSize, Name);
635 StrPtr += (NameStrLen * 4);
636 }
637
638 StrCpy (StrPtr, L"&PATH=");
639 StrPtr += 6;
640 BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
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 **/
657 BOOLEAN
658 EFIAPI
659 FindBlockName (
660 IN OUT CHAR16 *String,
661 IN UINTN Offset,
662 IN UINTN Width
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);
678 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
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);
695 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
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
723 @retval EFI_SUCCESS Operation completes successfully.
724 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
725 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
726
727 **/
728 EFI_STATUS
729 EFIAPI
730 GetBrowserData (
731 IN CONST EFI_GUID *VariableGuid, OPTIONAL
732 IN CONST CHAR16 *VariableName, OPTIONAL
733 IN OUT UINTN *BufferSize,
734 IN OUT UINT8 *Buffer
735 )
736 {
737 EFI_STATUS Status;
738 CONST CHAR16 *ConfigHdr;
739 CHAR16 *ConfigResp;
740 CHAR16 *StringPtr;
741 UINTN HeaderLen;
742 UINTN BufferLen;
743 CHAR16 *Progress;
744
745 //
746 // Locate protocols for use
747 //
748 Status = LocateFormBrowser2Protocols ();
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);
758
759 //
760 // First try allocate 0x4000 buffer for the formet storage data.
761 //
762 BufferLen = 0x4000;
763 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
764 if (ConfigResp == NULL) {
765 BufferLen = 0;
766 }
767
768 StringPtr = ConfigResp + HeaderLen;
769 *StringPtr = L'&';
770 StringPtr++;
771
772 Status = mFormBrowser2->BrowserCallback (
773 mFormBrowser2,
774 &BufferLen,
775 StringPtr,
776 TRUE,
777 VariableGuid,
778 VariableName
779 );
780 if (Status == EFI_BUFFER_TOO_SMALL) {
781 if (ConfigResp != NULL) {
782 FreePool (ConfigResp);
783 }
784
785 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
786 if (ConfigResp == NULL) {
787 return EFI_OUT_OF_RESOURCES;
788 }
789
790 StringPtr = ConfigResp + HeaderLen;
791 *StringPtr = L'&';
792 StringPtr++;
793
794 Status = mFormBrowser2->BrowserCallback (
795 mFormBrowser2,
796 &BufferLen,
797 StringPtr,
798 TRUE,
799 VariableGuid,
800 VariableName
801 );
802 }
803 if (EFI_ERROR (Status)) {
804 FreePool (ConfigResp);
805 return Status;
806 }
807 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
808
809 //
810 // Convert <ConfigResp> to buffer data
811 //
812 Status = mHiiConfigRouting->ConfigToBlock (
813 mHiiConfigRouting,
814 ConfigResp,
815 Buffer,
816 BufferSize,
817 &Progress
818 );
819 FreePool (ConfigResp);
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
840 @retval EFI_SUCCESS Operation completes successfully.
841 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
842 @retval Other Updating Browser uncommitted data failed.
843
844 **/
845 EFI_STATUS
846 EFIAPI
847 SetBrowserData (
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
853 )
854 {
855 EFI_STATUS Status;
856 CONST CHAR16 *ConfigHdr;
857 CHAR16 *ConfigResp;
858 CHAR16 *StringPtr;
859 UINTN HeaderLen;
860 UINTN BufferLen;
861 CHAR16 *Progress;
862 CHAR16 BlockName[33];
863 CHAR16 *ConfigRequest;
864 CONST CHAR16 *Request;
865
866 //
867 // Locate protocols for use
868 //
869 Status = LocateFormBrowser2Protocols ();
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));
892 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
893
894 Request = BlockName;
895 } else {
896 Request = RequestElement;
897 }
898
899 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
900 ConfigRequest = AllocateZeroPool (BufferLen);
901 if (ConfigRequest == NULL) {
902 return EFI_OUT_OF_RESOURCES;
903 }
904
905 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
906 StringPtr = ConfigRequest + HeaderLen;
907 StrCpy (StringPtr, Request);
908
909 //
910 // Convert buffer to <ConfigResp>
911 //
912 Status = mHiiConfigRouting->BlockToConfig (
913 mHiiConfigRouting,
914 ConfigRequest,
915 Buffer,
916 BufferSize,
917 &ConfigResp,
918 &Progress
919 );
920 if (EFI_ERROR (Status)) {
921 FreePool (ConfigRequest);
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 //
933 Status = mFormBrowser2->BrowserCallback (
934 mFormBrowser2,
935 &BufferSize,
936 StringPtr,
937 FALSE,
938 NULL,
939 NULL
940 );
941 FreePool (ConfigRequest);
942 return Status;
943 }