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