]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Library / EdkIfrSupportLib / IfrCommon.c
CommitLineData
878ddf1f 1/*++\r
7f47bef3 2Copyright (c) 2006, Intel Corporation\r
3All rights reserved. This program and the accompanying materials\r
4are licensed and made available under the terms and conditions of the BSD License\r
5which accompanies this distribution. The full text of the license may be found at\r
878ddf1f 6http://opensource.org/licenses/bsd-license.php \r
7f47bef3 7 \r
8THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
878ddf1f 10\r
11Module Name:\r
12 IfrCommon.c\r
13\r
14Abstract:\r
15\r
16 Common Library Routines to assist in IFR creation on-the-fly\r
17\r
18Revision History:\r
19\r
20--*/\r
21\r
22EFI_STATUS\r
7f47bef3 23EFIAPI\r
878ddf1f 24IfrLibConstruct (\r
25 IN EFI_HANDLE ImageHandle,\r
26 IN EFI_SYSTEM_TABLE *SystemTable\r
27 )\r
28{\r
29 return EFI_SUCCESS;\r
30}\r
31\r
32EFI_STATUS\r
33GetCurrentLanguage (\r
34 OUT CHAR16 *Lang\r
35 )\r
36/*++\r
37\r
38Routine Description:\r
39\r
40 Determine what is the current language setting\r
7f47bef3 41\r
878ddf1f 42Arguments:\r
7f47bef3 43\r
878ddf1f 44 Lang - Pointer of system language\r
7f47bef3 45\r
46Returns:\r
878ddf1f 47\r
48 Status code\r
49\r
50--*/\r
51{\r
52 EFI_STATUS Status;\r
53 UINTN Size;\r
54 UINTN Index;\r
55 CHAR8 Language[4];\r
56\r
57 //\r
58 // Getting the system language and placing it into our Global Data\r
59 //\r
60 Size = sizeof (Language);\r
61\r
62 Status = gRT->GetVariable (\r
63 (CHAR16 *) L"Lang",\r
64 &gEfiGlobalVariableGuid,\r
65 NULL,\r
66 &Size,\r
67 Language\r
68 );\r
69\r
70 if (EFI_ERROR (Status)) {\r
71 AsciiStrCpy (Language, "eng");\r
72 }\r
73\r
cdcaf781 74 for (Index = 0; Index < 3; Index++) {\r
878ddf1f 75 //\r
76 // Bitwise AND ascii value with 0xDF yields an uppercase value.\r
77 // Sign extend into a unicode value\r
78 //\r
79 Lang[Index] = (CHAR16) (Language[Index] & 0xDF);\r
80 }\r
81\r
82 //\r
83 // Null-terminate the value\r
84 //\r
85 Lang[3] = (CHAR16) 0;\r
86\r
87 return Status;\r
88}\r
89\r
90\r
91EFI_STATUS\r
92AddString (\r
93 IN VOID *StringBuffer,\r
94 IN CHAR16 *Language,\r
95 IN CHAR16 *String,\r
96 IN OUT STRING_REF *StringToken\r
97 )\r
98/*++\r
99\r
100Routine Description:\r
101\r
102 Add a string to the incoming buffer and return the token and offset data\r
7f47bef3 103\r
878ddf1f 104Arguments:\r
7f47bef3 105\r
878ddf1f 106 StringBuffer - The incoming buffer\r
7f47bef3 107\r
878ddf1f 108 Language - Currrent language\r
7f47bef3 109\r
878ddf1f 110 String - The string to be added\r
7f47bef3 111\r
878ddf1f 112 StringToken - The index where the string placed\r
7f47bef3 113\r
114Returns:\r
878ddf1f 115\r
116 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
7f47bef3 117\r
878ddf1f 118 EFI_SUCCESS - String successfully added to the incoming buffer\r
119\r
120--*/\r
121{\r
122 EFI_HII_STRING_PACK *StringPack;\r
123 EFI_HII_STRING_PACK *StringPackBuffer;\r
124 VOID *NewBuffer;\r
125 RELOFST *PackSource;\r
126 RELOFST *PackDestination;\r
127 UINT8 *Source;\r
128 UINT8 *Destination;\r
129 UINTN Index;\r
130 BOOLEAN Finished;\r
1cc8ee78 131 UINTN SizeofLanguage;\r
132 UINTN SizeofString;\r
878ddf1f 133\r
134 StringPack = (EFI_HII_STRING_PACK *) StringBuffer;\r
135 Finished = FALSE;\r
136\r
137 //\r
138 // Pre-allocate a buffer sufficient for us to work on.\r
139 // We will use it as a destination scratch pad to build data on\r
140 // and when complete shift the data back to the original buffer\r
141 //\r
142 NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);\r
143 if (NewBuffer == NULL) {\r
144 return EFI_OUT_OF_RESOURCES;\r
145 }\r
146\r
147 StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;\r
148\r
149 //\r
150 // StringPack is terminated with a length 0 entry\r
151 //\r
152 for (; StringPack->Header.Length != 0;) {\r
153 //\r
154 // If this stringpack's language is same as CurrentLanguage, use it\r
155 //\r
156 if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {\r
157 //\r
158 // We have some data in this string pack, copy the string package up to the string data\r
159 //\r
160 CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));\r
161\r
162 //\r
163 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer\r
164 //\r
165 StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));\r
166 StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));\r
167\r
168 PackSource = (RELOFST *) (StringPack + 1);\r
169 PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
170 for (Index = 0; PackSource[Index] != 0x0000; Index++) {\r
171 //\r
172 // Copy the stringpointers from old to new buffer\r
173 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)\r
174 //\r
175 PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));\r
176 }\r
7f47bef3 177\r
878ddf1f 178 //\r
179 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it\r
180 //\r
7f47bef3 181 PackDestination[Index] = (UINT16)(PackDestination[Index-1] +\r
878ddf1f 182 StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1])));\r
183 PackDestination[Index + 1] = (UINT16) 0;\r
184\r
185 //\r
186 // Index is the token value for the new string\r
187 //\r
188 *StringToken = (UINT16) Index;\r
189\r
190 //\r
191 // Source now points to the beginning of the old buffer strings\r
192 // Destination now points to the beginning of the new buffer strings\r
193 //\r
194 Source = (UINT8 *) &PackSource[Index + 1];\r
195 Destination = (UINT8 *) &PackDestination[Index + 2];\r
196\r
197 //\r
198 // This should copy all the strings from the old buffer to the new buffer\r
199 //\r
200 for (; Index != 0; Index--) {\r
201 //\r
202 // Copy Source string to destination buffer\r
203 //\r
204 StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);\r
205\r
206 //\r
207 // Adjust the source/destination to the next string location\r
208 //\r
209 Destination = Destination + StrSize ((CHAR16 *) Source);\r
210 Source = Source + StrSize ((CHAR16 *) Source);\r
211 }\r
7f47bef3 212\r
878ddf1f 213 //\r
214 // This copies the new string to the destination buffer\r
215 //\r
216 StrCpy ((CHAR16 *) Destination, (CHAR16 *) String);\r
217\r
218 //\r
219 // Adjust the size of the changed string pack by adding the size of the new string\r
220 // along with the size of the additional offset entry for the new string\r
221 //\r
222 StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST));\r
223\r
224 //\r
225 // Advance the buffers to point to the next spots.\r
226 //\r
227 StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);\r
228 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
229 Finished = TRUE;\r
230 continue;\r
231 }\r
232 //\r
233 // This isn't the language of the stringpack we were asked to add a string to\r
234 // so we need to copy it to the new buffer.\r
235 //\r
236 CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);\r
237\r
238 //\r
239 // Advance the buffers to point to the next spots.\r
240 //\r
241 StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);\r
242 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
243 }\r
7f47bef3 244\r
878ddf1f 245 //\r
246 // If we didn't copy the new data to a stringpack yet\r
247 //\r
248 if (!Finished) {\r
249 PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
250 //\r
251 // Pointing to a new string pack location\r
252 //\r
1cc8ee78 253 SizeofLanguage = StrSize (Language);\r
254 SizeofString = StrSize (String);\r
878ddf1f 255 StringPackBuffer->Header.Length = (UINT32)\r
256 (\r
257 sizeof (EFI_HII_STRING_PACK) -\r
258 sizeof (EFI_STRING) +\r
259 sizeof (RELOFST) +\r
260 sizeof (RELOFST) +\r
1cc8ee78 261 SizeofLanguage +\r
262 SizeofString\r
878ddf1f 263 );\r
264 StringPackBuffer->Header.Type = EFI_HII_STRING;\r
265 StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
266 StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
267 StringPackBuffer->Attributes = 0;\r
268 PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
269 PackDestination[1] = (UINT16) (PackDestination[0] + StrSize (Language));\r
270 PackDestination[2] = (UINT16) 0;\r
271\r
272 //\r
273 // The first string location will be set to destination. The minimum number of strings\r
274 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)\r
275 // and token 1 as the new string being added and and null entry for the stringpointers\r
276 //\r
277 Destination = (UINT8 *) &PackDestination[3];\r
278\r
279 //\r
280 // Copy the language name string to the new buffer\r
281 //\r
282 StrCpy ((CHAR16 *) Destination, Language);\r
283\r
284 //\r
285 // Advance the destination to the new empty spot\r
286 //\r
287 Destination = Destination + StrSize (Language);\r
288\r
289 //\r
290 // Copy the string to the new buffer\r
291 //\r
292 StrCpy ((CHAR16 *) Destination, String);\r
293\r
294 //\r
295 // Since we are starting with a new string pack - we know the new string is token 1\r
296 //\r
297 *StringToken = (UINT16) 1;\r
298 }\r
299\r
300 //\r
301 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
302 //\r
303 ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
304 CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
305\r
306 //\r
307 // Free the newly created buffer since we don't need it anymore\r
308 //\r
309 gBS->FreePool (NewBuffer);\r
310 return EFI_SUCCESS;\r
311}\r
312\r
313\r
314EFI_STATUS\r
315AddOpCode (\r
316 IN VOID *FormBuffer,\r
317 IN OUT VOID *OpCodeData\r
318 )\r
319/*++\r
320\r
321Routine Description:\r
322\r
323 Add op-code data to the FormBuffer\r
7f47bef3 324\r
878ddf1f 325Arguments:\r
7f47bef3 326\r
878ddf1f 327 FormBuffer - Form buffer to be inserted to\r
7f47bef3 328\r
878ddf1f 329 OpCodeData - Op-code data to be inserted\r
7f47bef3 330\r
331Returns:\r
878ddf1f 332\r
333 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
7f47bef3 334\r
878ddf1f 335 EFI_SUCCESS - Op-code data successfully inserted\r
336\r
337--*/\r
338{\r
339 EFI_HII_PACK_HEADER *NewBuffer;\r
340 UINT8 *Source;\r
341 UINT8 *Destination;\r
342\r
343 //\r
344 // Pre-allocate a buffer sufficient for us to work on.\r
345 // We will use it as a destination scratch pad to build data on\r
346 // and when complete shift the data back to the original buffer\r
347 //\r
348 NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);\r
349 if (NewBuffer == NULL) {\r
350 return EFI_OUT_OF_RESOURCES;\r
351 }\r
352\r
353 Source = (UINT8 *) FormBuffer;\r
354 Destination = (UINT8 *) NewBuffer;\r
355\r
356 //\r
357 // Copy the IFR Package header to the new buffer\r
358 //\r
359 CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));\r
360\r
361 //\r
362 // Advance Source and Destination to next op-code\r
363 //\r
364 Source = Source + sizeof (EFI_HII_PACK_HEADER);\r
365 Destination = Destination + sizeof (EFI_HII_PACK_HEADER);\r
366\r
367 //\r
368 // Copy data to the new buffer until we run into the end_form\r
369 //\r
370 for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) {\r
371 //\r
372 // If the this opcode is an end_form_set we better be creating and endform\r
373 // Nonetheless, we will add data before the end_form_set. This also provides\r
374 // for interesting behavior in the code we will run, but has no bad side-effects\r
375 // since we will possibly do a 0 byte copy in this particular end-case.\r
376 //\r
377 if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) {\r
378 break;\r
379 }\r
380\r
381 //\r
382 // Copy data to new buffer\r
383 //\r
384 CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
385\r
386 //\r
387 // Adjust Source/Destination to next op-code location\r
388 //\r
389 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
390 Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
391 }\r
392\r
393 //\r
394 // Prior to the end_form is where we insert the new op-code data\r
395 //\r
396 CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
397 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
398\r
399 NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length));\r
400\r
401 //\r
402 // Copy end-form data to new buffer\r
403 //\r
404 CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
405\r
406 //\r
407 // Adjust Source/Destination to next op-code location\r
408 //\r
409 Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
410 Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
411\r
412 //\r
413 // Copy end-formset data to new buffer\r
414 //\r
415 CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
416\r
417 //\r
418 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
419 //\r
420 ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
421 CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
422\r
423 //\r
424 // Free the newly created buffer since we don't need it anymore\r
425 //\r
426 gBS->FreePool (NewBuffer);\r
427 return EFI_SUCCESS;\r
428}\r
429\r
1cc8ee78 430STATIC\r
878ddf1f 431EFI_STATUS\r
432GetHiiInterface (\r
433 OUT EFI_HII_PROTOCOL **Hii\r
434 )\r
435/*++\r
436\r
437Routine Description:\r
438\r
439 Get the HII protocol interface\r
7f47bef3 440\r
878ddf1f 441Arguments:\r
7f47bef3 442\r
878ddf1f 443 Hii - HII protocol interface\r
7f47bef3 444\r
445Returns:\r
878ddf1f 446\r
447 Status code\r
448\r
449--*/\r
450{\r
451 EFI_STATUS Status;\r
452\r
453 //\r
454 // There should only be one HII protocol\r
455 //\r
456 Status = gBS->LocateProtocol (\r
457 &gEfiHiiProtocolGuid,\r
458 NULL,\r
459 (VOID **) Hii\r
460 );\r
461\r
462 return Status;;\r
463}\r
464\r
465\r
466EFI_STATUS\r
467ExtractDataFromHiiHandle (\r
468 IN EFI_HII_HANDLE HiiHandle,\r
469 IN OUT UINT16 *ImageLength,\r
470 OUT UINT8 *DefaultImage,\r
471 OUT EFI_GUID *Guid\r
472 )\r
473/*++\r
474\r
475Routine Description:\r
476\r
477 Extract information pertaining to the HiiHandle\r
7f47bef3 478\r
878ddf1f 479Arguments:\r
7f47bef3 480\r
878ddf1f 481 HiiHandle - Hii handle\r
7f47bef3 482\r
878ddf1f 483 ImageLength - For input, length of DefaultImage;\r
484 For output, length of actually required\r
7f47bef3 485\r
878ddf1f 486 DefaultImage - Image buffer prepared by caller\r
7f47bef3 487\r
878ddf1f 488 Guid - Guid information about the form\r
7f47bef3 489\r
490Returns:\r
878ddf1f 491\r
492 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
7f47bef3 493\r
878ddf1f 494 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength\r
7f47bef3 495\r
878ddf1f 496 EFI_SUCCESS - Successfully extract data from Hii database.\r
7f47bef3 497\r
498\r
878ddf1f 499--*/\r
500{\r
501 EFI_STATUS Status;\r
502 EFI_HII_PROTOCOL *Hii;\r
503 UINTN DataLength;\r
504 UINT8 *RawData;\r
505 UINT8 *OldData;\r
506 UINTN Index;\r
507 UINTN Temp;\r
508 UINTN SizeOfNvStore;\r
509 UINTN CachedStart;\r
510\r
511 DataLength = DEFAULT_FORM_BUFFER_SIZE;\r
512 SizeOfNvStore = 0;\r
513 CachedStart = 0;\r
514\r
515 Status = GetHiiInterface (&Hii);\r
516\r
517 if (EFI_ERROR (Status)) {\r
518 return Status;\r
519 }\r
520\r
521 //\r
522 // Allocate space for retrieval of IFR data\r
523 //\r
524 RawData = AllocateZeroPool (DataLength);\r
525 if (RawData == NULL) {\r
526 return EFI_OUT_OF_RESOURCES;\r
527 }\r
528\r
529 //\r
530 // Get all the forms associated with this HiiHandle\r
531 //\r
532 Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
533\r
534 if (EFI_ERROR (Status)) {\r
535 gBS->FreePool (RawData);\r
536\r
537 //\r
538 // Allocate space for retrieval of IFR data\r
539 //\r
540 RawData = AllocateZeroPool (DataLength);\r
541 if (RawData == NULL) {\r
542 return EFI_OUT_OF_RESOURCES;\r
543 }\r
544\r
545 //\r
546 // Get all the forms associated with this HiiHandle\r
547 //\r
548 Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
549 }\r
550\r
551 OldData = RawData;\r
552\r
553 //\r
554 // Point RawData to the beginning of the form data\r
555 //\r
556 RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
557\r
558 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
559 switch (RawData[Index]) {\r
560 case EFI_IFR_FORM_SET_OP:\r
561 //\r
562 // Copy the GUID information from this handle\r
563 //\r
564 CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
565 break;\r
566\r
567 case EFI_IFR_ONE_OF_OP:\r
568 case EFI_IFR_CHECKBOX_OP:\r
569 case EFI_IFR_NUMERIC_OP:\r
570 case EFI_IFR_DATE_OP:\r
571 case EFI_IFR_TIME_OP:\r
572 case EFI_IFR_PASSWORD_OP:\r
573 case EFI_IFR_STRING_OP:\r
574 //\r
575 // Remember, multiple op-codes may reference the same item, so let's keep a running\r
576 // marker of what the highest QuestionId that wasn't zero length. This will accurately\r
577 // maintain the Size of the NvStore\r
578 //\r
579 if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
580 Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
581 if (SizeOfNvStore < Temp) {\r
582 SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
583 }\r
584 }\r
585 }\r
586\r
587 Index = RawData[Index + 1] + Index;\r
588 }\r
7f47bef3 589\r
878ddf1f 590 //\r
591 // Return an error if buffer is too small\r
592 //\r
593 if (SizeOfNvStore > *ImageLength) {\r
594 gBS->FreePool (OldData);\r
595 *ImageLength = (UINT16) SizeOfNvStore;\r
596 return EFI_BUFFER_TOO_SMALL;\r
597 }\r
598\r
599 if (DefaultImage != NULL) {\r
600 ZeroMem (DefaultImage, SizeOfNvStore);\r
601 }\r
602\r
603 //\r
604 // Copy the default image information to the user's buffer\r
605 //\r
606 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
607 switch (RawData[Index]) {\r
608 case EFI_IFR_ONE_OF_OP:\r
609 CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
610 break;\r
611\r
612 case EFI_IFR_ONE_OF_OPTION_OP:\r
613 if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) {\r
614 CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);\r
615 }\r
616 break;\r
617\r
618 case EFI_IFR_CHECKBOX_OP:\r
619 DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags;\r
620 break;\r
621\r
622 case EFI_IFR_NUMERIC_OP:\r
623 CopyMem (\r
624 &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],\r
625 &((EFI_IFR_NUMERIC *) &RawData[Index])->Default,\r
626 2\r
627 );\r
628 break;\r
629\r
630 }\r
631\r
632 Index = RawData[Index + 1] + Index;\r
633 }\r
634\r
635 *ImageLength = (UINT16) SizeOfNvStore;\r
636\r
637 //\r
638 // Free our temporary repository of form data\r
639 //\r
640 gBS->FreePool (OldData);\r
641\r
642 return EFI_SUCCESS;\r
643}\r
644\r
645\r
646EFI_HII_HANDLE\r
647FindHiiHandle (\r
648 IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL\r
649 IN EFI_GUID *Guid\r
650 )\r
651/*++\r
652\r
653Routine Description:\r
654 Finds HII handle for given pack GUID previously registered with the HII.\r
655\r
656Arguments:\r
7f47bef3 657 HiiProtocol - pointer to pointer to HII protocol interface.\r
878ddf1f 658 If NULL, the interface will be found but not returned.\r
7f47bef3 659 If it points to NULL, the interface will be found and\r
878ddf1f 660 written back to the pointer that is pointed to.\r
661 Guid - The GUID of the pack that registered with the HII.\r
662\r
663Returns:\r
664 Handle to the HII pack previously registered by the memory driver.\r
665\r
666--*/\r
667{\r
668 EFI_STATUS Status;\r
669\r
670 EFI_HII_HANDLE *HiiHandleBuffer;\r
671 EFI_HII_HANDLE HiiHandle;\r
672 UINT16 HiiHandleBufferLength;\r
673 UINT32 NumberOfHiiHandles;\r
674 EFI_GUID HiiGuid;\r
675 EFI_HII_PROTOCOL *HiiProt;\r
676 UINT32 Index;\r
677 UINT16 Length;\r
678\r
679 HiiHandle = 0;\r
680 if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {\r
681 //\r
682 // The protocol has been passed in\r
683 //\r
684 HiiProt = *HiiProtocol;\r
685 } else {\r
686 gBS->LocateProtocol (\r
687 &gEfiHiiProtocolGuid,\r
688 NULL,\r
689 (VOID **) &HiiProt\r
690 );\r
691 if (HiiProt == NULL) {\r
692 return HiiHandle;\r
693 }\r
694\r
695 if (HiiProtocol != NULL) {\r
696 //\r
697 // Return back the HII protocol for the caller as promissed\r
698 //\r
699 *HiiProtocol = HiiProt;\r
700 }\r
701 }\r
702 //\r
703 // Allocate buffer\r
704 //\r
705 HiiHandleBufferLength = 10;\r
706 HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);\r
707 ASSERT (HiiHandleBuffer != NULL);\r
708\r
709 //\r
710 // Get the Handles of the packages that were registered with Hii\r
711 //\r
712 Status = HiiProt->FindHandles (\r
713 HiiProt,\r
714 &HiiHandleBufferLength,\r
715 HiiHandleBuffer\r
716 );\r
717\r
718 //\r
719 // Get a bigger bugffer if this one is to small, and try again\r
720 //\r
721 if (Status == EFI_BUFFER_TOO_SMALL) {\r
722\r
723 gBS->FreePool (HiiHandleBuffer);\r
724\r
725 HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);\r
726 ASSERT (HiiHandleBuffer != NULL);\r
727\r
728 Status = HiiProt->FindHandles (\r
729 HiiProt,\r
730 &HiiHandleBufferLength,\r
731 HiiHandleBuffer\r
732 );\r
733 }\r
734\r
735 if (EFI_ERROR (Status)) {\r
736 goto lbl_exit;\r
737 }\r
738\r
739 NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE);\r
740\r
741 //\r
742 // Iterate Hii handles and look for the one that matches our Guid\r
743 //\r
744 for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
745\r
746 Length = 0;\r
747 ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);\r
748\r
749 if (CompareGuid (&HiiGuid, Guid)) {\r
750\r
751 HiiHandle = HiiHandleBuffer[Index];\r
752 break;\r
753 }\r
754 }\r
755\r
756lbl_exit:\r
757 gBS->FreePool (HiiHandleBuffer);\r
758 return HiiHandle;\r
759}\r
760\r
761\r
762EFI_STATUS\r
763ValidateDataFromHiiHandle (\r
764 IN EFI_HII_HANDLE HiiHandle,\r
765 OUT BOOLEAN *Results\r
766 )\r
767/*++\r
768\r
769Routine Description:\r
770\r
771 Validate that the data associated with the HiiHandle in NVRAM is within\r
772 the reasonable parameters for that FormSet. Values for strings and passwords\r
773 are not verified due to their not having the equivalent of valid range settings.\r
7f47bef3 774\r
878ddf1f 775Arguments:\r
776\r
777 HiiHandle - Handle of the HII database entry to query\r
778\r
779 Results - If return Status is EFI_SUCCESS, Results provides valid data\r
780 TRUE = NVRAM Data is within parameters\r
781 FALSE = NVRAM Data is NOT within parameters\r
7f47bef3 782\r
783Returns:\r
878ddf1f 784\r
785 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
7f47bef3 786\r
878ddf1f 787 EFI_SUCCESS - Data successfully validated\r
788--*/\r
789{\r
790 EFI_STATUS Status;\r
791 EFI_HII_PROTOCOL *Hii;\r
792 EFI_GUID Guid;\r
793 UINT8 *RawData;\r
794 UINT8 *OldData;\r
795 UINTN RawDataLength;\r
796 UINT8 *VariableData;\r
797 UINTN Index;\r
798 UINTN Temp;\r
799 UINTN SizeOfNvStore;\r
800 UINTN CachedStart;\r
801 BOOLEAN GotMatch;\r
802\r
803 RawDataLength = DEFAULT_FORM_BUFFER_SIZE;\r
804 SizeOfNvStore = 0;\r
805 CachedStart = 0;\r
806 GotMatch = FALSE;\r
807 *Results = TRUE;\r
808\r
809 Status = GetHiiInterface (&Hii);\r
810\r
811 if (EFI_ERROR (Status)) {\r
812 return Status;\r
813 }\r
814\r
815 //\r
816 // Allocate space for retrieval of IFR data\r
817 //\r
818 RawData = AllocateZeroPool (RawDataLength);\r
819 if (RawData == NULL) {\r
820 return EFI_OUT_OF_RESOURCES;\r
821 }\r
822\r
823 //\r
824 // Get all the forms associated with this HiiHandle\r
825 //\r
826 Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
827\r
828 if (EFI_ERROR (Status)) {\r
829 gBS->FreePool (RawData);\r
830\r
831 //\r
832 // Allocate space for retrieval of IFR data\r
833 //\r
834 RawData = AllocateZeroPool (RawDataLength);\r
835 if (RawData == NULL) {\r
836 return EFI_OUT_OF_RESOURCES;\r
837 }\r
838\r
839 //\r
840 // Get all the forms associated with this HiiHandle\r
841 //\r
842 Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
843 }\r
844\r
845 OldData = RawData;\r
846\r
847 //\r
848 // Point RawData to the beginning of the form data\r
849 //\r
850 RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
851\r
852 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
853 if (RawData[Index] == EFI_IFR_FORM_SET_OP) {\r
854 CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
855 break;\r
856 }\r
857\r
858 Index = RawData[Index + 1] + Index;\r
859 }\r
860\r
861 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
862 switch (RawData[Index]) {\r
863 case EFI_IFR_FORM_SET_OP:\r
864 break;\r
865\r
866 case EFI_IFR_ONE_OF_OP:\r
867 case EFI_IFR_CHECKBOX_OP:\r
868 case EFI_IFR_NUMERIC_OP:\r
869 case EFI_IFR_DATE_OP:\r
870 case EFI_IFR_TIME_OP:\r
871 case EFI_IFR_PASSWORD_OP:\r
872 case EFI_IFR_STRING_OP:\r
873 //\r
874 // Remember, multiple op-codes may reference the same item, so let's keep a running\r
875 // marker of what the highest QuestionId that wasn't zero length. This will accurately\r
876 // maintain the Size of the NvStore\r
877 //\r
878 if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
879 Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
880 if (SizeOfNvStore < Temp) {\r
881 SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
882 }\r
883 }\r
884 }\r
885\r
886 Index = RawData[Index + 1] + Index;\r
887 }\r
7f47bef3 888\r
878ddf1f 889 //\r
890 // Allocate memory for our File Form Tags\r
891 //\r
892 VariableData = AllocateZeroPool (SizeOfNvStore);\r
893 if (VariableData == NULL) {\r
894 return EFI_OUT_OF_RESOURCES;\r
895 }\r
896\r
897 Status = gRT->GetVariable (\r
898 (CHAR16 *) L"Setup",\r
899 &Guid,\r
900 NULL,\r
901 &SizeOfNvStore,\r
902 (VOID *) VariableData\r
903 );\r
904\r
905 if (EFI_ERROR (Status)) {\r
906\r
907 //\r
908 // If there is a variable that exists already and it is larger than what we calculated the\r
909 // storage needs to be, we must assume the variable size from GetVariable is correct and not\r
910 // allow the truncation of the variable. It is very possible that the user who created the IFR\r
911 // we are cracking is not referring to a variable that was in a previous map, however we cannot\r
912 // allow it's truncation.\r
913 //\r
914 if (Status == EFI_BUFFER_TOO_SMALL) {\r
915 //\r
916 // Free the buffer that was allocated that was too small\r
917 //\r
918 gBS->FreePool (VariableData);\r
919\r
920 VariableData = AllocatePool (SizeOfNvStore);\r
921 if (VariableData == NULL) {\r
922 return EFI_OUT_OF_RESOURCES;\r
923 }\r
924\r
925 Status = gRT->GetVariable (\r
926 (CHAR16 *) L"Setup",\r
927 &Guid,\r
928 NULL,\r
929 &SizeOfNvStore,\r
930 (VOID *) VariableData\r
931 );\r
932 }\r
933 }\r
934\r
935 //\r
936 // Walk through the form and see that the variable data it refers to is ok.\r
937 // This allows for the possibility of stale (obsoleted) data in the variable\r
938 // can be overlooked without causing an error\r
939 //\r
940 for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
941 switch (RawData[Index]) {\r
942 case EFI_IFR_ONE_OF_OP:\r
943 //\r
944 // A one_of has no data, its the option that does - cache the storage Id\r
945 //\r
946 CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
947 break;\r
948\r
949 case EFI_IFR_ONE_OF_OPTION_OP:\r
950 //\r
951 // A one_of_option can be any value\r
952 //\r
953 if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {\r
954 GotMatch = TRUE;\r
955 }\r
956 break;\r
957\r
958 case EFI_IFR_END_ONE_OF_OP:\r
959 //\r
960 // At this point lets make sure that the data value in the NVRAM matches one of the options\r
961 //\r
962 if (!GotMatch) {\r
963 *Results = FALSE;\r
964 return EFI_SUCCESS;\r
965 }\r
966 break;\r
967\r
968 case EFI_IFR_CHECKBOX_OP:\r
969 //\r
970 // A checkbox is a boolean, so 0 and 1 are valid\r
971 // Remember, QuestionId corresponds to the offset location of the data in the variable\r
972 //\r
973 if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) {\r
974 *Results = FALSE;\r
975 return EFI_SUCCESS;\r
976 }\r
977 break;\r
978\r
979 case EFI_IFR_NUMERIC_OP:\r
980 if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||\r
981 (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {\r
982 *Results = FALSE;\r
983 return EFI_SUCCESS;\r
984 }\r
985 break;\r
986\r
987 }\r
988\r
989 Index = RawData[Index + 1] + Index;\r
990 }\r
991\r
992 //\r
993 // Free our temporary repository of form data\r
994 //\r
995 gBS->FreePool (OldData);\r
996 gBS->FreePool (VariableData);\r
997\r
998 return EFI_SUCCESS;\r
999}\r
1000\r