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