]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c
Fix the issue of Wide char help strings cannot break into multiple lines correctly
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / HiiDataBase / Dxe / Forms.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
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 Forms.c\r
15\r
16Abstract:\r
17\r
18 This file contains the form processing code to the HII database.\r
19\r
20--*/\r
21\r
22\r
23#include "HiiDatabase.h"\r
24\r
1cc8ee78 25STATIC\r
878ddf1f 26CHAR16*\r
27Ascii2Unicode (\r
28 OUT CHAR16 *UnicodeStr,\r
29 IN CHAR8 *AsciiStr\r
30 )\r
31/*++\r
32 \r
33 Routine Description:\r
34\r
35 This function converts ASCII string to Unicode string.\r
36 \r
37 Arguments:\r
38\r
39 UnicodeStr - NULL terminated Unicode output string.\r
40 AsciieStr - NULL terminated ASCII input string.\r
41 \r
42 Returns: \r
43\r
44 Start of the Unicode ouput string.\r
45 \r
46--*/\r
47\r
48{\r
49 CHAR16 *Str = UnicodeStr; \r
50 while (TRUE) {\r
51 *(UnicodeStr++) = (CHAR16) *AsciiStr;\r
52 if (*(AsciiStr++) == '\0') {\r
53 return Str;\r
54 }\r
55 }\r
56}\r
57\r
1cc8ee78 58STATIC\r
878ddf1f 59CHAR8*\r
60Unicode2Ascii (\r
61 OUT CHAR8 *AsciiStr,\r
62 IN CHAR16 *UnicodeStr\r
63 )\r
64/*++\r
65 \r
66 Routine Description:\r
67\r
68 This function converts Unicode string to ASCII string.\r
69 \r
70 Arguments:\r
71\r
72 AsciieStr - NULL terminated ASCII output string.\r
73 UnicodeStr - NULL terminated Unicode input string.\r
74 \r
75 Returns: \r
76\r
77 Start of the ASCII ouput string.\r
78 \r
79--*/\r
80\r
81{\r
82 CHAR8 *Str = AsciiStr; \r
83 while (TRUE) {\r
84 *(AsciiStr++) = (CHAR8) *UnicodeStr;\r
85 if (*(UnicodeStr++) == '\0') {\r
86 return Str;\r
87 }\r
88 }\r
89}\r
90\r
1cc8ee78 91STATIC\r
878ddf1f 92VOID\r
93ExtractDevicePathData (\r
94 IN EFI_HII_DATA_TABLE *DataTable,\r
95 IN UINT8 *IfrData,\r
96 IN OUT UINT8 **ExportBufferPtr\r
97 )\r
98/*++\r
99\r
100Routine Description:\r
101 \r
102Arguments:\r
103\r
104Returns: \r
105\r
106--*/\r
107{\r
108 UINT8 *ExportBuffer;\r
109\r
110 ExportBuffer = *ExportBufferPtr;\r
111\r
112 //\r
113 // BUGBUG - don't have devicepath data yet, setting dummy value\r
114 //\r
115 DataTable++;\r
116 ExportBuffer = (UINT8 *) DataTable;\r
117 ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH;\r
118 ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
119\r
120 //\r
121 // BUGBUG - part of hack - skip the Device Path Pack.....place some data\r
122 //\r
123 ExportBuffer = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK);\r
124\r
125 ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type = EFI_END_ENTIRE_DEVICE_PATH;\r
126 ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
127\r
128 //\r
129 // BUGBUG - still part of hack....\r
130 //\r
131 ExportBuffer = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
132 *ExportBufferPtr = ExportBuffer;\r
133}\r
134\r
1cc8ee78 135STATIC\r
878ddf1f 136VOID\r
137ExtractVariableData (\r
138 IN OUT EFI_HII_DATA_TABLE *DataTable,\r
139 IN UINT8 *IfrData,\r
140 IN OUT UINT8 **ExportBufferPtr\r
141 )\r
142/*++\r
143\r
144Routine Description:\r
145\r
146 This function extract the EFI_HII_VARIABLE_PACK portion from the \r
147 each of the EFI_HII_PACKAGE_INSTANCE in HII handle database.\r
148 \r
149Arguments:\r
150\r
511710d6 151 DataTable - On input, this parameter point to the EFI_HII_DATA_TABLE structure\r
878ddf1f 152 of the final data buffer for the EFI_HII_EXPORT interface. This function\r
153 update the NumberOfVariableData attribute.\r
154 IfrData - It points to a staring address of a EFI_HII_IFR_PACK structure.\r
511710d6 155 ExportBufferPtr - On input, it points the starting address of the data buffer to \r
878ddf1f 156 host the variable pack. On output, it is the starting address\r
157 of data buffer for the next extraction operation.\r
158Returns: \r
159\r
160 VOID\r
161 \r
162--*/\r
163{\r
164 EFI_HII_VARIABLE_PACK *VariableContents;\r
165 UINT8 *ExportBuffer;\r
166 UINTN Index;\r
167 UINTN Index2;\r
168 UINTN TempValue;\r
169 UINTN TempValue2;\r
170 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;\r
171 EFI_PHYSICAL_ADDRESS CallbackHandle;\r
172 EFI_STATUS Status;\r
173 CHAR16 *String;\r
174\r
175 FormCallback = NULL;\r
176 CallbackHandle = 0;\r
177 ExportBuffer = *ExportBufferPtr;\r
178\r
179 for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
180 VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
181\r
182 switch (IfrData[Index]) {\r
183 case EFI_IFR_FORM_SET_OP:\r
184 TempValue = EFI_HII_VARIABLE;\r
185 CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
186 CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
187\r
188 //\r
189 // If the variable has 0 size, do not process it\r
190 //\r
191 if (TempValue == 0) {\r
192 break;\r
193 }\r
194 //\r
195 // Add the size of the variable pack overhead. Later, will also add the size of the\r
196 // name of the variable.\r
197 //\r
198 TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);\r
199\r
200 CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
201 CopyMem (\r
202 &CallbackHandle,\r
203 &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle,\r
204 sizeof (EFI_PHYSICAL_ADDRESS)\r
205 );\r
206 if (CallbackHandle != 0) {\r
207 Status = gBS->HandleProtocol (\r
208 (EFI_HANDLE) (UINTN) CallbackHandle,\r
209 &gEfiFormCallbackProtocolGuid,\r
210 (VOID *) &FormCallback\r
211 );\r
1cc8ee78 212 ASSERT_EFI_ERROR (Status);\r
878ddf1f 213 }\r
214 //\r
215 // Since we have a "Setup" variable that wasn't specified by a variable op-code\r
216 // it will have a VariableId of 0. All other variable op-codes will have a designation\r
217 // of VariableId 1+\r
218 //\r
219 TempValue = 0;\r
220 CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16));\r
221 CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID));\r
222 TempValue = sizeof (SETUP_MAP_NAME);\r
223 CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));\r
224\r
225 //\r
226 // Add the size of the name to the Header Length\r
227 //\r
228 TempValue2 = 0;\r
229 CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));\r
230 TempValue2 = TempValue + TempValue2;\r
231 CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));\r
232\r
233 ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
234 CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME));\r
235 ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME);\r
236\r
237 CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
238\r
239 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
240 Status = FormCallback->NvRead (\r
241 FormCallback,\r
242 (CHAR16 *) SETUP_MAP_NAME,\r
243 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
244 NULL,\r
245 &TempValue,\r
246 ExportBuffer\r
247 );\r
1cc8ee78 248 ASSERT_EFI_ERROR (Status);\r
878ddf1f 249 } else {\r
250 Status = gRT->GetVariable (\r
251 (CHAR16 *) SETUP_MAP_NAME,\r
252 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
253 NULL,\r
254 &TempValue,\r
255 ExportBuffer\r
256 );\r
1cc8ee78 257 ASSERT_EFI_ERROR (Status);\r
878ddf1f 258 }\r
259\r
260 ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);\r
261 DataTable->NumberOfVariableData++;\r
262 break;\r
263\r
264 case EFI_IFR_VARSTORE_OP:\r
265 TempValue = EFI_HII_VARIABLE;\r
266 CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
267 CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));\r
268\r
269 //\r
270 // If the variable has 0 size, do not process it\r
271 //\r
272 if (TempValue == 0) {\r
273 break;\r
274 }\r
275 //\r
276 // Add the size of the variable pack overhead. Later, will also add the size of the\r
277 // name of the variable.\r
278 //\r
279 TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);\r
280\r
281 CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
282 CopyMem (&VariableContents->VariableId, &((EFI_IFR_VARSTORE *) &IfrData[Index])->VarId, sizeof (UINT16));\r
283 CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Guid, sizeof (EFI_GUID));\r
284 TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &IfrData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);\r
285 TempValue = TempValue * 2;\r
286 CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));\r
287\r
288 //\r
289 // Add the size of the name to the Header Length\r
290 //\r
291 TempValue2 = 0;\r
292 CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));\r
293 TempValue2 = TempValue + TempValue2;\r
294 CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));\r
295\r
296 ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
297 String = (CHAR16 *) ExportBuffer;\r
298 for (Index2 = 0; Index2 < TempValue / 2; Index2++) {\r
299 ExportBuffer[Index2 * 2] = IfrData[Index + sizeof (EFI_IFR_VARSTORE) + Index2];\r
300 ExportBuffer[Index2 * 2 + 1] = 0;\r
301 }\r
302\r
303 ExportBuffer = ExportBuffer + TempValue;\r
304\r
305 CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));\r
306\r
307 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
308 Status = FormCallback->NvRead (\r
309 FormCallback,\r
310 String,\r
311 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
312 NULL,\r
313 &TempValue,\r
314 ExportBuffer\r
315 );\r
1cc8ee78 316 ASSERT_EFI_ERROR (Status);\r
878ddf1f 317 } else {\r
318 Status = gRT->GetVariable (\r
319 String,\r
320 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
321 NULL,\r
322 &TempValue,\r
323 ExportBuffer\r
324 );\r
1cc8ee78 325 ASSERT_EFI_ERROR (Status);\r
878ddf1f 326 }\r
327\r
328 ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);\r
329 DataTable->NumberOfVariableData++;\r
330 break;\r
331 }\r
332\r
333 Index = IfrData[Index + 1] + Index;\r
334 }\r
335 //\r
336 // If we have added a variable pack, add a dummy empty one to signify the end\r
337 //\r
338 if (ExportBuffer != *ExportBufferPtr) {\r
339 VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
340 TempValue = EFI_HII_VARIABLE;\r
341 CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
342 TempValue = sizeof (EFI_HII_VARIABLE_PACK);\r
343 CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
344 ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
345 }\r
346\r
347 *ExportBufferPtr = ExportBuffer;\r
348}\r
349\r
350EFI_STATUS\r
351EFIAPI\r
352HiiExportDatabase (\r
353 IN EFI_HII_PROTOCOL *This,\r
354 IN EFI_HII_HANDLE Handle,\r
355 IN OUT UINTN *BufferSize,\r
356 OUT VOID *Buffer\r
357 )\r
358/*++\r
359\r
360Routine Description:\r
361 \r
362 This function allows a program to extract a form or form package that has \r
363 previously been registered with the EFI HII database.\r
364\r
365Arguments:\r
366\r
367Returns: \r
368\r
369--*/\r
370{\r
371 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
372 EFI_HII_DATA *HiiData;\r
373 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
374 EFI_HII_IFR_PACK *FormPack;\r
375 UINT8 *RawData;\r
376 UINT8 *ExportBuffer;\r
377 EFI_HII_EXPORT_TABLE *ExportTable;\r
378 EFI_HII_DATA_TABLE *DataTable;\r
878ddf1f 379 BOOLEAN VariableExist;\r
380 UINT16 NumberOfHiiDataTables;\r
381 UINTN SizeNeeded;\r
382 UINTN Index;\r
383 UINTN VariableSize;\r
384 UINTN TempValue;\r
385\r
386 if (This == NULL) {\r
387 return EFI_INVALID_PARAMETER;\r
388 }\r
389\r
390 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
391\r
392 HandleDatabase = HiiData->DatabaseHead;\r
393\r
394 FormPack = NULL;\r
395 RawData = NULL;\r
396 PackageInstance = NULL;\r
878ddf1f 397 NumberOfHiiDataTables = 0;\r
398 VariableSize = 0;\r
399 TempValue = 0;\r
400 SizeNeeded = sizeof (EFI_HII_EXPORT_TABLE);\r
401\r
402 //\r
403 // How many total tables are there?\r
404 //\r
405 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
406 if ((Handle != 0) && (Handle != HandleDatabase->Handle)) {\r
407 continue;\r
408 }\r
409\r
410 VariableExist = FALSE;\r
411 NumberOfHiiDataTables++;\r
412 PackageInstance = HandleDatabase->Buffer;\r
413 if (PackageInstance == NULL) {\r
414 continue;\r
415 }\r
416 //\r
417 // Extract Size of Export Package\r
418 //\r
419 SizeNeeded = SizeNeeded + PackageInstance->IfrSize \r
420 + PackageInstance->StringSize\r
421 + sizeof (EFI_HII_DATA_TABLE)\r
422 + sizeof (EFI_HII_DEVICE_PATH_PACK);\r
423\r
424 //\r
425 // BUGBUG We aren't inserting Device path data yet\r
426 //\r
427 SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
428\r
429 //\r
430 // Extract Size of Variable Data\r
431 //\r
432 if (PackageInstance->IfrSize > 0) {\r
433 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
434 } else {\r
435 //\r
436 // No IFR? No variable information\r
437 //\r
438 continue;\r
439 }\r
440\r
441 RawData = (UINT8 *) FormPack;\r
442\r
443 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
444 switch (RawData[Index]) {\r
445 case EFI_IFR_FORM_SET_OP:\r
446 CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16));\r
447 SizeNeeded = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK);\r
448 VariableExist = TRUE;\r
449 break;\r
450\r
451 case EFI_IFR_VARSTORE_OP:\r
452 CopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16));\r
453 SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK);\r
454 //\r
455 // We will be expanding the stored ASCII name to a Unicode string. This will cause some memory overhead\r
456 // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another\r
457 // instance of it. Essentially, 2 ASCII strings == 1 Unicode string in size.\r
458 //\r
459 TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);\r
460 SizeNeeded = SizeNeeded + TempValue * 2;\r
461 VariableExist = TRUE;\r
462 break;\r
463 }\r
464\r
465 Index = RawData[Index + 1] + Index;\r
466 }\r
467 //\r
468 // If a variable exists for this handle, add an additional variable pack overhead to\r
469 // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs\r
470 //\r
471 if (VariableExist) {\r
472 SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK);\r
473 }\r
474 }\r
475\r
476 if (SizeNeeded > *BufferSize) {\r
477 *BufferSize = SizeNeeded;\r
478 return EFI_BUFFER_TOO_SMALL;\r
479 }\r
480 //\r
481 // Zero out the incoming buffer\r
482 //\r
483 ZeroMem (Buffer, *BufferSize);\r
484\r
485 //\r
486 // Cast the Buffer to EFI_HII_EXPORT_TABLE\r
487 //\r
488 ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer;\r
489\r
490 //\r
491 // Set the Revision for the Export Table\r
492 //\r
493 CopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID));\r
494\r
495 ExportBuffer = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE));\r
496 HandleDatabase = HiiData->DatabaseHead;\r
497\r
498 //\r
499 // Check numeric value against the head of the database\r
500 //\r
501 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
502 DataTable = (EFI_HII_DATA_TABLE *) ExportBuffer;\r
503 PackageInstance = HandleDatabase->Buffer;\r
504 //\r
505 // If not asking for a specific handle, export the entire database\r
506 //\r
507 if (Handle == 0) {\r
508 ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;\r
509 CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));\r
510 DataTable->HiiHandle = PackageInstance->Handle;\r
511 DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE));\r
512\r
513 //\r
514 // Start Dumping DevicePath\r
515 //\r
516 ExtractDevicePathData (DataTable, RawData, &ExportBuffer);\r
517\r
518 if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) {\r
519 //\r
520 // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse\r
521 //\r
522 DataTable->DevicePathOffset = 0;\r
523 }\r
524\r
525 DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
526\r
527 if (PackageInstance->IfrSize > 0) {\r
528 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
529\r
530 RawData = (UINT8 *) FormPack;\r
531 TempValue = 0;\r
532\r
533 //\r
534 // Start dumping the Variable Data\r
535 //\r
536 ExtractVariableData (DataTable, RawData, &ExportBuffer);\r
537 DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
538\r
539 if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {\r
540 DataTable->VariableDataOffset = 0;\r
541 }\r
542 //\r
543 // Start dumping the IFR data (Note: It is in an IFR PACK)\r
544 //\r
545 CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);\r
546 ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);\r
547 DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
548\r
549 //\r
550 // Start dumping the String data (Note: It is in a String PACK)\r
551 //\r
552 if (PackageInstance->StringSize > 0) {\r
553 RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
554 CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
555 DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
556\r
557 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
558 for (; TempValue != 0;) {\r
559 DataTable->NumberOfLanguages++;\r
560 ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
561 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
562 }\r
563\r
564 ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
565 } else {\r
566 DataTable->StringDataOffset = 0;\r
567 }\r
568 } else {\r
569 //\r
570 // No IFR? No variable information. If Offset is 0, means there is none. (Hmm - this might be prunable - no strings to export if no IFR - we always have a stub)\r
571 //\r
572 DataTable->VariableDataOffset = 0;\r
573 DataTable->IfrDataOffset = 0;\r
574 DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
575\r
576 //\r
577 // Start dumping the String data - NOTE: It is in String Pack form\r
578 //\r
579 if (PackageInstance->StringSize > 0) {\r
580 RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
581 CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
582 DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
583\r
584 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
585 for (; TempValue != 0;) {\r
586 DataTable->NumberOfLanguages++;\r
587 ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
588 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
589 }\r
590\r
591 ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
592 } else {\r
593 DataTable->StringDataOffset = 0;\r
594 }\r
595 }\r
596 } else {\r
597 //\r
598 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
599 //\r
600 if (Handle == HandleDatabase->Handle) {\r
601 PackageInstance = HandleDatabase->Buffer;\r
602 ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;\r
603 DataTable->HiiHandle = PackageInstance->Handle;\r
604 CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));\r
605\r
606 //\r
607 // Start Dumping DevicePath\r
608 //\r
609 ExtractDevicePathData (DataTable, RawData, &ExportBuffer);\r
610 DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
611\r
612 if (PackageInstance->IfrSize > 0) {\r
613 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
614\r
615 RawData = (UINT8 *) FormPack;\r
616 TempValue = 0;\r
617\r
618 //\r
619 // Start dumping the Variable Data\r
620 //\r
621 ExtractVariableData (DataTable, RawData, &ExportBuffer);\r
622 DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
623\r
624 if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {\r
625 DataTable->VariableDataOffset = 0;\r
626 }\r
627 //\r
628 // Start dumping the IFR data\r
629 //\r
630 CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);\r
631 ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);\r
632 DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
633\r
634 //\r
635 // Start dumping the String data - NOTE: It is in String Pack form\r
636 //\r
637 if (PackageInstance->StringSize > 0) {\r
638 RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
639 CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
640 DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
641\r
642 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
643 for (; TempValue != 0;) {\r
644 DataTable->NumberOfLanguages++;\r
645 ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
646 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
647 }\r
648\r
649 ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
650 } else {\r
651 DataTable->StringDataOffset = 0;\r
652 }\r
653 } else {\r
654 //\r
655 // No IFR? No variable information. If Offset is 0, means there is none.\r
656 //\r
657 DataTable->VariableDataOffset = 0;\r
658 DataTable->IfrDataOffset = 0;\r
659 DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
660\r
661 //\r
662 // Start dumping the String data - Note: It is in String Pack form\r
663 //\r
664 if (PackageInstance->StringSize > 0) {\r
665 RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
666 CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
667 DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
668\r
669 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
670 for (; TempValue != 0;) {\r
671 DataTable->NumberOfLanguages++;\r
672 ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
673 CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
674 }\r
675\r
676 ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
677 } else {\r
678 DataTable->StringDataOffset = 0;\r
679 }\r
680 }\r
681 break;\r
682 }\r
683 }\r
684 }\r
685\r
686 return EFI_SUCCESS;\r
687}\r
688\r
689EFI_STATUS\r
690EFIAPI\r
691HiiGetForms (\r
692 IN EFI_HII_PROTOCOL *This,\r
693 IN EFI_HII_HANDLE Handle,\r
694 IN EFI_FORM_ID FormId,\r
695 IN OUT UINTN *BufferLengthTemp,\r
696 OUT UINT8 *Buffer\r
697 )\r
698/*++\r
699\r
700Routine Description:\r
701 \r
702 This function allows a program to extract a form or form package that has \r
703 previously been registered with the EFI HII database.\r
704\r
705Arguments:\r
706 This - A pointer to the EFI_HII_PROTOCOL instance.\r
707 \r
708 Handle - Handle on which the form resides. Type EFI_HII_HANDLE is defined in \r
709 EFI_HII_PROTOCOL.NewPack() in the Packages section.\r
710 \r
711 FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.\r
712 Type EFI_FORM_ID is defined in "Related Definitions" below.\r
713 \r
714 BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if\r
715 the length was sufficient and, if it was not, the length that is required to fit the\r
716 requested form(s).\r
717 \r
718 Buffer - The buffer designed to receive the form(s).\r
719\r
720Returns: \r
721\r
722 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength\r
723 was updated.\r
724 \r
725 EFI_INVALID_PARAMETER - The handle is unknown.\r
726 \r
727 EFI_NOT_FOUND - A form on the requested handle cannot be found with the\r
728 requested FormId.\r
729 \r
730 EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.\r
731\r
732--*/\r
733{\r
734 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
735 EFI_HII_DATA *HiiData;\r
736 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
737 EFI_HII_IFR_PACK *FormPack;\r
738 EFI_IFR_FORM *Form;\r
739 EFI_IFR_OP_HEADER *Location;\r
740 UINT16 *BufferLength = (UINT16 *) BufferLengthTemp;\r
741\r
742 if (This == NULL) {\r
743 return EFI_INVALID_PARAMETER;\r
744 }\r
745\r
746 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
747\r
748 HandleDatabase = HiiData->DatabaseHead;\r
749\r
750 PackageInstance = NULL;\r
751\r
752 //\r
753 // Check numeric value against the head of the database\r
754 //\r
755 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
756 //\r
757 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
758 //\r
759 if (Handle == HandleDatabase->Handle) {\r
760 PackageInstance = HandleDatabase->Buffer;\r
761 break;\r
762 }\r
763 }\r
764 //\r
765 // No handle was found - error condition\r
766 //\r
767 if (PackageInstance == NULL) {\r
768 return EFI_NOT_FOUND;\r
769 }\r
770 //\r
771 // Based on if there is IFR data in this package instance, determine\r
772 // what the location is of the beginning of the string data.\r
773 //\r
774 if (PackageInstance->IfrSize > 0) {\r
775 FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);\r
776 } else {\r
777 //\r
778 // If there is no IFR data return an error\r
779 //\r
780 return EFI_NOT_FOUND;\r
781 }\r
782 //\r
783 // If requesting the entire Form Package\r
784 //\r
785 if (FormId == 0) {\r
786 //\r
787 // Return an error if buffer is too small\r
788 //\r
789 if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {\r
790 *BufferLength = (UINT16) PackageInstance->IfrSize;\r
791 return EFI_BUFFER_TOO_SMALL;\r
792 }\r
793\r
794 CopyMem (Buffer, FormPack, PackageInstance->IfrSize);\r
795 return EFI_SUCCESS;\r
796 } else {\r
797 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
798 Location = (EFI_IFR_OP_HEADER *) FormPack;\r
799\r
800 //\r
801 // Look for the FormId requested\r
802 //\r
803 for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
804 switch (Location->OpCode) {\r
805 case EFI_IFR_FORM_OP:\r
806 Form = (EFI_IFR_FORM *) Location;\r
807\r
808 //\r
809 // If we found a Form Op-code and it is of the correct Id, copy it and return\r
810 //\r
811 if (Form->FormId == FormId) {\r
812 if (Location->Length > *BufferLength || Buffer == NULL) {\r
813 *BufferLength = Location->Length;\r
814 return EFI_BUFFER_TOO_SMALL;\r
815 } else {\r
816 for (; Location->OpCode != EFI_IFR_END_FORM_OP;) {\r
817 CopyMem (Buffer, Location, Location->Length);\r
818 Buffer = Buffer + Location->Length;\r
819 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
820 }\r
821\r
822 CopyMem (Buffer, Location, Location->Length);\r
823 return EFI_SUCCESS;\r
824 }\r
825 }\r
826\r
827 default:\r
828 break;\r
829 }\r
830 //\r
831 // Go to the next Op-Code\r
832 //\r
833 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
834 }\r
835 }\r
836\r
837 return EFI_SUCCESS;\r
838}\r
839\r
840//\r
841// Helper functions to HiiGetDefaultImage()\r
842//\r
843\r
844STATIC\r
845UINT8*\r
846HiiGetDefaultImageInitPack (\r
847 IN OUT EFI_HII_VARIABLE_PACK_LIST *VariablePackItem,\r
848 IN EFI_IFR_VARSTORE *VarStore\r
849 )\r
850/*++\r
851 \r
852 Routine Description:\r
853\r
854 Initialize the EFI_HII_VARIABLE_PACK_LIST structure and\r
855 prepare it ready to be used by HiiGetDefaultImagePopulateMap ().\r
856 \r
857 Arguments:\r
858\r
859 VariablePackItem - Variable Package List.\r
860 VarStore - IFR variable storage.\r
861 \r
862 Returns: \r
863\r
864 Return the pointer to the Map space.\r
865 \r
866--*/\r
867{\r
868 CHAR16 *Name16;\r
869 CHAR8 *Name8;\r
870 CHAR8 *Map;\r
871 EFI_HII_VARIABLE_PACK *VariablePack;\r
872\r
873 //\r
874 // Set pointer the pack right after the node\r
875 //\r
876 VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1);\r
877 VariablePack = VariablePackItem->VariablePack;\r
878\r
879 //\r
880 // Copy the var name to VariablePackItem from VarStore\r
881 // Needs ASCII->Unicode conversion.\r
882 //\r
883 ASSERT (VarStore->Header.Length > sizeof (*VarStore));\r
884 Name8 = (CHAR8 *) (VarStore + 1);\r
885 Name16 = (CHAR16 *) (VariablePack + 1);\r
886 Ascii2Unicode (Name16, Name8);\r
887\r
888 //\r
889 // Compute the other fields of the VariablePackItem\r
890 //\r
891 VariablePack->VariableId = VarStore->VarId;\r
892 CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID));\r
893 VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2);\r
894 VariablePack->Header.Length = sizeof (*VariablePack) \r
895 + VariablePack->VariableNameLength\r
896 + VarStore->Size;\r
897 //\r
898 // Return the pointer to the Map space.\r
899 //\r
900 Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength;\r
901\r
902 return (UINT8 *)Map;\r
903}\r
904\r
905STATIC\r
906VOID\r
907HiiGetDefaultImagePopulateMap (\r
908 IN OUT UINT8 *Map, \r
909 IN EFI_IFR_OP_HEADER *FormSet,\r
910 IN EFI_IFR_VARSTORE *VarStore,\r
911 IN UINTN DefaultMask\r
912 )\r
913/*++\r
914 \r
915 Routine Description:\r
916\r
917 Fill the Map with all the default values either from NV or Hii database.\r
918 \r
919 Arguments:\r
920\r
921 Map - Memory pointer to hold the default values.\r
922 FormSet - The starting EFI_IFR_OP_HEADER to begin retriving default values.\r
923 VarStore - IFR variable storage.\r
924 DefaultMask - The mask used to get the default variable.\r
925 \r
926 Returns: \r
927\r
928 VOID\r
929 \r
930--*/\r
931{\r
932 EFI_STATUS Status;\r
933 EFI_IFR_OP_HEADER *IfrItem;\r
934 UINT16 VarId;\r
935 EFI_IFR_VARSTORE_SELECT *VarSelect;\r
936 EFI_IFR_ONE_OF_OPTION *OneOfOpt;\r
937 EFI_IFR_CHECKBOX *CheckBox;\r
938 EFI_IFR_NUMERIC *Numeric;\r
939 UINTN Size;\r
940 UINTN SizeTmp;\r
941 EFI_IFR_NV_DATA *IfrNvData;\r
942 EFI_GUID Guid;\r
943 CHAR16 *Name16;\r
944 CHAR8 *Name8; \r
945 EFI_HANDLE CallbackHandle;\r
946 EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProt;\r
947\r
948 //\r
949 // Get the Map's Name/Guid/Szie from the Varstore.\r
950 // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode.\r
951 //\r
952 ASSERT (VarStore->Header.Length >= sizeof (*VarStore));\r
953 Name8 = (CHAR8 *) (VarStore + 1);\r
954 Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16));\r
955 Ascii2Unicode (Name16, Name8);\r
956 CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID));\r
957 Size = VarStore->Size;\r
958\r
959 //\r
960 // First, check if the map exists in the NV. If so, get it from NV and exit.\r
961 //\r
962 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
963 //\r
964 // Check if Manufaturing Defaults exist in the NV.\r
965 //\r
966 Status = EfiLibHiiVariableOverrideBySuffix (\r
967 HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE,\r
968 Name16,\r
969 &Guid,\r
970 Size,\r
971 Map\r
972 );\r
973 } else {\r
974 //\r
975 // All other cases default to Defaults. Check if Defaults exist in the NV.\r
976 //\r
977 Status = EfiLibHiiVariableOverrideBySuffix (\r
978 HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE,\r
979 Name16,\r
980 &Guid,\r
981 Size,\r
982 Map\r
983 );\r
984 }\r
985 if (!EFI_ERROR (Status)) {\r
986 //\r
987 // Either Defaults/Manufacturing variable exists and appears to be valid. \r
988 // The map is read, exit w/ success now.\r
989 //\r
990 gBS->FreePool (Name16);\r
991 return;\r
992 }\r
993\r
994 //\r
995 // First, prime the map with what already is in the NV.\r
996 // This is needed to cover a situation where the IFR does not contain all the \r
997 // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default.\r
998 // Ignore status. Either it gets read or not. \r
999 // \r
1000 FormCallbackProt = NULL;\r
1001 CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle));\r
1002 if (CallbackHandle != NULL) {\r
1003 Status = gBS->HandleProtocol (\r
1004 (EFI_HANDLE) (UINTN) CallbackHandle,\r
1005 &gEfiFormCallbackProtocolGuid,\r
1006 (VOID *) &FormCallbackProt\r
1007 );\r
1008 }\r
1009 if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) {\r
1010 //\r
1011 // Attempt to read using NvRead() callback. Probe first for existence and correct variable size.\r
1012 //\r
1013 SizeTmp = 0;\r
1014 Status = FormCallbackProt->NvRead (\r
1015 FormCallbackProt,\r
1016 Name16,\r
1017 &Guid,\r
1018 0,\r
1019 &SizeTmp,\r
1020 NULL\r
1021 );\r
1022 if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) {\r
1023 Status = FormCallbackProt->NvRead (\r
1024 FormCallbackProt,\r
1025 Name16,\r
1026 &Guid,\r
1027 0,\r
1028 &SizeTmp,\r
1029 Map\r
1030 );\r
1031 ASSERT_EFI_ERROR (Status);\r
1032 ASSERT (SizeTmp == Size);\r
1033 }\r
1034 } else {\r
1035 //\r
1036 // No callback available for this formset, read straight from NV. Deliberately ignore the Status. \r
1037 // The buffer will only be written if variable exists nd has correct size.\r
1038 //\r
1039 Status = EfiLibHiiVariableRetrieveFromNv (\r
1040 Name16,\r
1041 &Guid,\r
1042 Size,\r
1043 (VOID **) &Map\r
1044 );\r
1045 }\r
1046\r
1047 //\r
1048 // Iterate all IFR statements and for applicable, retrieve the default into the Map.\r
1049 //\r
1050 for (IfrItem = FormSet, VarId = 0; \r
1051 IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP; \r
1052 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length)\r
1053 ) {\r
1054\r
1055 //\r
1056 // Observe VarStore switch.\r
1057 //\r
1058 if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) {\r
1059 VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem;\r
1060 VarId = VarSelect->VarId;\r
1061 continue;\r
1062 }\r
1063\r
1064\r
1065 //\r
1066 // Skip opcodes that reference other VarStore than that specific to current map.\r
1067 // \r
1068 if (VarId != VarStore->VarId) {\r
1069 continue;\r
1070 }\r
1071 \r
1072 //\r
1073 // Extract the default value from this opcode if applicable, and apply it to the map.\r
1074 //\r
1075 IfrNvData = (EFI_IFR_NV_DATA *) IfrItem;\r
1076 switch (IfrItem->OpCode) {\r
1077\r
1078 case EFI_IFR_ONE_OF_OP:\r
1079 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1080 //\r
1081 // Get to the first EFI_IFR_ONE_OF_OPTION_OP\r
1082 //\r
1083 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length); \r
1084 ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode);\r
1085\r
1086 OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
1087 //\r
1088 // In the worst case, the first will be the default.\r
1089 //\r
1090 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1091\r
1092 while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) {\r
1093\r
1094 OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
1095 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
1096 if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
1097 //\r
1098 // In the worst case, the first will be the default.\r
1099 //\r
1100 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1101 break;\r
1102 }\r
1103 } else {\r
1104 if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) {\r
1105 //\r
1106 // In the worst case, the first will be the default.\r
1107 //\r
1108 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1109 break;\r
1110 }\r
1111 }\r
1112\r
1113 IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length);\r
1114 }\r
1115 continue;\r
1116 break;\r
1117\r
1118 case EFI_IFR_CHECKBOX_OP:\r
1119 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1120 CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem; \r
1121 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
1122 if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
1123 *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
1124 }\r
1125 } else {\r
1126 if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) {\r
1127 *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
1128 }\r
1129 }\r
1130 break;\r
1131\r
1132 case EFI_IFR_NUMERIC_OP:\r
1133 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1134 Numeric = (EFI_IFR_NUMERIC *) IfrItem;\r
1135 CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth);\r
1136 break;\r
1137\r
1138 case EFI_IFR_ORDERED_LIST_OP:\r
1139 case EFI_IFR_PASSWORD_OP:\r
1140 case EFI_IFR_STRING_OP:\r
1141 //\r
1142 // No support for default value for these opcodes.\r
1143 //\r
1144 break;\r
1145 }\r
1146 }\r
1147\r
1148 gBS->FreePool (Name16);\r
1149\r
1150}\r
1151\r
1152\r
1153EFI_STATUS\r
1154EFIAPI\r
1155HiiGetDefaultImage (\r
1156 IN EFI_HII_PROTOCOL *This,\r
1157 IN EFI_HII_HANDLE Handle,\r
1158 IN UINTN DefaultMask,\r
1159 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList\r
1160 )\r
1161/*++\r
1162 \r
1163 Routine Description:\r
1164\r
1165 This function allows a program to extract the NV Image \r
1166 that represents the default storage image\r
1167 \r
1168 Arguments:\r
1169 This - A pointer to the EFI_HII_PROTOCOL instance.\r
1170 Handle - The HII handle from which will have default data retrieved.\r
1171 UINTN - Mask used to retrieve the default image.\r
1172 VariablePackList - Callee allocated, tightly-packed, link list data \r
1173 structure that contain all default varaible packs\r
1174 from the Hii Database.\r
1175 \r
1176 Returns: \r
1177 EFI_NOT_FOUND - If Hii database does not contain any default images.\r
1178 EFI_INVALID_PARAMETER - Invalid input parameter.\r
1179 EFI_SUCCESS - Operation successful.\r
1180 \r
1181--*/\r
1182{\r
1183 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
1184 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
1185 EFI_IFR_OP_HEADER *FormSet;\r
1186 EFI_IFR_OP_HEADER *IfrItem;\r
1187 EFI_IFR_VARSTORE *VarStore;\r
1188 EFI_IFR_VARSTORE *VarStoreDefault;\r
1189 UINTN SetupMapNameSize;\r
1190 UINTN SizeOfMaps;\r
1191 EFI_HII_VARIABLE_PACK_LIST *PackList;\r
1192 EFI_HII_VARIABLE_PACK_LIST *PackListNext; \r
1193 EFI_HII_VARIABLE_PACK_LIST *PackListLast;\r
1194 UINT8 *Map;\r
1195\r
1196\r
1197 //\r
1198 // Find the IFR pack from the handle. Then get the formset from the pack.\r
1199 //\r
1200 PackageInstance = NULL;\r
1201 HandleDatabase = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead;\r
1202 for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
1203 if (Handle == HandleDatabase->Handle) {\r
1204 PackageInstance = HandleDatabase->Buffer;\r
1205 break;\r
1206 }\r
1207 }\r
1208 if (PackageInstance == NULL) {\r
1209 return EFI_INVALID_PARAMETER;\r
1210 }\r
1211 FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK));\r
1212\r
1213 //\r
1214 // Get the sizes of all the VARSTOREs in this VFR.\r
1215 // Then allocate enough space for all of them plus all maps\r
1216 //\r
1217 SizeOfMaps = 0;\r
1218 IfrItem = FormSet;\r
1219 while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
1220\r
1221 if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
1222 VarStore = (EFI_IFR_VARSTORE *) IfrItem;\r
1223 //\r
1224 // Size of the map\r
1225 //\r
1226 SizeOfMaps += VarStore->Size; \r
1227 //\r
1228 // add the size of the string, in Unicode\r
1229 //\r
1230 SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2; \r
1231 //\r
1232 // Space for node\r
1233 //\r
1234 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
1235 //\r
1236 // Space for linked list node \r
1237 //\r
1238 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
1239 }\r
1240\r
1241 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
1242 }\r
1243\r
1244 //\r
1245 // If the FormSet OpCode has a non-zero NvDataSize. There is a default \r
1246 // NvMap with ID=0, GUID that of the formset itself and "Setup" as name.\r
1247 //\r
1248 SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1;\r
1249 VarStoreDefault = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
1250\r
1251 if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) {\r
1252\r
1253 VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP;\r
1254 VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
1255 Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME);\r
1256 CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID));\r
1257 VarStoreDefault->VarId = 0;\r
1258 VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize;\r
1259\r
1260 //\r
1261 // Size of the map\r
1262 //\r
1263 SizeOfMaps += VarStoreDefault->Size; \r
1264 //\r
1265 // add the size of the string\r
1266 //\r
1267 SizeOfMaps += sizeof (SETUP_MAP_NAME); \r
1268 //\r
1269 // Space for node\r
1270 //\r
1271 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
1272 //\r
1273 // Space for linked list node \r
1274 //\r
1275 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
1276 }\r
1277\r
1278 if (0 == SizeOfMaps) {\r
1279 //\r
1280 // The IFR does not have any explicit or default map(s).\r
1281 //\r
1282 return EFI_NOT_FOUND; \r
1283 }\r
1284\r
1285 //\r
1286 // Allocate the return buffer\r
1287 //\r
1288 PackList = AllocateZeroPool (SizeOfMaps);\r
1289 ASSERT (NULL != PackList); \r
1290\r
1291 PackListNext = PackList;\r
1292 PackListLast = PackList;\r
1293\r
1294 //\r
1295 // Handle the default map first, if any.\r
1296 //\r
1297 if (0 != VarStoreDefault->Size) {\r
1298\r
1299 Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault);\r
1300\r
1301 HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask);\r
1302\r
1303 PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
1304 PackListLast = PackListNext;\r
1305 PackListNext = PackListNext->NextVariablePack;\r
1306 }\r
1307\r
1308\r
1309 //\r
1310 // Handle the explicit varstore(s)\r
1311 //\r
1312 IfrItem = FormSet;\r
1313 while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
1314\r
1315 if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
1316\r
1317 Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem);\r
1318\r
1319 HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask);\r
1320\r
1321 PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
1322 PackListLast = PackListNext;\r
1323 PackListNext = PackListNext->NextVariablePack;\r
1324 }\r
1325\r
1326 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
1327 }\r
1328\r
1329 PackListLast->NextVariablePack = NULL;\r
1330 *VariablePackList = PackList;\r
1331 \r
1332 return EFI_SUCCESS;\r
1333}\r
1334\r
1335\r
1336EFI_STATUS\r
1337EFIAPI\r
1338HiiUpdateForm (\r
1339 IN EFI_HII_PROTOCOL *This,\r
1340 IN EFI_HII_HANDLE Handle,\r
1341 IN EFI_FORM_LABEL Label,\r
1342 IN BOOLEAN AddData,\r
1343 IN EFI_HII_UPDATE_DATA *Data\r
1344 )\r
1345/*++\r
1346\r
1347Routine Description:\r
1348 This function allows the caller to update a form that has \r
1349 previously been registered with the EFI HII database.\r
1350\r
1351Arguments:\r
1352 Handle - Hii Handle associated with the Formset to modify\r
1353 Label - Update information starting immediately after this label in the IFR\r
1354 AddData - If TRUE, add data. If FALSE, remove data\r
1355 Data - If adding data, this is the pointer to the data to add\r
1356\r
1357Returns: \r
1358 EFI_SUCCESS - Update success.\r
1359 Other - Update fail.\r
1360\r
1361--*/\r
1362{\r
1363 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
1364 EFI_HII_DATA *HiiData;\r
1365 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
1366 EFI_HII_IFR_PACK *FormPack;\r
1367 EFI_IFR_OP_HEADER *Location;\r
1368 EFI_IFR_OP_HEADER *DataLocation;\r
1369 UINT8 *OtherBuffer;\r
1370 UINT8 *TempBuffer;\r
1371 UINT8 *OrigTempBuffer;\r
1372 UINTN TempBufferSize;\r
1373 UINTN Index;\r
1374\r
1375 OtherBuffer = NULL;\r
1376\r
1377 if (This == NULL) {\r
1378 return EFI_INVALID_PARAMETER;\r
1379 }\r
1380\r
1381 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
1382\r
1383 HandleDatabase = HiiData->DatabaseHead;\r
1384\r
1385 PackageInstance = NULL;\r
1386\r
1387 //\r
1388 // Check numeric value against the head of the database\r
1389 //\r
1390 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
1391 //\r
1392 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
1393 //\r
1394 if (Handle == HandleDatabase->Handle) {\r
1395 PackageInstance = HandleDatabase->Buffer;\r
1396 break;\r
1397 }\r
1398 }\r
1399 //\r
1400 // No handle was found - error condition\r
1401 //\r
1402 if (PackageInstance == NULL) {\r
1403 return EFI_INVALID_PARAMETER;\r
1404 }\r
1405 //\r
1406 // Calculate and allocate space for retrieval of IFR data\r
1407 //\r
1408 DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
1409 TempBufferSize = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance);\r
1410\r
1411 for (Index = 0; Index < Data->DataCount; Index++) {\r
1412 TempBufferSize += DataLocation->Length;\r
1413 DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
1414 }\r
1415\r
1416 TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize;\r
1417\r
1418 TempBuffer = AllocateZeroPool (TempBufferSize);\r
41a907e4 1419 ASSERT (TempBuffer != NULL);\r
1420\r
878ddf1f 1421 OrigTempBuffer = TempBuffer;\r
1422\r
1423 //\r
1424 // We update only packages with IFR information in it\r
1425 //\r
1426 if (PackageInstance->IfrSize == 0) {\r
1427 return EFI_INVALID_PARAMETER;\r
1428 }\r
1429\r
1430 CopyMem (\r
1431 TempBuffer,\r
1432 PackageInstance,\r
1433 ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance))\r
1434 );\r
1435\r
1436 TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance));\r
1437\r
1438 //\r
1439 // Based on if there is IFR data in this package instance, determine\r
1440 // what the location is of the beginning of the string data.\r
1441 //\r
1442 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
1443 Location = (EFI_IFR_OP_HEADER *) FormPack;\r
1444\r
1445 //\r
1446 // Look for the FormId requested\r
1447 //\r
1448 for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
1449 switch (Location->OpCode) {\r
1450 case EFI_IFR_FORM_SET_OP:\r
1451 //\r
1452 // If the FormSet has an update pending, pay attention.\r
1453 //\r
1454 if (Data->FormSetUpdate) {\r
1455 ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle;\r
1456 }\r
1457\r
1458 CopyMem (TempBuffer, Location, Location->Length);\r
1459 TempBuffer = TempBuffer + Location->Length;\r
1460 break;\r
1461\r
1462 case EFI_IFR_FORM_OP:\r
1463 //\r
1464 // If the Form has an update pending, pay attention.\r
1465 //\r
1466 if (Data->FormUpdate) {\r
1467 ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle;\r
1468 }\r
1469\r
1470 CopyMem (TempBuffer, Location, Location->Length);\r
1471 TempBuffer = TempBuffer + Location->Length;\r
1472 break;\r
1473\r
1474 case EFI_IFR_LABEL_OP:\r
1475 //\r
1476 // If the label does not match the requested update point, ignore it\r
1477 //\r
1478 if (((EFI_IFR_LABEL *) Location)->LabelId != Label) {\r
1479 //\r
1480 // Copy the label\r
1481 //\r
1482 CopyMem (TempBuffer, Location, Location->Length);\r
1483 TempBuffer = TempBuffer + Location->Length;\r
1484\r
1485 //\r
1486 // Go to the next Op-Code\r
1487 //\r
1488 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1489 continue;\r
1490 }\r
1491\r
1492 if (AddData) {\r
1493 //\r
1494 // Copy the label\r
1495 //\r
1496 CopyMem (TempBuffer, Location, Location->Length);\r
1497 TempBuffer = TempBuffer + Location->Length;\r
1498\r
1499 //\r
1500 // Add the DataCount amount of opcodes to TempBuffer\r
1501 //\r
1502 DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
1503 for (Index = 0; Index < Data->DataCount; Index++) {\r
1504 CopyMem (TempBuffer, DataLocation, DataLocation->Length);\r
1505 ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length;\r
1506 OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
1507 CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
1508 TempBuffer = TempBuffer + DataLocation->Length;\r
1509 DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
1510 }\r
1511 //\r
1512 // Go to the next Op-Code\r
1513 //\r
1514 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1515 continue;\r
1516 } else {\r
1517 //\r
1518 // Copy the label\r
1519 //\r
1520 CopyMem (TempBuffer, Location, Location->Length);\r
1521 TempBuffer = TempBuffer + Location->Length;\r
1522 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1523\r
1524 //\r
1525 // Remove the DataCount amount of opcodes unless we run into an end of form or a label\r
1526 //\r
1527 for (Index = 0; Index < Data->DataCount; Index++) {\r
1528 //\r
1529 // If we are about to skip an end form - bail out, since that is illegal\r
1530 //\r
1531 if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) {\r
1532 break;\r
1533 }\r
1534 //\r
1535 // By skipping Location entries, we are in effect not copying what was previously there\r
1536 //\r
1537 ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length;\r
1538 OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
1539 CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
1540 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1541 }\r
1542 }\r
1543\r
1544 default:\r
1545 CopyMem (TempBuffer, Location, Location->Length);\r
1546 TempBuffer = TempBuffer + Location->Length;\r
1547 break;\r
1548 }\r
1549 //\r
1550 // Go to the next Op-Code\r
1551 //\r
1552 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1553 }\r
1554 //\r
1555 // Copy the last op-code left behind from the for loop\r
1556 //\r
1557 CopyMem (TempBuffer, Location, Location->Length);\r
1558\r
1559 //\r
1560 // Advance to beginning of strings and copy them\r
1561 //\r
1562 TempBuffer = TempBuffer + Location->Length;\r
1563 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1564 CopyMem (TempBuffer, Location, PackageInstance->StringSize);\r
1565\r
1566 //\r
1567 // Free the old buffer, and assign into our database the latest buffer\r
1568 //\r
1569 gBS->FreePool (HandleDatabase->Buffer);\r
1570 HandleDatabase->Buffer = OrigTempBuffer;\r
1571\r
1572 return EFI_SUCCESS;\r
1573}\r