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