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