]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrForm.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / UefiEfiIfrSupportLib / UefiIfrForm.c
CommitLineData
c7f33ca4 1/*++\r
2\r
4ea9375a
HT
3Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
c7f33ca4 5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 UefiIfrForm.c\r
15\r
16Abstract:\r
17\r
18 Common Library Routines to assist handle HII elements.\r
19\r
20--*/\r
21\r
22#include "UefiIfrLibrary.h"\r
23\r
24//\r
25// Fake <ConfigHdr>\r
26//\r
27UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
28\r
29STATIC\r
30EFI_STATUS\r
31GetPackageDataFromPackageList (\r
32 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
33 IN UINT32 PackageIndex,\r
34 OUT UINT32 *BufferLen,\r
35 OUT EFI_HII_PACKAGE_HEADER **Buffer\r
36 )\r
37{\r
38 UINT32 Index;\r
39 EFI_HII_PACKAGE_HEADER *Package;\r
40 UINT32 Offset;\r
41 UINT32 PackageListLength;\r
42 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};\r
43\r
44 ASSERT(HiiPackageList != NULL);\r
45\r
46 if ((BufferLen == NULL) || (Buffer == NULL)) {\r
47 return EFI_INVALID_PARAMETER;\r
48 }\r
49\r
50 Package = NULL;\r
51 Index = 0;\r
52 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
53 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
54 while (Offset < PackageListLength) {\r
55 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
56 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
57 if (Index == PackageIndex) {\r
58 break;\r
59 }\r
60 Offset += PackageHeader.Length;\r
61 Index++;\r
62 }\r
63 if (Offset >= PackageListLength) {\r
64 //\r
65 // no package found in this Package List\r
66 //\r
67 return EFI_NOT_FOUND;\r
68 }\r
69\r
70 *BufferLen = PackageHeader.Length;\r
71 *Buffer = Package;\r
72 return EFI_SUCCESS;\r
73}\r
74\r
75STATIC\r
76EFI_STATUS\r
77UpdateFormPackageData (\r
78 IN EFI_GUID *FormSetGuid,\r
79 IN EFI_FORM_ID FormId,\r
80 IN EFI_HII_PACKAGE_HEADER *Package,\r
81 IN UINT32 PackageLength,\r
82 IN UINT16 Label,\r
83 IN BOOLEAN Insert,\r
84 IN EFI_HII_UPDATE_DATA *Data,\r
85 OUT UINT8 **TempBuffer,\r
86 OUT UINT32 *TempBufferSize\r
87 )\r
88{\r
89 UINTN AddSize;\r
90 UINT8 *BufferPos;\r
91 EFI_HII_PACKAGE_HEADER PackageHeader;\r
92 UINTN Offset;\r
93 EFI_IFR_OP_HEADER *IfrOpHdr;\r
94 BOOLEAN GetFormSet;\r
95 BOOLEAN GetForm;\r
96 UINT8 ExtendOpCode;\r
97 UINT16 LabelNumber;\r
98 BOOLEAN Updated;\r
99 EFI_IFR_OP_HEADER *AddOpCode;\r
100\r
101 if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {\r
102 return EFI_INVALID_PARAMETER;\r
103 }\r
104\r
105 *TempBufferSize = PackageLength;\r
106 if (Data != NULL) {\r
107 *TempBufferSize += Data->Offset;\r
108 }\r
109 *TempBuffer = EfiLibAllocateZeroPool (*TempBufferSize);\r
110 if (*TempBuffer == NULL) {\r
111 return EFI_OUT_OF_RESOURCES;\r
112 }\r
113\r
114 EfiCopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
115 *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);\r
116 BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
117\r
118 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
119 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
120 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
4cb43192 121 GetFormSet = (BOOLEAN)((FormSetGuid == NULL) ? TRUE : FALSE);\r
c7f33ca4 122 GetForm = FALSE;\r
123 Updated = FALSE;\r
124\r
125 while (Offset < PackageHeader.Length) {\r
126 EfiCopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
127 BufferPos += IfrOpHdr->Length;\r
128 *TempBufferSize += IfrOpHdr->Length;\r
129\r
130 switch (IfrOpHdr->OpCode) {\r
131 case EFI_IFR_FORM_SET_OP :\r
132 if (FormSetGuid != NULL) {\r
133 if (EfiCompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {\r
134 GetFormSet = TRUE;\r
135 }\r
136 }\r
137 break;\r
138\r
139 case EFI_IFR_FORM_OP:\r
140 if (EfiCompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
141 GetForm = TRUE;\r
142 }\r
143 break;\r
144\r
145 case EFI_IFR_GUID_OP :\r
146 if (!GetFormSet || !GetForm || Updated) {\r
147 //\r
148 // Go to the next Op-Code\r
149 //\r
150 Offset += IfrOpHdr->Length;\r
151 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
152 continue;\r
153 }\r
154\r
155 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
156 EfiCopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));\r
157 if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {\r
158 //\r
159 // Go to the next Op-Code\r
160 //\r
161 Offset += IfrOpHdr->Length;\r
162 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
163 continue;\r
164 }\r
165\r
166 if (Insert && (Data != NULL)) {\r
167 //\r
168 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove\r
169 // DataCount amount of opcodes unless runing into a label.\r
170 //\r
171 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;\r
172 AddSize = 0;\r
173 while (AddSize < Data->Offset) {\r
174 EfiCopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
175 BufferPos += AddOpCode->Length;\r
176 *TempBufferSize += AddOpCode->Length;\r
177\r
178 AddSize += AddOpCode->Length;\r
179 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);\r
180 }\r
181 } else {\r
182 //\r
183 // Search the next Label.\r
184 //\r
185 while (TRUE) {\r
186 Offset += IfrOpHdr->Length;\r
187 //\r
188 // Search the next label and Fail if not label found.\r
189 //\r
190 if (Offset >= PackageHeader.Length) {\r
191 goto Fail;\r
192 }\r
193 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
194 if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {\r
195 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
196 if (ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {\r
197 break;\r
198 }\r
199 }\r
200 }\r
201\r
202 if (Data != NULL) {\r
203 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;\r
204 AddSize = 0;\r
205 while (AddSize < Data->Offset) {\r
206 EfiCopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
207 BufferPos += AddOpCode->Length;\r
208 *TempBufferSize += AddOpCode->Length;\r
209\r
210 AddSize += AddOpCode->Length;\r
211 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);\r
212 }\r
213 }\r
214\r
215 //\r
216 // copy the next label\r
217 //\r
218 EfiCopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
219 BufferPos += IfrOpHdr->Length;\r
220 *TempBufferSize += IfrOpHdr->Length;\r
221 }\r
222\r
223 Updated = TRUE;\r
224 break;\r
225 default :\r
226 break;\r
227 }\r
228\r
229 //\r
230 // Go to the next Op-Code\r
231 //\r
232 Offset += IfrOpHdr->Length;\r
233 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
234 }\r
235\r
236 //\r
237 // Update the package length.\r
238 //\r
239 PackageHeader.Length = *TempBufferSize;\r
240 EfiCopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
241\r
242Fail:\r
243 if (!Updated) {\r
244 gBS->FreePool (*TempBuffer);\r
245 *TempBufferSize = 0;\r
246 return EFI_NOT_FOUND;\r
247 }\r
248\r
249 return EFI_SUCCESS;\r
250}\r
251\r
252EFI_STATUS\r
253IfrLibUpdateForm (\r
254 IN EFI_HII_HANDLE Handle,\r
255 IN EFI_GUID *FormSetGuid, OPTIONAL\r
256 IN EFI_FORM_ID FormId,\r
257 IN UINT16 Label,\r
258 IN BOOLEAN Insert,\r
259 IN EFI_HII_UPDATE_DATA *Data\r
260 )\r
261/*++\r
262\r
263Routine Description:\r
264 This function allows the caller to update a form that has\r
265 previously been registered with the EFI HII database.\r
266\r
267Arguments:\r
268 Handle - Hii Handle\r
269 FormSetGuid - The formset should be updated.\r
270 FormId - The form should be updated.\r
271 Label - Update information starting immediately after this label in the IFR\r
272 Insert - If TRUE and Data is not NULL, insert data after Label.\r
273 If FALSE, replace opcodes between two labels with Data\r
274 Data - The adding data; If NULL, remove opcodes between two Label.\r
275\r
276Returns:\r
277 EFI_SUCCESS - Update success.\r
278 Other - Update fail.\r
279\r
280--*/\r
281{\r
282 EFI_STATUS Status;\r
283 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
284 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
285 UINT32 Index;\r
286 EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;\r
287 UINTN BufferSize;\r
288 UINT8 *UpdateBufferPos;\r
289 EFI_HII_PACKAGE_HEADER PackageHeader;\r
290 EFI_HII_PACKAGE_HEADER *Package;\r
291 UINT32 PackageLength;\r
292 EFI_HII_PACKAGE_HEADER *TempBuffer;\r
293 UINT32 TempBufferSize;\r
294 BOOLEAN Updated;\r
295\r
296 if (Data == NULL) {\r
297 return EFI_INVALID_PARAMETER;\r
298 }\r
299\r
300 LocateHiiProtocols ();\r
301 HiiDatabase = gIfrLibHiiDatabase;\r
302\r
303 //\r
304 // Get the orginal package list\r
305 //\r
306 BufferSize = 0;\r
307 HiiPackageList = NULL;\r
308 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
309 if (Status == EFI_BUFFER_TOO_SMALL) {\r
310 HiiPackageList = EfiLibAllocatePool (BufferSize);\r
311 ASSERT (HiiPackageList != NULL);\r
312\r
313 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
314 if (EFI_ERROR (Status)) {\r
315 gBS->FreePool (HiiPackageList);\r
316 return Status;\r
317 }\r
318 }\r
319\r
320 //\r
321 // Calculate and allocate space for retrieval of IFR data\r
322 //\r
323 BufferSize += Data->Offset;\r
324 UpdateBuffer = EfiLibAllocateZeroPool (BufferSize);\r
325 if (UpdateBuffer == NULL) {\r
326 return EFI_OUT_OF_RESOURCES;\r
327 }\r
328\r
329 UpdateBufferPos = (UINT8 *) UpdateBuffer;\r
330\r
331 //\r
332 // copy the package list header\r
333 //\r
334 EfiCopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
335 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
336\r
337 Updated = FALSE;\r
338 for (Index = 0; ; Index++) {\r
339 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);\r
340 if (Status == EFI_SUCCESS) {\r
341 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
342 if ((PackageHeader.Type == EFI_HII_PACKAGE_FORM) && !Updated) {\r
343 Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);\r
344 if (!EFI_ERROR(Status)) {\r
345 if (FormSetGuid == NULL) {\r
346 Updated = TRUE;\r
347 }\r
348 EfiCopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);\r
349 UpdateBufferPos += TempBufferSize;\r
350 gBS->FreePool (TempBuffer);\r
351 continue;\r
352 }\r
353 }\r
354\r
355 EfiCopyMem (UpdateBufferPos, Package, PackageLength);\r
356 UpdateBufferPos += PackageLength;\r
357 } else if (Status == EFI_NOT_FOUND) {\r
358 break;\r
359 } else {\r
360 gBS->FreePool (HiiPackageList);\r
361 return Status;\r
362 }\r
363 }\r
364\r
365 //\r
366 // Update package list length\r
367 //\r
368 BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;\r
369 EfiCopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));\r
370\r
371 gBS->FreePool (HiiPackageList);\r
372\r
373 return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);\r
374}\r
375\r
376EFI_STATUS\r
377IfrLibCreatePopUp (\r
378 IN UINTN NumberOfLines,\r
379 OUT EFI_INPUT_KEY *KeyValue,\r
380 IN CHAR16 *String,\r
381 ...\r
382 )\r
383/*++\r
384\r
385Routine Description:\r
386 Draw a dialog and return the selected key.\r
387\r
388Arguments:\r
389 NumberOfLines - The number of lines for the dialog box\r
390 KeyValue - The EFI_KEY value returned if HotKey is TRUE..\r
391 String - Pointer to the first string in the list\r
392 ... - A series of (quantity == NumberOfLines) text strings which\r
393 will be used to construct the dialog box\r
394\r
395Returns:\r
396 EFI_SUCCESS - Displayed dialog and received user interaction\r
397 EFI_INVALID_PARAMETER - One of the parameters was invalid.\r
398\r
399--*/\r
400{\r
401 UINTN Index;\r
402 UINTN Count;\r
403 UINTN Start;\r
404 UINTN End;\r
405 UINTN Top;\r
406 UINTN Bottom;\r
407 CHAR16 *StringPtr;\r
408 UINTN LeftColumn;\r
409 UINTN RightColumn;\r
410 UINTN TopRow;\r
411 UINTN BottomRow;\r
412 UINTN DimensionsWidth;\r
413 UINTN DimensionsHeight;\r
414 VA_LIST Marker;\r
415 EFI_INPUT_KEY Key;\r
416 UINTN LargestString;\r
417 CHAR16 *StackString;\r
418 EFI_STATUS Status;\r
419 UINTN StringLen;\r
420 CHAR16 *LineBuffer;\r
421 CHAR16 **StringArray;\r
422 EFI_EVENT TimerEvent;\r
423 EFI_EVENT WaitList[2];\r
424 UINTN CurrentAttribute;\r
425 EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut;\r
426\r
427 if ((KeyValue == NULL) || (String == NULL)) {\r
428 return EFI_INVALID_PARAMETER;\r
429 }\r
430\r
431 TopRow = 0;\r
432 BottomRow = 0;\r
433 LeftColumn = 0;\r
434 RightColumn = 0;\r
435\r
436 ConOut = gST->ConOut;\r
437 ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);\r
438\r
439 DimensionsWidth = RightColumn - LeftColumn;\r
440 DimensionsHeight = BottomRow - TopRow;\r
441\r
442 CurrentAttribute = ConOut->Mode->Attribute;\r
443\r
444 LineBuffer = EfiLibAllocateZeroPool (DimensionsWidth * sizeof (CHAR16));\r
445 ASSERT (LineBuffer != NULL);\r
446\r
447 //\r
448 // Determine the largest string in the dialog box\r
449 // Notice we are starting with 1 since String is the first string\r
450 //\r
451 StringArray = EfiLibAllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));\r
452 LargestString = EfiStrLen (String);\r
453 StringArray[0] = String;\r
454\r
455 VA_START (Marker, String);\r
456 for (Index = 1; Index < NumberOfLines; Index++) {\r
457 StackString = VA_ARG (Marker, CHAR16 *);\r
458\r
459 if (StackString == NULL) {\r
460 return EFI_INVALID_PARAMETER;\r
461 }\r
462\r
463 StringArray[Index] = StackString;\r
464 StringLen = EfiStrLen (StackString);\r
465 if (StringLen > LargestString) {\r
466 LargestString = StringLen;\r
467 }\r
468 }\r
469\r
470 if ((LargestString + 2) > DimensionsWidth) {\r
471 LargestString = DimensionsWidth - 2;\r
472 }\r
473\r
474 //\r
475 // Subtract the PopUp width from total Columns, allow for one space extra on\r
476 // each end plus a border.\r
477 //\r
478 Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;\r
479 End = Start + LargestString + 1;\r
480\r
481 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;\r
482 Bottom = Top + NumberOfLines + 2;\r
483\r
484 //\r
485 // Disable cursor\r
486 //\r
487 ConOut->EnableCursor (ConOut, FALSE);\r
488 ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);\r
489\r
490 StringPtr = &LineBuffer[0];\r
491 *StringPtr++ = BOXDRAW_DOWN_RIGHT;\r
492 for (Index = 0; Index < LargestString; Index++) {\r
493 *StringPtr++ = BOXDRAW_HORIZONTAL;\r
494 }\r
495 *StringPtr++ = BOXDRAW_DOWN_LEFT;\r
496 *StringPtr = L'\0';\r
497\r
498 ConOut->SetCursorPosition (ConOut, Start, Top);\r
499 ConOut->OutputString (ConOut, LineBuffer);\r
500\r
501 for (Index = 0; Index < NumberOfLines; Index++) {\r
502 StringPtr = &LineBuffer[0];\r
503 *StringPtr++ = BOXDRAW_VERTICAL;\r
504\r
505 for (Count = 0; Count < LargestString; Count++) {\r
506 StringPtr[Count] = L' ';\r
507 }\r
508\r
509 StringLen = EfiStrLen (StringArray[Index]);\r
510 if (StringLen > LargestString) {\r
511 StringLen = LargestString;\r
512 }\r
513 EfiCopyMem (\r
514 StringPtr + ((LargestString - StringLen) / 2),\r
515 StringArray[Index],\r
516 StringLen * sizeof (CHAR16)\r
517 );\r
518 StringPtr += LargestString;\r
519\r
520 *StringPtr++ = BOXDRAW_VERTICAL;\r
521 *StringPtr = L'\0';\r
522\r
523 ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);\r
524 ConOut->OutputString (ConOut, LineBuffer);\r
525 }\r
526\r
527 StringPtr = &LineBuffer[0];\r
528 *StringPtr++ = BOXDRAW_UP_RIGHT;\r
529 for (Index = 0; Index < LargestString; Index++) {\r
530 *StringPtr++ = BOXDRAW_HORIZONTAL;\r
531 }\r
532 *StringPtr++ = BOXDRAW_UP_LEFT;\r
533 *StringPtr = L'\0';\r
534\r
535 ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);\r
536 ConOut->OutputString (ConOut, LineBuffer);\r
537\r
538 do {\r
539 Status = gBS->CreateEvent (EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent);\r
540\r
541 //\r
542 // Set a timer event of 1 second expiration\r
543 //\r
544 gBS->SetTimer (\r
545 TimerEvent,\r
546 TimerRelative,\r
547 10000000\r
548 );\r
549\r
550 //\r
551 // Wait for the keystroke event or the timer\r
552 //\r
553 WaitList[0] = gST->ConIn->WaitForKey;\r
554 WaitList[1] = TimerEvent;\r
555 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
556\r
557 //\r
558 // Check for the timer expiration\r
559 //\r
560 if (!EFI_ERROR (Status) && Index == 1) {\r
561 Status = EFI_TIMEOUT;\r
562 }\r
563\r
564 gBS->CloseEvent (TimerEvent);\r
565 } while (Status == EFI_TIMEOUT);\r
566\r
567 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
568 EfiCopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
569\r
570 ConOut->SetAttribute (ConOut, CurrentAttribute);\r
571 ConOut->EnableCursor (ConOut, TRUE);\r
572\r
573 return Status;\r
574}\r
575\r
576EFI_STATUS\r
577ExtractDefault(\r
578 IN VOID *Buffer,\r
579 IN UINTN *BufferSize,\r
580 UINTN Number,\r
581 ...\r
582 )\r
583/*++\r
584\r
585 Routine Description:\r
586\r
587 Configure the buffer accrording to ConfigBody strings.\r
588\r
589 Arguments:\r
590 DefaultId - the ID of default.\r
591 Buffer - the start address of buffer.\r
592 BufferSize - the size of buffer.\r
593 Number - the number of the strings.\r
594\r
595 Returns:\r
596 EFI_BUFFER_TOO_SMALL - the BufferSize is too small to operate.\r
597 EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0.\r
598 EFI_SUCCESS - Operation successful.\r
599\r
600--*/\r
601{\r
602 VA_LIST Args;\r
603 UINTN Index;\r
604 UINT32 TotalLen;\r
605 UINT8 *BufCfgArray;\r
606 UINT8 *BufferPos;\r
607 UINT16 Offset;\r
608 UINT16 Width;\r
609 UINT8 *Value;\r
610\r
611 if ((Buffer == NULL) || (BufferSize == NULL)) {\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 Offset = 0;\r
616 Width = 0;\r
617 Value = NULL;\r
618\r
619 VA_START (Args, Number);\r
620 for (Index = 0; Index < Number; Index++) {\r
621 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
622 EfiCopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));\r
623 BufferPos = BufCfgArray + sizeof (UINT32);\r
624\r
625 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
626 EfiCopyMem (&Offset, BufferPos, sizeof (UINT16));\r
627 BufferPos += sizeof (UINT16);\r
628 EfiCopyMem (&Width, BufferPos, sizeof (UINT16));\r
629 BufferPos += sizeof (UINT16);\r
630 Value = BufferPos;\r
631 BufferPos += Width;\r
632\r
633 if ((UINTN)(Offset + Width) > *BufferSize) {\r
634 return EFI_BUFFER_TOO_SMALL;\r
635 }\r
636\r
637 EfiCopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
638 }\r
639 }\r
640 VA_END (Args);\r
641\r
642 *BufferSize = (UINTN)Offset;\r
643\r
644 return EFI_SUCCESS;\r
645}\r
646\r
647STATIC\r
648VOID\r
649SwapBuffer (\r
650 IN OUT UINT8 *Buffer,\r
651 IN UINTN BufferSize\r
652 )\r
653/*++\r
654\r
655Routine Description:\r
656 Swap bytes in the buffer.\r
657\r
658Arguments:\r
659 Buffer - Binary buffer.\r
660 BufferSize - Size of the buffer in bytes.\r
661\r
662Returns:\r
663 None.\r
664\r
665--*/\r
666{\r
667 UINTN Index;\r
668 UINT8 Temp;\r
669 UINTN SwapCount;\r
670\r
671 SwapCount = (BufferSize - 1) / 2;\r
672 for (Index = 0; Index < SwapCount; Index++) {\r
673 Temp = Buffer[Index];\r
674 Buffer[Index] = Buffer[BufferSize - 1 - Index];\r
675 Buffer[BufferSize - 1 - Index] = Temp;\r
676 }\r
677}\r
678\r
679EFI_STATUS\r
680BufferToHexString (\r
681 IN OUT CHAR16 *Str,\r
682 IN UINT8 *Buffer,\r
683 IN UINTN BufferSize\r
684 )\r
685/*++\r
686\r
687Routine Description:\r
688 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().\r
689\r
690Arguments:\r
691 Str - String for output\r
692 Buffer - Binary buffer.\r
693 BufferSize - Size of the buffer in bytes.\r
694\r
695Returns:\r
696 EFI_SUCCESS - The function completed successfully.\r
697\r
698--*/\r
699{\r
700 EFI_STATUS Status;\r
701 UINT8 *NewBuffer;\r
702 UINTN StrBufferLen;\r
703\r
704 NewBuffer = EfiLibAllocateCopyPool (BufferSize, Buffer);\r
705 SwapBuffer (NewBuffer, BufferSize);\r
706\r
707 StrBufferLen = (BufferSize + 1) * sizeof (CHAR16);\r
708 Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);\r
709\r
710 gBS->FreePool (NewBuffer);\r
711\r
712 return Status;\r
713}\r
714\r
715EFI_STATUS\r
716HexStringToBuffer (\r
717 IN OUT UINT8 *Buffer,\r
718 IN OUT UINTN *BufferSize,\r
719 IN CHAR16 *Str\r
720 )\r
721/*++\r
722\r
723Routine Description:\r
724 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().\r
725\r
726Arguments:\r
727 Buffer - Pointer to buffer that receives the data.\r
728 BufferSize - Length in bytes of the buffer to hold converted data.\r
729 If routine return with EFI_SUCCESS, containing length of converted data.\r
730 If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.\r
731 Str - String to be converted from.\r
732\r
733Returns:\r
734 EFI_SUCCESS - The function completed successfully.\r
735\r
736--*/\r
737{\r
738 EFI_STATUS Status;\r
739 UINTN ConvertedStrLen;\r
740\r
741 ConvertedStrLen = 0;\r
742 Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);\r
743 if (!EFI_ERROR (Status)) {\r
744 SwapBuffer (Buffer, ConvertedStrLen);\r
745 }\r
746\r
747 return Status;\r
748}\r
749\r
750EFI_STATUS\r
751ConstructConfigHdr (\r
752 IN OUT CHAR16 *ConfigHdr,\r
753 IN OUT UINTN *StrBufferLen,\r
754 IN EFI_GUID *Guid,\r
755 IN CHAR16 *Name, OPTIONAL\r
756 IN EFI_HANDLE *DriverHandle\r
757 )\r
758/*++\r
759\r
760Routine Description:\r
761 Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
762\r
763Arguments:\r
764 ConfigHdr - Pointer to the ConfigHdr string.\r
765 StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string.\r
766 Includes tailing '\0' character.\r
767 On output:\r
768 If return EFI_SUCCESS, containing length of ConfigHdr string buffer.\r
769 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
770 Guid - Routing information: GUID.\r
771 Name - Routing information: NAME.\r
772 DriverHandle - Driver handle which contains the routing information: PATH.\r
773\r
774Returns:\r
775 EFI_SUCCESS - Routine success.\r
776 EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small.\r
777\r
778--*/\r
779{\r
780 EFI_STATUS Status;\r
781 UINTN NameStrLen;\r
782 UINTN DevicePathSize;\r
783 UINTN BufferSize;\r
784 CHAR16 *StrPtr;\r
785 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
786\r
787 if (Name == NULL) {\r
788 //\r
789 // There will be no "NAME" in <ConfigHdr> for Name/Value storage\r
790 //\r
791 NameStrLen = 0;\r
792 } else {\r
793 //\r
794 // For buffer storage\r
795 //\r
796 NameStrLen = EfiStrLen (Name);\r
797 }\r
798\r
799 //\r
800 // Retrieve DevicePath Protocol associated with this HiiPackageList\r
801 //\r
802 Status = gBS->HandleProtocol (\r
803 DriverHandle,\r
804 &gEfiDevicePathProtocolGuid,\r
57d40fe2 805 (VOID **) &DevicePath\r
c7f33ca4 806 );\r
807 if (EFI_ERROR (Status)) {\r
808 return Status;\r
809 }\r
810\r
811 DevicePathSize = EfiDevicePathSize (DevicePath);\r
812\r
813 //\r
814 // GUID=<HexCh>32&NAME=<Alpha>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
815 // | 5 | 32 | 6 | NameStrLen | 6 | DevicePathStrLen |\r
816 //\r
817 BufferSize = (5 + 32 + 6 + NameStrLen + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);\r
818 if (*StrBufferLen < BufferSize) {\r
819 *StrBufferLen = BufferSize;\r
820 return EFI_BUFFER_TOO_SMALL;\r
821 }\r
822\r
823 *StrBufferLen = BufferSize;\r
824\r
825 StrPtr = ConfigHdr;\r
826\r
827 EfiStrCpy (StrPtr, L"GUID=");\r
828 StrPtr += 5;\r
829 BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));\r
830 StrPtr += 32;\r
831\r
832 EfiStrCpy (StrPtr, L"&NAME=");\r
833 StrPtr += 6;\r
834 if (Name != NULL) {\r
835 EfiStrCpy (StrPtr, Name);\r
836 StrPtr += NameStrLen;\r
837 }\r
838\r
839 EfiStrCpy (StrPtr, L"&PATH=");\r
840 StrPtr += 6;\r
841 BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);\r
842\r
843 return EFI_SUCCESS;\r
844}\r
845\r
846BOOLEAN\r
847FindBlockName (\r
848 IN OUT CHAR16 *String,\r
849 UINTN Offset,\r
850 UINTN Width\r
851 )\r
852/*++\r
853\r
854Routine Description:\r
855 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
856\r
857Arguments:\r
858 String - The string to be searched in.\r
859 Offset - Offset in BlockName.\r
860 Width - Width in BlockName.\r
861\r
862Returns:\r
863 TRUE - Block name found.\r
864 FALSE - Block name not found.\r
865\r
866--*/\r
867{\r
868 EFI_STATUS Status;\r
869 UINTN Data;\r
870 UINTN BufferSize;\r
871 UINTN ConvertedStrLen;\r
872\r
873 while ((String = EfiStrStr (String, L"&OFFSET=")) != NULL) {\r
874 //\r
875 // Skip '&OFFSET='\r
876 //\r
877 String = String + 8;\r
878\r
879 Data = 0;\r
880 BufferSize = sizeof (UINTN);\r
881 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
882 if (EFI_ERROR (Status)) {\r
883 return FALSE;\r
884 }\r
885 String = String + ConvertedStrLen;\r
886\r
887 if (Data != Offset) {\r
888 continue;\r
889 }\r
890\r
891 if (EfiStrnCmp (String, L"&WIDTH=", 7) != 0) {\r
892 return FALSE;\r
893 }\r
894 String = String + 7;\r
895\r
896 Data = 0;\r
897 BufferSize = sizeof (UINTN);\r
898 Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
899 if (EFI_ERROR (Status)) {\r
900 return FALSE;\r
901 }\r
902 if (Data == Width) {\r
903 return TRUE;\r
904 }\r
905\r
906 String = String + ConvertedStrLen;\r
907 }\r
908\r
909 return FALSE;\r
910}\r
911\r
912EFI_STATUS\r
913GetBrowserData (\r
914 EFI_GUID *VariableGuid, OPTIONAL\r
915 CHAR16 *VariableName, OPTIONAL\r
916 UINTN *BufferSize,\r
917 UINT8 *Buffer\r
918 )\r
919/*++\r
920\r
921Routine Description:\r
922 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.\r
923\r
924Arguments:\r
925 VariableGuid - An optional field to indicate the target variable GUID name to use.\r
926 VariableName - An optional field to indicate the target human-readable variable name.\r
927 BufferSize - On input: Length in bytes of buffer to hold retrived data.\r
928 On output:\r
929 If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired.\r
930 Buffer - Buffer to hold retrived data.\r
931\r
932Returns:\r
933 EFI_SUCCESS - Routine success.\r
934 EFI_BUFFER_TOO_SMALL - The intput buffer is too small.\r
935\r
936--*/\r
937{\r
938 EFI_STATUS Status;\r
939 CHAR16 *ConfigHdr;\r
940 CHAR16 *ConfigResp;\r
941 CHAR16 *StringPtr;\r
942 UINTN HeaderLen;\r
943 UINTN BufferLen;\r
944 CHAR16 *Progress;\r
945 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
946 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
947\r
948 //\r
949 // Locate protocols for use\r
950 //\r
57d40fe2 951 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
c7f33ca4 952 if (EFI_ERROR (Status)) {\r
953 return Status;\r
954 }\r
955\r
57d40fe2 956 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
c7f33ca4 957 if (EFI_ERROR (Status)) {\r
958 return Status;\r
959 }\r
960\r
961 //\r
962 // Retrive formset storage data from Form Browser\r
963 //\r
964 ConfigHdr = mFakeConfigHdr;\r
965 HeaderLen = EfiStrLen (ConfigHdr);\r
966\r
967 BufferLen = 0x4000;\r
968 ConfigResp = EfiLibAllocateZeroPool (BufferLen + HeaderLen);\r
969\r
970 StringPtr = ConfigResp + HeaderLen;\r
971 *StringPtr = L'&';\r
972 StringPtr++;\r
973\r
974 Status = FormBrowser2->BrowserCallback (\r
975 FormBrowser2,\r
976 &BufferLen,\r
977 StringPtr,\r
978 TRUE,\r
979 VariableGuid,\r
980 VariableName\r
981 );\r
982 if (Status == EFI_BUFFER_TOO_SMALL) {\r
983 gBS->FreePool (ConfigResp);\r
984 ConfigResp = EfiLibAllocateZeroPool (BufferLen + HeaderLen);\r
985\r
986 StringPtr = ConfigResp + HeaderLen;\r
987 *StringPtr = L'&';\r
988 StringPtr++;\r
989\r
990 Status = FormBrowser2->BrowserCallback (\r
991 FormBrowser2,\r
992 &BufferLen,\r
993 StringPtr,\r
994 TRUE,\r
995 VariableGuid,\r
996 VariableName\r
997 );\r
998 }\r
999 if (EFI_ERROR (Status)) {\r
1000 gBS->FreePool (ConfigResp);\r
1001 return Status;\r
1002 }\r
1003 EfiCopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));\r
1004\r
1005 //\r
1006 // Convert <ConfigResp> to buffer data\r
1007 //\r
1008 Status = HiiConfigRouting->ConfigToBlock (\r
1009 HiiConfigRouting,\r
1010 ConfigResp,\r
1011 Buffer,\r
1012 BufferSize,\r
1013 &Progress\r
1014 );\r
1015 gBS->FreePool (ConfigResp);\r
1016\r
1017 return Status;\r
1018}\r
1019\r
1020EFI_STATUS\r
1021SetBrowserData (\r
1022 EFI_GUID *VariableGuid, OPTIONAL\r
1023 CHAR16 *VariableName, OPTIONAL\r
1024 UINTN BufferSize,\r
1025 UINT8 *Buffer,\r
1026 CHAR16 *RequestElement OPTIONAL\r
1027 )\r
1028/*++\r
1029\r
1030Routine Description:\r
1031 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.\r
1032\r
1033Arguments:\r
1034 VariableGuid - An optional field to indicate the target variable GUID name to use.\r
1035 VariableName - An optional field to indicate the target human-readable variable name.\r
1036 BufferSize - Length in bytes of buffer to hold retrived data.\r
1037 Buffer - Buffer to hold retrived data.\r
1038 RequestElement - An optional field to specify which part of the buffer data\r
1039 will be send back to Browser. If NULL, the whole buffer of\r
1040 data will be committed to Browser.\r
1041 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
1042\r
1043Returns:\r
1044 EFI_SUCCESS - Routine success.\r
1045 Other - Updating Browser uncommitted data failed.\r
1046\r
1047--*/\r
1048{\r
1049 EFI_STATUS Status;\r
1050 CHAR16 *ConfigHdr;\r
1051 CHAR16 *ConfigResp;\r
1052 CHAR16 *StringPtr;\r
1053 UINTN HeaderLen;\r
1054 UINTN BufferLen;\r
1055 CHAR16 *Progress;\r
1056 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
1057 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
1058 CHAR16 BlockName[33];\r
1059 CHAR16 *ConfigRequest;\r
1060 CHAR16 *Request;\r
1061\r
1062 //\r
1063 // Locate protocols for use\r
1064 //\r
57d40fe2 1065 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
c7f33ca4 1066 if (EFI_ERROR (Status)) {\r
1067 return Status;\r
1068 }\r
1069\r
57d40fe2 1070 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
c7f33ca4 1071 if (EFI_ERROR (Status)) {\r
1072 return Status;\r
1073 }\r
1074\r
1075 //\r
1076 // Prepare <ConfigRequest>\r
1077 //\r
1078 ConfigHdr = mFakeConfigHdr;\r
1079 HeaderLen = EfiStrLen (ConfigHdr);\r
1080\r
1081 if (RequestElement == NULL) {\r
1082 //\r
1083 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>\r
1084 //\r
1085 BlockName[0] = L'\0';\r
1086 EfiStrCpy (BlockName, L"&OFFSET=0&WIDTH=");\r
1087\r
1088 //\r
1089 // String lenghth of L"&OFFSET=0&WIDTH=" is 16\r
1090 //\r
1091 StringPtr = BlockName + 16;\r
1092 BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));\r
1093 BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));\r
1094\r
1095 Request = BlockName;\r
1096 } else {\r
1097 Request = RequestElement;\r
1098 }\r
1099\r
1100 BufferLen = HeaderLen * sizeof (CHAR16) + EfiStrSize (Request);\r
1101 ConfigRequest = EfiLibAllocateZeroPool (BufferLen);\r
1102\r
1103 EfiCopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));\r
1104 StringPtr = ConfigRequest + HeaderLen;\r
1105 EfiStrCpy (StringPtr, Request);\r
1106\r
1107 //\r
1108 // Convert buffer to <ConfigResp>\r
1109 //\r
1110 Status = HiiConfigRouting->BlockToConfig (\r
1111 HiiConfigRouting,\r
1112 ConfigRequest,\r
1113 Buffer,\r
1114 BufferSize,\r
1115 &ConfigResp,\r
1116 &Progress\r
1117 );\r
1118 if (EFI_ERROR (Status)) {\r
1119 gBS->FreePool (ConfigResp);\r
1120 return Status;\r
1121 }\r
1122\r
1123 //\r
1124 // Skip <ConfigHdr> and '&'\r
1125 //\r
1126 StringPtr = ConfigResp + HeaderLen + 1;\r
1127\r
1128 //\r
1129 // Change uncommitted data in Browser\r
1130 //\r
1131 Status = FormBrowser2->BrowserCallback (\r
1132 FormBrowser2,\r
1133 &BufferSize,\r
1134 StringPtr,\r
1135 FALSE,\r
1136 NULL,\r
1137 NULL\r
1138 );\r
1139 gBS->FreePool (ConfigResp);\r
1140 return Status;\r
1141}\r