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