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