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