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