]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/IfrSupportLib/UefiIfrForm.c
follow up the comments from code review.
[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 BufferToHexString (
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
404 **/
405 EFI_STATUS
406 EFIAPI
407 HexStringToBuffer (
408 IN OUT UINT8 *Buffer,
409 IN OUT UINTN *BufferSize,
410 IN CHAR16 *Str
411 )
412 {
413 EFI_STATUS Status;
414 UINTN ConvertedStrLen;
415
416 ConvertedStrLen = 0;
417 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
418 if (!EFI_ERROR (Status)) {
419 SwapBuffer (Buffer, ConvertedStrLen);
420 }
421
422 return Status;
423 }
424
425 /**
426 Convert binary representation Config string (e.g. "0041004200430044") to the
427 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
428 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
429
430 @param UnicodeString Original Unicode string.
431 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
432 Includes tailing '\0' character.
433 On output:
434 If return EFI_SUCCESS, containing length of Unicode string buffer.
435 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
436 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
437
438 @retval EFI_SUCCESS Routine success.
439 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
440
441 **/
442 EFI_STATUS
443 EFIAPI
444 ConfigStringToUnicode (
445 IN OUT CHAR16 *UnicodeString,
446 IN OUT UINTN *StrBufferLen,
447 IN CHAR16 *ConfigString
448 )
449 {
450 UINTN Index;
451 UINTN Len;
452 UINTN BufferSize;
453 CHAR16 BackupChar;
454
455 Len = StrLen (ConfigString) / 4;
456 BufferSize = (Len + 1) * sizeof (CHAR16);
457
458 if (*StrBufferLen < BufferSize) {
459 *StrBufferLen = BufferSize;
460 return EFI_BUFFER_TOO_SMALL;
461 }
462
463 *StrBufferLen = BufferSize;
464
465 for (Index = 0; Index < Len; Index++) {
466 BackupChar = ConfigString[4];
467 ConfigString[4] = L'\0';
468
469 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
470
471 ConfigString[4] = BackupChar;
472
473 ConfigString += 4;
474 UnicodeString += 1;
475 }
476
477 //
478 // Add tailing '\0' character
479 //
480 *UnicodeString = L'\0';
481
482 return EFI_SUCCESS;
483 }
484
485 /**
486 Convert Unicode string to binary representation Config string, e.g.
487 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
488 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
489
490 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
491 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
492 Includes tailing '\0' character.
493 On output:
494 If return EFI_SUCCESS, containing length of Unicode string buffer.
495 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
496 @param UnicodeString Original Unicode string.
497
498 @retval EFI_SUCCESS Routine success.
499 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
500
501 **/
502 EFI_STATUS
503 EFIAPI
504 UnicodeToConfigString (
505 IN OUT CHAR16 *ConfigString,
506 IN OUT UINTN *StrBufferLen,
507 IN CHAR16 *UnicodeString
508 )
509 {
510 UINTN Index;
511 UINTN Len;
512 UINTN BufferSize;
513 CHAR16 *String;
514
515 Len = StrLen (UnicodeString);
516 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
517
518 if (*StrBufferLen < BufferSize) {
519 *StrBufferLen = BufferSize;
520 return EFI_BUFFER_TOO_SMALL;
521 }
522
523 *StrBufferLen = BufferSize;
524 String = ConfigString;
525
526 for (Index = 0; Index < Len; Index++) {
527 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
528
529 ConfigString += 4;
530 UnicodeString += 1;
531 }
532
533 //
534 // Add tailing '\0' character
535 //
536 *ConfigString = L'\0';
537
538 //
539 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
540 //
541 ToLower (String);
542 return EFI_SUCCESS;
543 }
544
545 /**
546 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
547
548 @param ConfigHdr Pointer to the ConfigHdr string.
549 @param StrBufferLen On input: Length in bytes of buffer to hold the
550 ConfigHdr string. Includes tailing '\0' character.
551 On output: If return EFI_SUCCESS, containing
552 length of ConfigHdr string buffer. If return
553 EFI_BUFFER_TOO_SMALL, containg length of string
554 buffer desired.
555 @param Guid Routing information: GUID.
556 @param Name Routing information: NAME.
557 @param DriverHandle Driver handle which contains the routing
558 information: PATH.
559
560 @retval EFI_SUCCESS Routine success.
561 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
562
563 **/
564 EFI_STATUS
565 EFIAPI
566 ConstructConfigHdr (
567 IN OUT CHAR16 *ConfigHdr,
568 IN OUT UINTN *StrBufferLen,
569 IN CONST EFI_GUID *Guid,
570 IN CHAR16 *Name, OPTIONAL
571 IN EFI_HANDLE *DriverHandle
572 )
573 {
574 EFI_STATUS Status;
575 UINTN NameStrLen;
576 UINTN DevicePathSize;
577 UINTN BufferSize;
578 CHAR16 *StrPtr;
579 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
580
581 if (Name == NULL) {
582 //
583 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
584 //
585 NameStrLen = 0;
586 } else {
587 //
588 // For buffer storage
589 //
590 NameStrLen = StrLen (Name);
591 }
592
593 //
594 // Retrieve DevicePath Protocol associated with this HiiPackageList
595 //
596 Status = gBS->HandleProtocol (
597 DriverHandle,
598 &gEfiDevicePathProtocolGuid,
599 (VOID **) &DevicePath
600 );
601 if (EFI_ERROR (Status)) {
602 return Status;
603 }
604
605 DevicePathSize = GetDevicePathSize (DevicePath);
606
607 //
608 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
609 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
610 //
611 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
612 if (*StrBufferLen < BufferSize) {
613 *StrBufferLen = BufferSize;
614 return EFI_BUFFER_TOO_SMALL;
615 }
616
617 *StrBufferLen = BufferSize;
618
619 StrPtr = ConfigHdr;
620
621 StrCpy (StrPtr, L"GUID=");
622 StrPtr += 5;
623 BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
624 StrPtr += 32;
625
626 //
627 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
628 //
629 StrCpy (StrPtr, L"&NAME=");
630 StrPtr += 6;
631 if (Name != NULL) {
632 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
633 UnicodeToConfigString (StrPtr, &BufferSize, Name);
634 StrPtr += (NameStrLen * 4);
635 }
636
637 StrCpy (StrPtr, L"&PATH=");
638 StrPtr += 6;
639 BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
640
641 return EFI_SUCCESS;
642 }
643
644
645 /**
646 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
647
648 @param String The string to be searched in.
649 @param Offset Offset in BlockName.
650 @param Width Width in BlockName.
651
652 @retval TRUE Block name found.
653 @retval FALSE Block name not found.
654
655 **/
656 BOOLEAN
657 EFIAPI
658 FindBlockName (
659 IN OUT CHAR16 *String,
660 IN UINTN Offset,
661 IN UINTN Width
662 )
663 {
664 EFI_STATUS Status;
665 UINTN Data;
666 UINTN BufferSize;
667 UINTN ConvertedStrLen;
668
669 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
670 //
671 // Skip '&OFFSET='
672 //
673 String = String + 8;
674
675 Data = 0;
676 BufferSize = sizeof (UINTN);
677 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
678 if (EFI_ERROR (Status)) {
679 return FALSE;
680 }
681 String = String + ConvertedStrLen;
682
683 if (Data != Offset) {
684 continue;
685 }
686
687 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
688 return FALSE;
689 }
690 String = String + 7;
691
692 Data = 0;
693 BufferSize = sizeof (UINTN);
694 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
695 if (EFI_ERROR (Status)) {
696 return FALSE;
697 }
698 if (Data == Width) {
699 return TRUE;
700 }
701
702 String = String + ConvertedStrLen;
703 }
704
705 return FALSE;
706 }
707
708
709 /**
710 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
711
712 @param VariableGuid An optional field to indicate the target variable
713 GUID name to use.
714 @param VariableName An optional field to indicate the target
715 human-readable variable name.
716 @param BufferSize On input: Length in bytes of buffer to hold
717 retrived data. On output: If return
718 EFI_BUFFER_TOO_SMALL, containg length of buffer
719 desired.
720 @param Buffer Buffer to hold retrived data.
721
722 @retval EFI_SUCCESS Routine success.
723 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
724 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
725
726 **/
727 EFI_STATUS
728 EFIAPI
729 GetBrowserData (
730 IN CONST EFI_GUID *VariableGuid, OPTIONAL
731 IN CONST CHAR16 *VariableName, OPTIONAL
732 IN OUT UINTN *BufferSize,
733 IN OUT UINT8 *Buffer
734 )
735 {
736 EFI_STATUS Status;
737 CONST CHAR16 *ConfigHdr;
738 CHAR16 *ConfigResp;
739 CHAR16 *StringPtr;
740 UINTN HeaderLen;
741 UINTN BufferLen;
742 CHAR16 *Progress;
743
744 //
745 // Locate protocols for use
746 //
747 Status = LocateFormBrowser2Protocols ();
748 if (EFI_ERROR (Status)) {
749 return Status;
750 }
751
752 //
753 // Retrive formset storage data from Form Browser
754 //
755 ConfigHdr = mFakeConfigHdr;
756 HeaderLen = StrLen (ConfigHdr);
757
758 //
759 // First try allocate 0x4000 buffer for the formet storage data.
760 //
761 BufferLen = 0x4000;
762 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
763 if (ConfigResp == NULL) {
764 BufferLen = 0;
765 }
766
767 StringPtr = ConfigResp + HeaderLen;
768 *StringPtr = L'&';
769 StringPtr++;
770
771 Status = mFormBrowser2->BrowserCallback (
772 mFormBrowser2,
773 &BufferLen,
774 StringPtr,
775 TRUE,
776 VariableGuid,
777 VariableName
778 );
779 if (Status == EFI_BUFFER_TOO_SMALL) {
780 if (ConfigResp != NULL) {
781 FreePool (ConfigResp);
782 }
783
784 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
785 if (ConfigResp == NULL) {
786 return EFI_OUT_OF_RESOURCES;
787 }
788
789 StringPtr = ConfigResp + HeaderLen;
790 *StringPtr = L'&';
791 StringPtr++;
792
793 Status = mFormBrowser2->BrowserCallback (
794 mFormBrowser2,
795 &BufferLen,
796 StringPtr,
797 TRUE,
798 VariableGuid,
799 VariableName
800 );
801 }
802 if (EFI_ERROR (Status)) {
803 FreePool (ConfigResp);
804 return Status;
805 }
806 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
807
808 //
809 // Convert <ConfigResp> to buffer data
810 //
811 Status = mHiiConfigRouting->ConfigToBlock (
812 mHiiConfigRouting,
813 ConfigResp,
814 Buffer,
815 BufferSize,
816 &Progress
817 );
818 FreePool (ConfigResp);
819
820 return Status;
821 }
822
823
824 /**
825 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
826
827 @param VariableGuid An optional field to indicate the target variable
828 GUID name to use.
829 @param VariableName An optional field to indicate the target
830 human-readable variable name.
831 @param BufferSize Length in bytes of buffer to hold retrived data.
832 @param Buffer Buffer to hold retrived data.
833 @param RequestElement An optional field to specify which part of the
834 buffer data will be send back to Browser. If NULL,
835 the whole buffer of data will be committed to
836 Browser. <RequestElement> ::=
837 &OFFSET=<Number>&WIDTH=<Number>*
838
839 @retval EFI_SUCCESS Routine success.
840 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
841 @retval Other Updating Browser uncommitted data failed.
842
843 **/
844 EFI_STATUS
845 EFIAPI
846 SetBrowserData (
847 IN CONST EFI_GUID *VariableGuid, OPTIONAL
848 IN CONST CHAR16 *VariableName, OPTIONAL
849 IN UINTN BufferSize,
850 IN CONST UINT8 *Buffer,
851 IN CONST CHAR16 *RequestElement OPTIONAL
852 )
853 {
854 EFI_STATUS Status;
855 CONST CHAR16 *ConfigHdr;
856 CHAR16 *ConfigResp;
857 CHAR16 *StringPtr;
858 UINTN HeaderLen;
859 UINTN BufferLen;
860 CHAR16 *Progress;
861 CHAR16 BlockName[33];
862 CHAR16 *ConfigRequest;
863 CONST CHAR16 *Request;
864
865 //
866 // Locate protocols for use
867 //
868 Status = LocateFormBrowser2Protocols ();
869 if (EFI_ERROR (Status)) {
870 return Status;
871 }
872
873 //
874 // Prepare <ConfigRequest>
875 //
876 ConfigHdr = mFakeConfigHdr;
877 HeaderLen = StrLen (ConfigHdr);
878
879 if (RequestElement == NULL) {
880 //
881 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
882 //
883 BlockName[0] = L'\0';
884 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
885
886 //
887 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
888 //
889 StringPtr = BlockName + 16;
890 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
891 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
892
893 Request = BlockName;
894 } else {
895 Request = RequestElement;
896 }
897
898 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
899 ConfigRequest = AllocateZeroPool (BufferLen);
900 if (ConfigRequest == NULL) {
901 return EFI_OUT_OF_RESOURCES;
902 }
903
904 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
905 StringPtr = ConfigRequest + HeaderLen;
906 StrCpy (StringPtr, Request);
907
908 //
909 // Convert buffer to <ConfigResp>
910 //
911 Status = mHiiConfigRouting->BlockToConfig (
912 mHiiConfigRouting,
913 ConfigRequest,
914 Buffer,
915 BufferSize,
916 &ConfigResp,
917 &Progress
918 );
919 if (EFI_ERROR (Status)) {
920 FreePool (ConfigRequest);
921 return Status;
922 }
923
924 //
925 // Skip <ConfigHdr> and '&'
926 //
927 StringPtr = ConfigResp + HeaderLen + 1;
928
929 //
930 // Change uncommitted data in Browser
931 //
932 Status = mFormBrowser2->BrowserCallback (
933 mFormBrowser2,
934 &BufferSize,
935 StringPtr,
936 FALSE,
937 NULL,
938 NULL
939 );
940 FreePool (ConfigRequest);
941 return Status;
942 }