]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrParser.c
clean up for IPF ICC tool chain.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / UefiIfrParser.c
CommitLineData
59336178 1/** @file\r
2Parser for IFR binary encoding.\r
3\r
4Copyright (c) 2008, Intel Corporation\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
a9d85320 15#include <PiDxe.h>\r
16\r
17#include <Protocol/Print.h>\r
18#include <Protocol/HiiConfigAccess.h>\r
19#include <Protocol/HiiConfigRouting.h>\r
20#include <Protocol/HiiDatabase.h>\r
21#include <Protocol/HiiString.h>\r
22\r
23#include <Library/BaseLib.h>\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/DebugLib.h>\r
26#include <Library/HiiLib.h>\r
27#include <Library/IfrSupportLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/PrintLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31\r
32#include <MdeModuleHii.h>\r
33\r
59336178 34#include "UefiIfrParser.h"\r
59336178 35\r
a9d85320 36#include "UefiIfrParserExpression.h"\r
59336178 37\r
38UINT16 mStatementIndex;\r
59336178 39\r
40BOOLEAN mInScopeSubtitle;\r
41BOOLEAN mInScopeSuppress;\r
42BOOLEAN mInScopeGrayOut;\r
59336178 43\r
a9d85320 44EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID;\r
45extern EFI_GUID mTianoHiiIfrGuid;\r
46\r
47LIST_ENTRY *\r
48GetOneOfOptionMapEntryListHead (\r
49 IN CONST FORM_BROWSER_FORMSET *FormSet,\r
50 IN UINT16 QuestionId\r
51 )\r
52{\r
53 LIST_ENTRY *Link;\r
54 ONE_OF_OPTION_MAP *Map;\r
55\r
56 Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);\r
57\r
58 while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {\r
59 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
60 if (QuestionId == Map->QuestionId) {\r
61 return &Map->OneOfOptionMapEntryListHead;\r
62 }\r
63 Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);\r
64 }\r
65 \r
66 return NULL;\r
67}\r
68\r
69VOID\r
70DestoryOneOfOptionMap (\r
71 IN LIST_ENTRY *OneOfOptionMapListHead\r
72 )\r
73{\r
74 ONE_OF_OPTION_MAP *Map;\r
75 ONE_OF_OPTION_MAP_ENTRY *MapEntry;\r
76 LIST_ENTRY *Link;\r
77 LIST_ENTRY *Link2;\r
78\r
79 while (!IsListEmpty (OneOfOptionMapListHead)) {\r
80 Link = GetFirstNode (OneOfOptionMapListHead);\r
81 \r
82 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
83\r
84 while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {\r
85 Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);\r
86 \r
87 MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);\r
88\r
89 RemoveEntryList (Link2);\r
90\r
91 FreePool (MapEntry);\r
92 }\r
93\r
94 RemoveEntryList (Link);\r
95 FreePool (Map);\r
96 }\r
97}\r
98\r
59336178 99\r
100/**\r
101 Initialize Statement header members.\r
102\r
103 @param OpCodeData Pointer of the raw OpCode data.\r
104 @param FormSet Pointer of the current FormSe.\r
105 @param Form Pointer of the current Form.\r
106\r
107 @return The Statement.\r
108\r
109**/\r
110FORM_BROWSER_STATEMENT *\r
111CreateStatement (\r
112 IN UINT8 *OpCodeData,\r
113 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
114 IN OUT FORM_BROWSER_FORM *Form\r
115 )\r
116{\r
117 FORM_BROWSER_STATEMENT *Statement;\r
118 EFI_IFR_STATEMENT_HEADER *StatementHdr;\r
119\r
120 if (Form == NULL) {\r
121 //\r
122 // We are currently not in a Form Scope, so just skip this Statement\r
123 //\r
124 return NULL;\r
125 }\r
126\r
127 Statement = &FormSet->StatementBuffer[mStatementIndex];\r
128 mStatementIndex++;\r
129\r
130 InitializeListHead (&Statement->DefaultListHead);\r
131 InitializeListHead (&Statement->OptionListHead);\r
59336178 132\r
133 Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;\r
134\r
135 Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
136\r
137 StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
138 CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));\r
139 CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));\r
140\r
59336178 141 Statement->InSubtitle = mInScopeSubtitle;\r
142\r
143 //\r
144 // Insert this Statement into current Form\r
145 //\r
146 InsertTailList (&Form->StatementListHead, &Statement->Link);\r
147\r
148 return Statement;\r
149}\r
150\r
59336178 151/**\r
152 Initialize Question's members.\r
153\r
154 @param OpCodeData Pointer of the raw OpCode data.\r
155 @param FormSet Pointer of the current FormSet.\r
156 @param Form Pointer of the current Form.\r
157\r
158 @return The Question.\r
159\r
160**/\r
161FORM_BROWSER_STATEMENT *\r
162CreateQuestion (\r
163 IN UINT8 *OpCodeData,\r
164 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
165 IN OUT FORM_BROWSER_FORM *Form\r
166 )\r
167{\r
168 FORM_BROWSER_STATEMENT *Statement;\r
169 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
170 LIST_ENTRY *Link;\r
171 FORMSET_STORAGE *Storage;\r
59336178 172\r
173 Statement = CreateStatement (OpCodeData, FormSet, Form);\r
174 if (Statement == NULL) {\r
175 return NULL;\r
176 }\r
177\r
178 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
179 CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));\r
180 CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
181 CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));\r
182\r
a9d85320 183 if (FormSet->MaxQuestionId < QuestionHdr->QuestionId) {\r
184 FormSet->MaxQuestionId = QuestionHdr->QuestionId;\r
185 }\r
186\r
59336178 187 Statement->QuestionFlags = QuestionHdr->Flags;\r
188\r
189 if (Statement->VarStoreId == 0) {\r
190 //\r
191 // VarStoreId of zero indicates no variable storage\r
192 //\r
193 return Statement;\r
194 }\r
195\r
196 //\r
197 // Find Storage for this Question\r
198 //\r
199 Link = GetFirstNode (&FormSet->StorageListHead);\r
200 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
201 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
202\r
203 if (Storage->VarStoreId == Statement->VarStoreId) {\r
204 Statement->Storage = Storage;\r
205 break;\r
206 }\r
207\r
208 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
209 }\r
210 ASSERT (Statement->Storage != NULL);\r
211\r
59336178 212 return Statement;\r
213}\r
214\r
59336178 215/**\r
216 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.\r
217\r
218 @param FormSet Pointer of the current FormSet\r
219\r
220 @return Pointer to a FORMSET_STORAGE data structure.\r
221\r
222**/\r
223FORMSET_STORAGE *\r
224CreateStorage (\r
225 IN FORM_BROWSER_FORMSET *FormSet\r
226 )\r
227{\r
228 FORMSET_STORAGE *Storage;\r
229\r
230 Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));\r
231 Storage->Signature = FORMSET_STORAGE_SIGNATURE;\r
59336178 232 InsertTailList (&FormSet->StorageListHead, &Storage->Link);\r
233\r
234 return Storage;\r
235}\r
236\r
59336178 237/**\r
238 Free resources of a storage\r
239\r
240 @param Storage Pointer of the storage\r
241\r
242 @return None.\r
243\r
244**/\r
245VOID\r
246DestroyStorage (\r
247 IN FORMSET_STORAGE *Storage\r
248 )\r
249{\r
59336178 250 if (Storage == NULL) {\r
251 return;\r
252 }\r
253\r
a9d85320 254 if (Storage->Name!= NULL) {\r
255 FreePool (Storage->Name);\r
59336178 256 }\r
257\r
7001eaf8 258 FreePool (Storage);\r
59336178 259}\r
260\r
261\r
262/**\r
263 Free resources of a Statement\r
264\r
265 @param Statement Pointer of the Statement\r
266\r
267 @return None.\r
268\r
269**/\r
270VOID\r
271DestroyStatement (\r
272 IN OUT FORM_BROWSER_STATEMENT *Statement\r
273 )\r
274{\r
275 LIST_ENTRY *Link;\r
276 QUESTION_DEFAULT *Default;\r
277 QUESTION_OPTION *Option;\r
59336178 278\r
279 //\r
280 // Free Default value List\r
281 //\r
282 while (!IsListEmpty (&Statement->DefaultListHead)) {\r
283 Link = GetFirstNode (&Statement->DefaultListHead);\r
284 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
285 RemoveEntryList (&Default->Link);\r
286\r
287 gBS->FreePool (Default);\r
288 }\r
289\r
290 //\r
291 // Free Options List\r
292 //\r
293 while (!IsListEmpty (&Statement->OptionListHead)) {\r
294 Link = GetFirstNode (&Statement->OptionListHead);\r
295 Option = QUESTION_OPTION_FROM_LINK (Link);\r
296 RemoveEntryList (&Option->Link);\r
297\r
298 gBS->FreePool (Option);\r
299 }\r
300\r
59336178 301}\r
302\r
303\r
7001eaf8 304\r
59336178 305/**\r
306 Free resources of a Form\r
307\r
308 @param Form Pointer of the Form\r
309\r
310 @return None.\r
311\r
312**/\r
313VOID\r
314DestroyForm (\r
315 IN OUT FORM_BROWSER_FORM *Form\r
316 )\r
317{\r
318 LIST_ENTRY *Link;\r
59336178 319 FORM_BROWSER_STATEMENT *Statement;\r
320\r
59336178 321 //\r
322 // Free Statements/Questions\r
323 //\r
324 while (!IsListEmpty (&Form->StatementListHead)) {\r
325 Link = GetFirstNode (&Form->StatementListHead);\r
326 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
327 RemoveEntryList (&Statement->Link);\r
328\r
329 DestroyStatement (Statement);\r
330 }\r
331\r
332 //\r
333 // Free this Form\r
334 //\r
335 gBS->FreePool (Form);\r
336}\r
337\r
338\r
339/**\r
340 Free resources allocated for a FormSet\r
341\r
342 @param FormSet Pointer of the FormSet\r
343\r
344 @return None.\r
345\r
346**/\r
347VOID\r
348DestroyFormSet (\r
349 IN OUT FORM_BROWSER_FORMSET *FormSet\r
350 )\r
351{\r
352 LIST_ENTRY *Link;\r
353 FORMSET_STORAGE *Storage;\r
354 FORMSET_DEFAULTSTORE *DefaultStore;\r
355 FORM_BROWSER_FORM *Form;\r
356\r
357 //\r
358 // Free IFR binary buffer\r
359 //\r
7001eaf8 360 FreePool (FormSet->IfrBinaryData);\r
59336178 361\r
362 //\r
363 // Free FormSet Storage\r
364 //\r
365 if (FormSet->StorageListHead.ForwardLink != NULL) {\r
366 while (!IsListEmpty (&FormSet->StorageListHead)) {\r
367 Link = GetFirstNode (&FormSet->StorageListHead);\r
368 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
369 RemoveEntryList (&Storage->Link);\r
370\r
371 DestroyStorage (Storage);\r
372 }\r
373 }\r
374\r
375 //\r
376 // Free FormSet Default Store\r
377 //\r
378 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {\r
379 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
380 Link = GetFirstNode (&FormSet->DefaultStoreListHead);\r
381 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);\r
382 RemoveEntryList (&DefaultStore->Link);\r
383\r
384 gBS->FreePool (DefaultStore);\r
385 }\r
386 }\r
387\r
388 //\r
389 // Free Forms\r
390 //\r
391 if (FormSet->FormListHead.ForwardLink != NULL) {\r
392 while (!IsListEmpty (&FormSet->FormListHead)) {\r
393 Link = GetFirstNode (&FormSet->FormListHead);\r
394 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
395 RemoveEntryList (&Form->Link);\r
396\r
397 DestroyForm (Form);\r
398 }\r
399 }\r
400\r
7001eaf8 401 if (FormSet->StatementBuffer != NULL) {\r
402 FreePool (FormSet->StatementBuffer);\r
403 }\r
59336178 404\r
a9d85320 405 DestoryOneOfOptionMap (&FormSet->OneOfOptionMapListHead);\r
406 \r
7001eaf8 407 FreePool (FormSet);\r
59336178 408}\r
409\r
410\r
411/**\r
412 Tell whether this Operand is an Expression OpCode or not\r
413\r
414 @param Operand Operand of an IFR OpCode.\r
415\r
416 @retval TRUE This is an Expression OpCode.\r
417 @retval FALSE Not an Expression OpCode.\r
418\r
419**/\r
420BOOLEAN\r
421IsExpressionOpCode (\r
422 IN UINT8 Operand\r
423 )\r
424{\r
425 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||\r
426 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
427 (Operand == EFI_IFR_CATENATE_OP)\r
428 ) {\r
429 return TRUE;\r
430 } else {\r
431 return FALSE;\r
432 }\r
433}\r
434\r
435\r
436/**\r
437 Calculate number of Statemens(Questions) and Expression OpCodes.\r
438\r
439 @param FormSet The FormSet to be counted.\r
440 @param NumberOfStatement Number of Statemens(Questions)\r
441 @param NumberOfExpression Number of Expression OpCodes\r
442\r
443 @return None.\r
444\r
445**/\r
446VOID\r
447CountOpCodes (\r
448 IN FORM_BROWSER_FORMSET *FormSet,\r
449 IN OUT UINT16 *NumberOfStatement,\r
450 IN OUT UINT16 *NumberOfExpression\r
451 )\r
452{\r
453 UINT16 StatementCount;\r
454 UINT16 ExpressionCount;\r
455 UINT8 *OpCodeData;\r
456 UINTN Offset;\r
457 UINTN OpCodeLen;\r
458\r
459 Offset = 0;\r
460 StatementCount = 0;\r
461 ExpressionCount = 0;\r
462\r
463 while (Offset < FormSet->IfrBinaryLength) {\r
464 OpCodeData = FormSet->IfrBinaryData + Offset;\r
465 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
466 Offset += OpCodeLen;\r
467\r
468 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {\r
469 ExpressionCount++;\r
470 } else {\r
471 StatementCount++;\r
472 }\r
473 }\r
474\r
475 *NumberOfStatement = StatementCount;\r
476 *NumberOfExpression = ExpressionCount;\r
477}\r
478\r
479\r
480/**\r
481 Parse opcodes in the formset IFR binary.\r
482\r
483 @param FormSet Pointer of the FormSet data structure.\r
484\r
485 @retval EFI_SUCCESS Opcode parse success.\r
486 @retval Other Opcode parse fail.\r
487\r
488**/\r
489EFI_STATUS\r
490ParseOpCodes (\r
491 IN FORM_BROWSER_FORMSET *FormSet\r
492 )\r
493{\r
494 EFI_STATUS Status;\r
495 UINT16 Index;\r
496 FORM_BROWSER_FORM *CurrentForm;\r
497 FORM_BROWSER_STATEMENT *CurrentStatement;\r
59336178 498 UINT8 Operand;\r
499 UINT8 Scope;\r
500 UINTN OpCodeOffset;\r
501 UINTN OpCodeLength;\r
502 UINT8 *OpCodeData;\r
503 UINT8 ScopeOpCode;\r
504 FORMSET_STORAGE *Storage;\r
505 FORMSET_DEFAULTSTORE *DefaultStore;\r
506 QUESTION_DEFAULT *CurrentDefault;\r
507 QUESTION_OPTION *CurrentOption;\r
508 CHAR8 *AsciiString;\r
509 UINT16 NumberOfStatement;\r
510 UINT16 NumberOfExpression;\r
511 EFI_IMAGE_ID *ImageId;\r
59336178 512 EFI_HII_VALUE *Value;\r
a9d85320 513 LIST_ENTRY *OneOfOptinMapEntryListHead;\r
514 EFI_IFR_GUID_OPTIONKEY *OptionMap;\r
515 ONE_OF_OPTION_MAP *OneOfOptionMap;\r
516 ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
517 UINT8 OneOfType;\r
518 EFI_IFR_ONE_OF *OneOfOpcode;\r
59336178 519\r
520 mInScopeSubtitle = FALSE;\r
59336178 521 mInScopeSuppress = FALSE;\r
59336178 522 mInScopeGrayOut = FALSE;\r
59336178 523 CurrentDefault = NULL;\r
524 CurrentOption = NULL;\r
a9d85320 525\r
526 //\r
527 // Set to a invalid value.\r
528 //\r
529 OneOfType = (UINT8) -1;\r
59336178 530\r
531 //\r
532 // Get the number of Statements and Expressions\r
533 //\r
534 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
a9d85320 535 FormSet->NumberOfStatement = NumberOfStatement;\r
59336178 536\r
537 mStatementIndex = 0;\r
538 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));\r
539 if (FormSet->StatementBuffer == NULL) {\r
540 return EFI_OUT_OF_RESOURCES;\r
541 }\r
542\r
59336178 543 InitializeListHead (&FormSet->StorageListHead);\r
544 InitializeListHead (&FormSet->DefaultStoreListHead);\r
545 InitializeListHead (&FormSet->FormListHead);\r
a9d85320 546 InitializeListHead (&FormSet->OneOfOptionMapListHead);\r
59336178 547\r
548 CurrentForm = NULL;\r
549 CurrentStatement = NULL;\r
550\r
551 ResetScopeStack ();\r
552\r
553 OpCodeOffset = 0;\r
554 while (OpCodeOffset < FormSet->IfrBinaryLength) {\r
555 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;\r
556\r
557 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
558 OpCodeOffset += OpCodeLength;\r
559 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
560 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;\r
561\r
562 //\r
563 // If scope bit set, push onto scope stack\r
564 //\r
565 if (Scope) {\r
566 PushScope (Operand);\r
567 }\r
568\r
59336178 569 if (IsExpressionOpCode (Operand)) {\r
59336178 570 continue;\r
571 }\r
572\r
573 //\r
574 // Parse the Opcode\r
575 //\r
576 switch (Operand) {\r
577\r
578 case EFI_IFR_FORM_SET_OP:\r
579 //\r
580 // check the formset GUID\r
581 //\r
5a58200d 582 if (!CompareGuid ((EFI_GUID *)(VOID *)&FormSet->Guid, (EFI_GUID *)(VOID *)&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)) {\r
59336178 583 return EFI_INVALID_PARAMETER;\r
584 }\r
585\r
586 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
587 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
588 break;\r
589\r
590 case EFI_IFR_FORM_OP:\r
591 //\r
592 // Create a new Form for this FormSet\r
593 //\r
594 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));\r
595 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;\r
a9d85320 596\r
59336178 597 InitializeListHead (&CurrentForm->StatementListHead);\r
598\r
599 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));\r
600 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
601\r
602 //\r
603 // Insert into Form list of this FormSet\r
604 //\r
605 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
606 break;\r
607\r
608 //\r
609 // Storage\r
610 //\r
611 case EFI_IFR_VARSTORE_OP:\r
612 //\r
613 // Create a buffer Storage for this FormSet\r
614 //\r
615 Storage = CreateStorage (FormSet);\r
616 Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
617\r
618 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
619 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
620 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
621\r
59336178 622 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
623 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
624 ASSERT (Storage->Name != NULL);\r
625 for (Index = 0; AsciiString[Index] != 0; Index++) {\r
626 Storage->Name[Index] = (CHAR16) AsciiString[Index];\r
627 }\r
628\r
59336178 629 break;\r
630\r
631 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
a9d85320 632 ASSERT (FALSE);\r
59336178 633\r
59336178 634 break;\r
635\r
636 case EFI_IFR_VARSTORE_EFI_OP:\r
637 //\r
638 // Create a EFI variable Storage for this FormSet\r
639 //\r
640 Storage = CreateStorage (FormSet);\r
641 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
642\r
643 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
644 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
645 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));\r
646 break;\r
647\r
648 //\r
649 // DefaultStore\r
650 //\r
651 case EFI_IFR_DEFAULTSTORE_OP:\r
652 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));\r
653 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;\r
654\r
655 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));\r
656 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));\r
657\r
658 //\r
659 // Insert to DefaultStore list of this Formset\r
660 //\r
661 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);\r
662 break;\r
663\r
664 //\r
665 // Statements\r
666 //\r
667 case EFI_IFR_SUBTITLE_OP:\r
668 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
669 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;\r
670\r
671 if (Scope) {\r
672 mInScopeSubtitle = TRUE;\r
673 }\r
674 break;\r
675\r
676 case EFI_IFR_TEXT_OP:\r
677 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
678\r
679 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
680 break;\r
681\r
682 //\r
683 // Questions\r
684 //\r
685 case EFI_IFR_ACTION_OP:\r
686 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
687\r
688 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {\r
689 //\r
690 // No QuestionConfig present, so no configuration string will be processed\r
691 //\r
692 CurrentStatement->QuestionConfig = 0;\r
693 } else {\r
694 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));\r
695 }\r
696 break;\r
697\r
698 case EFI_IFR_RESET_BUTTON_OP:\r
699 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
700\r
701 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
702 break;\r
703\r
704 case EFI_IFR_REF_OP:\r
705 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
706\r
707 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
708 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
709 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
710\r
711 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
712 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
713\r
714 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
715 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
716 }\r
717 }\r
718 }\r
719 break;\r
720\r
721 case EFI_IFR_ONE_OF_OP:\r
722 case EFI_IFR_NUMERIC_OP:\r
723 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
724\r
725 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;\r
726 Value = &CurrentStatement->HiiValue;\r
727\r
728 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {\r
729 case EFI_IFR_NUMERIC_SIZE_1:\r
730 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;\r
731 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;\r
732 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;\r
733 CurrentStatement->StorageWidth = sizeof (UINT8);\r
734 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
735 break;\r
736\r
737 case EFI_IFR_NUMERIC_SIZE_2:\r
738 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));\r
739 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));\r
740 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));\r
741 CurrentStatement->StorageWidth = sizeof (UINT16);\r
742 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
743 break;\r
744\r
745 case EFI_IFR_NUMERIC_SIZE_4:\r
746 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));\r
747 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));\r
748 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));\r
749 CurrentStatement->StorageWidth = sizeof (UINT32);\r
750 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
751 break;\r
752\r
753 case EFI_IFR_NUMERIC_SIZE_8:\r
754 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));\r
755 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));\r
756 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));\r
757 CurrentStatement->StorageWidth = sizeof (UINT64);\r
758 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
759 break;\r
760\r
761 default:\r
762 break;\r
763 }\r
764\r
a9d85320 765 if (Operand == EFI_IFR_ONE_OF_OP) {\r
766 OneOfOpcode = (EFI_IFR_ONE_OF *) OpCodeData;\r
98b16b9d 767 OneOfType = (UINT8) (OneOfOpcode->Flags & EFI_IFR_NUMERIC_SIZE);\r
a9d85320 768 }\r
59336178 769 break;\r
770\r
771 case EFI_IFR_ORDERED_LIST_OP:\r
772 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
773\r
774 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;\r
775 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
776 CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));\r
59336178 777\r
778 //\r
779 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver\r
780 // has to use FormBrowser2.Callback() to retrieve the uncommited data for\r
781 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).\r
782 //\r
783 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;\r
784 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);\r
785\r
59336178 786 break;\r
787\r
788 case EFI_IFR_CHECKBOX_OP:\r
789 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
790\r
791 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;\r
792 CurrentStatement->StorageWidth = sizeof (BOOLEAN);\r
793 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;\r
794\r
59336178 795 break;\r
796\r
797 case EFI_IFR_STRING_OP:\r
798 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
799\r
800 //\r
801 // MinSize is the minimum number of characters that can be accepted for this opcode,\r
802 // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
803 // The characters are stored as Unicode, so the storage width should multiply 2.\r
804 //\r
805 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;\r
806 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;\r
807 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));\r
808 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;\r
809\r
810 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
811 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);\r
812\r
59336178 813 break;\r
814\r
815 case EFI_IFR_PASSWORD_OP:\r
816 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
817\r
818 //\r
819 // MinSize is the minimum number of characters that can be accepted for this opcode,\r
820 // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
821 // The characters are stored as Unicode, so the storage width should multiply 2.\r
822 //\r
823 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));\r
824 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));\r
825 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));\r
826\r
827 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
828 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);\r
829\r
59336178 830 break;\r
831\r
832 case EFI_IFR_DATE_OP:\r
833 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
834\r
835 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;\r
836 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;\r
837\r
59336178 838 break;\r
839\r
840 case EFI_IFR_TIME_OP:\r
841 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
842\r
843 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;\r
844 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;\r
845\r
59336178 846 break;\r
847\r
848 //\r
849 // Default\r
850 //\r
851 case EFI_IFR_DEFAULT_OP:\r
852 //\r
853 // EFI_IFR_DEFAULT appear in scope of a Question,\r
854 // It creates a default value for the current question.\r
855 // A Question may have more than one Default value which have different default types.\r
856 //\r
857 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));\r
858 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;\r
859\r
860 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;\r
861 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));\r
862 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
863 ExtendValueToU64 (&CurrentDefault->Value);\r
864\r
865 //\r
866 // Insert to Default Value list of current Question\r
867 //\r
868 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);\r
869\r
59336178 870 break;\r
871\r
872 //\r
873 // Option\r
874 //\r
875 case EFI_IFR_ONE_OF_OPTION_OP:\r
876 //\r
877 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.\r
878 // It create a selection for use in current Question.\r
879 //\r
880 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));\r
881 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;\r
882\r
883 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;\r
884 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;\r
885 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));\r
886 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
887 ExtendValueToU64 (&CurrentOption->Value);\r
888\r
59336178 889 //\r
890 // Insert to Option list of current Question\r
891 //\r
892 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);\r
893 break;\r
894\r
895 //\r
896 // Conditional\r
897 //\r
898 case EFI_IFR_NO_SUBMIT_IF_OP:\r
899 case EFI_IFR_INCONSISTENT_IF_OP:\r
59336178 900 break;\r
901\r
902 case EFI_IFR_SUPPRESS_IF_OP:\r
59336178 903 break;\r
904\r
905 case EFI_IFR_GRAY_OUT_IF_OP:\r
59336178 906 break;\r
907\r
908 case EFI_IFR_DISABLE_IF_OP:\r
a9d85320 909 ASSERT (FALSE);\r
59336178 910\r
59336178 911\r
912 //\r
913 // Expression\r
914 //\r
915 case EFI_IFR_VALUE_OP:\r
59336178 916 break;\r
917\r
918 case EFI_IFR_RULE_OP:\r
59336178 919 break;\r
920\r
921 //\r
922 // Image\r
923 //\r
924 case EFI_IFR_IMAGE_OP:\r
925 //\r
926 // Get ScopeOpcode from top of stack\r
927 //\r
928 PopScope (&ScopeOpCode);\r
929 PushScope (ScopeOpCode);\r
930\r
931 switch (ScopeOpCode) {\r
932 case EFI_IFR_FORM_SET_OP:\r
933 ImageId = &FormSet->ImageId;\r
934 break;\r
935\r
936 case EFI_IFR_FORM_OP:\r
937 ImageId = &CurrentForm->ImageId;\r
938 break;\r
939\r
940 case EFI_IFR_ONE_OF_OPTION_OP:\r
941 ImageId = &CurrentOption->ImageId;\r
942 break;\r
943\r
944 default:\r
945 ImageId = &CurrentStatement->ImageId;\r
946 break;\r
947 }\r
948\r
949 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));\r
950 break;\r
951\r
952 //\r
953 // Refresh\r
954 //\r
955 case EFI_IFR_REFRESH_OP:\r
956 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;\r
957 break;\r
958\r
959 //\r
960 // Vendor specific\r
961 //\r
962 case EFI_IFR_GUID_OP:\r
a9d85320 963 OptionMap = (EFI_IFR_GUID_OPTIONKEY *) OpCodeData;\r
964 \r
965 if (CompareGuid (&mTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
59336178 966 //\r
967 // Tiano specific GUIDed opcodes\r
968 //\r
969 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
970 case EFI_IFR_EXTEND_OP_LABEL:\r
971 //\r
972 // just ignore label\r
973 //\r
974 break;\r
975\r
59336178 976\r
977 case EFI_IFR_EXTEND_OP_CLASS:\r
978 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));\r
979 break;\r
980\r
981 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
982 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));\r
983 break;\r
984\r
985 default:\r
986 break;\r
987 }\r
a9d85320 988 } \r
989 else if (CompareGuid ((EFI_GUID *)(VOID *)&OptionMap->Guid, &mFrameworkHiiCompatibilityGuid)) {\r
990 if (OptionMap->ExtendOpCode == EFI_IFR_EXTEND_OP_OPTIONKEY) {\r
991 OneOfOptinMapEntryListHead = GetOneOfOptionMapEntryListHead (FormSet, OptionMap->QuestionId);\r
992 if (OneOfOptinMapEntryListHead == NULL) {\r
993 OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP));\r
994 ASSERT (OneOfOptionMap != NULL);\r
995\r
996 OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;\r
997 OneOfOptionMap->QuestionId = OptionMap->QuestionId;\r
998\r
999 //\r
1000 // Make sure OneOfType is initialized.\r
1001 //\r
1002 ASSERT (OneOfType != (UINT8) -1);\r
1003 OneOfOptionMap->ValueType = OneOfType;\r
1004 InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
1005 OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead;\r
1006 InsertTailList (&FormSet->OneOfOptionMapListHead, &OneOfOptionMap->Link);\r
1007 }\r
1008 OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));\r
1009 ASSERT (OneOfOptionMapEntry != NULL);\r
1010\r
1011 OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE;\r
1012 OneOfOptionMapEntry->FwKey = OptionMap->KeyValue;\r
1013 CopyMem (&OneOfOptionMapEntry->Value, &OptionMap->OptionValue, sizeof (EFI_IFR_TYPE_VALUE));\r
1014 \r
1015 InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);\r
1016 }\r
1017 }\r
59336178 1018 break;\r
1019\r
1020 //\r
1021 // Scope End\r
1022 //\r
1023 case EFI_IFR_END_OP:\r
1024 Status = PopScope (&ScopeOpCode);\r
1025 if (EFI_ERROR (Status)) {\r
1026 ResetScopeStack ();\r
1027 return Status;\r
1028 }\r
1029\r
1030 switch (ScopeOpCode) {\r
1031 case EFI_IFR_FORM_SET_OP:\r
1032 //\r
1033 // End of FormSet, update FormSet IFR binary length\r
1034 // to stop parsing substantial OpCodes\r
1035 //\r
1036 FormSet->IfrBinaryLength = OpCodeOffset;\r
1037 break;\r
1038\r
1039 case EFI_IFR_FORM_OP:\r
1040 //\r
1041 // End of Form\r
1042 //\r
1043 CurrentForm = NULL;\r
1044 break;\r
1045\r
1046 case EFI_IFR_ONE_OF_OPTION_OP:\r
1047 //\r
1048 // End of Option\r
1049 //\r
1050 CurrentOption = NULL;\r
1051 break;\r
1052\r
1053 case EFI_IFR_SUBTITLE_OP:\r
1054 mInScopeSubtitle = FALSE;\r
1055 break;\r
1056\r
1057 case EFI_IFR_NO_SUBMIT_IF_OP:\r
1058 case EFI_IFR_INCONSISTENT_IF_OP:\r
1059 //\r
1060 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF\r
1061 //\r
1062 break;\r
1063\r
59336178 1064 case EFI_IFR_GRAY_OUT_IF_OP:\r
1065 mInScopeGrayOut = FALSE;\r
1066 break;\r
1067\r
59336178 1068 default:\r
1069 if (IsExpressionOpCode (ScopeOpCode)) {\r
59336178 1070 }\r
1071 break;\r
1072 }\r
1073 break;\r
1074\r
1075 default:\r
1076 break;\r
1077 }\r
1078 }\r
1079\r
1080 return EFI_SUCCESS;\r
1081}\r
1082\r
1083\r
1084\r
1085\r