]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c
1.enhanced security check.
[mirror_edk2.git] / MdeModulePkg / Library / UefiIfrSupportLib / UefiIfrForm.c
CommitLineData
08e4b3cf 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
ac7e320c 20GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mIfrSupportLibHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
08e4b3cf 21\r
aa79b0b3 22//\r
23// Fake <ConfigHdr>\r
24//\r
25GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
26\r
08e4b3cf 27/**\r
28 This function locate FormBrowser2 protocols for later usage.\r
29\r
30 @return Status the status to locate protocol.\r
31**/\r
32EFI_STATUS\r
33LocateFormBrowser2Protocols (\r
34 VOID\r
35 )\r
36{\r
37 EFI_STATUS Status;\r
38 //\r
39 // Locate protocols for later usage\r
40 //\r
41 if (mFormBrowser2 == NULL) {\r
42 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2);\r
43 if (EFI_ERROR (Status)) {\r
44 return Status;\r
45 }\r
46 }\r
47 \r
48 if (mIfrSupportLibHiiConfigRouting == NULL) {\r
49 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mIfrSupportLibHiiConfigRouting);\r
50 if (EFI_ERROR (Status)) {\r
51 return Status;\r
52 }\r
53 }\r
54\r
55 return EFI_SUCCESS;\r
56}\r
57\r
08e4b3cf 58/**\r
59 Draw a dialog and return the selected key.\r
60\r
61 @param NumberOfLines The number of lines for the dialog box\r
62 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
35d59af3 63 @param String The first String to be displayed in the Pop-Up.\r
08e4b3cf 64 @param Marker A series of (quantity == NumberOfLines - 1) text\r
65 strings which will be used to construct the dialog\r
66 box\r
67\r
68 @retval EFI_SUCCESS Displayed dialog and received user interaction\r
69 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.\r
70 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
71\r
72**/\r
73EFI_STATUS\r
74EFIAPI\r
75IfrLibCreatePopUp2 (\r
76 IN UINTN NumberOfLines,\r
77 OUT EFI_INPUT_KEY *KeyValue,\r
35d59af3 78 IN CHAR16 *String,\r
08e4b3cf 79 IN VA_LIST Marker\r
80 )\r
81{\r
82 UINTN Index;\r
83 UINTN Count;\r
84 UINTN Start;\r
85 UINTN Top;\r
86 CHAR16 *StringPtr;\r
87 UINTN LeftColumn;\r
88 UINTN RightColumn;\r
89 UINTN TopRow;\r
90 UINTN BottomRow;\r
91 UINTN DimensionsWidth;\r
92 UINTN DimensionsHeight;\r
93 EFI_INPUT_KEY Key;\r
94 UINTN LargestString;\r
95 CHAR16 *StackString;\r
96 EFI_STATUS Status;\r
97 UINTN StringLen;\r
98 CHAR16 *LineBuffer;\r
99 CHAR16 **StringArray;\r
100 EFI_EVENT TimerEvent;\r
101 EFI_EVENT WaitList[2];\r
102 UINTN CurrentAttribute;\r
103 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
08e4b3cf 104\r
08e4b3cf 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
35d59af3 289 VA_START (Marker, String);\r
08e4b3cf 290\r
35d59af3 291 Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, String, Marker);\r
08e4b3cf 292\r
293 VA_END (Marker);\r
294\r
295 return Status;\r
296}\r
297\r
298/**\r
299 Extract block name from the array generated by VFR compiler. The name of\r
300 this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".\r
301 Format of this array is:\r
302 Array length | 4-bytes\r
303 Offset | 2-bytes\r
304 Width | 2-bytes\r
305 Offset | 2-bytes\r
306 Width | 2-bytes\r
307 ... ...\r
308\r
309 @param Buffer Array generated by VFR compiler.\r
310 @param BlockName The returned <BlockName>\r
311\r
312 @retval EFI_OUT_OF_RESOURCES Run out of memory resource.\r
313 @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL.\r
314 @retval EFI_SUCCESS Operation successful.\r
315\r
316**/\r
317EFI_STATUS\r
318ExtractBlockName (\r
319 IN UINT8 *Buffer,\r
320 OUT CHAR16 **BlockName\r
321 )\r
322\r
323{\r
324 UINTN Index;\r
325 UINT32 Length;\r
326 UINT32 BlockNameNumber;\r
327 UINTN HexStringBufferLen;\r
328 CHAR16 *StringPtr;\r
329\r
330 if ((Buffer == NULL) || (BlockName == NULL)) {\r
331 return EFI_INVALID_PARAMETER;\r
332 }\r
333\r
334 //\r
335 // Calculate number of Offset/Width pair\r
336 //\r
337 CopyMem (&Length, Buffer, sizeof (UINT32));\r
338 BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2);\r
339\r
340 //\r
341 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
342 // | 8 | 4 | 7 | 4 |\r
343 //\r
344 StringPtr = AllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));\r
08e4b3cf 345 if (StringPtr == NULL) {\r
346 return EFI_OUT_OF_RESOURCES;\r
347 }\r
fa7b3168 348 *BlockName = StringPtr;\r
08e4b3cf 349\r
350 Buffer += sizeof (UINT32);\r
351 for (Index = 0; Index < BlockNameNumber; Index++) {\r
352 StrCpy (StringPtr, L"&OFFSET=");\r
353 StringPtr += 8;\r
354\r
355 HexStringBufferLen = 5;\r
356 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
357 Buffer += sizeof (UINT16);\r
358 StringPtr += 4;\r
359\r
360 StrCpy (StringPtr, L"&WIDTH=");\r
361 StringPtr += 7;\r
362\r
363 HexStringBufferLen = 5;\r
364 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
365 Buffer += sizeof (UINT16);\r
366 StringPtr += 4;\r
367 }\r
368\r
369 return EFI_SUCCESS;\r
370}\r
371\r
372/**\r
373\r
374 Extract block config from the array generated by VFR compiler. The name of\r
375 this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".\r
376\r
377 @param Buffer - Array generated by VFR compiler.\r
378 @param BlockConfig - The returned <BlockConfig>\r
379\r
380 @retval EFI_OUT_OF_RESOURCES - Run out of memory resource.\r
381 @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.\r
382 @retval EFI_SUCCESS - Operation successful.\r
383\r
384**/\r
385EFI_STATUS\r
386ExtractBlockConfig (\r
387 IN UINT8 *Buffer,\r
388 OUT CHAR16 **BlockConfig\r
389 )\r
390{\r
391 UINT32 Length;\r
392 UINT16 Width;\r
393 UINTN HexStringBufferLen;\r
394 CHAR16 *StringPtr;\r
395 UINT8 *BufferEnd;\r
396 CHAR16 *StringEnd;\r
397 EFI_STATUS Status;\r
398\r
399 if ((Buffer == NULL) || (BlockConfig == NULL)) {\r
400 return EFI_INVALID_PARAMETER;\r
401 }\r
402\r
403 //\r
404 // Calculate length of AltResp string\r
405 // Format of Default value array is:\r
406 // Array length | 4-bytes\r
407 // Offset | 2-bytes\r
408 // Width | 2-bytes\r
409 // Value | Variable length\r
410 // Offset | 2-bytes\r
411 // Width | 2-bytes\r
412 // Value | Variable length\r
413 // ... ...\r
414 // When value is 1 byte in length, overhead of AltResp string will be maximum,\r
415 // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+\r
416 // | 8 | 4 | 7 | 4 | 7 |2|\r
417 // so the maximum length of BlockConfig could be calculated as:\r
418 // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7\r
419 //\r
420 CopyMem (&Length, Buffer, sizeof (UINT32));\r
421 BufferEnd = Buffer + Length;\r
422 StringPtr = AllocatePool (Length * 7 * sizeof (CHAR16));\r
423 *BlockConfig = StringPtr;\r
424 if (StringPtr == NULL) {\r
425 return EFI_OUT_OF_RESOURCES;\r
426 }\r
427 StringEnd = StringPtr + (Length * 7);\r
428\r
429 Buffer += sizeof (UINT32);\r
430 while (Buffer < BufferEnd) {\r
431 StrCpy (StringPtr, L"&OFFSET=");\r
432 StringPtr += 8;\r
433\r
434 HexStringBufferLen = 5;\r
435 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
436 Buffer += sizeof (UINT16);\r
437 StringPtr += 4;\r
438\r
439 StrCpy (StringPtr, L"&WIDTH=");\r
440 StringPtr += 7;\r
441\r
442 HexStringBufferLen = 5;\r
443 BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
444 CopyMem (&Width, Buffer, sizeof (UINT16));\r
445 Buffer += sizeof (UINT16);\r
446 StringPtr += 4;\r
447\r
448 StrCpy (StringPtr, L"&VALUE=");\r
449 StringPtr += 7;\r
450\r
451 HexStringBufferLen = StringEnd - StringPtr;\r
452 Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width);\r
453 if (EFI_ERROR (Status)) {\r
454 return Status;\r
455 }\r
456 Buffer += Width;\r
457 StringPtr += (Width * 2);\r
458 }\r
459\r
460 return EFI_SUCCESS;\r
461}\r
462\r
463/**\r
464 Construct <ConfigAltResp> for a buffer storage.\r
465\r
466 @param ConfigRequest The Config request string. If set to NULL, all the\r
467 configurable elements will be extracted from BlockNameArray.\r
468 @param ConfigAltResp The returned <ConfigAltResp>.\r
469 @param Progress On return, points to a character in the Request.\r
470 @param Guid GUID of the buffer storage.\r
471 @param Name Name of the buffer storage.\r
472 @param DriverHandle The DriverHandle which is used to invoke HiiDatabase\r
473 protocol interface NewPackageList().\r
474 @param BufferStorage Content of the buffer storage.\r
475 @param BufferStorageSize Length in bytes of the buffer storage.\r
476 @param BlockNameArray Array generated by VFR compiler.\r
477 @param NumberAltCfg Number of Default value array generated by VFR compiler.\r
478 The sequential input parameters will be number of\r
479 AltCfgId and DefaultValueArray pairs. When set to 0,\r
480 there will be no <AltResp>.\r
481\r
482 retval EFI_OUT_OF_RESOURCES Run out of memory resource.\r
483 retval EFI_INVALID_PARAMETER ConfigAltResp is NULL.\r
484 retval EFI_SUCCESS Operation successful.\r
485\r
486**/\r
487EFI_STATUS\r
488ConstructConfigAltResp (\r
489 IN EFI_STRING ConfigRequest, OPTIONAL\r
490 OUT EFI_STRING *Progress,\r
491 OUT EFI_STRING *ConfigAltResp,\r
492 IN EFI_GUID *Guid,\r
493 IN CHAR16 *Name,\r
494 IN EFI_HANDLE *DriverHandle,\r
495 IN VOID *BufferStorage,\r
496 IN UINTN BufferStorageSize,\r
497 IN VOID *BlockNameArray, OPTIONAL\r
498 IN UINTN NumberAltCfg,\r
499 ...\r
500//IN UINT16 AltCfgId,\r
501//IN VOID *DefaultValueArray,\r
502 )\r
503{\r
504 EFI_STATUS Status;\r
505 CHAR16 *ConfigHdr;\r
506 CHAR16 *BlockName;\r
507 CHAR16 *DescHdr;\r
508 CHAR16 *StringPtr;\r
509 CHAR16 **AltCfg;\r
510 UINT16 AltCfgId;\r
511 VOID *DefaultValueArray;\r
512 UINTN StrBufferLen;\r
513 EFI_STRING ConfigResp;\r
514 EFI_STRING TempStr;\r
515 VA_LIST Args;\r
516 UINTN AltRespLen;\r
517 UINTN Index;\r
518 BOOLEAN NeedFreeConfigRequest;\r
519 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
520 UINTN Len;\r
521\r
522 if (ConfigAltResp == NULL) {\r
523 return EFI_INVALID_PARAMETER;\r
524 }\r
fa7b3168 525 \r
526 DescHdr = NULL;\r
527 StringPtr = NULL;\r
528 AltCfg = NULL;\r
529 ConfigResp = NULL;\r
530 BlockName = NULL;\r
531 NeedFreeConfigRequest = FALSE;\r
08e4b3cf 532\r
533 //\r
534 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
535 //\r
536 ConfigHdr = NULL;\r
537 StrBufferLen = 0;\r
538 Status = ConstructConfigHdr (\r
539 ConfigHdr,\r
540 &StrBufferLen,\r
541 Guid,\r
542 Name,\r
543 DriverHandle\r
544 );\r
fa7b3168 545 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
546 ConfigHdr = AllocateZeroPool (StrBufferLen);\r
547 if (ConfigHdr == NULL) {\r
548 Status = EFI_OUT_OF_RESOURCES;\r
549 goto Exit;\r
08e4b3cf 550 }\r
fa7b3168 551 Status = ConstructConfigHdr (\r
552 ConfigHdr,\r
553 &StrBufferLen,\r
554 Guid,\r
555 Name,\r
556 DriverHandle\r
557 );\r
08e4b3cf 558\r
559 if (EFI_ERROR (Status)) {\r
fa7b3168 560 goto Exit;\r
08e4b3cf 561 }\r
562\r
563 //\r
564 // Construct <ConfigResp>\r
565 //\r
08e4b3cf 566 if (ConfigRequest == NULL) {\r
567 //\r
568 // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray\r
569 //\r
570 Status = ExtractBlockName (BlockNameArray, &BlockName);\r
571 if (EFI_ERROR (Status)) {\r
fa7b3168 572 goto Exit;\r
08e4b3cf 573 }\r
574 \r
575 Len = StrSize (ConfigHdr);\r
576 ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16));\r
fa7b3168 577 if (ConfigRequest == NULL) {\r
578 Status = EFI_OUT_OF_RESOURCES;\r
579 goto Exit;\r
580 }\r
581 \r
08e4b3cf 582 StrCpy (ConfigRequest, ConfigHdr);\r
583 StrCat (ConfigRequest, BlockName);\r
584 NeedFreeConfigRequest = TRUE;\r
fa7b3168 585\r
08e4b3cf 586 }\r
587\r
588 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
589 if (EFI_ERROR (Status)) {\r
590 return Status;\r
591 }\r
592\r
593 Status = HiiConfigRouting->BlockToConfig (\r
594 HiiConfigRouting,\r
595 ConfigRequest,\r
596 BufferStorage,\r
597 BufferStorageSize,\r
598 &ConfigResp,\r
599 (Progress == NULL) ? &TempStr : Progress\r
600 );\r
601 if (EFI_ERROR (Status)) {\r
602 return Status;\r
603 }\r
604\r
fa7b3168 605 AltRespLen = 0;\r
08e4b3cf 606 //\r
607 // Construct <AltResp>\r
608 //\r
fa7b3168 609 if (NumberAltCfg > 0) {\r
610 DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));\r
611 if (DescHdr == NULL) {\r
612 Status = EFI_OUT_OF_RESOURCES;\r
613 goto Exit;\r
614 }\r
615 \r
616 StringPtr = DescHdr;\r
617 AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));\r
618 if (AltCfg == NULL) {\r
619 Status = EFI_OUT_OF_RESOURCES;\r
620 goto Exit;\r
621 }\r
08e4b3cf 622\r
fa7b3168 623 VA_START (Args, NumberAltCfg);\r
624 for (Index = 0; Index < NumberAltCfg; Index++) {\r
625 AltCfgId = (UINT16) VA_ARG (Args, UINT16);\r
626 DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);\r
627 \r
628 //\r
629 // '&' <ConfigHdr>\r
630 //\r
631 AltRespLen += (StrLen (ConfigHdr) + 1);\r
632 \r
633 StringPtr = DescHdr + Index * 16;\r
634 StrCpy (StringPtr, L"&ALTCFG=");\r
635 AltRespLen += (8 + sizeof (UINT16) * 2);\r
636 \r
637 StrBufferLen = 5;\r
638 BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));\r
639 Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);\r
640 if (EFI_ERROR (Status)) {\r
641 goto Exit;\r
642 }\r
643 AltRespLen += StrLen (AltCfg[Index]);\r
08e4b3cf 644 }\r
fa7b3168 645 VA_END (Args);\r
08e4b3cf 646 }\r
08e4b3cf 647\r
648 //\r
649 // Generate the final <ConfigAltResp>\r
650 //\r
651 StrBufferLen = (StrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16);\r
652 TempStr = AllocateZeroPool (StrBufferLen);\r
653 *ConfigAltResp = TempStr;\r
654 if (TempStr == NULL) {\r
fa7b3168 655 goto Exit;\r
08e4b3cf 656 }\r
657\r
658 //\r
659 // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*\r
660 //\r
661 StrCpy (TempStr, ConfigResp);\r
662 for (Index = 0; Index < NumberAltCfg; Index++) {\r
663 StrCat (TempStr, L"&");\r
664 StrCat (TempStr, ConfigHdr);\r
665 StrCat (TempStr, DescHdr + Index * 16);\r
666 StrCat (TempStr, AltCfg[Index]);\r
667\r
fca1cc71 668 FreePool (AltCfg[Index]);\r
08e4b3cf 669 }\r
670\r
fa7b3168 671Exit:\r
08e4b3cf 672 if (NeedFreeConfigRequest) {\r
fca1cc71 673 FreePool (ConfigRequest);\r
08e4b3cf 674 }\r
fca1cc71 675 FreePool (ConfigHdr);\r
fa7b3168 676 if (ConfigResp != NULL) {\r
677 FreePool (ConfigResp);\r
678 }\r
679\r
680 if (BlockName != NULL) {\r
681 FreePool (BlockName);\r
682 }\r
683\r
684 if (NumberAltCfg > 0) {\r
685 FreePool (DescHdr);\r
686 FreePool (AltCfg);\r
687 }\r
08e4b3cf 688\r
689 return EFI_SUCCESS;\r
690}\r
691\r
692/**\r
693 Swap bytes in the buffer. This is a internal function.\r
694\r
695 @param Buffer Binary buffer.\r
696 @param BufferSize Size of the buffer in bytes.\r
697\r
698 @return None.\r
699\r
700**/\r
701VOID\r
702SwapBuffer (\r
703 IN OUT UINT8 *Buffer,\r
704 IN UINTN BufferSize\r
705 )\r
706{\r
707 UINTN Index;\r
708 UINT8 Temp;\r
709 UINTN SwapCount;\r
710\r
711 SwapCount = BufferSize / 2;\r
712 for (Index = 0; Index < SwapCount; Index++) {\r
713 Temp = Buffer[Index];\r
714 Buffer[Index] = Buffer[BufferSize - 1 - Index];\r
715 Buffer[BufferSize - 1 - Index] = Temp;\r
716 }\r
717}\r
718\r
719/**\r
720 Converts the unicode character of the string from uppercase to lowercase.\r
721 This is a internal function.\r
722\r
723 @param Str String to be converted\r
724\r
725**/\r
726VOID\r
727EFIAPI\r
728ToLower (\r
729 IN OUT CHAR16 *Str\r
730 )\r
731{\r
732 CHAR16 *Ptr;\r
733 \r
734 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {\r
735 if (*Ptr >= L'A' && *Ptr <= L'Z') {\r
736 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');\r
737 }\r
738 }\r
739}\r
740\r
741\r
742/**\r
743 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().\r
744\r
745 @param Str String for output\r
746 @param Buffer Binary buffer.\r
747 @param BufferSize Size of the buffer in bytes.\r
748\r
749 @retval EFI_SUCCESS The function completed successfully.\r
750 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
751\r
752**/\r
753EFI_STATUS\r
754EFIAPI\r
755BufInReverseOrderToHexString (\r
756 IN OUT CHAR16 *Str,\r
757 IN UINT8 *Buffer,\r
758 IN UINTN BufferSize\r
759 )\r
760{\r
761 EFI_STATUS Status;\r
762 UINT8 *NewBuffer;\r
763 UINTN StrBufferLen;\r
764\r
765 NewBuffer = AllocateCopyPool (BufferSize, Buffer);\r
766 if (NewBuffer == NULL) {\r
767 return EFI_OUT_OF_RESOURCES;\r
768 }\r
769 SwapBuffer (NewBuffer, BufferSize);\r
770\r
771 StrBufferLen = BufferSize * sizeof (CHAR16) + 1;\r
772 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);\r
773\r
774 FreePool (NewBuffer);\r
775 //\r
776 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
777 //\r
778 ToLower (Str);\r
779\r
780 return Status;\r
781}\r
782\r
783\r
784/**\r
785 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().\r
786\r
787 @param Buffer Pointer to buffer that receives the data.\r
788 @param BufferSize Length in bytes of the buffer to hold converted\r
789 data. If routine return with EFI_SUCCESS,\r
790 containing length of converted data. If routine\r
791 return with EFI_BUFFER_TOO_SMALL, containg length\r
792 of buffer desired.\r
793 @param Str String to be converted from.\r
794\r
795 @retval EFI_SUCCESS The function completed successfully.\r
796 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize\r
797 will be updated to the size required for the converstion.\r
798\r
799**/\r
800EFI_STATUS\r
801EFIAPI\r
802HexStringToBufInReverseOrder (\r
803 IN OUT UINT8 *Buffer,\r
804 IN OUT UINTN *BufferSize,\r
805 IN CHAR16 *Str\r
806 )\r
807{\r
808 EFI_STATUS Status;\r
809 UINTN ConvertedStrLen;\r
810\r
811 ConvertedStrLen = 0;\r
812 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);\r
813 if (!EFI_ERROR (Status)) {\r
814 SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2);\r
815 }\r
816\r
817 return Status;\r
818}\r
819\r
820/**\r
821 Convert binary representation Config string (e.g. "0041004200430044") to the\r
822 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.\r
823 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").\r
824\r
825 @param UnicodeString Original Unicode string.\r
826 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.\r
827 Includes tailing '\0' character.\r
828 On output:\r
829 If return EFI_SUCCESS, containing length of Unicode string buffer.\r
830 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
831 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+\r
832\r
833 @retval EFI_SUCCESS Operation completes successfully.\r
834 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.\r
835\r
836**/\r
837EFI_STATUS\r
838EFIAPI\r
839ConfigStringToUnicode (\r
840 IN OUT CHAR16 *UnicodeString,\r
841 IN OUT UINTN *StrBufferLen,\r
842 IN CHAR16 *ConfigString\r
843 )\r
844{\r
845 UINTN Index;\r
846 UINTN Len;\r
847 UINTN BufferSize;\r
848 CHAR16 BackupChar;\r
849\r
850 Len = StrLen (ConfigString) / 4;\r
851 BufferSize = (Len + 1) * sizeof (CHAR16);\r
852\r
853 if (*StrBufferLen < BufferSize) {\r
854 *StrBufferLen = BufferSize;\r
855 return EFI_BUFFER_TOO_SMALL;\r
856 }\r
857\r
858 *StrBufferLen = BufferSize;\r
859\r
860 for (Index = 0; Index < Len; Index++) {\r
861 BackupChar = ConfigString[4];\r
862 ConfigString[4] = L'\0';\r
863\r
864 HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);\r
865\r
866 ConfigString[4] = BackupChar;\r
867\r
868 ConfigString += 4;\r
869 UnicodeString += 1;\r
870 }\r
871\r
872 //\r
873 // Add tailing '\0' character\r
874 //\r
875 *UnicodeString = L'\0';\r
876\r
877 return EFI_SUCCESS;\r
878}\r
879\r
880/**\r
881 Convert Unicode string to binary representation Config string, e.g.\r
882 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.\r
883 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").\r
884\r
885 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+\r
886 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.\r
887 Includes tailing '\0' character.\r
888 On output:\r
889 If return EFI_SUCCESS, containing length of Unicode string buffer.\r
890 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
891 @param UnicodeString Original Unicode string.\r
892\r
893 @retval EFI_SUCCESS Operation completes successfully.\r
894 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.\r
895\r
896**/\r
897EFI_STATUS\r
898EFIAPI\r
899UnicodeToConfigString (\r
900 IN OUT CHAR16 *ConfigString,\r
901 IN OUT UINTN *StrBufferLen,\r
902 IN CHAR16 *UnicodeString\r
903 )\r
904{\r
905 UINTN Index;\r
906 UINTN Len;\r
907 UINTN BufferSize;\r
908 CHAR16 *String;\r
909\r
910 Len = StrLen (UnicodeString);\r
911 BufferSize = (Len * 4 + 1) * sizeof (CHAR16);\r
912\r
913 if (*StrBufferLen < BufferSize) {\r
914 *StrBufferLen = BufferSize;\r
915 return EFI_BUFFER_TOO_SMALL;\r
916 }\r
917\r
918 *StrBufferLen = BufferSize;\r
919 String = ConfigString;\r
920\r
921 for (Index = 0; Index < Len; Index++) {\r
922 BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);\r
923\r
924 ConfigString += 4;\r
925 UnicodeString += 1;\r
926 }\r
927\r
928 //\r
929 // Add tailing '\0' character\r
930 //\r
931 *ConfigString = L'\0';\r
932\r
933 //\r
934 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
935 //\r
936 ToLower (String); \r
937 return EFI_SUCCESS;\r
938}\r
939\r
940/**\r
941 Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
942\r
943 @param ConfigHdr Pointer to the ConfigHdr string.\r
944 @param StrBufferLen On input: Length in bytes of buffer to hold the\r
945 ConfigHdr string. Includes tailing '\0' character.\r
946 On output: If return EFI_SUCCESS, containing\r
947 length of ConfigHdr string buffer. If return\r
948 EFI_BUFFER_TOO_SMALL, containg length of string\r
949 buffer desired.\r
950 @param Guid Routing information: GUID.\r
951 @param Name Routing information: NAME.\r
952 @param DriverHandle Driver handle which contains the routing\r
953 information: PATH.\r
954\r
955 @retval EFI_SUCCESS Operation completes successfully.\r
956 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.\r
957\r
958**/\r
959EFI_STATUS\r
960EFIAPI\r
961ConstructConfigHdr (\r
962 IN OUT CHAR16 *ConfigHdr,\r
963 IN OUT UINTN *StrBufferLen,\r
964 IN CONST EFI_GUID *Guid,\r
965 IN CHAR16 *Name, OPTIONAL\r
966 IN EFI_HANDLE *DriverHandle\r
967 )\r
968{\r
969 EFI_STATUS Status;\r
970 UINTN NameStrLen;\r
971 UINTN DevicePathSize;\r
972 UINTN BufferSize;\r
973 CHAR16 *StrPtr;\r
974 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
975\r
df80a83c 976 //\r
c55426ab 977 // Make sure when ConfigHdr is NULL, StrBufferlen must be 0\r
df80a83c 978 //\r
979 ASSERT (!(ConfigHdr == NULL && *StrBufferLen != 0));\r
980\r
08e4b3cf 981 if (Name == NULL) {\r
982 //\r
983 // There will be no "NAME" in <ConfigHdr> for Name/Value storage\r
984 //\r
985 NameStrLen = 0;\r
986 } else {\r
987 //\r
988 // For buffer storage\r
989 //\r
990 NameStrLen = StrLen (Name);\r
991 }\r
992\r
993 //\r
994 // Retrieve DevicePath Protocol associated with this HiiPackageList\r
995 //\r
996 Status = gBS->HandleProtocol (\r
997 DriverHandle,\r
998 &gEfiDevicePathProtocolGuid,\r
999 (VOID **) &DevicePath\r
1000 );\r
1001 if (EFI_ERROR (Status)) {\r
1002 return Status;\r
1003 }\r
1004\r
1005 DevicePathSize = GetDevicePathSize (DevicePath);\r
1006\r
1007 //\r
1008 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
1009 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
1010 //\r
1011 BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);\r
7174e04c 1012 if ((*StrBufferLen == 0) || *StrBufferLen < BufferSize) {\r
08e4b3cf 1013 *StrBufferLen = BufferSize;\r
1014 return EFI_BUFFER_TOO_SMALL;\r
1015 }\r
1016\r
1017 *StrBufferLen = BufferSize;\r
1018\r
1019 StrPtr = ConfigHdr;\r
1020\r
1021 StrCpy (StrPtr, L"GUID=");\r
1022 StrPtr += 5;\r
1023 BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));\r
1024 StrPtr += 32;\r
1025\r
1026 //\r
1027 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"\r
1028 //\r
1029 StrCpy (StrPtr, L"&NAME=");\r
1030 StrPtr += 6;\r
1031 if (Name != NULL) {\r
1032 BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);\r
1033 UnicodeToConfigString (StrPtr, &BufferSize, Name);\r
1034 StrPtr += (NameStrLen * 4);\r
1035 }\r
1036\r
1037 StrCpy (StrPtr, L"&PATH=");\r
1038 StrPtr += 6;\r
1039 BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);\r
1040\r
1041 return EFI_SUCCESS;\r
1042}\r
1043\r
1044/**\r
1045 Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.\r
1046\r
1047 @param ConfigString Either <ConfigRequest> or <ConfigResp>.\r
1048 @param StorageGuid GUID of the storage.\r
1049 @param StorageName Name of the stoarge.\r
1050\r
1051 @retval TRUE Routing information is correct in ConfigString.\r
1052 @retval FALSE Routing information is incorrect in ConfigString.\r
1053\r
1054**/\r
1055BOOLEAN\r
1056IsConfigHdrMatch (\r
1057 IN EFI_STRING ConfigString,\r
1058 IN EFI_GUID *StorageGuid, OPTIONAL\r
1059 IN CHAR16 *StorageName OPTIONAL\r
1060 )\r
1061{\r
1062 EFI_STATUS Status;\r
1063 BOOLEAN Match;\r
1064 EFI_GUID Guid;\r
1065 CHAR16 *Name;\r
1066 CHAR16 *StrPtr;\r
1067 UINTN BufferSize;\r
1068\r
1069 //\r
1070 // <ConfigHdr> ::=\r
1071 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
1072 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
1073 //\r
1074 if (StrLen (ConfigString) <= (5 + 32 + 6)) {\r
1075 return FALSE;\r
1076 }\r
1077\r
1078 //\r
1079 // Compare GUID\r
1080 //\r
1081 if (StorageGuid != NULL) {\r
1082\r
1083 StrPtr = ConfigString + 5 + 32;\r
1084 if (*StrPtr != L'&') {\r
1085 return FALSE;\r
1086 }\r
1087 *StrPtr = L'\0';\r
1088\r
1089 BufferSize = sizeof (EFI_GUID);\r
1090 Status = HexStringToBufInReverseOrder (\r
1091 (UINT8 *) &Guid,\r
1092 &BufferSize,\r
1093 ConfigString + 5\r
1094 );\r
1095 *StrPtr = L'&';\r
1096\r
1097 if (EFI_ERROR (Status)) {\r
1098 return FALSE;\r
1099 }\r
1100\r
1101 if (!CompareGuid (&Guid, StorageGuid)) {\r
1102 return FALSE;\r
1103 }\r
1104 }\r
1105\r
1106 //\r
1107 // Compare Name\r
1108 //\r
1109 Match = TRUE;\r
1110 if (StorageName != NULL) {\r
1111 StrPtr = ConfigString + 5 + 32 + 6;\r
1112 while (*StrPtr != L'\0' && *StrPtr != L'&') {\r
1113 StrPtr++;\r
1114 }\r
1115 if (*StrPtr != L'&') {\r
1116 return FALSE;\r
1117 }\r
1118\r
1119 *StrPtr = L'\0';\r
1120 BufferSize = (((UINTN) StrPtr) - ((UINTN) &ConfigString[5 + 32 + 6])) / 4 + sizeof (CHAR16);\r
1121 Name = AllocatePool (BufferSize);\r
1122 ASSERT (Name != NULL);\r
1123 Status = ConfigStringToUnicode (\r
1124 Name,\r
1125 &BufferSize,\r
1126 ConfigString + 5 + 32 + 6\r
1127 );\r
1128 *StrPtr = L'&';\r
1129\r
1130 if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) {\r
1131 Match = FALSE;\r
1132 }\r
fca1cc71 1133 FreePool (Name);\r
08e4b3cf 1134 }\r
1135\r
1136 return Match;\r
1137}\r
1138\r
1139/**\r
1140 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
1141\r
1142 @param String The string to be searched in.\r
1143 @param Offset Offset in BlockName.\r
1144 @param Width Width in BlockName.\r
1145\r
1146 @retval TRUE Block name found.\r
1147 @retval FALSE Block name not found.\r
1148\r
1149**/\r
1150BOOLEAN\r
1151EFIAPI\r
1152FindBlockName (\r
1153 IN OUT CHAR16 *String,\r
1154 IN UINTN Offset,\r
1155 IN UINTN Width\r
1156 )\r
1157{\r
1158 EFI_STATUS Status;\r
1159 UINTN Data;\r
1160 UINTN BufferSize;\r
1161 UINTN ConvertedStrLen;\r
1162\r
1163 while ((String = StrStr (String, L"&OFFSET=")) != NULL) {\r
1164 //\r
1165 // Skip '&OFFSET='\r
1166 //\r
1167 String = String + 8;\r
1168\r
1169 Data = 0;\r
1170 BufferSize = sizeof (UINTN);\r
1171 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
1172 if (EFI_ERROR (Status)) {\r
1173 return FALSE;\r
1174 }\r
1175 String = String + ConvertedStrLen;\r
1176\r
1177 if (Data != Offset) {\r
1178 continue;\r
1179 }\r
1180\r
1181 if (StrnCmp (String, L"&WIDTH=", 7) != 0) {\r
1182 return FALSE;\r
1183 }\r
1184 String = String + 7;\r
1185\r
1186 Data = 0;\r
1187 BufferSize = sizeof (UINTN);\r
1188 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
1189 if (EFI_ERROR (Status)) {\r
1190 return FALSE;\r
1191 }\r
1192 if (Data == Width) {\r
1193 return TRUE;\r
1194 }\r
1195\r
1196 String = String + ConvertedStrLen;\r
1197 }\r
1198\r
1199 return FALSE;\r
1200}\r
1201\r
1202\r
1203/**\r
1204 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.\r
1205\r
1206 @param VariableGuid An optional field to indicate the target variable\r
1207 GUID name to use.\r
1208 @param VariableName An optional field to indicate the target\r
1209 human-readable variable name.\r
1210 @param BufferSize On input: Length in bytes of buffer to hold\r
1211 retrived data. On output: If return\r
1212 EFI_BUFFER_TOO_SMALL, containg length of buffer\r
1213 desired.\r
1214 @param Buffer Buffer to hold retrived data.\r
1215\r
1216 @retval EFI_SUCCESS Operation completes successfully.\r
1217 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.\r
1218 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
1219\r
1220**/\r
1221EFI_STATUS\r
1222EFIAPI\r
1223GetBrowserData (\r
1224 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
1225 IN CONST CHAR16 *VariableName, OPTIONAL\r
1226 IN OUT UINTN *BufferSize,\r
1227 IN OUT UINT8 *Buffer\r
1228 )\r
1229{\r
1230 EFI_STATUS Status;\r
1231 CONST CHAR16 *ConfigHdr;\r
1232 CHAR16 *ConfigResp;\r
1233 CHAR16 *StringPtr;\r
1234 UINTN HeaderLen;\r
1235 UINTN BufferLen;\r
1236 CHAR16 *Progress;\r
1237\r
1238 //\r
1239 // Locate protocols for use\r
1240 //\r
1241 Status = LocateFormBrowser2Protocols ();\r
1242 if (EFI_ERROR (Status)) {\r
1243 return Status;\r
1244 }\r
1245\r
1246 //\r
1247 // Retrive formset storage data from Form Browser\r
1248 //\r
1249 ConfigHdr = mFakeConfigHdr;\r
1250 HeaderLen = StrLen (ConfigHdr);\r
1251 \r
1252 //\r
1253 // First try allocate 0x4000 buffer for the formet storage data.\r
1254 //\r
1255 BufferLen = 0x4000;\r
1256 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
1257 if (ConfigResp == NULL) {\r
fa7b3168 1258 return EFI_OUT_OF_RESOURCES;\r
08e4b3cf 1259 }\r
1260\r
1261 StringPtr = ConfigResp + HeaderLen;\r
1262 *StringPtr = L'&';\r
1263 StringPtr++;\r
1264\r
1265 Status = mFormBrowser2->BrowserCallback (\r
1266 mFormBrowser2,\r
1267 &BufferLen,\r
1268 StringPtr,\r
1269 TRUE,\r
1270 VariableGuid,\r
1271 VariableName\r
1272 );\r
1273 if (Status == EFI_BUFFER_TOO_SMALL) {\r
fa7b3168 1274 FreePool (ConfigResp);\r
08e4b3cf 1275\r
1276 ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
1277 if (ConfigResp == NULL) {\r
1278 return EFI_OUT_OF_RESOURCES;\r
1279 }\r
1280\r
1281 StringPtr = ConfigResp + HeaderLen;\r
1282 *StringPtr = L'&';\r
1283 StringPtr++;\r
1284\r
1285 Status = mFormBrowser2->BrowserCallback (\r
1286 mFormBrowser2,\r
1287 &BufferLen,\r
1288 StringPtr,\r
1289 TRUE,\r
1290 VariableGuid,\r
1291 VariableName\r
1292 );\r
1293 }\r
1294 if (EFI_ERROR (Status)) {\r
1295 FreePool (ConfigResp);\r
1296 return Status;\r
1297 }\r
1298 CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));\r
1299\r
1300 //\r
1301 // Convert <ConfigResp> to buffer data\r
1302 //\r
1303 Status = mIfrSupportLibHiiConfigRouting->ConfigToBlock (\r
1304 mIfrSupportLibHiiConfigRouting,\r
1305 ConfigResp,\r
1306 Buffer,\r
1307 BufferSize,\r
1308 &Progress\r
1309 );\r
1310 FreePool (ConfigResp);\r
1311\r
1312 return Status;\r
1313}\r
1314\r
1315\r
1316/**\r
1317 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.\r
1318\r
1319 @param VariableGuid An optional field to indicate the target variable\r
1320 GUID name to use.\r
1321 @param VariableName An optional field to indicate the target\r
1322 human-readable variable name.\r
1323 @param BufferSize Length in bytes of buffer to hold retrived data.\r
1324 @param Buffer Buffer to hold retrived data.\r
1325 @param RequestElement An optional field to specify which part of the\r
1326 buffer data will be send back to Browser. If NULL,\r
1327 the whole buffer of data will be committed to\r
1328 Browser. <RequestElement> ::=\r
1329 &OFFSET=<Number>&WIDTH=<Number>*\r
1330\r
1331 @retval EFI_SUCCESS Operation completes successfully.\r
1332 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
1333 @retval Other Updating Browser uncommitted data failed.\r
1334\r
1335**/\r
1336EFI_STATUS\r
1337EFIAPI\r
1338SetBrowserData (\r
1339 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
1340 IN CONST CHAR16 *VariableName, OPTIONAL\r
1341 IN UINTN BufferSize,\r
1342 IN CONST UINT8 *Buffer,\r
1343 IN CONST CHAR16 *RequestElement OPTIONAL\r
1344 )\r
1345{\r
1346 EFI_STATUS Status;\r
1347 CONST CHAR16 *ConfigHdr;\r
1348 CHAR16 *ConfigResp;\r
1349 CHAR16 *StringPtr;\r
1350 UINTN HeaderLen;\r
1351 UINTN BufferLen;\r
1352 CHAR16 *Progress;\r
1353 CHAR16 BlockName[33];\r
1354 CHAR16 *ConfigRequest;\r
1355 CONST CHAR16 *Request;\r
1356\r
1357 //\r
1358 // Locate protocols for use\r
1359 //\r
1360 Status = LocateFormBrowser2Protocols ();\r
1361 if (EFI_ERROR (Status)) {\r
1362 return Status;\r
1363 }\r
1364\r
1365 //\r
1366 // Prepare <ConfigRequest>\r
1367 //\r
1368 ConfigHdr = mFakeConfigHdr;\r
1369 HeaderLen = StrLen (ConfigHdr);\r
1370\r
1371 if (RequestElement == NULL) {\r
1372 //\r
1373 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>\r
1374 //\r
1375 BlockName[0] = L'\0';\r
1376 StrCpy (BlockName, L"&OFFSET=0&WIDTH=");\r
1377\r
1378 //\r
1379 // String lenghth of L"&OFFSET=0&WIDTH=" is 16\r
1380 //\r
1381 StringPtr = BlockName + 16;\r
1382 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));\r
1383 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));\r
1384\r
1385 Request = BlockName;\r
1386 } else {\r
1387 Request = RequestElement;\r
1388 }\r
1389\r
1390 BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);\r
1391 ConfigRequest = AllocateZeroPool (BufferLen);\r
1392 if (ConfigRequest == NULL) {\r
1393 return EFI_OUT_OF_RESOURCES;\r
1394 }\r
1395\r
1396 CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));\r
1397 StringPtr = ConfigRequest + HeaderLen;\r
1398 StrCpy (StringPtr, Request);\r
1399\r
1400 //\r
1401 // Convert buffer to <ConfigResp>\r
1402 //\r
1403 Status = mIfrSupportLibHiiConfigRouting->BlockToConfig (\r
1404 mIfrSupportLibHiiConfigRouting,\r
1405 ConfigRequest,\r
1406 Buffer,\r
1407 BufferSize,\r
1408 &ConfigResp,\r
1409 &Progress\r
1410 );\r
1411 if (EFI_ERROR (Status)) {\r
1412 FreePool (ConfigRequest);\r
1413 return Status;\r
1414 }\r
1415\r
1416 //\r
1417 // Skip <ConfigHdr> and '&'\r
1418 //\r
1419 StringPtr = ConfigResp + HeaderLen + 1;\r
1420\r
1421 //\r
1422 // Change uncommitted data in Browser\r
1423 //\r
1424 Status = mFormBrowser2->BrowserCallback (\r
1425 mFormBrowser2,\r
1426 &BufferSize,\r
1427 StringPtr,\r
1428 FALSE,\r
1429 VariableGuid,\r
1430 VariableName\r
1431 );\r
1432 FreePool (ConfigRequest);\r
1433 return Status;\r
1434}\r
ac7e320c
LG
1435\r
1436/**\r
1437 Test if a Unicode character is a hexadecimal digit. If true, the input\r
1438 Unicode character is converted to a byte. \r
1439\r
1440 This function tests if a Unicode character is a hexadecimal digit. If true, the input\r
1441 Unicode character is converted to a byte. For example, Unicode character\r
1442 L'A' will be converted to 0x0A. \r
1443\r
1444 If Digit is NULL, then ASSERT.\r
1445\r
1446 @param Digit The output hexadecimal digit.\r
1447\r
1448 @param Char The input Unicode character.\r
1449\r
1450 @retval TRUE Char is in the range of Hexadecimal number. Digit is updated\r
1451 to the byte value of the number.\r
1452 @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep\r
1453 intact.\r
1454\r
1455**/\r
1456BOOLEAN\r
1457EFIAPI\r
1458IsHexDigit (\r
1459 OUT UINT8 *Digit,\r
1460 IN CHAR16 Char\r
1461 )\r
1462{\r
1463 ASSERT (Digit != NULL);\r
1464 \r
1465 if ((Char >= L'0') && (Char <= L'9')) {\r
1466 *Digit = (UINT8) (Char - L'0');\r
1467 return TRUE;\r
1468 }\r
1469\r
1470 if ((Char >= L'A') && (Char <= L'F')) {\r
1471 *Digit = (UINT8) (Char - L'A' + 0x0A);\r
1472 return TRUE;\r
1473 }\r
1474\r
1475 if ((Char >= L'a') && (Char <= L'f')) {\r
1476 *Digit = (UINT8) (Char - L'a' + 0x0A);\r
1477 return TRUE;\r
1478 }\r
1479\r
1480 return FALSE;\r
1481}\r
1482\r
1483/** \r
1484 Convert binary buffer to a Unicode String in a specified sequence. \r
1485\r
1486 This function converts bytes in the memory block pointed by Buffer to a Unicode String Str. \r
1487 Each byte will be represented by two Unicode characters. For example, byte 0xA1 will \r
1488 be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character \r
1489 for the Most Significant Nibble will be put before the Unicode Character for the Least Significant\r
1490 Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1". \r
1491 For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the \r
1492 the last character in the output string. The one next to first byte will be put into the\r
1493 character before the last character. This rules applies to the rest of the bytes. The Unicode\r
1494 character by the last byte will be put into the first character in the output string. For example,\r
1495 the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to\r
1496 a Unicode string equal to L"12345678abcdef1234".\r
1497\r
1498 @param String On input, String is pointed to the buffer allocated for the convertion.\r
1499 @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.\r
1500 The StringLen required to convert a N bytes Buffer will be a least equal to or greater \r
1501 than 2*N + 1.\r
1502 @param Buffer The pointer to a input buffer.\r
1503 @param BufferSizeInBytes Length in bytes of the input buffer.\r
1504\r
1505\r
1506 @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding\r
1507 Unicode character and placed into the right place in String.\r
1508 @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to\r
1509 complete the convertion. \r
1510**/\r
1511RETURN_STATUS\r
1512EFIAPI\r
1513BufToHexString (\r
1514 IN OUT CHAR16 *String,\r
1515 IN OUT UINTN *StringLen,\r
1516 IN CONST UINT8 *Buffer,\r
1517 IN UINTN BufferSizeInBytes\r
1518 )\r
1519{\r
1520 UINTN Idx;\r
1521 UINT8 Byte;\r
1522 UINTN StrLen;\r
1523\r
1524 //\r
1525 // Make sure string is either passed or allocate enough.\r
1526 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
1527 // Plus the Unicode termination character.\r
1528 //\r
1529 StrLen = BufferSizeInBytes * 2;\r
1530 if (StrLen > ((*StringLen) - 1)) {\r
1531 *StringLen = StrLen + 1;\r
1532 return RETURN_BUFFER_TOO_SMALL;\r
1533 }\r
1534\r
1535 *StringLen = StrLen + 1;\r
1536 //\r
1537 // Ends the string.\r
1538 //\r
1539 String[StrLen] = L'\0'; \r
1540\r
1541 for (Idx = 0; Idx < BufferSizeInBytes; Idx++) {\r
1542 Byte = Buffer[Idx];\r
1543 String[StrLen - 1 - Idx * 2] = mIfrSupportLibHexStr [Byte & 0xF];\r
1544 String[StrLen - 2 - Idx * 2] = mIfrSupportLibHexStr [Byte >> 4];\r
1545 }\r
1546\r
1547 return RETURN_SUCCESS;\r
1548}\r
1549\r
1550\r
1551/**\r
1552 Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.\r
1553\r
1554 This function converts a Unicode string consisting of characters in the range of Hexadecimal\r
1555 character (L'0' to L'9', L'A' to L'F' and L'a' to L'f') to a output byte buffer. The function will stop\r
1556 at the first non-hexadecimal character or the NULL character. The convertion process can be\r
1557 simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be \r
1558 converted into one byte. The first Unicode character represents the Most Significant Nibble and the\r
1559 second Unicode character represents the Least Significant Nibble in the output byte. \r
1560 The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode \r
1561 characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes. \r
1562 The last pair represent the first byte in the output buffer. \r
1563\r
1564 For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes \r
1565 (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".\r
1566\r
1567 If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least \r
1568 N/2 (if N is even) or (N+1)/2 (if N if odd) bytes. \r
1569\r
4a1102c9 1570 If either Buffer, BufferSizeInBytes or String is NULL, then ASSERT ().\r
1571\r
ac7e320c
LG
1572 @param Buffer The output buffer allocated by the caller.\r
1573 @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to \r
1574 contain the size of the Buffer which is actually used for the converstion.\r
1575 For Unicode string with 2*N hexadecimal characters (not including the \r
1576 tailing NULL character), N bytes of Buffer will be used for the output.\r
1577 @param String The input hexadecimal string.\r
1578 @param ConvertedStrLen The number of hexadecimal characters used to produce content in output\r
1579 buffer Buffer.\r
1580\r
1581 @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes\r
1582 will be updated to the size required for the converstion.\r
1583 @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String\r
1584 is hexadecimal. If ConvertedStrLen is not NULL, it is updated\r
1585 to the number of hexadecimal character used for the converstion.\r
1586**/\r
1587RETURN_STATUS\r
1588EFIAPI\r
1589HexStringToBuf (\r
1590 OUT UINT8 *Buffer, \r
1591 IN OUT UINTN *BufferSizeInBytes,\r
1592 IN CONST CHAR16 *String,\r
1593 OUT UINTN *ConvertedStrLen OPTIONAL\r
1594 )\r
1595{\r
1596 UINTN HexCnt;\r
1597 UINTN Idx;\r
1598 UINTN BufferLength;\r
1599 UINT8 Digit;\r
1600 UINT8 Byte;\r
1601\r
4a1102c9 1602 ASSERT (Buffer != NULL);\r
1603 ASSERT (BufferSizeInBytes != NULL);\r
1604 ASSERT (String != NULL);\r
1605\r
ac7e320c
LG
1606 //\r
1607 // Find out how many hex characters the string has.\r
1608 //\r
1609 for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, String[Idx]); Idx++, HexCnt++);\r
1610\r
1611 if (HexCnt == 0) {\r
1612 *ConvertedStrLen = 0;\r
1613 return RETURN_SUCCESS;\r
1614 }\r
1615 //\r
1616 // Two Unicode characters make up 1 buffer byte. Round up.\r
1617 //\r
1618 BufferLength = (HexCnt + 1) / 2; \r
1619\r
1620 //\r
1621 // Test if buffer is passed enough.\r
1622 //\r
1623 if (BufferLength > (*BufferSizeInBytes)) {\r
1624 *BufferSizeInBytes = BufferLength;\r
1625 return RETURN_BUFFER_TOO_SMALL;\r
1626 }\r
1627\r
1628 *BufferSizeInBytes = BufferLength;\r
1629\r
1630 for (Idx = 0; Idx < HexCnt; Idx++) {\r
1631\r
1632 IsHexDigit (&Digit, String[HexCnt - 1 - Idx]);\r
1633\r
1634 //\r
1635 // For odd charaters, write the lower nibble for each buffer byte,\r
1636 // and for even characters, the upper nibble.\r
1637 //\r
1638 if ((Idx & 1) == 0) {\r
1639 Byte = Digit;\r
1640 } else {\r
1641 Byte = Buffer[Idx / 2];\r
1642 Byte &= 0x0F;\r
1643 Byte = (UINT8) (Byte | Digit << 4);\r
1644 }\r
1645\r
1646 Buffer[Idx / 2] = Byte;\r
1647 }\r
1648\r
1649 if (ConvertedStrLen != NULL) {\r
1650 *ConvertedStrLen = HexCnt;\r
1651 }\r
1652\r
1653 return RETURN_SUCCESS;\r
1654}\r