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