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