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