]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c
Add checking for memory allocation in UI modules.
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / HiiDataBase / Dxe / Forms.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Forms.c\r
15\r
16Abstract:\r
17\r
18 This file contains the form processing code to the HII database.\r
19\r
20--*/\r
21\r
22\r
23#include "HiiDatabase.h"\r
24\r
25CHAR16*\r
26Ascii2Unicode (\r
27 OUT CHAR16 *UnicodeStr,\r
28 IN CHAR8 *AsciiStr\r
29 )\r
30/*++\r
31 \r
32 Routine Description:\r
33\r
34 This function converts ASCII string to Unicode string.\r
35 \r
36 Arguments:\r
37\r
38 UnicodeStr - NULL terminated Unicode output string.\r
39 AsciieStr - NULL terminated ASCII input string.\r
40 \r
41 Returns: \r
42\r
43 Start of the Unicode ouput string.\r
44 \r
45--*/\r
46\r
47{\r
48 CHAR16 *Str = UnicodeStr; \r
49 while (TRUE) {\r
50 *(UnicodeStr++) = (CHAR16) *AsciiStr;\r
51 if (*(AsciiStr++) == '\0') {\r
52 return Str;\r
53 }\r
54 }\r
55}\r
56\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
89VOID\r
90ExtractDevicePathData (\r
91 IN EFI_HII_DATA_TABLE *DataTable,\r
92 IN UINT8 *IfrData,\r
93 IN OUT UINT8 **ExportBufferPtr\r
94 )\r
95/*++\r
96\r
97Routine Description:\r
98 \r
99Arguments:\r
100\r
101Returns: \r
102\r
103--*/\r
104{\r
105 UINT8 *ExportBuffer;\r
106\r
107 ExportBuffer = *ExportBufferPtr;\r
108\r
109 //\r
110 // BUGBUG - don't have devicepath data yet, setting dummy value\r
111 //\r
112 DataTable++;\r
113 ExportBuffer = (UINT8 *) DataTable;\r
114 ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH;\r
115 ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
116\r
117 //\r
118 // BUGBUG - part of hack - skip the Device Path Pack.....place some data\r
119 //\r
120 ExportBuffer = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK);\r
121\r
122 ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type = EFI_END_ENTIRE_DEVICE_PATH;\r
123 ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
124\r
125 //\r
126 // BUGBUG - still part of hack....\r
127 //\r
128 ExportBuffer = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
129 *ExportBufferPtr = ExportBuffer;\r
130}\r
131\r
132VOID\r
133ExtractVariableData (\r
134 IN OUT EFI_HII_DATA_TABLE *DataTable,\r
135 IN UINT8 *IfrData,\r
136 IN OUT UINT8 **ExportBufferPtr\r
137 )\r
138/*++\r
139\r
140Routine Description:\r
141\r
142 This function extract the EFI_HII_VARIABLE_PACK portion from the \r
143 each of the EFI_HII_PACKAGE_INSTANCE in HII handle database.\r
144 \r
145Arguments:\r
146\r
511710d6 147 DataTable - On input, this parameter point to the EFI_HII_DATA_TABLE structure\r
878ddf1f 148 of the final data buffer for the EFI_HII_EXPORT interface. This function\r
149 update the NumberOfVariableData attribute.\r
150 IfrData - It points to a staring address of a EFI_HII_IFR_PACK structure.\r
511710d6 151 ExportBufferPtr - On input, it points the starting address of the data buffer to \r
878ddf1f 152 host the variable pack. On output, it is the starting address\r
153 of data buffer for the next extraction operation.\r
154Returns: \r
155\r
156 VOID\r
157 \r
158--*/\r
159{\r
160 EFI_HII_VARIABLE_PACK *VariableContents;\r
161 UINT8 *ExportBuffer;\r
162 UINTN Index;\r
163 UINTN Index2;\r
164 UINTN TempValue;\r
165 UINTN TempValue2;\r
166 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;\r
167 EFI_PHYSICAL_ADDRESS CallbackHandle;\r
168 EFI_STATUS Status;\r
169 CHAR16 *String;\r
170\r
171 FormCallback = NULL;\r
172 CallbackHandle = 0;\r
173 ExportBuffer = *ExportBufferPtr;\r
174\r
175 for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
176 VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
177\r
178 switch (IfrData[Index]) {\r
179 case EFI_IFR_FORM_SET_OP:\r
180 TempValue = EFI_HII_VARIABLE;\r
181 CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
182 CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
183\r
184 //\r
185 // If the variable has 0 size, do not process it\r
186 //\r
187 if (TempValue == 0) {\r
188 break;\r
189 }\r
190 //\r
191 // Add the size of the variable pack overhead. Later, will also add the size of the\r
192 // name of the variable.\r
193 //\r
194 TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);\r
195\r
196 CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
197 CopyMem (\r
198 &CallbackHandle,\r
199 &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle,\r
200 sizeof (EFI_PHYSICAL_ADDRESS)\r
201 );\r
202 if (CallbackHandle != 0) {\r
203 Status = gBS->HandleProtocol (\r
204 (EFI_HANDLE) (UINTN) CallbackHandle,\r
205 &gEfiFormCallbackProtocolGuid,\r
206 (VOID *) &FormCallback\r
207 );\r
208 }\r
209 //\r
210 // Since we have a "Setup" variable that wasn't specified by a variable op-code\r
211 // it will have a VariableId of 0. All other variable op-codes will have a designation\r
212 // of VariableId 1+\r
213 //\r
214 TempValue = 0;\r
215 CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16));\r
216 CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID));\r
217 TempValue = sizeof (SETUP_MAP_NAME);\r
218 CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));\r
219\r
220 //\r
221 // Add the size of the name to the Header Length\r
222 //\r
223 TempValue2 = 0;\r
224 CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));\r
225 TempValue2 = TempValue + TempValue2;\r
226 CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));\r
227\r
228 ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
229 CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME));\r
230 ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME);\r
231\r
232 CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
233\r
234 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
235 Status = FormCallback->NvRead (\r
236 FormCallback,\r
237 (CHAR16 *) SETUP_MAP_NAME,\r
238 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
239 NULL,\r
240 &TempValue,\r
241 ExportBuffer\r
242 );\r
243 } else {\r
244 Status = gRT->GetVariable (\r
245 (CHAR16 *) SETUP_MAP_NAME,\r
246 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
247 NULL,\r
248 &TempValue,\r
249 ExportBuffer\r
250 );\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 } else {\r
310 Status = gRT->GetVariable (\r
311 String,\r
312 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
313 NULL,\r
314 &TempValue,\r
315 ExportBuffer\r
316 );\r
317 }\r
318\r
319 ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);\r
320 DataTable->NumberOfVariableData++;\r
321 break;\r
322 }\r
323\r
324 Index = IfrData[Index + 1] + Index;\r
325 }\r
326 //\r
327 // If we have added a variable pack, add a dummy empty one to signify the end\r
328 //\r
329 if (ExportBuffer != *ExportBufferPtr) {\r
330 VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
331 TempValue = EFI_HII_VARIABLE;\r
332 CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
333 TempValue = sizeof (EFI_HII_VARIABLE_PACK);\r
334 CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
335 ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
336 }\r
337\r
338 *ExportBufferPtr = ExportBuffer;\r
339}\r
340\r
341EFI_STATUS\r
342EFIAPI\r
343HiiExportDatabase (\r
344 IN EFI_HII_PROTOCOL *This,\r
345 IN EFI_HII_HANDLE Handle,\r
346 IN OUT UINTN *BufferSize,\r
347 OUT VOID *Buffer\r
348 )\r
349/*++\r
350\r
351Routine Description:\r
352 \r
353 This function allows a program to extract a form or form package that has \r
354 previously been registered with the EFI HII database.\r
355\r
356Arguments:\r
357\r
358Returns: \r
359\r
360--*/\r
361{\r
362 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
363 EFI_HII_DATA *HiiData;\r
364 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
365 EFI_HII_IFR_PACK *FormPack;\r
366 UINT8 *RawData;\r
367 UINT8 *ExportBuffer;\r
368 EFI_HII_EXPORT_TABLE *ExportTable;\r
369 EFI_HII_DATA_TABLE *DataTable;\r
370 BOOLEAN InsufficientSize;\r
371 BOOLEAN VariableExist;\r
372 UINT16 NumberOfHiiDataTables;\r
373 UINTN SizeNeeded;\r
374 UINTN Index;\r
375 UINTN VariableSize;\r
376 UINTN TempValue;\r
377\r
378 if (This == NULL) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381\r
382 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
383\r
384 HandleDatabase = HiiData->DatabaseHead;\r
385\r
386 FormPack = NULL;\r
387 RawData = NULL;\r
388 PackageInstance = NULL;\r
389 InsufficientSize = FALSE;\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
412 SizeNeeded = SizeNeeded + PackageInstance->IfrSize \r
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
694 \r
695 This function allows a program to extract a form or form package that has \r
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
700 \r
701 Handle - Handle on which the form resides. Type EFI_HII_HANDLE is defined in \r
702 EFI_HII_PROTOCOL.NewPack() in the Packages section.\r
703 \r
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
706 \r
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
710 \r
711 Buffer - The buffer designed to receive the form(s).\r
712\r
713Returns: \r
714\r
715 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength\r
716 was updated.\r
717 \r
718 EFI_INVALID_PARAMETER - The handle is unknown.\r
719 \r
720 EFI_NOT_FOUND - A form on the requested handle cannot be found with the\r
721 requested FormId.\r
722 \r
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\r
735 if (This == NULL) {\r
736 return EFI_INVALID_PARAMETER;\r
737 }\r
738\r
739 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
740\r
741 HandleDatabase = HiiData->DatabaseHead;\r
742\r
743 PackageInstance = NULL;\r
744\r
745 //\r
746 // Check numeric value against the head of the database\r
747 //\r
748 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
749 //\r
750 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
751 //\r
752 if (Handle == HandleDatabase->Handle) {\r
753 PackageInstance = HandleDatabase->Buffer;\r
754 break;\r
755 }\r
756 }\r
757 //\r
758 // No handle was found - error condition\r
759 //\r
760 if (PackageInstance == NULL) {\r
761 return EFI_NOT_FOUND;\r
762 }\r
763 //\r
764 // Based on if there is IFR data in this package instance, determine\r
765 // what the location is of the beginning of the string data.\r
766 //\r
767 if (PackageInstance->IfrSize > 0) {\r
768 FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);\r
769 } else {\r
770 //\r
771 // If there is no IFR data return an error\r
772 //\r
773 return EFI_NOT_FOUND;\r
774 }\r
775 //\r
776 // If requesting the entire Form Package\r
777 //\r
778 if (FormId == 0) {\r
779 //\r
780 // Return an error if buffer is too small\r
781 //\r
782 if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {\r
783 *BufferLength = (UINT16) PackageInstance->IfrSize;\r
784 return EFI_BUFFER_TOO_SMALL;\r
785 }\r
786\r
787 CopyMem (Buffer, FormPack, PackageInstance->IfrSize);\r
788 return EFI_SUCCESS;\r
789 } else {\r
790 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
791 Location = (EFI_IFR_OP_HEADER *) FormPack;\r
792\r
793 //\r
794 // Look for the FormId requested\r
795 //\r
796 for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
797 switch (Location->OpCode) {\r
798 case EFI_IFR_FORM_OP:\r
799 Form = (EFI_IFR_FORM *) Location;\r
800\r
801 //\r
802 // If we found a Form Op-code and it is of the correct Id, copy it and return\r
803 //\r
804 if (Form->FormId == FormId) {\r
805 if (Location->Length > *BufferLength || Buffer == NULL) {\r
806 *BufferLength = Location->Length;\r
807 return EFI_BUFFER_TOO_SMALL;\r
808 } else {\r
809 for (; Location->OpCode != EFI_IFR_END_FORM_OP;) {\r
810 CopyMem (Buffer, Location, Location->Length);\r
811 Buffer = Buffer + Location->Length;\r
812 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
813 }\r
814\r
815 CopyMem (Buffer, Location, Location->Length);\r
816 return EFI_SUCCESS;\r
817 }\r
818 }\r
819\r
820 default:\r
821 break;\r
822 }\r
823 //\r
824 // Go to the next Op-Code\r
825 //\r
826 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
827 }\r
828 }\r
829\r
830 return EFI_SUCCESS;\r
831}\r
832\r
833//\r
834// Helper functions to HiiGetDefaultImage()\r
835//\r
836\r
837STATIC\r
838UINT8*\r
839HiiGetDefaultImageInitPack (\r
840 IN OUT EFI_HII_VARIABLE_PACK_LIST *VariablePackItem,\r
841 IN EFI_IFR_VARSTORE *VarStore\r
842 )\r
843/*++\r
844 \r
845 Routine Description:\r
846\r
847 Initialize the EFI_HII_VARIABLE_PACK_LIST structure and\r
848 prepare it ready to be used by HiiGetDefaultImagePopulateMap ().\r
849 \r
850 Arguments:\r
851\r
852 VariablePackItem - Variable Package List.\r
853 VarStore - IFR variable storage.\r
854 \r
855 Returns: \r
856\r
857 Return the pointer to the Map space.\r
858 \r
859--*/\r
860{\r
861 CHAR16 *Name16;\r
862 CHAR8 *Name8;\r
863 CHAR8 *Map;\r
864 EFI_HII_VARIABLE_PACK *VariablePack;\r
865\r
866 //\r
867 // Set pointer the pack right after the node\r
868 //\r
869 VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1);\r
870 VariablePack = VariablePackItem->VariablePack;\r
871\r
872 //\r
873 // Copy the var name to VariablePackItem from VarStore\r
874 // Needs ASCII->Unicode conversion.\r
875 //\r
876 ASSERT (VarStore->Header.Length > sizeof (*VarStore));\r
877 Name8 = (CHAR8 *) (VarStore + 1);\r
878 Name16 = (CHAR16 *) (VariablePack + 1);\r
879 Ascii2Unicode (Name16, Name8);\r
880\r
881 //\r
882 // Compute the other fields of the VariablePackItem\r
883 //\r
884 VariablePack->VariableId = VarStore->VarId;\r
885 CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID));\r
886 VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2);\r
887 VariablePack->Header.Length = sizeof (*VariablePack) \r
888 + VariablePack->VariableNameLength\r
889 + VarStore->Size;\r
890 //\r
891 // Return the pointer to the Map space.\r
892 //\r
893 Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength;\r
894\r
895 return (UINT8 *)Map;\r
896}\r
897\r
898STATIC\r
899VOID\r
900HiiGetDefaultImagePopulateMap (\r
901 IN OUT UINT8 *Map, \r
902 IN EFI_IFR_OP_HEADER *FormSet,\r
903 IN EFI_IFR_VARSTORE *VarStore,\r
904 IN UINTN DefaultMask\r
905 )\r
906/*++\r
907 \r
908 Routine Description:\r
909\r
910 Fill the Map with all the default values either from NV or Hii database.\r
911 \r
912 Arguments:\r
913\r
914 Map - Memory pointer to hold the default values.\r
915 FormSet - The starting EFI_IFR_OP_HEADER to begin retriving default values.\r
916 VarStore - IFR variable storage.\r
917 DefaultMask - The mask used to get the default variable.\r
918 \r
919 Returns: \r
920\r
921 VOID\r
922 \r
923--*/\r
924{\r
925 EFI_STATUS Status;\r
926 EFI_IFR_OP_HEADER *IfrItem;\r
927 UINT16 VarId;\r
928 EFI_IFR_VARSTORE_SELECT *VarSelect;\r
929 EFI_IFR_ONE_OF_OPTION *OneOfOpt;\r
930 EFI_IFR_CHECKBOX *CheckBox;\r
931 EFI_IFR_NUMERIC *Numeric;\r
932 UINTN Size;\r
933 UINTN SizeTmp;\r
934 EFI_IFR_NV_DATA *IfrNvData;\r
935 EFI_GUID Guid;\r
936 CHAR16 *Name16;\r
937 CHAR8 *Name8; \r
938 EFI_HANDLE CallbackHandle;\r
939 EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProt;\r
940\r
941 //\r
942 // Get the Map's Name/Guid/Szie from the Varstore.\r
943 // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode.\r
944 //\r
945 ASSERT (VarStore->Header.Length >= sizeof (*VarStore));\r
946 Name8 = (CHAR8 *) (VarStore + 1);\r
947 Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16));\r
948 Ascii2Unicode (Name16, Name8);\r
949 CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID));\r
950 Size = VarStore->Size;\r
951\r
952 //\r
953 // First, check if the map exists in the NV. If so, get it from NV and exit.\r
954 //\r
955 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
956 //\r
957 // Check if Manufaturing Defaults exist in the NV.\r
958 //\r
959 Status = EfiLibHiiVariableOverrideBySuffix (\r
960 HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE,\r
961 Name16,\r
962 &Guid,\r
963 Size,\r
964 Map\r
965 );\r
966 } else {\r
967 //\r
968 // All other cases default to Defaults. Check if Defaults exist in the NV.\r
969 //\r
970 Status = EfiLibHiiVariableOverrideBySuffix (\r
971 HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE,\r
972 Name16,\r
973 &Guid,\r
974 Size,\r
975 Map\r
976 );\r
977 }\r
978 if (!EFI_ERROR (Status)) {\r
979 //\r
980 // Either Defaults/Manufacturing variable exists and appears to be valid. \r
981 // The map is read, exit w/ success now.\r
982 //\r
983 gBS->FreePool (Name16);\r
984 return;\r
985 }\r
986\r
987 //\r
988 // First, prime the map with what already is in the NV.\r
989 // This is needed to cover a situation where the IFR does not contain all the \r
990 // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default.\r
991 // Ignore status. Either it gets read or not. \r
992 // \r
993 FormCallbackProt = NULL;\r
994 CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle));\r
995 if (CallbackHandle != NULL) {\r
996 Status = gBS->HandleProtocol (\r
997 (EFI_HANDLE) (UINTN) CallbackHandle,\r
998 &gEfiFormCallbackProtocolGuid,\r
999 (VOID *) &FormCallbackProt\r
1000 );\r
1001 }\r
1002 if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) {\r
1003 //\r
1004 // Attempt to read using NvRead() callback. Probe first for existence and correct variable size.\r
1005 //\r
1006 SizeTmp = 0;\r
1007 Status = FormCallbackProt->NvRead (\r
1008 FormCallbackProt,\r
1009 Name16,\r
1010 &Guid,\r
1011 0,\r
1012 &SizeTmp,\r
1013 NULL\r
1014 );\r
1015 if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) {\r
1016 Status = FormCallbackProt->NvRead (\r
1017 FormCallbackProt,\r
1018 Name16,\r
1019 &Guid,\r
1020 0,\r
1021 &SizeTmp,\r
1022 Map\r
1023 );\r
1024 ASSERT_EFI_ERROR (Status);\r
1025 ASSERT (SizeTmp == Size);\r
1026 }\r
1027 } else {\r
1028 //\r
1029 // No callback available for this formset, read straight from NV. Deliberately ignore the Status. \r
1030 // The buffer will only be written if variable exists nd has correct size.\r
1031 //\r
1032 Status = EfiLibHiiVariableRetrieveFromNv (\r
1033 Name16,\r
1034 &Guid,\r
1035 Size,\r
1036 (VOID **) &Map\r
1037 );\r
1038 }\r
1039\r
1040 //\r
1041 // Iterate all IFR statements and for applicable, retrieve the default into the Map.\r
1042 //\r
1043 for (IfrItem = FormSet, VarId = 0; \r
1044 IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP; \r
1045 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length)\r
1046 ) {\r
1047\r
1048 //\r
1049 // Observe VarStore switch.\r
1050 //\r
1051 if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) {\r
1052 VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem;\r
1053 VarId = VarSelect->VarId;\r
1054 continue;\r
1055 }\r
1056\r
1057\r
1058 //\r
1059 // Skip opcodes that reference other VarStore than that specific to current map.\r
1060 // \r
1061 if (VarId != VarStore->VarId) {\r
1062 continue;\r
1063 }\r
1064 \r
1065 //\r
1066 // Extract the default value from this opcode if applicable, and apply it to the map.\r
1067 //\r
1068 IfrNvData = (EFI_IFR_NV_DATA *) IfrItem;\r
1069 switch (IfrItem->OpCode) {\r
1070\r
1071 case EFI_IFR_ONE_OF_OP:\r
1072 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1073 //\r
1074 // Get to the first EFI_IFR_ONE_OF_OPTION_OP\r
1075 //\r
1076 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length); \r
1077 ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode);\r
1078\r
1079 OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
1080 //\r
1081 // In the worst case, the first will be the default.\r
1082 //\r
1083 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1084\r
1085 while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) {\r
1086\r
1087 OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
1088 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
1089 if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
1090 //\r
1091 // In the worst case, the first will be the default.\r
1092 //\r
1093 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1094 break;\r
1095 }\r
1096 } else {\r
1097 if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) {\r
1098 //\r
1099 // In the worst case, the first will be the default.\r
1100 //\r
1101 CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
1102 break;\r
1103 }\r
1104 }\r
1105\r
1106 IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length);\r
1107 }\r
1108 continue;\r
1109 break;\r
1110\r
1111 case EFI_IFR_CHECKBOX_OP:\r
1112 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1113 CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem; \r
1114 if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
1115 if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
1116 *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
1117 }\r
1118 } else {\r
1119 if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) {\r
1120 *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
1121 }\r
1122 }\r
1123 break;\r
1124\r
1125 case EFI_IFR_NUMERIC_OP:\r
1126 ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
1127 Numeric = (EFI_IFR_NUMERIC *) IfrItem;\r
1128 CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth);\r
1129 break;\r
1130\r
1131 case EFI_IFR_ORDERED_LIST_OP:\r
1132 case EFI_IFR_PASSWORD_OP:\r
1133 case EFI_IFR_STRING_OP:\r
1134 //\r
1135 // No support for default value for these opcodes.\r
1136 //\r
1137 break;\r
1138 }\r
1139 }\r
1140\r
1141 gBS->FreePool (Name16);\r
1142\r
1143}\r
1144\r
1145\r
1146EFI_STATUS\r
1147EFIAPI\r
1148HiiGetDefaultImage (\r
1149 IN EFI_HII_PROTOCOL *This,\r
1150 IN EFI_HII_HANDLE Handle,\r
1151 IN UINTN DefaultMask,\r
1152 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList\r
1153 )\r
1154/*++\r
1155 \r
1156 Routine Description:\r
1157\r
1158 This function allows a program to extract the NV Image \r
1159 that represents the default storage image\r
1160 \r
1161 Arguments:\r
1162 This - A pointer to the EFI_HII_PROTOCOL instance.\r
1163 Handle - The HII handle from which will have default data retrieved.\r
1164 UINTN - Mask used to retrieve the default image.\r
1165 VariablePackList - Callee allocated, tightly-packed, link list data \r
1166 structure that contain all default varaible packs\r
1167 from the Hii Database.\r
1168 \r
1169 Returns: \r
1170 EFI_NOT_FOUND - If Hii database does not contain any default images.\r
1171 EFI_INVALID_PARAMETER - Invalid input parameter.\r
1172 EFI_SUCCESS - Operation successful.\r
1173 \r
1174--*/\r
1175{\r
1176 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
1177 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
1178 EFI_IFR_OP_HEADER *FormSet;\r
1179 EFI_IFR_OP_HEADER *IfrItem;\r
1180 EFI_IFR_VARSTORE *VarStore;\r
1181 EFI_IFR_VARSTORE *VarStoreDefault;\r
1182 UINTN SetupMapNameSize;\r
1183 UINTN SizeOfMaps;\r
1184 EFI_HII_VARIABLE_PACK_LIST *PackList;\r
1185 EFI_HII_VARIABLE_PACK_LIST *PackListNext; \r
1186 EFI_HII_VARIABLE_PACK_LIST *PackListLast;\r
1187 UINT8 *Map;\r
1188\r
1189\r
1190 //\r
1191 // Find the IFR pack from the handle. Then get the formset from the pack.\r
1192 //\r
1193 PackageInstance = NULL;\r
1194 HandleDatabase = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead;\r
1195 for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
1196 if (Handle == HandleDatabase->Handle) {\r
1197 PackageInstance = HandleDatabase->Buffer;\r
1198 break;\r
1199 }\r
1200 }\r
1201 if (PackageInstance == NULL) {\r
1202 return EFI_INVALID_PARAMETER;\r
1203 }\r
1204 FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK));\r
1205\r
1206 //\r
1207 // Get the sizes of all the VARSTOREs in this VFR.\r
1208 // Then allocate enough space for all of them plus all maps\r
1209 //\r
1210 SizeOfMaps = 0;\r
1211 IfrItem = FormSet;\r
1212 while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
1213\r
1214 if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
1215 VarStore = (EFI_IFR_VARSTORE *) IfrItem;\r
1216 //\r
1217 // Size of the map\r
1218 //\r
1219 SizeOfMaps += VarStore->Size; \r
1220 //\r
1221 // add the size of the string, in Unicode\r
1222 //\r
1223 SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2; \r
1224 //\r
1225 // Space for node\r
1226 //\r
1227 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
1228 //\r
1229 // Space for linked list node \r
1230 //\r
1231 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
1232 }\r
1233\r
1234 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
1235 }\r
1236\r
1237 //\r
1238 // If the FormSet OpCode has a non-zero NvDataSize. There is a default \r
1239 // NvMap with ID=0, GUID that of the formset itself and "Setup" as name.\r
1240 //\r
1241 SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1;\r
1242 VarStoreDefault = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
1243\r
1244 if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) {\r
1245\r
1246 VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP;\r
1247 VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
1248 Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME);\r
1249 CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID));\r
1250 VarStoreDefault->VarId = 0;\r
1251 VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize;\r
1252\r
1253 //\r
1254 // Size of the map\r
1255 //\r
1256 SizeOfMaps += VarStoreDefault->Size; \r
1257 //\r
1258 // add the size of the string\r
1259 //\r
1260 SizeOfMaps += sizeof (SETUP_MAP_NAME); \r
1261 //\r
1262 // Space for node\r
1263 //\r
1264 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
1265 //\r
1266 // Space for linked list node \r
1267 //\r
1268 SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
1269 }\r
1270\r
1271 if (0 == SizeOfMaps) {\r
1272 //\r
1273 // The IFR does not have any explicit or default map(s).\r
1274 //\r
1275 return EFI_NOT_FOUND; \r
1276 }\r
1277\r
1278 //\r
1279 // Allocate the return buffer\r
1280 //\r
1281 PackList = AllocateZeroPool (SizeOfMaps);\r
1282 ASSERT (NULL != PackList); \r
1283\r
1284 PackListNext = PackList;\r
1285 PackListLast = PackList;\r
1286\r
1287 //\r
1288 // Handle the default map first, if any.\r
1289 //\r
1290 if (0 != VarStoreDefault->Size) {\r
1291\r
1292 Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault);\r
1293\r
1294 HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask);\r
1295\r
1296 PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
1297 PackListLast = PackListNext;\r
1298 PackListNext = PackListNext->NextVariablePack;\r
1299 }\r
1300\r
1301\r
1302 //\r
1303 // Handle the explicit varstore(s)\r
1304 //\r
1305 IfrItem = FormSet;\r
1306 while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
1307\r
1308 if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
1309\r
1310 Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem);\r
1311\r
1312 HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask);\r
1313\r
1314 PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
1315 PackListLast = PackListNext;\r
1316 PackListNext = PackListNext->NextVariablePack;\r
1317 }\r
1318\r
1319 IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
1320 }\r
1321\r
1322 PackListLast->NextVariablePack = NULL;\r
1323 *VariablePackList = PackList;\r
1324 \r
1325 return EFI_SUCCESS;\r
1326}\r
1327\r
1328\r
1329EFI_STATUS\r
1330EFIAPI\r
1331HiiUpdateForm (\r
1332 IN EFI_HII_PROTOCOL *This,\r
1333 IN EFI_HII_HANDLE Handle,\r
1334 IN EFI_FORM_LABEL Label,\r
1335 IN BOOLEAN AddData,\r
1336 IN EFI_HII_UPDATE_DATA *Data\r
1337 )\r
1338/*++\r
1339\r
1340Routine Description:\r
1341 This function allows the caller to update a form that has \r
1342 previously been registered with the EFI HII database.\r
1343\r
1344Arguments:\r
1345 Handle - Hii Handle associated with the Formset to modify\r
1346 Label - Update information starting immediately after this label in the IFR\r
1347 AddData - If TRUE, add data. If FALSE, remove data\r
1348 Data - If adding data, this is the pointer to the data to add\r
1349\r
1350Returns: \r
1351 EFI_SUCCESS - Update success.\r
1352 Other - Update fail.\r
1353\r
1354--*/\r
1355{\r
1356 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
1357 EFI_HII_DATA *HiiData;\r
1358 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
1359 EFI_HII_IFR_PACK *FormPack;\r
1360 EFI_IFR_OP_HEADER *Location;\r
1361 EFI_IFR_OP_HEADER *DataLocation;\r
1362 UINT8 *OtherBuffer;\r
1363 UINT8 *TempBuffer;\r
1364 UINT8 *OrigTempBuffer;\r
1365 UINTN TempBufferSize;\r
1366 UINTN Index;\r
1367\r
1368 OtherBuffer = NULL;\r
1369\r
1370 if (This == NULL) {\r
1371 return EFI_INVALID_PARAMETER;\r
1372 }\r
1373\r
1374 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
1375\r
1376 HandleDatabase = HiiData->DatabaseHead;\r
1377\r
1378 PackageInstance = NULL;\r
1379\r
1380 //\r
1381 // Check numeric value against the head of the database\r
1382 //\r
1383 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
1384 //\r
1385 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
1386 //\r
1387 if (Handle == HandleDatabase->Handle) {\r
1388 PackageInstance = HandleDatabase->Buffer;\r
1389 break;\r
1390 }\r
1391 }\r
1392 //\r
1393 // No handle was found - error condition\r
1394 //\r
1395 if (PackageInstance == NULL) {\r
1396 return EFI_INVALID_PARAMETER;\r
1397 }\r
1398 //\r
1399 // Calculate and allocate space for retrieval of IFR data\r
1400 //\r
1401 DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
1402 TempBufferSize = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance);\r
1403\r
1404 for (Index = 0; Index < Data->DataCount; Index++) {\r
1405 TempBufferSize += DataLocation->Length;\r
1406 DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
1407 }\r
1408\r
1409 TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize;\r
1410\r
1411 TempBuffer = AllocateZeroPool (TempBufferSize);\r
41a907e4 1412 ASSERT (TempBuffer != NULL);\r
1413\r
878ddf1f 1414 OrigTempBuffer = TempBuffer;\r
1415\r
1416 //\r
1417 // We update only packages with IFR information in it\r
1418 //\r
1419 if (PackageInstance->IfrSize == 0) {\r
1420 return EFI_INVALID_PARAMETER;\r
1421 }\r
1422\r
1423 CopyMem (\r
1424 TempBuffer,\r
1425 PackageInstance,\r
1426 ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance))\r
1427 );\r
1428\r
1429 TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance));\r
1430\r
1431 //\r
1432 // Based on if there is IFR data in this package instance, determine\r
1433 // what the location is of the beginning of the string data.\r
1434 //\r
1435 FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
1436 Location = (EFI_IFR_OP_HEADER *) FormPack;\r
1437\r
1438 //\r
1439 // Look for the FormId requested\r
1440 //\r
1441 for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
1442 switch (Location->OpCode) {\r
1443 case EFI_IFR_FORM_SET_OP:\r
1444 //\r
1445 // If the FormSet has an update pending, pay attention.\r
1446 //\r
1447 if (Data->FormSetUpdate) {\r
1448 ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle;\r
1449 }\r
1450\r
1451 CopyMem (TempBuffer, Location, Location->Length);\r
1452 TempBuffer = TempBuffer + Location->Length;\r
1453 break;\r
1454\r
1455 case EFI_IFR_FORM_OP:\r
1456 //\r
1457 // If the Form has an update pending, pay attention.\r
1458 //\r
1459 if (Data->FormUpdate) {\r
1460 ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle;\r
1461 }\r
1462\r
1463 CopyMem (TempBuffer, Location, Location->Length);\r
1464 TempBuffer = TempBuffer + Location->Length;\r
1465 break;\r
1466\r
1467 case EFI_IFR_LABEL_OP:\r
1468 //\r
1469 // If the label does not match the requested update point, ignore it\r
1470 //\r
1471 if (((EFI_IFR_LABEL *) Location)->LabelId != Label) {\r
1472 //\r
1473 // Copy the label\r
1474 //\r
1475 CopyMem (TempBuffer, Location, Location->Length);\r
1476 TempBuffer = TempBuffer + Location->Length;\r
1477\r
1478 //\r
1479 // Go to the next Op-Code\r
1480 //\r
1481 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1482 continue;\r
1483 }\r
1484\r
1485 if (AddData) {\r
1486 //\r
1487 // Copy the label\r
1488 //\r
1489 CopyMem (TempBuffer, Location, Location->Length);\r
1490 TempBuffer = TempBuffer + Location->Length;\r
1491\r
1492 //\r
1493 // Add the DataCount amount of opcodes to TempBuffer\r
1494 //\r
1495 DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
1496 for (Index = 0; Index < Data->DataCount; Index++) {\r
1497 CopyMem (TempBuffer, DataLocation, DataLocation->Length);\r
1498 ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length;\r
1499 OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
1500 CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
1501 TempBuffer = TempBuffer + DataLocation->Length;\r
1502 DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
1503 }\r
1504 //\r
1505 // Go to the next Op-Code\r
1506 //\r
1507 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1508 continue;\r
1509 } else {\r
1510 //\r
1511 // Copy the label\r
1512 //\r
1513 CopyMem (TempBuffer, Location, Location->Length);\r
1514 TempBuffer = TempBuffer + Location->Length;\r
1515 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1516\r
1517 //\r
1518 // Remove the DataCount amount of opcodes unless we run into an end of form or a label\r
1519 //\r
1520 for (Index = 0; Index < Data->DataCount; Index++) {\r
1521 //\r
1522 // If we are about to skip an end form - bail out, since that is illegal\r
1523 //\r
1524 if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) {\r
1525 break;\r
1526 }\r
1527 //\r
1528 // By skipping Location entries, we are in effect not copying what was previously there\r
1529 //\r
1530 ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length;\r
1531 OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
1532 CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
1533 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1534 }\r
1535 }\r
1536\r
1537 default:\r
1538 CopyMem (TempBuffer, Location, Location->Length);\r
1539 TempBuffer = TempBuffer + Location->Length;\r
1540 break;\r
1541 }\r
1542 //\r
1543 // Go to the next Op-Code\r
1544 //\r
1545 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1546 }\r
1547 //\r
1548 // Copy the last op-code left behind from the for loop\r
1549 //\r
1550 CopyMem (TempBuffer, Location, Location->Length);\r
1551\r
1552 //\r
1553 // Advance to beginning of strings and copy them\r
1554 //\r
1555 TempBuffer = TempBuffer + Location->Length;\r
1556 Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
1557 CopyMem (TempBuffer, Location, PackageInstance->StringSize);\r
1558\r
1559 //\r
1560 // Free the old buffer, and assign into our database the latest buffer\r
1561 //\r
1562 gBS->FreePool (HandleDatabase->Buffer);\r
1563 HandleDatabase->Buffer = OrigTempBuffer;\r
1564\r
1565 return EFI_SUCCESS;\r
1566}\r