Initial import.
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / SetupBrowser / Dxe / ProcessOptions.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 ProcessOptions.c\r
15\r
16Abstract:\r
17 \r
18 Implementation for handling the User Interface option processing.\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "Setup.h"\r
25#include "Ui.h"\r
26\r
27EFI_STATUS\r
28ExtractRequestedNvMap (\r
29 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
30 IN UINT16 VariableId,\r
31 OUT EFI_VARIABLE_DEFINITION **VariableDefinition\r
32 )\r
33{\r
34 *VariableDefinition = FileFormTags->VariableDefinitions;\r
35\r
36 //\r
37 // Extract the data from the NV variable - consumer will free the buffer.\r
38 //\r
39 for (; *VariableDefinition != NULL; *VariableDefinition = (*VariableDefinition)->Next) {\r
40 //\r
41 // If there is a variable with this ID return with EFI_SUCCESS\r
42 //\r
43 if (!CompareMem (&(*VariableDefinition)->VariableId, &VariableId, sizeof (UINT16))) {\r
44 return EFI_SUCCESS;\r
45 }\r
46 }\r
47\r
48 return EFI_NOT_FOUND;\r
49}\r
50\r
51EFI_STATUS\r
52ExtractNvValue (\r
53 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
54 IN UINT16 VariableId,\r
55 IN UINT16 VariableSize,\r
56 IN UINT16 OffsetValue,\r
57 OUT VOID **Buffer\r
58 )\r
59{\r
60 EFI_STATUS Status;\r
61 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
62\r
63 Status = ExtractRequestedNvMap (FileFormTags, VariableId, &VariableDefinition);\r
64\r
65 if (!EFI_ERROR (Status)) {\r
66 //\r
67 // Allocate sufficient space for the data and copy it into the outgoing buffer\r
68 //\r
69 if (VariableSize != 0) {\r
70 *Buffer = AllocateZeroPool (VariableSize);\r
71 ASSERT (*Buffer != NULL);\r
72 CopyMem (*Buffer, &VariableDefinition->NvRamMap[OffsetValue], VariableSize);\r
73 }\r
74 return EFI_SUCCESS;\r
75 }\r
76\r
77 return Status;\r
78}\r
79\r
80VOID\r
81AdjustNvMap (\r
82 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
83 IN UI_MENU_OPTION *MenuOption\r
84 )\r
85{\r
86 CHAR8 *NvRamMap;\r
87 UINTN SizeRequired;\r
88 UINTN Index;\r
89 UINTN CachedStart;\r
90 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
91\r
92 CachedStart = 0;\r
93\r
94 SizeRequired = MenuOption->ThisTag->StorageStart + MenuOption->ThisTag->StorageWidth;\r
95\r
96 ExtractRequestedNvMap (FileFormTags, MenuOption->Tags->VariableNumber, &VariableDefinition);\r
97\r
98 //\r
99 // We arrived here because the current NvRamMap is too small for the new op-code to store things and\r
100 // we need to adjust the buffer to support this.\r
101 //\r
102 NvRamMap = AllocateZeroPool (SizeRequired + 1);\r
103 ASSERT (NvRamMap != NULL);\r
104\r
105 //\r
106 // Copy current NvRamMap to the new NvRamMap\r
107 //\r
108 CopyMem (NvRamMap, VariableDefinition->NvRamMap, VariableDefinition->VariableFakeSize);\r
109\r
110 //\r
111 // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap\r
112 //\r
113 for (Index = MenuOption->TagIndex;\r
114 (MenuOption->Tags[Index].Operand != EFI_IFR_END_FORM_OP) && (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP);\r
115 Index++\r
116 ) {\r
117\r
118 switch (MenuOption->Tags[Index].Operand) {\r
119 case EFI_IFR_ORDERED_LIST_OP:\r
120 case EFI_IFR_ONE_OF_OP:\r
121 CachedStart = MenuOption->Tags[Index].StorageStart;\r
122 break;\r
123\r
124 case EFI_IFR_ONE_OF_OPTION_OP:\r
125 if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) {\r
126 CopyMem (&NvRamMap[CachedStart], &MenuOption->Tags[Index].Value, 2);\r
127 }\r
128 break;\r
129\r
130 case EFI_IFR_CHECKBOX_OP:\r
131 CopyMem (&NvRamMap[MenuOption->Tags[Index].StorageStart], &MenuOption->Tags[Index].Flags, 1);\r
132 break;\r
133\r
134 case EFI_IFR_NUMERIC_OP:\r
135 case EFI_IFR_DATE_OP:\r
136 case EFI_IFR_TIME_OP:\r
137 case EFI_IFR_STRING_OP:\r
138 case EFI_IFR_PASSWORD_OP:\r
139 CopyMem (\r
140 &NvRamMap[MenuOption->Tags[Index].StorageStart],\r
141 &MenuOption->Tags[Index].Value,\r
142 MenuOption->Tags[Index].StorageWidth\r
143 );\r
144 break;\r
145\r
146 }\r
147 }\r
148\r
149 gBS->FreePool (VariableDefinition->NvRamMap);\r
150 VariableDefinition->NvRamMap = NvRamMap;\r
151 VariableDefinition->VariableFakeSize = (UINT16) SizeRequired;\r
152}\r
153\r
154EFI_STATUS\r
155ProcessOptions (\r
156 IN UI_MENU_OPTION *MenuOption,\r
157 IN BOOLEAN Selected,\r
158 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,\r
159 IN EFI_IFR_DATA_ARRAY *PageData,\r
160 OUT CHAR16 **OptionString\r
161 )\r
162{\r
163 EFI_STATUS Status;\r
164 CHAR16 *StringPtr;\r
165 UINTN Index;\r
166 UINTN CachedIndex;\r
167 EFI_FILE_FORM_TAGS *FileFormTags;\r
168 EFI_TAG *Tag;\r
169 CHAR16 FormattedNumber[6];\r
170 UINT16 Number;\r
171 UINT16 Value;\r
172 UINT16 *ValueArray;\r
173 UINT16 *NvRamMap;\r
174 CHAR8 *TmpNvRamMap;\r
175 UINTN Default;\r
176 UINTN StringCount;\r
177 CHAR16 Character[2];\r
178 UINTN Count;\r
179 EFI_TIME Time;\r
180 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;\r
181 STRING_REF PopUp;\r
182 CHAR16 NullCharacter;\r
183 EFI_INPUT_KEY Key;\r
184 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
185 BOOLEAN OrderedList;\r
186 BOOLEAN Initialized;\r
187 UINT16 KeyValue;\r
188 BOOLEAN Skip;\r
189\r
190 FileFormTags = FileFormTagsHead;\r
191\r
192 for (Index = 0; Index < MenuOption->IfrNumber; Index++) {\r
193 FileFormTags = FileFormTags->NextFile;\r
194 }\r
195\r
196 OrderedList = FALSE;\r
197 Initialized = FALSE;\r
198 ValueArray = NULL;\r
199 VariableDefinition = NULL;\r
200 Skip = FALSE;\r
201\r
202 ZeroMem (&Time, sizeof (EFI_TIME));\r
203\r
204 StringPtr = (CHAR16 *) L"\0";\r
205 Tag = MenuOption->ThisTag;\r
206 ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);\r
207\r
208 if (Tag->StorageStart > VariableDefinition->VariableSize) {\r
209 NvRamMap = (UINT16 *) &VariableDefinition->FakeNvRamMap[Tag->StorageStart];\r
210 } else {\r
211 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
212 }\r
213\r
214 StringCount = 0;\r
215 Character[1] = 0;\r
216 Count = 0;\r
217 Default = 0;\r
218 NullCharacter = CHAR_NULL;\r
219 FormCallback = NULL;\r
220\r
221 if (MenuOption->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
222 OrderedList = TRUE;\r
223 if (((UINT8 *) NvRamMap)[0] != 0x00) {\r
224 Initialized = TRUE;\r
225 }\r
226 }\r
227\r
228 ZeroMem (FormattedNumber, 12);\r
229\r
230 Status = gBS->HandleProtocol (\r
231 (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,\r
232 &gEfiFormCallbackProtocolGuid,\r
233 (VOID **) &FormCallback\r
234 );\r
235\r
236 if (*OptionString != NULL) {\r
237 gBS->FreePool (*OptionString);\r
238 *OptionString = NULL;\r
239 }\r
240\r
241 switch (Tag->Operand) {\r
242\r
243 case EFI_IFR_ORDERED_LIST_OP:\r
244 case EFI_IFR_ONE_OF_OP:\r
245 //\r
246 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
247 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
248 // the NvMap so that we can properly display the information\r
249 //\r
250 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
251 AdjustNvMap (FileFormTags, MenuOption);\r
252 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
253 }\r
254\r
255 CachedIndex = MenuOption->TagIndex;\r
256\r
257 //\r
258 // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,\r
259 // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks\r
260 // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice\r
261 //\r
262 for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {\r
263 //\r
264 // We found an option - which assumedly has a string. We will eventually have to support\r
265 // wrapping of strings. For now, let's pretend they don't wrap and code that up.\r
266 //\r
267 // Count how many strings there are\r
268 //\r
269 if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {\r
270 //\r
271 // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too\r
272 //\r
273 if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_INTERACTIVE) {\r
274 MenuOption->Tags[CachedIndex].Flags = (UINT8) (MenuOption->Tags[CachedIndex].Flags | EFI_IFR_FLAG_INTERACTIVE);\r
275 }\r
276\r
277 StringCount++;\r
278 }\r
279 }\r
280 //\r
281 // We now know how many strings we will have, so we can allocate the\r
282 // space required for the array or strings.\r
283 //\r
284 *OptionString = AllocateZeroPool (StringCount * (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
285 ASSERT (*OptionString);\r
286\r
287 //\r
288 // Add left delimeter to string\r
289 //\r
290 *OptionString[0] = LEFT_ONEOF_DELIMITER;\r
291\r
292 //\r
293 // Retrieve the current OneOf value\r
294 //\r
295 if (Selected) {\r
296 //\r
297 // Auto selection from list\r
298 //\r
299 Value = 0;\r
300 //\r
301 // Copy current setting to the seed Value\r
302 //\r
303 if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
304 ValueArray = AllocateZeroPool (MenuOption->ThisTag->StorageWidth);\r
305 ASSERT (ValueArray != NULL);\r
306 CopyMem (ValueArray, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
307 } else {\r
308 CopyMem (&Value, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
309 CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
310 }\r
311\r
312 Number = Value;\r
313 if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
314 Status = GetSelectionInputPopUp (MenuOption, Tag, MenuOption->ThisTag->StorageWidth, ValueArray, &KeyValue);\r
315 } else {\r
316 Status = GetSelectionInputPopUp (MenuOption, Tag, 1, &Value, &KeyValue);\r
317 }\r
318\r
319 if (!EFI_ERROR (Status)) {\r
320 if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
321 CopyMem (NvRamMap, ValueArray, MenuOption->ThisTag->StorageWidth);\r
322 gBS->FreePool (ValueArray);\r
323 } else {\r
324 //\r
325 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
326 //\r
327 CopyMem (NvRamMap, &Value, Tag->StorageWidth);\r
328 MenuOption->ThisTag->Key = KeyValue;\r
329 }\r
330 //\r
331 // If a late check is required save off the information. This is used when consistency checks\r
332 // are required, but certain values might be bound by an impossible consistency check such as\r
333 // if two questions are bound by consistency checks and each only has two possible choices, there\r
334 // would be no way for a user to switch the values. Thus we require late checking.\r
335 //\r
336 if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {\r
337 CopyMem (&Tag->OldValue, &Value, Tag->StorageWidth);\r
338 } else {\r
339 //\r
340 // In theory, passing the value and the Id are sufficient to determine what needs\r
341 // to be done. The Id is the key to look for the entry needed in the Inconsistency\r
342 // database. That will yields operand and ID data - and since the ID's correspond\r
343 // to the NV storage, we can determine the values for other IDs there.\r
344 //\r
345 if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {\r
346 if (PopUp == 0x0000) {\r
347 //\r
348 // Restore Old Value\r
349 //\r
350 if (!Tag->Suppress && !Tag->GrayOut) {\r
351 CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);\r
352 }\r
353 break;\r
354 }\r
355\r
356 StringPtr = GetToken (PopUp, MenuOption->Handle);\r
357\r
358 CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);\r
359\r
360 do {\r
361 Status = WaitForKeyStroke (&Key);\r
362\r
363 switch (Key.UnicodeChar) {\r
364\r
365 case CHAR_CARRIAGE_RETURN:\r
366 //\r
367 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
368 //\r
369 CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);\r
370 gBS->FreePool (StringPtr);\r
371 break;\r
372\r
373 default:\r
374 break;\r
375 }\r
376 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
377 }\r
378 }\r
379\r
380 UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);\r
381 } else {\r
382 if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
383 gBS->FreePool (ValueArray);\r
384 }\r
385\r
386 return EFI_SUCCESS;\r
387 }\r
388 } else {\r
389 for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {\r
390 //\r
391 // We found an option - which assumedly has a string. We will eventually have to support\r
392 // wrapping of strings. For now, let's pretend they don't wrap and code that up.\r
393 //\r
394 if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {\r
395 if (OrderedList) {\r
396 if (!Initialized) {\r
397 //\r
398 // If the first entry is invalid, then the "default" settings are based on what is reflected\r
399 // in the order of the op-codes\r
400 //\r
401 ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1] = (UINT8) MenuOption->Tags[Index].Value;\r
402 }\r
403 //\r
404 // Only display 3 lines of stuff at most\r
405 //\r
406 if ((Index - MenuOption->TagIndex) > ORDERED_LIST_SIZE) {\r
407 break;\r
408 }\r
409\r
410 if (((Index - MenuOption->TagIndex) != 1) && !Skip) {\r
411 Character[0] = LEFT_ONEOF_DELIMITER;\r
412 NewStrCat (OptionString[0], Character);\r
413 }\r
414\r
415 MenuOption->ThisTag->NumberOfLines = (UINT16) (Index - MenuOption->TagIndex);\r
416 if (!Initialized) {\r
417 StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle);\r
418 } else {\r
419 for (Value = (UINT16) (MenuOption->TagIndex + 1);\r
420 MenuOption->Tags[Value].Operand != EFI_IFR_END_ONE_OF_OP;\r
421 Value++\r
422 ) {\r
423 if (MenuOption->Tags[Value].Value == ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1]) {\r
424 StringPtr = GetToken (MenuOption->Tags[Value].Text, MenuOption->Handle);\r
425 break;\r
426 }\r
427 }\r
428\r
429 if (MenuOption->Tags[Value].Operand == EFI_IFR_END_ONE_OF_OP) {\r
430 Skip = TRUE;\r
431 continue;\r
432 }\r
433 }\r
434\r
435 Skip = FALSE;\r
436 NewStrCat (OptionString[0], StringPtr);\r
437 Character[0] = RIGHT_ONEOF_DELIMITER;\r
438 NewStrCat (OptionString[0], Character);\r
439 Character[0] = CHAR_CARRIAGE_RETURN;\r
440 NewStrCat (OptionString[0], Character);\r
441\r
442 //\r
443 // Remove Buffer allocated for StringPtr after it has been used.\r
444 //\r
445 gBS->FreePool (StringPtr);\r
446 } else {\r
447 //\r
448 // The option value is the same as what is stored in NV store. Print this.\r
449 //\r
450 if (!CompareMem (&(MenuOption->Tags[Index].Value), NvRamMap, MenuOption->ThisTag->StorageWidth)) {\r
451 StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle);\r
452 NewStrCat (OptionString[0], StringPtr);\r
453 Character[0] = RIGHT_ONEOF_DELIMITER;\r
454 NewStrCat (OptionString[0], Character);\r
455 //\r
456 // Remove Buffer allocated for StringPtr after it has been used.\r
457 //\r
458 gBS->FreePool (StringPtr);\r
459 Default = 0;\r
460 break;\r
461 }\r
462\r
463 if ((MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) == 1) {\r
464 Default = MenuOption->Tags[Index].Text;\r
465 Value = MenuOption->Tags[Index].Value;\r
466 };\r
467 }\r
468 }\r
469 }\r
470 //\r
471 // We didn't find a value that matched a setting in the NVRAM Map - display default - set default\r
472 //\r
473 if (Default != 0) {\r
474 //\r
475 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
476 //\r
477 CopyMem (NvRamMap, &Value, MenuOption->ThisTag->StorageWidth);\r
478\r
479 StringPtr = GetToken ((UINT16) Default, MenuOption->Handle);\r
480 NewStrCat (OptionString[0], StringPtr);\r
481 Character[0] = RIGHT_ONEOF_DELIMITER;\r
482 NewStrCat (OptionString[0], Character);\r
483 //\r
484 // Remove Buffer allocated for StringPtr after it has been used.\r
485 //\r
486 gBS->FreePool (StringPtr);\r
487 }\r
488 }\r
489 break;\r
490\r
491 case EFI_IFR_CHECKBOX_OP:\r
492 //\r
493 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
494 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
495 // the NvMap so that we can properly display the information\r
496 //\r
497 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
498 AdjustNvMap (FileFormTags, MenuOption);\r
499 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
500 }\r
501\r
502 Default = Tag->Flags & 1;\r
503 //\r
504 // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN\r
505 //\r
506 *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
507 ASSERT (*OptionString);\r
508\r
509 //\r
510 // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if\r
511 // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not\r
512 // an active field for Checkboxes.\r
513 //\r
514 StrnCpy (OptionString[0], (CHAR16 *) LEFT_CHECKBOX_DELIMITER, 1);\r
515\r
516 //\r
517 // Since this is a BOOLEAN operation, flip bit 0 upon selection\r
518 //\r
519 if (Selected) {\r
520 Tag->Value = (UINT16) (Tag->Value ^ 1);\r
521 *(UINT8 *) NvRamMap = (UINT8) (Tag->Value & 1);\r
522 UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);\r
523 }\r
524\r
525 if ((*(UINT8 *) NvRamMap & 1) == 0x01) {\r
526 NewStrCat (OptionString[0], (CHAR16 *) CHECK_ON);\r
527 //\r
528 // If someone reset default variables - we may need to reload from our NvMapping....\r
529 //\r
530 Tag->Value = *(UINT8 *) NvRamMap;\r
531 } else {\r
532 //\r
533 // If someone reset default variables - we may need to reload from our NvMapping....\r
534 //\r
535 NewStrCat (OptionString[0], (CHAR16 *) CHECK_OFF);\r
536 Tag->Value = *(UINT8 *) NvRamMap;\r
537 }\r
538\r
539 NewStrCat (OptionString[0], (CHAR16 *) RIGHT_CHECKBOX_DELIMITER);\r
540 NewStrCat (OptionString[0], StringPtr);\r
541 break;\r
542\r
543 case EFI_IFR_NUMERIC_OP:\r
544 //\r
545 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
546 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
547 // the NvMap so that we can properly display the information\r
548 //\r
549 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
550 AdjustNvMap (FileFormTags, MenuOption);\r
551 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
552 }\r
553\r
554 *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
555 ASSERT (*OptionString);\r
556\r
557 //\r
558 // Add left delimeter to string\r
559 //\r
560 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
561\r
562 //\r
563 // Retrieve the current numeric value\r
564 //\r
565 if (Selected) {\r
566 //\r
567 // Go ask for input\r
568 //\r
569 if (Tag->Step == 0) {\r
570 //\r
571 // Manual Input\r
572 //\r
573 Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, REGULAR_NUMERIC, &Number);\r
574 if (!EFI_ERROR (Status)) {\r
575 CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
576 UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);\r
577\r
578 //\r
579 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
580 //\r
581 CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);\r
582 } else {\r
583 return EFI_SUCCESS;\r
584 }\r
585 } else {\r
586 //\r
587 // Auto selection from list\r
588 //\r
589 if ((((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) > Tag->Maximum) || ((UINT8) (*NvRamMap) < Tag->Minimum)) ||\r
590 (((Tag->StorageWidth == 2) && *NvRamMap > Tag->Maximum) || (*NvRamMap < Tag->Minimum))\r
591 ) {\r
592 //\r
593 // Seed Number with valid value if currently invalid\r
594 //\r
595 Number = Tag->Default;\r
596 } else {\r
597 if (Tag->StorageWidth == 1) {\r
598 Number = (UINT8) (*NvRamMap);\r
599 } else {\r
600 Number = *NvRamMap;\r
601 }\r
602 }\r
603\r
604 Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, REGULAR_NUMERIC, &Number);\r
605 if (!EFI_ERROR (Status)) {\r
606 CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
607 UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);\r
608\r
609 //\r
610 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
611 //\r
612 CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);\r
613 } else {\r
614 return EFI_SUCCESS;\r
615 }\r
616 }\r
617 } else {\r
618 if (((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) <= Tag->Maximum && (UINT8) (*NvRamMap) >= Tag->Minimum) ||\r
619 ((Tag->StorageWidth == 2) && *NvRamMap <= Tag->Maximum && *NvRamMap >= Tag->Minimum)\r
620 ) {\r
621 if (Tag->StorageWidth == 1) {\r
622 Number = (UINT8) (*NvRamMap);\r
623 } else {\r
624 Number = *NvRamMap;\r
625 }\r
626 UnicodeValueToString (\r
627 FormattedNumber, \r
628 FALSE, \r
629 (UINTN) Number, \r
630 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
631 );\r
632 Number = (UINT16) GetStringWidth (FormattedNumber);\r
633 StrnCpy (OptionString[0] + 1, FormattedNumber, Number);\r
634 } else {\r
635 //\r
636 // If *NvRamMap isn't within parameters, set it to within parameters\r
637 //\r
638 //\r
639 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth\r
640 //\r
641 CopyMem (NvRamMap, &Tag->Default, MenuOption->ThisTag->StorageWidth);\r
642 Number = Tag->Default;\r
643\r
644 UnicodeValueToString (\r
645 FormattedNumber, \r
646 FALSE, \r
647 (UINTN) Number, \r
648 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
649 );\r
650 Number = (UINT16) GetStringWidth (FormattedNumber);\r
651 StrnCpy (OptionString[0] + 1, FormattedNumber, Number);\r
652 }\r
653\r
654 *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;\r
655 NewStrCat (OptionString[0] + (Number / 2) + 1, StringPtr);\r
656 }\r
657 break;\r
658\r
659 case EFI_IFR_DATE_OP:\r
660 //\r
661 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
662 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
663 // the NvMap so that we can properly display the information\r
664 //\r
665 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
666 AdjustNvMap (FileFormTags, MenuOption);\r
667 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
668 }\r
669\r
670 Status = gRT->GetTime (&Time, NULL);\r
671 if (EFI_ERROR (Status)) {\r
672 return EFI_SUCCESS;\r
673 }\r
674 //\r
675 // This for loop advances Index till it points immediately after a date entry. We can then\r
676 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date\r
677 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index\r
678 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3\r
679 // date operands.\r
680 //\r
681 //\r
682 // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code\r
683 // against such silliness.\r
684 //\r
685 // Also, we want to internationalize the order of the date information. We need to code for it as well.\r
686 //\r
687 for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_DATE_OP; Index++)\r
688 ;\r
689\r
690 //\r
691 // Count 0 = We entered on the first Date operand\r
692 // Count 1 = We entered on the second Date operand\r
693 // Count 2 = We entered on the third Date operand\r
694 //\r
695 Count = 3 - (Index - MenuOption->TagIndex);\r
696 if (Count > 2) {\r
697 return EFI_SUCCESS;\r
698 }\r
699 //\r
700 // This is similar to numerics, except for the following:\r
701 // We will under normal circumstances get 3 consecutive calls\r
702 // to process this opcodes data.\r
703 //\r
704 *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
705 ASSERT (*OptionString);\r
706\r
707 switch (Count) {\r
708 case 0:\r
709 if (Selected) {\r
710 Number = (UINT16) Time.Month;\r
711\r
712 if (Tag->Step == 0) {\r
713 MenuOption->OptCol++;\r
714 Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);\r
715 } else {\r
716 //\r
717 // Seed value with current setting\r
718 //\r
719 Tag->Value = (UINT16) Time.Month;\r
720 Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);\r
721 }\r
722\r
723 if (!EFI_ERROR (Status)) {\r
724 Time.Month = (UINT8) Number;\r
725 gRT->SetTime (&Time);\r
726 }\r
727 }\r
728\r
729 VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Month;\r
730 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
731\r
732 UnicodeValueToString (\r
733 FormattedNumber, \r
734 FALSE, \r
735 (UINTN) Time.Month, \r
736 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
737 );\r
738 Number = (UINT16) GetStringWidth (FormattedNumber);\r
739\r
740 if (Number == 4) {\r
741 FormattedNumber[2] = FormattedNumber[1];\r
742 FormattedNumber[1] = FormattedNumber[0];\r
743 FormattedNumber[0] = L'0';\r
744 Number = 6;\r
745 }\r
746\r
747 StrnCpy (OptionString[0] + 1, FormattedNumber, Number);\r
748 *(OptionString[0] + Number / 2) = DATE_SEPARATOR;\r
749 StrCat (OptionString[0] + (Number / 2) + 1, StringPtr);\r
750 break;\r
751\r
752 case 1:\r
753 if (Selected) {\r
754 Number = (UINT16) Time.Day;\r
755\r
756 if (Tag->Step == 0) {\r
757 Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);\r
758 } else {\r
759 //\r
760 // Seed value with current setting\r
761 //\r
762 Tag->Value = (UINT16) Time.Day;\r
763 Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);\r
764 }\r
765\r
766 if (!EFI_ERROR (Status)) {\r
767 Time.Day = (UINT8) Number;\r
768 gRT->SetTime (&Time);\r
769 }\r
770 }\r
771\r
772 VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Day;\r
773 SetUnicodeMem (OptionString[0], 4, L' ');\r
774\r
775 UnicodeValueToString (\r
776 FormattedNumber, \r
777 FALSE, \r
778 (UINTN) Time.Day, \r
779 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
780 );\r
781 Number = (UINT16) GetStringWidth (FormattedNumber);\r
782 if (Number == 4) {\r
783 FormattedNumber[2] = FormattedNumber[1];\r
784 FormattedNumber[1] = FormattedNumber[0];\r
785 FormattedNumber[0] = L'0';\r
786 Number = 6;\r
787 }\r
788\r
789 StrnCpy (OptionString[0] + 4, FormattedNumber, Number);\r
790 *(OptionString[0] + Number / 2 + 3) = DATE_SEPARATOR;\r
791 StrCat (OptionString[0] + (Number / 2) + 4, StringPtr);\r
792 break;\r
793\r
794 case 2:\r
795 if (Selected) {\r
796 Number = (UINT16) Time.Year;\r
797\r
798 if (Tag->Step == 0) {\r
799 Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);\r
800 } else {\r
801 //\r
802 // Seed value with current setting\r
803 //\r
804 Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);\r
805 }\r
806\r
807 if (!EFI_ERROR (Status)) {\r
808 Time.Year = (UINT16) Number;\r
809 gRT->SetTime (&Time);\r
810 }\r
811 }\r
812\r
813 Tag->Value = (UINT16) Time.Year;\r
814 VariableDefinition->FakeNvRamMap[Tag->Id] = (UINT8) Tag->Value;\r
815 VariableDefinition->FakeNvRamMap[Tag->Id + 1] = (UINT8) (Tag->Value >> 8);\r
816 SetUnicodeMem (OptionString[0], 7, L' ');\r
817 UnicodeValueToString (\r
818 FormattedNumber, \r
819 FALSE, \r
820 (UINTN) Time.Year, \r
821 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
822 );\r
823 Number = (UINT16) GetStringWidth (FormattedNumber);\r
824 StrnCpy (OptionString[0] + 7, FormattedNumber, Number);\r
825 *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER;\r
826 StrCat (OptionString[0] + (Number / 2) + 7, StringPtr);\r
827 break;\r
828 }\r
829\r
830 break;\r
831\r
832 //\r
833 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG\r
834 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone\r
835 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction\r
836 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG\r
837 //\r
838 case EFI_IFR_TIME_OP:\r
839 //\r
840 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
841 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
842 // the NvMap so that we can properly display the information\r
843 //\r
844 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
845 AdjustNvMap (FileFormTags, MenuOption);\r
846 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
847 }\r
848\r
849 Status = gRT->GetTime (&Time, NULL);\r
850 if (EFI_ERROR (Status)) {\r
851 return EFI_SUCCESS;\r
852 }\r
853 //\r
854 // This is similar to numerics, except for the following:\r
855 // We will under normal circumstances get 3 consecutive calls\r
856 // to process this opcodes data.\r
857 //\r
858 *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
859 ASSERT (*OptionString);\r
860\r
861 //\r
862 // This for loop advances Index till it points immediately after a date entry. We can then\r
863 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date\r
864 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index\r
865 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3\r
866 // date operands.\r
867 //\r
868 for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_TIME_OP; Index++)\r
869 ;\r
870 //\r
871 // Count 0 = We entered on the first Date operand\r
872 // Count 1 = We entered on the second Date operand\r
873 // Count 2 = We entered on the third Date operand\r
874 //\r
875 Count = 3 - (Index - MenuOption->TagIndex);\r
876 if (Count > 2) {\r
877 return EFI_SUCCESS;\r
878 }\r
879\r
880 switch (Count) {\r
881 case 0:\r
882 Number = Time.Hour;\r
883 break;\r
884\r
885 case 1:\r
886 Number = Time.Minute;\r
887 break;\r
888\r
889 case 2:\r
890 Number = Time.Second;\r
891 }\r
892 //\r
893 // Retrieve the current numeric value\r
894 //\r
895 if (Selected) {\r
896 //\r
897 // Go ask for input\r
898 //\r
899 if (Tag->Step == 0) {\r
900 //\r
901 // Manual Input\r
902 //\r
903 Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, TIME_NUMERIC, &Number);\r
904 if (!EFI_ERROR (Status)) {\r
905 *NvRamMap = Number;\r
906 Time.Nanosecond = 0;\r
907 gRT->SetTime (&Time);\r
908 } else {\r
909 return EFI_SUCCESS;\r
910 }\r
911 } else {\r
912 //\r
913 // Auto selection from list\r
914 //\r
915 Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, TIME_NUMERIC, &Number);\r
916 if (!EFI_ERROR (Status)) {\r
917 *NvRamMap = Number;\r
918 } else {\r
919 return EFI_SUCCESS;\r
920 }\r
921 }\r
922\r
923 switch (Count) {\r
924 case 0:\r
925 Time.Hour = (UINT8) Number;\r
926 break;\r
927\r
928 case 1:\r
929 Time.Minute = (UINT8) Number;\r
930 break;\r
931\r
932 case 2:\r
933 Time.Second = (UINT8) Number;\r
934 }\r
935\r
936 Time.Nanosecond = 0;\r
937 gRT->SetTime (&Time);\r
938 } else {\r
939 switch (Count) {\r
940 case 0:\r
941 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
942 UnicodeValueToString (\r
943 FormattedNumber, \r
944 FALSE, \r
945 (UINTN) Time.Hour, \r
946 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
947 );\r
948 Number = (UINT16) GetStringWidth (FormattedNumber);\r
949 if (Number == 4) {\r
950 FormattedNumber[2] = FormattedNumber[1];\r
951 FormattedNumber[1] = FormattedNumber[0];\r
952 FormattedNumber[0] = L'0';\r
953 Number = 6;\r
954 }\r
955\r
956 StrnCpy (OptionString[0] + 1, FormattedNumber, Number);\r
957 *(OptionString[0] + Number / 2) = TIME_SEPARATOR;\r
958 StrCat (OptionString[0] + (Number / 2) + 1, StringPtr);\r
959 break;\r
960\r
961 case 1:\r
962 SetUnicodeMem (OptionString[0], 4, L' ');\r
963 UnicodeValueToString (\r
964 FormattedNumber, \r
965 FALSE, \r
966 (UINTN) Time.Minute, \r
967 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
968 );\r
969 Number = (UINT16) GetStringWidth (FormattedNumber);\r
970 if (Number == 4) {\r
971 FormattedNumber[2] = FormattedNumber[1];\r
972 FormattedNumber[1] = FormattedNumber[0];\r
973 FormattedNumber[0] = L'0';\r
974 Number = 6;\r
975 }\r
976\r
977 StrnCpy (OptionString[0] + 4, FormattedNumber, Number);\r
978 *(OptionString[0] + Number / 2 + 3) = TIME_SEPARATOR;\r
979 StrCat (OptionString[0] + (Number / 2) + 4, StringPtr);\r
980 break;\r
981\r
982 case 2:\r
983 SetUnicodeMem (OptionString[0], 7, L' ');\r
984 UnicodeValueToString (\r
985 FormattedNumber, \r
986 FALSE, \r
987 (UINTN) Time.Second, \r
988 (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))\r
989 );\r
990 Number = (UINT16) GetStringWidth (FormattedNumber);\r
991 if (Number == 4) {\r
992 FormattedNumber[2] = FormattedNumber[1];\r
993 FormattedNumber[1] = FormattedNumber[0];\r
994 FormattedNumber[0] = L'0';\r
995 Number = 6;\r
996 }\r
997\r
998 StrnCpy (OptionString[0] + 7, FormattedNumber, Number);\r
999 *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER;\r
1000 StrCat (OptionString[0] + (Number / 2) + 7, StringPtr);\r
1001 break;\r
1002 }\r
1003 //\r
1004 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG\r
1005 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone\r
1006 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction\r
1007 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG\r
1008 //\r
1009 }\r
1010 break;\r
1011\r
1012 case EFI_IFR_STRING_OP:\r
1013 //\r
1014 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
1015 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
1016 // the NvMap so that we can properly display the information\r
1017 //\r
1018 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
1019 AdjustNvMap (FileFormTags, MenuOption);\r
1020 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
1021 }\r
1022\r
1023 *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);\r
1024 ASSERT (*OptionString);\r
1025\r
1026 if (Selected) {\r
1027 StringPtr = AllocateZeroPool (Tag->Maximum);\r
1028 ASSERT (StringPtr);\r
1029\r
1030 Status = ReadString (MenuOption, StringPtr);\r
1031\r
1032 if (!EFI_ERROR (Status)) {\r
1033 CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);\r
1034 CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);\r
1035\r
1036 UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);\r
1037 }\r
1038\r
1039 gBS->FreePool (StringPtr);\r
1040 return Status;\r
1041 } else {\r
1042 for (Index = 0; Index < gOptionBlockWidth; Index++) {\r
1043 if (VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)] != 0x0000) {\r
1044 CopyMem (OptionString[0] + Index, &VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)], 2);\r
1045 } else {\r
1046 if (Index == 0) {\r
1047 *(OptionString[0] + Index) = '_';\r
1048 *(OptionString[0] + 1 + Index) = 0;\r
1049 }\r
1050 break;\r
1051 }\r
1052 }\r
1053\r
1054 return Status;\r
1055 }\r
1056\r
1057 case EFI_IFR_PASSWORD_OP:\r
1058 //\r
1059 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically\r
1060 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust\r
1061 // the NvMap so that we can properly display the information\r
1062 //\r
1063 if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {\r
1064 AdjustNvMap (FileFormTags, MenuOption);\r
1065 NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];\r
1066 }\r
1067\r
1068 if (Selected) {\r
1069 StringPtr = AllocateZeroPool (Tag->Maximum);\r
1070 ASSERT (StringPtr);\r
1071\r
1072 //\r
1073 // If interactive, read the password and do the appropriate callbacks in that routine.\r
1074 // Since interactive passwords assume to handle the password data in a separate variable\r
1075 // storage, we don't need to do more than what is below for password callbacks\r
1076 //\r
1077 if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {\r
1078 MenuOption->Tags[0].CallbackHandle = FileFormTags->FormTags.Tags[0].CallbackHandle;\r
1079 Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);\r
1080 ZeroMem (StringPtr, Tag->Maximum);\r
1081\r
1082 if (EFI_ERROR (Status)) {\r
1083 if (Status == EFI_NOT_READY) {\r
1084 gBS->FreePool (StringPtr);\r
1085 return EFI_SUCCESS;\r
1086 }\r
1087 }\r
1088\r
1089 Status = ReadPassword (MenuOption, TRUE, Tag, PageData, TRUE, FileFormTags, StringPtr);\r
1090 gBS->FreePool (StringPtr);\r
1091 return EFI_SUCCESS;\r
1092 }\r
1093\r
1094 for (Index = 0; Index < Tag->Maximum; Index++) {\r
1095 if (VariableDefinition->NvRamMap[Tag->StorageStart + Index] != 0x00) {\r
1096 //\r
1097 // There is something there! Prompt for password\r
1098 //\r
1099 Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);\r
1100 if (EFI_ERROR (Status)) {\r
1101 gBS->FreePool (StringPtr);\r
1102 return EFI_SUCCESS;\r
1103 }\r
1104\r
1105 if (Tag->Encoding == 1) {\r
1106 EncodePassword (StringPtr, (UINT8) Tag->Maximum);\r
1107 Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);\r
1108 } else {\r
1109 Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);\r
1110 }\r
1111\r
1112 if (Status != 0) {\r
1113 gBS->FreePool (StringPtr);\r
1114 return EFI_SUCCESS;\r
1115 } else {\r
1116 break;\r
1117 }\r
1118 }\r
1119 }\r
1120 //\r
1121 // Clean the string\r
1122 //\r
1123 ZeroMem (StringPtr, Tag->Maximum);\r
1124\r
1125 //\r
1126 // No password set! Go ahead and prompt the user for a password.\r
1127 //\r
1128 Status = ReadPassword (MenuOption, FALSE, Tag, PageData, FALSE, FileFormTags, StringPtr);\r
1129\r
1130 if (EFI_ERROR (Status)) {\r
1131 //\r
1132 // User couldn't figure out how to type two identical passwords\r
1133 //\r
1134 gBS->FreePool (StringPtr);\r
1135 return EFI_SUCCESS;\r
1136 }\r
1137 //\r
1138 // Very simple example of how one MIGHT do password encoding\r
1139 //\r
1140 if (Tag->Encoding == 1) {\r
1141 EncodePassword (StringPtr, (UINT8) Tag->Maximum);\r
1142 }\r
1143\r
1144 TmpNvRamMap = AllocatePool (VariableDefinition->VariableSize);\r
1145 ASSERT (TmpNvRamMap != NULL);\r
1146\r
1147 Count = VariableDefinition->VariableSize;\r
1148\r
1149 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
1150 Status = FormCallback->NvRead (\r
1151 FormCallback,\r
1152 VariableDefinition->VariableName,\r
1153 &VariableDefinition->Guid,\r
1154 NULL,\r
1155 &Count,\r
1156 (VOID *) TmpNvRamMap\r
1157 );\r
1158 } else {\r
1159 Status = gRT->GetVariable (\r
1160 VariableDefinition->VariableName,\r
1161 &VariableDefinition->Guid,\r
1162 NULL,\r
1163 &Count,\r
1164 (VOID *) TmpNvRamMap\r
1165 );\r
1166 }\r
1167\r
1168 CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);\r
1169 CopyMem (&TmpNvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);\r
1170\r
1171 if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {\r
1172 Status = FormCallback->NvWrite (\r
1173 FormCallback,\r
1174 VariableDefinition->VariableName,\r
1175 &VariableDefinition->Guid,\r
1176 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1177 VariableDefinition->VariableSize,\r
1178 (VOID *) TmpNvRamMap,\r
1179 &gResetRequired\r
1180 );\r
1181 } else {\r
1182 Status = gRT->SetVariable (\r
1183 VariableDefinition->VariableName,\r
1184 &VariableDefinition->Guid,\r
1185 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1186 VariableDefinition->VariableSize,\r
1187 (VOID *) TmpNvRamMap\r
1188 );\r
1189 }\r
1190\r
1191 gBS->FreePool (TmpNvRamMap);\r
1192 gBS->FreePool (StringPtr);\r
1193 break;\r
1194 }\r
1195\r
1196 default:\r
1197 break;\r
1198 }\r
1199\r
1200 return EFI_SUCCESS;\r
1201}\r
1202\r
1203VOID\r
1204ProcessHelpString (\r
1205 IN CHAR16 *StringPtr,\r
1206 OUT CHAR16 **FormattedString,\r
1207 IN UINTN RowCount\r
1208 )\r
1209{\r
1210 UINTN CurrIndex;\r
1211 UINTN PrevIndex;\r
1212 UINTN SearchIndex;\r
1213 UINTN PrevSearchIndex;\r
1214 UINTN StringCount;\r
1215 UINTN PageCount;\r
1216\r
1217 StringCount = 0;\r
1218 PrevIndex = 0;\r
1219 CurrIndex = gHelpBlockWidth - 1;\r
1220\r
1221 if (*FormattedString != NULL) {\r
1222 gBS->FreePool (*FormattedString);\r
1223 *FormattedString = NULL;\r
1224 }\r
1225\r
1226 for (; CurrIndex > PrevIndex; CurrIndex--) {\r
1227 //\r
1228 // In the case where the string ended and a new one is immediately after it\r
1229 // we need to check for the null-terminator and reset the CurrIndex\r
1230 //\r
1231 SearchIndex = CurrIndex;\r
1232 PrevSearchIndex = PrevIndex;\r
1233\r
1234 for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) {\r
1235 if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) {\r
1236 CurrIndex = PrevSearchIndex;\r
1237 break;\r
1238 }\r
1239\r
1240 if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) {\r
1241 if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) {\r
1242 //\r
1243 // Found a "\n",advance to the next new line.\r
1244 //\r
1245 CurrIndex = PrevSearchIndex + 1;\r
1246 break;\r
1247 } else {\r
1248 //\r
1249 // Found a "\r",return to the start of the current line.\r
1250 //\r
1251 PrevIndex = PrevSearchIndex + 1;\r
1252 CurrIndex = PrevSearchIndex + gHelpBlockWidth;\r
1253 continue;\r
1254 }\r
1255 }\r
1256 }\r
1257\r
1258 //\r
1259 // End of the string, thus stop counting.\r
1260 //\r
1261 if (StringPtr[CurrIndex] == CHAR_NULL) {\r
1262 StringCount++;\r
1263 break;\r
1264 }\r
1265 //\r
1266 // The premise is that for every HELP_BLOCK_WIDTH we rewind\r
1267 // until we find the first space. That is the delimiter for\r
1268 // the string, and we will then advance our CurrIndex another\r
1269 // HELP_BLOCK_WIDTH and continue the process breaking the larger\r
1270 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.\r
1271 //\r
1272 if (StringPtr[CurrIndex] == CHAR_SPACE) {\r
1273 //\r
1274 // How many strings have been found?\r
1275 //\r
1276 StringCount++;\r
1277 PrevIndex = CurrIndex + 1;\r
1278 CurrIndex = CurrIndex + gHelpBlockWidth;\r
1279 }\r
1280 //\r
1281 // Found a Linefeed, advance to the next line.\r
1282 //\r
1283 if (StringPtr[CurrIndex] == CHAR_LINEFEED) {\r
1284 StringCount++;\r
1285 PrevIndex = CurrIndex + 1;\r
1286 CurrIndex = CurrIndex + gHelpBlockWidth;\r
1287 }\r
1288 }\r
1289 //\r
1290 // endfor\r
1291 //\r
1292 // Round the value up one (doesn't hurt)\r
1293 //\r
1294 StringCount++;\r
1295\r
1296 //\r
1297 // Determine the number of pages this help string occupies\r
1298 //\r
1299 PageCount = StringCount / RowCount;\r
1300 if (StringCount % RowCount > 0) {\r
1301 PageCount++;\r
1302 }\r
1303 //\r
1304 // Convert the PageCount into lines so we can allocate the correct buffer size\r
1305 //\r
1306 StringCount = PageCount * RowCount;\r
1307\r
1308 //\r
1309 // We now know how many strings we will have, so we can allocate the\r
1310 // space required for the array or strings.\r
1311 //\r
1312 *FormattedString = AllocateZeroPool ((StringCount) * (gHelpBlockWidth + 1) * 2);\r
1313 ASSERT (*FormattedString);\r
1314\r
1315 StringCount = 0;\r
1316 PrevIndex = 0;\r
1317 CurrIndex = gHelpBlockWidth - 1;\r
1318\r
1319 for (; CurrIndex > PrevIndex; CurrIndex--) {\r
1320 //\r
1321 // In the case where the string ended and a new one is immediately after it\r
1322 // we need to check for the null-terminator and reset the CurrIndex\r
1323 //\r
1324 SearchIndex = CurrIndex;\r
1325 PrevSearchIndex = PrevIndex;\r
1326\r
1327 for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) {\r
1328 if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) {\r
1329 CurrIndex = PrevSearchIndex;\r
1330 break;\r
1331 }\r
1332\r
1333 if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) {\r
1334 if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) {\r
1335 //\r
1336 // Found a "\n",advance to the next new line.\r
1337 //\r
1338 CurrIndex = PrevSearchIndex + 1;\r
1339 break;\r
1340 } else {\r
1341 //\r
1342 // Found a "\r",return to the start of the current line.\r
1343 //\r
1344 PrevIndex = PrevSearchIndex + 1;\r
1345 CurrIndex = PrevSearchIndex + gHelpBlockWidth;\r
1346 continue;\r
1347 }\r
1348 }\r
1349 }\r
1350\r
1351 //\r
1352 // End of the string, thus stop counting.\r
1353 //\r
1354 if (StringPtr[CurrIndex] == CHAR_NULL) {\r
1355 //\r
1356 // Copy the fragment to the FormattedString buffer\r
1357 //\r
1358 StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex);\r
1359 StringCount++;\r
1360 break;\r
1361 }\r
1362 //\r
1363 // The premise is that for every HELP_BLOCK_WIDTH we rewind\r
1364 // until we find the first space. That is the delimiter for\r
1365 // the string, and we will then advance our CurrIndex another\r
1366 // HELP_BLOCK_WIDTH and continue the process breaking the larger\r
1367 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.\r
1368 //\r
1369 if (StringPtr[CurrIndex] == CHAR_SPACE) {\r
1370 //\r
1371 // Copy the fragment to the FormattedString buffer\r
1372 //\r
1373 StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex);\r
1374 StringCount++;\r
1375 PrevIndex = CurrIndex + 1;\r
1376 CurrIndex = CurrIndex + gHelpBlockWidth;\r
1377 }\r
1378 //\r
1379 // Found a LineFeed, advance to the next line.\r
1380 //\r
1381 if (StringPtr[CurrIndex] == CHAR_LINEFEED) {\r
1382 StringPtr[CurrIndex] = CHAR_SPACE;\r
1383 //\r
1384 // "\n" is represented as CHAR_CARRIAGE_RETURN + CHAR_LINEFEED,check this.\r
1385 //\r
1386 if (StringPtr[CurrIndex - 1] == CHAR_CARRIAGE_RETURN) {\r
1387 StringPtr[CurrIndex - 1] = CHAR_SPACE;\r
1388 }\r
1389\r
1390 StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex);\r
1391 StringCount++;\r
1392 PrevIndex = CurrIndex + 1;\r
1393 CurrIndex = CurrIndex + gHelpBlockWidth;\r
1394 }\r
1395 }\r
1396 //\r
1397 // endfor\r
1398 //\r
1399 return ;\r
1400}\r
1401\r
1402VOID\r
1403IfrToFormTag (\r
1404 IN UINT8 OpCode,\r
1405 IN EFI_TAG *TargetTag,\r
1406 IN VOID *FormData,\r
1407 EFI_VARIABLE_DEFINITION *VariableDefinitionsHead\r
1408 )\r
1409{\r
1410 UINT16 TempValue;\r
1411 CHAR16 *VariableName;\r
1412 CHAR8 *AsciiString;\r
1413 EFI_VARIABLE_DEFINITION *VariableDefinitions;\r
1414 EFI_VARIABLE_DEFINITION *PreviousVariableDefinitions;\r
1415 STATIC UINT16 VariableSize;\r
1416 EFI_GUID Guid;\r
1417 STATIC UINT16 CurrentVariable;\r
1418 STATIC UINT16 CurrentVariable2;\r
1419 UINTN Index;\r
1420\r
1421 switch (OpCode) {\r
1422 case EFI_IFR_FORM_OP:\r
1423 CopyMem (&TargetTag->Id, &((EFI_IFR_FORM *) FormData)->FormId, sizeof (UINT16));\r
1424 CopyMem (&TargetTag->Text, &((EFI_IFR_FORM *) FormData)->FormTitle, sizeof (UINT16));\r
1425 TargetTag->VariableNumber = CurrentVariable;\r
1426 if (VariableDefinitionsHead != NULL) {\r
1427 VariableName = AllocateZeroPool (12);\r
1428 ASSERT (VariableName != NULL);\r
1429 CopyMem (VariableName, L"Setup", 12);\r
1430 VariableDefinitionsHead->VariableName = VariableName;\r
1431 VariableDefinitionsHead->VariableSize = VariableSize;\r
1432 CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID));\r
1433 }\r
1434 break;\r
1435\r
1436 case EFI_IFR_SUBTITLE_OP:\r
1437 TargetTag->NumberOfLines = 1;\r
1438 CopyMem (&TargetTag->Text, &((EFI_IFR_SUBTITLE *) FormData)->SubTitle, sizeof (UINT16));\r
1439 TargetTag->VariableNumber = CurrentVariable;\r
1440 break;\r
1441\r
1442 case EFI_IFR_TEXT_OP:\r
1443 TargetTag->NumberOfLines = 1;\r
1444 CopyMem (&TargetTag->Text, &((EFI_IFR_TEXT *) FormData)->Text, sizeof (UINT16));\r
1445 CopyMem (&TargetTag->Help, &((EFI_IFR_TEXT *) FormData)->Help, sizeof (UINT16));\r
1446 TargetTag->VariableNumber = CurrentVariable;\r
1447\r
1448 //\r
1449 // To optimize the encoding size, certain opcodes have optional fields such as those\r
1450 // inside the if() statement. If the encoded length is the complete size, then we\r
1451 // know we have valid data encoded that we want to integrate\r
1452 //\r
1453 if (((EFI_IFR_TEXT *) FormData)->Header.Length == sizeof (EFI_IFR_TEXT)) {\r
1454 //\r
1455 // Text has no help associated with it, but in case there is a second entry due to\r
1456 // dynamic/interactive flags being active, bring this data over.\r
1457 //\r
1458 CopyMem (&TargetTag->TextTwo, &((EFI_IFR_TEXT *) FormData)->TextTwo, sizeof (UINT16));\r
1459 TargetTag->Flags = ((EFI_IFR_TEXT *) FormData)->Flags;\r
1460 CopyMem (&TargetTag->Key, &((EFI_IFR_TEXT *) FormData)->Key, sizeof (UINT16));\r
1461 }\r
1462 break;\r
1463\r
1464 case EFI_IFR_ONE_OF_OPTION_OP:\r
1465 CopyMem (&TargetTag->Text, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Option, sizeof (UINT16));\r
1466 CopyMem (&TargetTag->Value, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Value, sizeof (UINT16));\r
1467 TargetTag->Flags = ((EFI_IFR_ONE_OF_OPTION *) FormData)->Flags;\r
1468 CopyMem (&TargetTag->Key, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Key, sizeof (UINT16));\r
1469 TargetTag->VariableNumber = CurrentVariable;\r
1470 break;\r
1471\r
1472 case EFI_IFR_CHECKBOX_OP:\r
1473 TargetTag->Flags = ((EFI_IFR_CHECKBOX *) FormData)->Flags;\r
1474 TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);\r
1475 CopyMem (&TargetTag->Key, &((EFI_IFR_CHECKBOX *) FormData)->Key, sizeof (UINT16));\r
1476 TargetTag->VariableNumber = CurrentVariable;\r
1477 break;\r
1478\r
1479 case EFI_IFR_NUMERIC_OP:\r
1480 TargetTag->Flags = ((EFI_IFR_NUMERIC *) FormData)->Flags;\r
1481 CopyMem (&TargetTag->Key, &((EFI_IFR_NUMERIC *) FormData)->Key, sizeof (UINT16));\r
1482 TargetTag->VariableNumber = CurrentVariable;\r
1483 break;\r
1484\r
1485 case EFI_IFR_STRING_OP:\r
1486 TempValue = 0;\r
1487 CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MinSize, sizeof (UINT8));\r
1488 TempValue = (UINT16) (TempValue * 2);\r
1489 CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16));\r
1490\r
1491 CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MaxSize, sizeof (UINT8));\r
1492 TempValue = (UINT16) (TempValue * 2);\r
1493 CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16));\r
1494 CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16));\r
1495 TargetTag->Flags = (UINT8) (((EFI_IFR_STRING *) FormData)->Flags);\r
1496 TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);\r
1497 CopyMem (&TargetTag->Key, &((EFI_IFR_STRING *) FormData)->Key, sizeof (UINT16));\r
1498 TargetTag->VariableNumber = CurrentVariable;\r
1499 break;\r
1500\r
1501 case EFI_IFR_PASSWORD_OP:\r
1502 TempValue = 0;\r
1503 CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MinSize, sizeof (UINT8));\r
1504 TempValue = (UINT16) (TempValue * 2);\r
1505 CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16));\r
1506\r
1507 CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MaxSize, sizeof (UINT8));\r
1508 TempValue = (UINT16) (TempValue * 2);\r
1509 CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16));\r
1510 CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16));\r
1511 TargetTag->Flags = ((EFI_IFR_PASSWORD *) FormData)->Flags;\r
1512 TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);\r
1513 CopyMem (&TargetTag->Key, &((EFI_IFR_PASSWORD *) FormData)->Key, sizeof (UINT16));\r
1514 CopyMem (&TargetTag->Encoding, &((EFI_IFR_PASSWORD *) FormData)->Encoding, sizeof (UINT16));\r
1515 TargetTag->VariableNumber = CurrentVariable;\r
1516 break;\r
1517\r
1518 case EFI_IFR_VARSTORE_OP:\r
1519 //\r
1520 // It should NEVER be NULL\r
1521 //\r
1522 if (VariableDefinitionsHead == NULL) {\r
1523 break;\r
1524 }\r
1525\r
1526 VariableDefinitions = VariableDefinitionsHead;\r
1527\r
1528 //\r
1529 // Advance VariableDefinitions to the last entry\r
1530 //\r
1531 for (; VariableDefinitions != NULL; VariableDefinitions = VariableDefinitions->Next) {\r
1532 PreviousVariableDefinitions = VariableDefinitions;\r
1533 //\r
1534 // If there is a variable with this GUID and ID already, we need to bail out\r
1535 //\r
1536 if (!CompareMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID)) &&\r
1537 !CompareMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16))\r
1538 ) {\r
1539 return ;\r
1540 }\r
1541\r
1542 if (VariableDefinitions->Next == NULL) {\r
1543 break;\r
1544 }\r
1545 }\r
1546 //\r
1547 // If the last entry has a variable in it already, allocate a new entry and use it\r
1548 //\r
1549 if (VariableDefinitions->VariableName != NULL) {\r
1550 VariableDefinitions->Next = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));\r
1551 ASSERT (VariableDefinitions->Next != NULL);\r
1552 PreviousVariableDefinitions = VariableDefinitions;\r
1553 VariableDefinitions = VariableDefinitions->Next;\r
1554 VariableDefinitions->Previous = PreviousVariableDefinitions;\r
1555 }\r
1556 //\r
1557 // Copy the Variable data to our linked list\r
1558 //\r
1559 CopyMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16));\r
1560 CopyMem (&VariableDefinitions->VariableSize, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));\r
1561 CopyMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID));\r
1562\r
1563 //\r
1564 // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition\r
1565 // due to it being variable sized. There are rules preventing it from being > 40 characters long and should\r
1566 // be enforced by the compiler.\r
1567 //\r
1568 AsciiString = (CHAR8 *) (&((EFI_IFR_VARSTORE *) FormData)->Size);\r
1569 AsciiString = AsciiString + 2;\r
1570 VariableDefinitions->VariableName = AllocateZeroPool ((AsciiStrLen (AsciiString) + 1) * 2);\r
1571 ASSERT (VariableDefinitions->VariableName != NULL);\r
1572 for (Index = 0; AsciiString[Index] != 0; Index++) {\r
1573 VariableDefinitions->VariableName[Index] = (CHAR16) AsciiString[Index];\r
1574 }\r
1575\r
1576 VariableDefinitions->VariableName[Index] = 0;\r
1577\r
1578 //\r
1579 // Propogate the tag information for this op-code\r
1580 //\r
1581 CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16));\r
1582 CopyMem (&TargetTag->GuidValue, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID));\r
1583 CopyMem (&TargetTag->StorageWidth, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));\r
1584 CopyMem (&TargetTag->Maximum, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));\r
1585 break;\r
1586\r
1587 case EFI_IFR_VARSTORE_SELECT_OP:\r
1588 CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16));\r
1589 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16));\r
1590 CurrentVariable2 = CurrentVariable;\r
1591 break;\r
1592\r
1593 case EFI_IFR_VARSTORE_SELECT_PAIR_OP:\r
1594 CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16));\r
1595 CopyMem (\r
1596 &TargetTag->VariableNumber2,\r
1597 &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId,\r
1598 sizeof (UINT16)\r
1599 );\r
1600 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16));\r
1601 CopyMem (&CurrentVariable2, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId, sizeof (UINT16));\r
1602 break;\r
1603\r
1604 case EFI_IFR_REF_OP:\r
1605 TargetTag->NumberOfLines = 1;\r
1606 CopyMem (&TargetTag->Id, &((EFI_IFR_REF *) FormData)->FormId, sizeof (UINT16));\r
1607 CopyMem (&TargetTag->Key, &((EFI_IFR_REF *) FormData)->Key, sizeof (UINT16));\r
1608 CopyMem (&TargetTag->Text, &((EFI_IFR_REF *) FormData)->Prompt, sizeof (UINT16));\r
1609 CopyMem (&TargetTag->Help, &((EFI_IFR_REF *) FormData)->Help, sizeof (UINT16));\r
1610 TargetTag->Flags = ((EFI_IFR_REF *) FormData)->Flags;\r
1611 TargetTag->VariableNumber = CurrentVariable;\r
1612 break;\r
1613\r
1614 case EFI_IFR_EQ_ID_VAL_OP:\r
1615 CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_ID_VAL *) FormData)->Value, sizeof (UINT16));\r
1616 CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_VAL *) FormData)->QuestionId, sizeof (UINT16));\r
1617 TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_VAL *) FormData)->Width;\r
1618 TargetTag->VariableNumber = CurrentVariable;\r
1619 break;\r
1620\r
1621 case EFI_IFR_EQ_VAR_VAL_OP:\r
1622 CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_VAR_VAL *) FormData)->Value, sizeof (UINT16));\r
1623 CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_VAR_VAL *) FormData)->VariableId, sizeof (UINT16));\r
1624 TargetTag->VariableNumber = CurrentVariable;\r
1625 break;\r
1626\r
1627 case EFI_IFR_EQ_ID_ID_OP:\r
1628 CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId1, sizeof (UINT16));\r
1629 CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId2, sizeof (UINT16));\r
1630 TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_ID *) FormData)->Width;\r
1631 TargetTag->VariableNumber = CurrentVariable;\r
1632 TargetTag->VariableNumber = CurrentVariable2;\r
1633 break;\r
1634\r
1635 case EFI_IFR_EQ_ID_LIST_OP:\r
1636 CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_LIST *) FormData)->QuestionId, sizeof (UINT16));\r
1637 CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_LIST *) FormData)->ListLength, sizeof (UINT16));\r
1638 TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_LIST *) FormData)->Width;\r
1639\r
1640 TargetTag->IntList = AllocateZeroPool (TargetTag->Id2 * sizeof (UINT16));\r
1641 ASSERT (TargetTag->IntList);\r
1642\r
1643 for (TempValue = 0; TempValue < TargetTag->Id2; TempValue++) {\r
1644 CopyMem (\r
1645 &TargetTag->IntList[TempValue],\r
1646 &((EFI_IFR_EQ_ID_LIST *) FormData)->ValueList[TempValue],\r
1647 sizeof (UINT16)\r
1648 );\r
1649 }\r
1650\r
1651 TargetTag->VariableNumber = CurrentVariable;\r
1652 break;\r
1653\r
1654 case EFI_IFR_FORM_SET_OP:\r
1655 CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) FormData)->NvDataSize, sizeof (UINT16));\r
1656 CopyMem (&Guid, &((EFI_IFR_FORM_SET *) FormData)->Guid, sizeof (EFI_GUID));\r
1657 //\r
1658 // If there is a size specified in the formste, we will establish a "default" variable\r
1659 //\r
1660 if (VariableDefinitionsHead != NULL) {\r
1661 VariableName = AllocateZeroPool (12);\r
1662 ASSERT (VariableName != NULL);\r
1663 CopyMem (VariableName, L"Setup", 12);\r
1664 VariableDefinitionsHead->VariableName = VariableName;\r
1665 VariableDefinitionsHead->VariableSize = VariableSize;\r
1666 CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID));\r
1667 }\r
1668 break;\r
1669\r
1670 case EFI_IFR_END_FORM_SET_OP:\r
1671 CurrentVariable = 0;\r
1672 CurrentVariable2 = 0;\r
1673 break;\r
1674 }\r
1675\r
1676 return ;\r
1677}\r