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