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