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