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