]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigKeywordHandler.c
CommitLineData
87bfeb11
ED
1/** @file\r
2Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.\r
3\r
d1102dba 4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
87bfeb11
ED
6\r
7**/\r
8\r
87bfeb11
ED
9#include "HiiDatabase.h"\r
10\r
1436aea4 11extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
87bfeb11
ED
12\r
13/**\r
14 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
15 from <PathHdr> of <MultiKeywordRequest>.\r
16\r
17 This is a internal function.\r
18\r
19 @param String MultiKeywordRequest string.\r
20 @param DevicePathData Binary of a UEFI device path.\r
21 @param NextString string follow the possible PathHdr string.\r
22\r
23 @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.\r
4a429716 24 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.\r
87bfeb11
ED
25 @retval EFI_SUCCESS The device path is retrieved and translated to binary format.\r
26 The Input string not include PathHdr section.\r
27\r
28**/\r
29EFI_STATUS\r
30ExtractDevicePath (\r
1436aea4
MK
31 IN EFI_STRING String,\r
32 OUT UINT8 **DevicePathData,\r
33 OUT EFI_STRING *NextString\r
87bfeb11
ED
34 )\r
35{\r
1436aea4
MK
36 UINTN Length;\r
37 EFI_STRING PathHdr;\r
38 UINT8 *DevicePathBuffer;\r
39 CHAR16 TemStr[2];\r
40 UINTN Index;\r
41 UINT8 DigitUint8;\r
42 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
87bfeb11
ED
43\r
44 ASSERT (NextString != NULL && DevicePathData != NULL);\r
45\r
46 //\r
47 // KeywordRequest == NULL case.\r
48 //\r
49 if (String == NULL) {\r
50 *DevicePathData = NULL;\r
1436aea4 51 *NextString = NULL;\r
87bfeb11
ED
52 return EFI_SUCCESS;\r
53 }\r
54\r
55 //\r
56 // Skip '&' if exist.\r
57 //\r
58 if (*String == L'&') {\r
1436aea4 59 String++;\r
87bfeb11
ED
60 }\r
61\r
62 //\r
63 // Find the 'PATH=' of <PathHdr>.\r
64 //\r
65 if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {\r
66 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
67 return EFI_INVALID_PARAMETER;\r
68 } else {\r
69 //\r
70 // Not include PathHdr, return success and DevicePath = NULL.\r
71 //\r
72 *DevicePathData = NULL;\r
1436aea4 73 *NextString = String;\r
87bfeb11
ED
74 return EFI_SUCCESS;\r
75 }\r
76 }\r
77\r
78 //\r
79 // Check whether path data does exist.\r
80 //\r
81 String += StrLen (L"PATH=");\r
82 if (*String == 0) {\r
83 return EFI_INVALID_PARAMETER;\r
84 }\r
1436aea4 85\r
87bfeb11
ED
86 PathHdr = String;\r
87\r
88 //\r
89 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
90 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
91 // of UEFI device path.\r
92 //\r
1436aea4
MK
93 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {\r
94 }\r
87bfeb11
ED
95\r
96 //\r
97 // Save the return next keyword string value.\r
98 //\r
99 *NextString = String;\r
100\r
101 //\r
102 // Check DevicePath Length\r
103 //\r
104 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
105 return EFI_INVALID_PARAMETER;\r
106 }\r
d1102dba 107\r
87bfeb11
ED
108 //\r
109 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
110 // as the device path resides in RAM memory.\r
111 // Translate the data into binary.\r
112 //\r
1436aea4 113 DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);\r
87bfeb11
ED
114 if (DevicePathBuffer == NULL) {\r
115 return EFI_OUT_OF_RESOURCES;\r
116 }\r
d1102dba 117\r
87bfeb11
ED
118 //\r
119 // Convert DevicePath\r
120 //\r
121 ZeroMem (TemStr, sizeof (TemStr));\r
1436aea4
MK
122 for (Index = 0; Index < Length; Index++) {\r
123 TemStr[0] = PathHdr[Index];\r
124 DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
87bfeb11 125 if ((Index & 1) == 0) {\r
1436aea4 126 DevicePathBuffer[Index/2] = DigitUint8;\r
87bfeb11 127 } else {\r
1436aea4 128 DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);\r
87bfeb11
ED
129 }\r
130 }\r
d1102dba 131\r
87bfeb11
ED
132 //\r
133 // Validate DevicePath\r
134 //\r
1436aea4 135 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;\r
87bfeb11
ED
136 while (!IsDevicePathEnd (DevicePath)) {\r
137 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
138 //\r
139 // Invalid device path\r
140 //\r
141 FreePool (DevicePathBuffer);\r
142 return EFI_INVALID_PARAMETER;\r
143 }\r
1436aea4 144\r
87bfeb11
ED
145 DevicePath = NextDevicePathNode (DevicePath);\r
146 }\r
147\r
148 //\r
149 // return the device path\r
150 //\r
151 *DevicePathData = DevicePathBuffer;\r
152\r
153 return EFI_SUCCESS;\r
154}\r
155\r
156/**\r
157 Get NameSpace from the input NameSpaceId string.\r
158\r
159 This is a internal function.\r
160\r
161 @param String <NameSpaceId> format string.\r
162 @param NameSpace Return the name space string.\r
163 @param NextString Return the next string follow namespace.\r
164\r
165 @retval EFI_SUCCESS Get the namespace string success.\r
166 @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.\r
167\r
168**/\r
169EFI_STATUS\r
170ExtractNameSpace (\r
1436aea4
MK
171 IN EFI_STRING String,\r
172 OUT CHAR8 **NameSpace,\r
173 OUT EFI_STRING *NextString\r
87bfeb11
ED
174 )\r
175{\r
1436aea4
MK
176 CHAR16 *TmpPtr;\r
177 UINTN NameSpaceSize;\r
87bfeb11
ED
178\r
179 ASSERT (NameSpace != NULL);\r
180\r
181 TmpPtr = NULL;\r
182\r
183 //\r
184 // Input NameSpaceId == NULL\r
185 //\r
186 if (String == NULL) {\r
187 *NameSpace = NULL;\r
188 if (NextString != NULL) {\r
189 *NextString = NULL;\r
190 }\r
1436aea4 191\r
87bfeb11
ED
192 return EFI_SUCCESS;\r
193 }\r
194\r
195 //\r
196 // Skip '&' if exist.\r
197 //\r
198 if (*String == L'&') {\r
199 String++;\r
200 }\r
201\r
202 if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
1436aea4 205\r
87bfeb11
ED
206 String += StrLen (L"NAMESPACE=");\r
207\r
208 TmpPtr = StrStr (String, L"&");\r
209 if (TmpPtr != NULL) {\r
d1102dba 210 *TmpPtr = 0;\r
87bfeb11 211 }\r
1436aea4 212\r
87bfeb11
ED
213 if (NextString != NULL) {\r
214 *NextString = String + StrLen (String);\r
215 }\r
216\r
217 //\r
218 // Input NameSpace is unicode string. The language in String package is ascii string.\r
219 // Here will convert the unicode string to ascii and save it.\r
220 //\r
b68ccac1 221 NameSpaceSize = StrLen (String) + 1;\r
1436aea4 222 *NameSpace = AllocatePool (NameSpaceSize);\r
87bfeb11
ED
223 if (*NameSpace == NULL) {\r
224 return EFI_OUT_OF_RESOURCES;\r
225 }\r
1436aea4 226\r
b68ccac1 227 UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);\r
87bfeb11
ED
228\r
229 if (TmpPtr != NULL) {\r
d1102dba 230 *TmpPtr = L'&';\r
87bfeb11
ED
231 }\r
232\r
233 return EFI_SUCCESS;\r
234}\r
235\r
236/**\r
237 Get Keyword from the input KeywordRequest string.\r
238\r
239 This is a internal function.\r
240\r
241 @param String KeywordRequestformat string.\r
242 @param Keyword return the extract keyword string.\r
4a429716 243 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
244\r
245 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 246 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
247\r
248**/\r
249EFI_STATUS\r
250ExtractKeyword (\r
1436aea4
MK
251 IN EFI_STRING String,\r
252 OUT EFI_STRING *Keyword,\r
253 OUT EFI_STRING *NextString\r
87bfeb11
ED
254 )\r
255{\r
256 EFI_STRING TmpPtr;\r
257\r
258 ASSERT ((Keyword != NULL) && (NextString != NULL));\r
d1102dba 259\r
87bfeb11
ED
260 TmpPtr = NULL;\r
261\r
262 //\r
263 // KeywordRequest == NULL case.\r
264 //\r
265 if (String == NULL) {\r
1436aea4 266 *Keyword = NULL;\r
87bfeb11
ED
267 *NextString = NULL;\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
271 //\r
272 // Skip '&' if exist.\r
273 //\r
274 if (*String == L'&') {\r
275 String++;\r
276 }\r
277\r
278 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
279 return EFI_INVALID_PARAMETER;\r
280 }\r
281\r
282 String += StrLen (L"KEYWORD=");\r
d1102dba 283\r
87bfeb11
ED
284 TmpPtr = StrStr (String, L"&");\r
285 if (TmpPtr != NULL) {\r
d1102dba 286 *TmpPtr = 0;\r
87bfeb11 287 }\r
1436aea4 288\r
87bfeb11
ED
289 *NextString = String + StrLen (String);\r
290\r
291 *Keyword = AllocateCopyPool (StrSize (String), String);\r
292 if (*Keyword == NULL) {\r
293 return EFI_OUT_OF_RESOURCES;\r
294 }\r
295\r
296 if (TmpPtr != NULL) {\r
297 *TmpPtr = L'&';\r
298 }\r
d1102dba 299\r
87bfeb11
ED
300 return EFI_SUCCESS;\r
301}\r
302\r
303/**\r
304 Get value from the input KeywordRequest string.\r
305\r
306 This is a internal function.\r
307\r
308 @param String KeywordRequestformat string.\r
309 @param Value return the extract value string.\r
4a429716 310 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
311\r
312 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 313 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
314\r
315**/\r
316EFI_STATUS\r
317ExtractValue (\r
1436aea4
MK
318 IN EFI_STRING String,\r
319 OUT EFI_STRING *Value,\r
320 OUT EFI_STRING *NextString\r
87bfeb11
ED
321 )\r
322{\r
323 EFI_STRING TmpPtr;\r
324\r
325 ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));\r
326\r
327 //\r
328 // Skip '&' if exist.\r
329 //\r
330 if (*String == L'&') {\r
331 String++;\r
332 }\r
333\r
334 if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {\r
335 return EFI_INVALID_PARAMETER;\r
336 }\r
337\r
338 String += StrLen (L"VALUE=");\r
d1102dba 339\r
87bfeb11
ED
340 TmpPtr = StrStr (String, L"&");\r
341 if (TmpPtr != NULL) {\r
d1102dba 342 *TmpPtr = 0;\r
87bfeb11 343 }\r
1436aea4 344\r
87bfeb11
ED
345 *NextString = String + StrLen (String);\r
346\r
347 *Value = AllocateCopyPool (StrSize (String), String);\r
348 if (*Value == NULL) {\r
349 return EFI_OUT_OF_RESOURCES;\r
350 }\r
351\r
352 if (TmpPtr != NULL) {\r
353 *TmpPtr = L'&';\r
354 }\r
d1102dba 355\r
87bfeb11
ED
356 return EFI_SUCCESS;\r
357}\r
358\r
359/**\r
360 Get filter from the input KeywordRequest string.\r
361\r
362 This is a internal function.\r
363\r
364 @param String KeywordRequestformat string.\r
365 @param FilterFlags return the filter condition.\r
4a429716 366 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
367\r
368 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 369 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
370\r
371**/\r
372BOOLEAN\r
373ExtractFilter (\r
1436aea4
MK
374 IN EFI_STRING String,\r
375 OUT UINT8 *FilterFlags,\r
376 OUT EFI_STRING *NextString\r
87bfeb11
ED
377 )\r
378{\r
1436aea4
MK
379 CHAR16 *PathPtr;\r
380 CHAR16 *KeywordPtr;\r
381 BOOLEAN RetVal;\r
87bfeb11
ED
382\r
383 ASSERT ((FilterFlags != NULL) && (NextString != NULL));\r
384\r
385 //\r
386 // String end, no filter section.\r
387 //\r
388 if (String == NULL) {\r
389 *NextString = NULL;\r
390 return FALSE;\r
391 }\r
d1102dba 392\r
87bfeb11 393 *FilterFlags = 0;\r
1436aea4 394 RetVal = TRUE;\r
87bfeb11
ED
395\r
396 //\r
397 // Skip '&' if exist.\r
398 //\r
399 if (*String == L'&') {\r
400 String++;\r
401 }\r
402\r
403 if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {\r
404 //\r
405 // Find ReadOnly filter.\r
406 //\r
407 *FilterFlags |= EFI_KEYWORD_FILTER_READONY;\r
1436aea4 408 String += StrLen (L"ReadOnly");\r
87bfeb11
ED
409 } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {\r
410 //\r
411 // Find ReadWrite filter.\r
412 //\r
413 *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;\r
1436aea4 414 String += StrLen (L"ReadWrite");\r
87bfeb11
ED
415 } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {\r
416 //\r
417 // Find Buffer Filter.\r
418 //\r
419 *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;\r
1436aea4 420 String += StrLen (L"Buffer");\r
87bfeb11
ED
421 } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {\r
422 //\r
423 // Find Numeric Filter\r
424 //\r
425 String += StrLen (L"Numeric");\r
426 if (*String != L':') {\r
427 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;\r
428 } else {\r
429 String++;\r
430 switch (*String) {\r
1436aea4
MK
431 case L'1':\r
432 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;\r
433 break;\r
434 case L'2':\r
435 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;\r
436 break;\r
437 case L'4':\r
438 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;\r
439 break;\r
440 case L'8':\r
441 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;\r
442 break;\r
443 default:\r
444 ASSERT (FALSE);\r
445 break;\r
87bfeb11 446 }\r
1436aea4 447\r
87bfeb11
ED
448 String++;\r
449 }\r
450 } else {\r
451 //\r
452 // Check whether other filter item defined by Platform.\r
453 //\r
454 if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||\r
1436aea4
MK
455 (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0))\r
456 {\r
87bfeb11
ED
457 //\r
458 // New KeywordRequest start, no platform defined filter.\r
459 //\r
460 } else {\r
461 //\r
462 // Platform defined filter rule.\r
463 // Just skip platform defined filter rule, return success.\r
464 //\r
1436aea4
MK
465 PathPtr = StrStr (String, L"&PATH");\r
466 KeywordPtr = StrStr (String, L"&KEYWORD");\r
467 if ((PathPtr != NULL) && (KeywordPtr != NULL)) {\r
87bfeb11
ED
468 //\r
469 // If both sections exist, return the first follow string.\r
470 //\r
471 String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;\r
472 } else if (PathPtr != NULL) {\r
473 //\r
474 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.\r
475 //\r
476 ASSERT (FALSE);\r
477 } else if (KeywordPtr != NULL) {\r
478 //\r
479 // Just to the next keyword section.\r
480 //\r
481 String = KeywordPtr;\r
482 } else {\r
483 //\r
4a429716 484 // Only has platform defined filter section, just skip it.\r
87bfeb11
ED
485 //\r
486 String += StrLen (String);\r
487 }\r
488 }\r
1436aea4 489\r
87bfeb11
ED
490 RetVal = FALSE;\r
491 }\r
492\r
493 *NextString = String;\r
494\r
495 return RetVal;\r
496}\r
497\r
498/**\r
499 Extract Readonly flag from opcode.\r
500\r
501 This is a internal function.\r
502\r
503 @param OpCodeData Input opcode for this question.\r
504\r
505 @retval TRUE This question is readonly.\r
506 @retval FALSE This question is not readonly.\r
507\r
508**/\r
509BOOLEAN\r
510ExtractReadOnlyFromOpCode (\r
1436aea4 511 IN UINT8 *OpCodeData\r
87bfeb11
ED
512 )\r
513{\r
1436aea4 514 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
87bfeb11
ED
515\r
516 ASSERT (OpCodeData != NULL);\r
517\r
1436aea4 518 QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
87bfeb11
ED
519\r
520 return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;\r
521}\r
522\r
523/**\r
524 Create a circuit to check the filter section.\r
525\r
526 This is a internal function.\r
527\r
4a429716 528 @param OpCodeData The question binary ifr data.\r
87bfeb11 529 @param KeywordRequest KeywordRequestformat string.\r
4a429716 530 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
531 @param ReadOnly Return whether this question is read only.\r
532\r
533 @retval KEYWORD_HANDLER_NO_ERROR Success validate.\r
534 @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.\r
535\r
536**/\r
537UINT32\r
538ValidateFilter (\r
1436aea4
MK
539 IN UINT8 *OpCodeData,\r
540 IN CHAR16 *KeywordRequest,\r
541 OUT CHAR16 **NextString,\r
542 OUT BOOLEAN *ReadOnly\r
87bfeb11
ED
543 )\r
544{\r
1436aea4
MK
545 CHAR16 *NextFilter;\r
546 CHAR16 *StringPtr;\r
547 UINT8 FilterFlags;\r
548 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
549 EFI_IFR_OP_HEADER *OpCodeHdr;\r
550 UINT8 Flags;\r
551 UINT32 RetVal;\r
552\r
553 RetVal = KEYWORD_HANDLER_NO_ERROR;\r
87bfeb11
ED
554 StringPtr = KeywordRequest;\r
555\r
1436aea4
MK
556 OpCodeHdr = (EFI_IFR_OP_HEADER *)OpCodeData;\r
557 QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
558 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {\r
87bfeb11
ED
559 Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));\r
560 } else {\r
561 Flags = 0;\r
562 }\r
563\r
564 //\r
565 // Get ReadOnly flag from Question.\r
d1102dba 566 //\r
1436aea4 567 *ReadOnly = ExtractReadOnlyFromOpCode (OpCodeData);\r
87bfeb11
ED
568\r
569 while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {\r
570 switch (FilterFlags) {\r
1436aea4
MK
571 case EFI_KEYWORD_FILTER_READONY:\r
572 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {\r
573 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
574 goto Done;\r
575 }\r
87bfeb11 576\r
1436aea4 577 break;\r
87bfeb11 578\r
1436aea4
MK
579 case EFI_KEYWORD_FILTER_REAWRITE:\r
580 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {\r
581 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
582 goto Done;\r
583 }\r
87bfeb11 584\r
1436aea4 585 break;\r
87bfeb11 586\r
1436aea4
MK
587 case EFI_KEYWORD_FILTER_BUFFER:\r
588 //\r
589 // Only these three opcode use numeric value type.\r
590 //\r
591 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) || (OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP)) {\r
592 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
593 goto Done;\r
594 }\r
87bfeb11 595\r
1436aea4 596 break;\r
87bfeb11 597\r
1436aea4
MK
598 case EFI_KEYWORD_FILTER_NUMERIC:\r
599 if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {\r
600 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
601 goto Done;\r
602 }\r
87bfeb11 603\r
1436aea4 604 break;\r
87bfeb11 605\r
1436aea4
MK
606 case EFI_KEYWORD_FILTER_NUMERIC_1:\r
607 case EFI_KEYWORD_FILTER_NUMERIC_2:\r
608 case EFI_KEYWORD_FILTER_NUMERIC_4:\r
609 case EFI_KEYWORD_FILTER_NUMERIC_8:\r
610 if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {\r
611 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
612 goto Done;\r
613 }\r
87bfeb11 614\r
1436aea4
MK
615 //\r
616 // For numeric and oneof, it has flags field to specify the detail numeric type.\r
617 //\r
618 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {\r
619 switch (Flags & EFI_IFR_NUMERIC_SIZE) {\r
620 case EFI_IFR_NUMERIC_SIZE_1:\r
621 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {\r
622 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
623 goto Done;\r
624 }\r
625\r
626 break;\r
627\r
628 case EFI_IFR_NUMERIC_SIZE_2:\r
629 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {\r
630 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
631 goto Done;\r
632 }\r
633\r
634 break;\r
635\r
636 case EFI_IFR_NUMERIC_SIZE_4:\r
637 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {\r
638 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
639 goto Done;\r
640 }\r
641\r
642 break;\r
643\r
644 case EFI_IFR_NUMERIC_SIZE_8:\r
645 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {\r
646 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
647 goto Done;\r
648 }\r
649\r
650 break;\r
651\r
652 default:\r
653 ASSERT (FALSE);\r
654 break;\r
655 }\r
87bfeb11 656 }\r
87bfeb11 657\r
1436aea4
MK
658 break;\r
659\r
660 default:\r
661 ASSERT (FALSE);\r
662 break;\r
87bfeb11
ED
663 }\r
664\r
665 //\r
666 // Jump to the next filter.\r
667 //\r
668 StringPtr = NextFilter;\r
669 }\r
d1102dba 670\r
87bfeb11
ED
671Done:\r
672 //\r
673 // The current filter which is processing.\r
674 //\r
675 *NextString = StringPtr;\r
676\r
677 return RetVal;\r
678}\r
679\r
680/**\r
681 Get HII_DATABASE_RECORD from the input device path info.\r
682\r
683 This is a internal function.\r
684\r
685 @param DevicePath UEFI device path protocol.\r
686\r
687 @retval Internal data base record.\r
688\r
689**/\r
690HII_DATABASE_RECORD *\r
691GetRecordFromDevicePath (\r
1436aea4 692 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
87bfeb11
ED
693 )\r
694{\r
1436aea4
MK
695 LIST_ENTRY *Link;\r
696 UINT8 *DevicePathPkg;\r
697 UINT8 *CurrentDevicePath;\r
698 UINTN DevicePathSize;\r
699 HII_DATABASE_RECORD *TempDatabase;\r
87bfeb11
ED
700\r
701 ASSERT (DevicePath != NULL);\r
702\r
703 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
1436aea4 704 TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
87bfeb11
ED
705 DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;\r
706 if (DevicePathPkg != NULL) {\r
707 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4 708 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);\r
87bfeb11
ED
709 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {\r
710 return TempDatabase;\r
711 }\r
712 }\r
713 }\r
714\r
715 return NULL;\r
716}\r
717\r
718/**\r
d1102dba 719 Calculate the size of StringSrc and output it. Also copy string text from src\r
87bfeb11
ED
720 to dest.\r
721\r
722 This is a internal function.\r
723\r
724 @param StringSrc Points to current null-terminated string.\r
725 @param BufferSize Length of the buffer.\r
d1102dba 726 @param StringDest Buffer to store the string text.\r
87bfeb11 727\r
4a429716 728 @retval EFI_SUCCESS The string text was outputted successfully.\r
87bfeb11
ED
729 @retval EFI_OUT_OF_RESOURCES Out of resource.\r
730\r
731**/\r
732EFI_STATUS\r
733GetUnicodeStringTextAndSize (\r
1436aea4
MK
734 IN UINT8 *StringSrc,\r
735 OUT UINTN *BufferSize,\r
736 OUT EFI_STRING *StringDest\r
87bfeb11
ED
737 )\r
738{\r
739 UINTN StringSize;\r
740 UINT8 *StringPtr;\r
741\r
742 ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);\r
743\r
744 StringSize = sizeof (CHAR16);\r
745 StringPtr = StringSrc;\r
1436aea4 746 while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {\r
87bfeb11 747 StringSize += sizeof (CHAR16);\r
1436aea4 748 StringPtr += sizeof (CHAR16);\r
87bfeb11
ED
749 }\r
750\r
751 *StringDest = AllocatePool (StringSize);\r
752 if (*StringDest == NULL) {\r
753 return EFI_OUT_OF_RESOURCES;\r
754 }\r
d1102dba 755\r
87bfeb11
ED
756 CopyMem (*StringDest, StringSrc, StringSize);\r
757\r
758 *BufferSize = StringSize;\r
759 return EFI_SUCCESS;\r
760}\r
761\r
762/**\r
763 Find the string id for the input keyword.\r
764\r
765 @param StringPackage Hii string package instance.\r
766 @param KeywordValue Input keyword value.\r
767 @param StringId The string's id, which is unique within PackageList.\r
768\r
769\r
770 @retval EFI_SUCCESS The string text and font is retrieved\r
771 successfully.\r
772 @retval EFI_NOT_FOUND The specified text or font info can not be found\r
773 out.\r
774 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
775 task.\r
776**/\r
777EFI_STATUS\r
778GetStringIdFromString (\r
1436aea4
MK
779 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
780 IN CHAR16 *KeywordValue,\r
781 OUT EFI_STRING_ID *StringId\r
87bfeb11
ED
782 )\r
783{\r
1436aea4
MK
784 UINT8 *BlockHdr;\r
785 EFI_STRING_ID CurrentStringId;\r
786 UINTN BlockSize;\r
787 UINTN Index;\r
788 UINT8 *StringTextPtr;\r
789 UINTN Offset;\r
790 UINT16 StringCount;\r
791 UINT16 SkipCount;\r
792 UINT8 Length8;\r
793 EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
794 UINT32 Length32;\r
795 UINTN StringSize;\r
796 CHAR16 *String;\r
797 CHAR8 *AsciiKeywordValue;\r
798 UINTN KeywordValueSize;\r
799 EFI_STATUS Status;\r
87bfeb11
ED
800\r
801 ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);\r
802 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
803\r
804 CurrentStringId = 1;\r
1436aea4
MK
805 Status = EFI_SUCCESS;\r
806 String = NULL;\r
807 BlockHdr = StringPackage->StringBlock;\r
808 BlockSize = 0;\r
809 Offset = 0;\r
87bfeb11
ED
810\r
811 //\r
812 // Make a ascii keyword value for later use.\r
813 //\r
1436aea4 814 KeywordValueSize = StrLen (KeywordValue) + 1;\r
b68ccac1 815 AsciiKeywordValue = AllocatePool (KeywordValueSize);\r
87bfeb11
ED
816 if (AsciiKeywordValue == NULL) {\r
817 return EFI_OUT_OF_RESOURCES;\r
818 }\r
1436aea4 819\r
b68ccac1 820 UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);\r
87bfeb11
ED
821\r
822 while (*BlockHdr != EFI_HII_SIBT_END) {\r
823 switch (*BlockHdr) {\r
1436aea4
MK
824 case EFI_HII_SIBT_STRING_SCSU:\r
825 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
826 StringTextPtr = BlockHdr + Offset;\r
827 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
828 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {\r
87bfeb11
ED
829 *StringId = CurrentStringId;\r
830 goto Done;\r
831 }\r
87bfeb11 832\r
1436aea4
MK
833 CurrentStringId++;\r
834 break;\r
87bfeb11 835\r
1436aea4
MK
836 case EFI_HII_SIBT_STRING_SCSU_FONT:\r
837 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
838 StringTextPtr = BlockHdr + Offset;\r
839 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {\r
87bfeb11
ED
840 *StringId = CurrentStringId;\r
841 goto Done;\r
842 }\r
1436aea4
MK
843\r
844 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
87bfeb11 845 CurrentStringId++;\r
1436aea4 846 break;\r
87bfeb11 847\r
1436aea4
MK
848 case EFI_HII_SIBT_STRINGS_SCSU:\r
849 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
850 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
851 BlockSize += StringTextPtr - BlockHdr;\r
87bfeb11 852\r
1436aea4
MK
853 for (Index = 0; Index < StringCount; Index++) {\r
854 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);\r
855 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {\r
856 *StringId = CurrentStringId;\r
857 goto Done;\r
858 }\r
87bfeb11 859\r
1436aea4
MK
860 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
861 CurrentStringId++;\r
862 }\r
863\r
864 break;\r
865\r
866 case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
867 CopyMem (\r
868 &StringCount,\r
869 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
870 sizeof (UINT16)\r
871 );\r
872 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
873 BlockSize += StringTextPtr - BlockHdr;\r
874\r
875 for (Index = 0; Index < StringCount; Index++) {\r
876 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);\r
877 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {\r
878 *StringId = CurrentStringId;\r
879 goto Done;\r
880 }\r
881\r
882 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
883 CurrentStringId++;\r
884 }\r
885\r
886 break;\r
887\r
888 case EFI_HII_SIBT_STRING_UCS2:\r
889 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
890 StringTextPtr = BlockHdr + Offset;\r
891 //\r
892 // Use StringSize to store the size of the specified string, including the NULL\r
893 // terminator.\r
894 //\r
87bfeb11
ED
895 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
896 if (EFI_ERROR (Status)) {\r
897 goto Done;\r
898 }\r
1436aea4 899\r
763cfa73 900 ASSERT (String != NULL);\r
1436aea4 901 if (StrCmp (KeywordValue, String) == 0) {\r
87bfeb11
ED
902 *StringId = CurrentStringId;\r
903 goto Done;\r
904 }\r
1436aea4
MK
905\r
906 BlockSize += Offset + StringSize;\r
87bfeb11 907 CurrentStringId++;\r
1436aea4 908 break;\r
87bfeb11 909\r
1436aea4
MK
910 case EFI_HII_SIBT_STRING_UCS2_FONT:\r
911 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
912 StringTextPtr = BlockHdr + Offset;\r
913 //\r
914 // Use StringSize to store the size of the specified string, including the NULL\r
915 // terminator.\r
916 //\r
87bfeb11
ED
917 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
918 if (EFI_ERROR (Status)) {\r
919 goto Done;\r
920 }\r
1436aea4 921\r
763cfa73 922 ASSERT (String != NULL);\r
1436aea4 923 if (StrCmp (KeywordValue, String) == 0) {\r
87bfeb11
ED
924 *StringId = CurrentStringId;\r
925 goto Done;\r
926 }\r
1436aea4
MK
927\r
928 BlockSize += Offset + StringSize;\r
87bfeb11 929 CurrentStringId++;\r
1436aea4 930 break;\r
87bfeb11 931\r
1436aea4
MK
932 case EFI_HII_SIBT_STRINGS_UCS2:\r
933 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
934 StringTextPtr = BlockHdr + Offset;\r
935 BlockSize += Offset;\r
936 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
937 for (Index = 0; Index < StringCount; Index++) {\r
938 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
939 if (EFI_ERROR (Status)) {\r
940 goto Done;\r
941 }\r
87bfeb11 942\r
1436aea4
MK
943 ASSERT (String != NULL);\r
944 BlockSize += StringSize;\r
945 if (StrCmp (KeywordValue, String) == 0) {\r
946 *StringId = CurrentStringId;\r
947 goto Done;\r
948 }\r
87bfeb11 949\r
1436aea4
MK
950 StringTextPtr = StringTextPtr + StringSize;\r
951 CurrentStringId++;\r
952 }\r
87bfeb11 953\r
1436aea4 954 break;\r
87bfeb11 955\r
1436aea4
MK
956 case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
957 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
958 StringTextPtr = BlockHdr + Offset;\r
959 BlockSize += Offset;\r
960 CopyMem (\r
961 &StringCount,\r
962 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
963 sizeof (UINT16)\r
964 );\r
965 for (Index = 0; Index < StringCount; Index++) {\r
966 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
967 if (EFI_ERROR (Status)) {\r
968 goto Done;\r
969 }\r
87bfeb11 970\r
1436aea4
MK
971 ASSERT (String != NULL);\r
972 BlockSize += StringSize;\r
973 if (StrCmp (KeywordValue, String) == 0) {\r
974 *StringId = CurrentStringId;\r
975 goto Done;\r
976 }\r
87bfeb11 977\r
1436aea4
MK
978 StringTextPtr = StringTextPtr + StringSize;\r
979 CurrentStringId++;\r
980 }\r
87bfeb11 981\r
1436aea4
MK
982 break;\r
983\r
984 case EFI_HII_SIBT_DUPLICATE:\r
985 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
986 CurrentStringId++;\r
987 break;\r
988\r
989 case EFI_HII_SIBT_SKIP1:\r
990 SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
991 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);\r
992 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
993 break;\r
994\r
995 case EFI_HII_SIBT_SKIP2:\r
996 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
997 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);\r
998 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
999 break;\r
1000\r
1001 case EFI_HII_SIBT_EXT1:\r
1002 CopyMem (\r
1003 &Length8,\r
1004 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1005 sizeof (UINT8)\r
1006 );\r
1007 BlockSize += Length8;\r
1008 break;\r
1009\r
1010 case EFI_HII_SIBT_EXT2:\r
1011 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
1012 BlockSize += Ext2.Length;\r
1013 break;\r
1014\r
1015 case EFI_HII_SIBT_EXT4:\r
1016 CopyMem (\r
1017 &Length32,\r
1018 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1019 sizeof (UINT32)\r
1020 );\r
1021\r
1022 BlockSize += Length32;\r
1023 break;\r
1024\r
1025 default:\r
1026 break;\r
87bfeb11
ED
1027 }\r
1028\r
1029 if (String != NULL) {\r
1030 FreePool (String);\r
1031 String = NULL;\r
1032 }\r
1033\r
1436aea4 1034 BlockHdr = StringPackage->StringBlock + BlockSize;\r
87bfeb11
ED
1035 }\r
1036\r
1037 Status = EFI_NOT_FOUND;\r
1038\r
1039Done:\r
1040 if (AsciiKeywordValue != NULL) {\r
1041 FreePool (AsciiKeywordValue);\r
1042 }\r
1436aea4 1043\r
87bfeb11
ED
1044 if (String != NULL) {\r
1045 FreePool (String);\r
1046 }\r
1436aea4 1047\r
87bfeb11
ED
1048 return Status;\r
1049}\r
1050\r
1051/**\r
1052 Find the next valid string id for the input string id.\r
1053\r
1054 @param StringPackage Hii string package instance.\r
1055 @param StringId The current string id which is already got.\r
1056 1 means just begin to get the string id.\r
1057 @param KeywordValue Return the string for the next string id.\r
1058\r
1059\r
1060 @retval EFI_STRING_ID Not 0 means a valid stringid found.\r
1061 0 means not found a valid string id.\r
1062**/\r
1063EFI_STRING_ID\r
1064GetNextStringId (\r
1436aea4
MK
1065 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
1066 IN EFI_STRING_ID StringId,\r
1067 OUT EFI_STRING *KeywordValue\r
87bfeb11
ED
1068 )\r
1069{\r
1436aea4
MK
1070 UINT8 *BlockHdr;\r
1071 EFI_STRING_ID CurrentStringId;\r
1072 UINTN BlockSize;\r
1073 UINTN Index;\r
1074 UINT8 *StringTextPtr;\r
1075 UINTN Offset;\r
1076 UINT16 StringCount;\r
1077 UINT16 SkipCount;\r
1078 UINT8 Length8;\r
1079 EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
1080 UINT32 Length32;\r
1081 BOOLEAN FindString;\r
1082 UINTN StringSize;\r
1083 CHAR16 *String;\r
87bfeb11
ED
1084\r
1085 ASSERT (StringPackage != NULL);\r
1086 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
1087\r
1088 CurrentStringId = 1;\r
1436aea4
MK
1089 FindString = FALSE;\r
1090 String = NULL;\r
87bfeb11
ED
1091\r
1092 //\r
1093 // Parse the string blocks to get the string text and font.\r
1094 //\r
1095 BlockHdr = StringPackage->StringBlock;\r
1096 BlockSize = 0;\r
1097 Offset = 0;\r
1098 while (*BlockHdr != EFI_HII_SIBT_END) {\r
1099 switch (*BlockHdr) {\r
1436aea4
MK
1100 case EFI_HII_SIBT_STRING_SCSU:\r
1101 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
1102 StringTextPtr = BlockHdr + Offset;\r
87bfeb11 1103\r
87bfeb11 1104 if (FindString) {\r
1436aea4 1105 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);\r
b68ccac1 1106 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1107 if (*KeywordValue == NULL) {\r
1108 return 0;\r
1109 }\r
1436aea4
MK
1110\r
1111 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1112 return CurrentStringId;\r
1113 } else if (CurrentStringId == StringId) {\r
1114 FindString = TRUE;\r
1115 }\r
1116\r
1436aea4 1117 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
87bfeb11 1118 CurrentStringId++;\r
1436aea4 1119 break;\r
87bfeb11 1120\r
1436aea4
MK
1121 case EFI_HII_SIBT_STRING_SCSU_FONT:\r
1122 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
1123 StringTextPtr = BlockHdr + Offset;\r
87bfeb11 1124\r
87bfeb11 1125 if (FindString) {\r
1436aea4 1126 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);\r
b68ccac1 1127 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1128 if (*KeywordValue == NULL) {\r
1129 return 0;\r
1130 }\r
1436aea4
MK
1131\r
1132 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1133 return CurrentStringId;\r
1134 } else if (CurrentStringId == StringId) {\r
1135 FindString = TRUE;\r
1136 }\r
1137\r
1436aea4 1138 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
87bfeb11 1139 CurrentStringId++;\r
1436aea4 1140 break;\r
87bfeb11 1141\r
1436aea4
MK
1142 case EFI_HII_SIBT_STRINGS_SCSU:\r
1143 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1144 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
1145 BlockSize += StringTextPtr - BlockHdr;\r
1146\r
1147 for (Index = 0; Index < StringCount; Index++) {\r
1148 if (FindString) {\r
1149 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1150 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1151 if (*KeywordValue == NULL) {\r
1152 return 0;\r
1153 }\r
87bfeb11 1154\r
1436aea4
MK
1155 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);\r
1156 return CurrentStringId;\r
1157 } else if (CurrentStringId == StringId) {\r
1158 FindString = TRUE;\r
1159 }\r
87bfeb11 1160\r
1436aea4
MK
1161 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1162 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1163 CurrentStringId++;\r
1164 }\r
87bfeb11 1165\r
1436aea4 1166 break;\r
87bfeb11 1167\r
1436aea4
MK
1168 case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
1169 CopyMem (\r
1170 &StringCount,\r
1171 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1172 sizeof (UINT16)\r
1173 );\r
1174 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
1175 BlockSize += StringTextPtr - BlockHdr;\r
1176\r
1177 for (Index = 0; Index < StringCount; Index++) {\r
1178 if (FindString) {\r
1179 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1180 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1181 if (*KeywordValue == NULL) {\r
1182 return 0;\r
1183 }\r
87bfeb11 1184\r
1436aea4
MK
1185 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);\r
1186 return CurrentStringId;\r
1187 } else if (CurrentStringId == StringId) {\r
1188 FindString = TRUE;\r
1189 }\r
1190\r
1191 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1192 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);\r
1193 CurrentStringId++;\r
1194 }\r
1195\r
1196 break;\r
1197\r
1198 case EFI_HII_SIBT_STRING_UCS2:\r
1199 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
1200 StringTextPtr = BlockHdr + Offset;\r
1201 //\r
1202 // Use StringSize to store the size of the specified string, including the NULL\r
1203 // terminator.\r
1204 //\r
1205 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1206 if (FindString && (String != NULL) && (*String != L'\0')) {\r
1207 //\r
1208 // String protocol use this type for the string id which has value for other package.\r
1209 // It will allocate an empty string block for this string id. so here we also check\r
1210 // *String != L'\0' to prohibit this case.\r
1211 //\r
87bfeb11
ED
1212 *KeywordValue = String;\r
1213 return CurrentStringId;\r
1214 } else if (CurrentStringId == StringId) {\r
1215 FindString = TRUE;\r
1216 }\r
1217\r
1436aea4 1218 BlockSize += Offset + StringSize;\r
87bfeb11 1219 CurrentStringId++;\r
1436aea4 1220 break;\r
87bfeb11 1221\r
1436aea4
MK
1222 case EFI_HII_SIBT_STRING_UCS2_FONT:\r
1223 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
1224 StringTextPtr = BlockHdr + Offset;\r
1225 //\r
1226 // Use StringSize to store the size of the specified string, including the NULL\r
1227 // terminator.\r
1228 //\r
87bfeb11
ED
1229 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1230 if (FindString) {\r
1231 *KeywordValue = String;\r
1232 return CurrentStringId;\r
1233 } else if (CurrentStringId == StringId) {\r
1234 FindString = TRUE;\r
1235 }\r
1236\r
1436aea4 1237 BlockSize += Offset + StringSize;\r
87bfeb11 1238 CurrentStringId++;\r
1436aea4 1239 break;\r
87bfeb11 1240\r
1436aea4
MK
1241 case EFI_HII_SIBT_STRINGS_UCS2:\r
1242 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
1243 StringTextPtr = BlockHdr + Offset;\r
1244 BlockSize += Offset;\r
1245 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1246 for (Index = 0; Index < StringCount; Index++) {\r
1247 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1248\r
1249 if (FindString) {\r
1250 *KeywordValue = String;\r
1251 return CurrentStringId;\r
1252 } else if (CurrentStringId == StringId) {\r
1253 FindString = TRUE;\r
1254 }\r
87bfeb11 1255\r
1436aea4
MK
1256 BlockSize += StringSize;\r
1257 StringTextPtr = StringTextPtr + StringSize;\r
1258 CurrentStringId++;\r
1259 }\r
87bfeb11 1260\r
1436aea4 1261 break;\r
87bfeb11 1262\r
1436aea4
MK
1263 case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
1264 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
1265 StringTextPtr = BlockHdr + Offset;\r
1266 BlockSize += Offset;\r
1267 CopyMem (\r
1268 &StringCount,\r
1269 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1270 sizeof (UINT16)\r
1271 );\r
1272 for (Index = 0; Index < StringCount; Index++) {\r
1273 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1274 if (FindString) {\r
1275 *KeywordValue = String;\r
1276 return CurrentStringId;\r
1277 } else if (CurrentStringId == StringId) {\r
1278 FindString = TRUE;\r
1279 }\r
87bfeb11 1280\r
1436aea4
MK
1281 BlockSize += StringSize;\r
1282 StringTextPtr = StringTextPtr + StringSize;\r
1283 CurrentStringId++;\r
1284 }\r
87bfeb11 1285\r
1436aea4 1286 break;\r
87bfeb11 1287\r
1436aea4
MK
1288 case EFI_HII_SIBT_DUPLICATE:\r
1289 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
1290 CurrentStringId++;\r
1291 break;\r
87bfeb11 1292\r
1436aea4
MK
1293 case EFI_HII_SIBT_SKIP1:\r
1294 SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
1295 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);\r
1296 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
1297 break;\r
1298\r
1299 case EFI_HII_SIBT_SKIP2:\r
1300 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1301 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);\r
1302 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
1303 break;\r
1304\r
1305 case EFI_HII_SIBT_EXT1:\r
1306 CopyMem (\r
1307 &Length8,\r
1308 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1309 sizeof (UINT8)\r
1310 );\r
1311 BlockSize += Length8;\r
1312 break;\r
1313\r
1314 case EFI_HII_SIBT_EXT2:\r
1315 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
1316 BlockSize += Ext2.Length;\r
1317 break;\r
1318\r
1319 case EFI_HII_SIBT_EXT4:\r
1320 CopyMem (\r
1321 &Length32,\r
1322 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1323 sizeof (UINT32)\r
1324 );\r
1325\r
1326 BlockSize += Length32;\r
1327 break;\r
1328\r
1329 default:\r
1330 break;\r
87bfeb11
ED
1331 }\r
1332\r
1333 if (String != NULL) {\r
1334 FreePool (String);\r
1335 String = NULL;\r
1336 }\r
1337\r
1436aea4 1338 BlockHdr = StringPackage->StringBlock + BlockSize;\r
87bfeb11
ED
1339 }\r
1340\r
1341 return 0;\r
1342}\r
1343\r
1344/**\r
1345 Get string package from the input NameSpace string.\r
1346\r
1347 This is a internal function.\r
1348\r
1349 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
1350 @param NameSpace NameSpace format string.\r
1351 @param KeywordValue Keyword value.\r
1352 @param StringId String Id for this keyword.\r
1353\r
4a429716 1354 @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.\r
87bfeb11
ED
1355 @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.\r
1356 @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.\r
1357 @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.\r
1358\r
1359**/\r
1360UINT32\r
1361GetStringIdFromRecord (\r
1436aea4
MK
1362 IN HII_DATABASE_RECORD *DatabaseRecord,\r
1363 IN CHAR8 **NameSpace,\r
1364 IN CHAR16 *KeywordValue,\r
1365 OUT EFI_STRING_ID *StringId\r
87bfeb11
ED
1366 )\r
1367{\r
1368 LIST_ENTRY *Link;\r
1369 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
1370 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
1371 EFI_STATUS Status;\r
1372 CHAR8 *Name;\r
5f25ead9 1373 UINT32 RetVal;\r
87bfeb11
ED
1374\r
1375 ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);\r
1376\r
1377 PackageListNode = DatabaseRecord->PackageList;\r
1436aea4 1378 RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
87bfeb11
ED
1379\r
1380 if (*NameSpace != NULL) {\r
1381 Name = *NameSpace;\r
1382 } else {\r
1383 Name = UEFI_CONFIG_LANG;\r
1384 }\r
1385\r
1386 for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {\r
1387 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1388\r
1436aea4 1389 if (AsciiStrnCmp (Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {\r
d1102dba 1390 Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);\r
87bfeb11 1391 if (EFI_ERROR (Status)) {\r
6c20eda7 1392 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
87bfeb11
ED
1393 } else {\r
1394 if (*NameSpace == NULL) {\r
1395 *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
1396 if (*NameSpace == NULL) {\r
1397 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
1398 }\r
1399 }\r
1436aea4 1400\r
87bfeb11
ED
1401 return KEYWORD_HANDLER_NO_ERROR;\r
1402 }\r
1403 }\r
1404 }\r
1405\r
5f25ead9 1406 return RetVal;\r
87bfeb11
ED
1407}\r
1408\r
1409/**\r
1410 Tell whether this Operand is an Statement OpCode.\r
1411\r
1412 @param Operand Operand of an IFR OpCode.\r
1413\r
1414 @retval TRUE This is an Statement OpCode.\r
1415 @retval FALSE Not an Statement OpCode.\r
1416\r
1417**/\r
1418BOOLEAN\r
1419IsStatementOpCode (\r
1436aea4 1420 IN UINT8 Operand\r
87bfeb11
ED
1421 )\r
1422{\r
1423 if ((Operand == EFI_IFR_SUBTITLE_OP) ||\r
1424 (Operand == EFI_IFR_TEXT_OP) ||\r
1425 (Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
1426 (Operand == EFI_IFR_REF_OP) ||\r
1427 (Operand == EFI_IFR_ACTION_OP) ||\r
1428 (Operand == EFI_IFR_NUMERIC_OP) ||\r
1429 (Operand == EFI_IFR_ORDERED_LIST_OP) ||\r
1430 (Operand == EFI_IFR_CHECKBOX_OP) ||\r
1431 (Operand == EFI_IFR_STRING_OP) ||\r
1432 (Operand == EFI_IFR_PASSWORD_OP) ||\r
1433 (Operand == EFI_IFR_DATE_OP) ||\r
1434 (Operand == EFI_IFR_TIME_OP) ||\r
1435 (Operand == EFI_IFR_GUID_OP) ||\r
1436aea4
MK
1436 (Operand == EFI_IFR_ONE_OF_OP))\r
1437 {\r
87bfeb11
ED
1438 return TRUE;\r
1439 }\r
1440\r
1441 return FALSE;\r
1442}\r
1443\r
1444/**\r
1445 Tell whether this Operand is an Statement OpCode.\r
1446\r
1447 @param Operand Operand of an IFR OpCode.\r
1448\r
1449 @retval TRUE This is an Statement OpCode.\r
1450 @retval FALSE Not an Statement OpCode.\r
1451\r
1452**/\r
1453BOOLEAN\r
1454IsStorageOpCode (\r
1436aea4 1455 IN UINT8 Operand\r
87bfeb11
ED
1456 )\r
1457{\r
1458 if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
1459 (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
1436aea4
MK
1460 (Operand == EFI_IFR_VARSTORE_EFI_OP))\r
1461 {\r
87bfeb11
ED
1462 return TRUE;\r
1463 }\r
1464\r
1465 return FALSE;\r
1466}\r
1467\r
1468/**\r
1469 Base on the prompt string id to find the question.\r
1470\r
1471 @param FormPackage The input form package.\r
1472 @param KeywordStrId The input prompt string id for one question.\r
1473\r
1474 @retval the opcode for the question.\r
1475\r
1476**/\r
d1102dba 1477UINT8 *\r
87bfeb11 1478FindQuestionFromStringId (\r
1436aea4
MK
1479 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,\r
1480 IN EFI_STRING_ID KeywordStrId\r
87bfeb11
ED
1481 )\r
1482{\r
1436aea4
MK
1483 UINT8 *OpCodeData;\r
1484 UINT32 Offset;\r
1485 EFI_IFR_STATEMENT_HEADER *StatementHeader;\r
1486 EFI_IFR_OP_HEADER *OpCodeHeader;\r
1487 UINT32 FormDataLen;\r
87bfeb11
ED
1488\r
1489 ASSERT (FormPackage != NULL);\r
1490\r
1491 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4 1492 Offset = 0;\r
87bfeb11 1493 while (Offset < FormDataLen) {\r
1436aea4
MK
1494 OpCodeData = FormPackage->IfrData + Offset;\r
1495 OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;\r
87bfeb11 1496\r
1436aea4
MK
1497 if (IsStatementOpCode (OpCodeHeader->OpCode)) {\r
1498 StatementHeader = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
87bfeb11
ED
1499 if (StatementHeader->Prompt == KeywordStrId) {\r
1500 return OpCodeData;\r
1501 }\r
1502 }\r
1503\r
1504 Offset += OpCodeHeader->Length;\r
1505 }\r
1506\r
1507 return NULL;\r
1508}\r
1509\r
1510/**\r
1511 Base on the varstore id to find the storage info.\r
1512\r
1513 @param FormPackage The input form package.\r
1514 @param VarStoreId The input storage id.\r
1515\r
1516 @retval the opcode for the storage.\r
1517\r
1518**/\r
1519UINT8 *\r
1520FindStorageFromVarId (\r
1436aea4
MK
1521 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,\r
1522 IN EFI_VARSTORE_ID VarStoreId\r
87bfeb11
ED
1523 )\r
1524{\r
1436aea4
MK
1525 UINT8 *OpCodeData;\r
1526 UINT32 Offset;\r
1527 EFI_IFR_OP_HEADER *OpCodeHeader;\r
1528 UINT32 FormDataLen;\r
87bfeb11
ED
1529\r
1530 ASSERT (FormPackage != NULL);\r
1531\r
1532 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4 1533 Offset = 0;\r
87bfeb11 1534 while (Offset < FormDataLen) {\r
1436aea4
MK
1535 OpCodeData = FormPackage->IfrData + Offset;\r
1536 OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;\r
87bfeb11 1537\r
1436aea4 1538 if (IsStorageOpCode (OpCodeHeader->OpCode)) {\r
87bfeb11 1539 switch (OpCodeHeader->OpCode) {\r
1436aea4
MK
1540 case EFI_IFR_VARSTORE_OP:\r
1541 if (VarStoreId == ((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId) {\r
1542 return OpCodeData;\r
1543 }\r
87bfeb11 1544\r
1436aea4 1545 break;\r
87bfeb11 1546\r
1436aea4
MK
1547 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1548 if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId) {\r
1549 return OpCodeData;\r
1550 }\r
87bfeb11 1551\r
1436aea4
MK
1552 break;\r
1553\r
1554 case EFI_IFR_VARSTORE_EFI_OP:\r
1555 if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId) {\r
1556 return OpCodeData;\r
1557 }\r
1558\r
1559 break;\r
1560\r
1561 default:\r
1562 break;\r
87bfeb11
ED
1563 }\r
1564 }\r
1565\r
1566 Offset += OpCodeHeader->Length;\r
1567 }\r
1568\r
1569 return NULL;\r
1570}\r
1571\r
1572/**\r
1573 Get width info for one question.\r
1574\r
1575 @param OpCodeData The input opcode for one question.\r
1576\r
1577 @retval the width info for one question.\r
1578\r
1579**/\r
d1102dba 1580UINT16\r
87bfeb11 1581GetWidth (\r
1436aea4 1582 IN UINT8 *OpCodeData\r
87bfeb11
ED
1583 )\r
1584{\r
1436aea4 1585 UINT8 *NextOpCodeData;\r
87bfeb11
ED
1586\r
1587 ASSERT (OpCodeData != NULL);\r
1588\r
1436aea4
MK
1589 switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {\r
1590 case EFI_IFR_REF_OP:\r
1591 return (UINT16)sizeof (EFI_HII_REF);\r
87bfeb11 1592\r
1436aea4
MK
1593 case EFI_IFR_ONE_OF_OP:\r
1594 case EFI_IFR_NUMERIC_OP:\r
1595 switch (((EFI_IFR_ONE_OF *)OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1596 case EFI_IFR_NUMERIC_SIZE_1:\r
1597 return (UINT16)sizeof (UINT8);\r
d1102dba 1598\r
1436aea4
MK
1599 case EFI_IFR_NUMERIC_SIZE_2:\r
1600 return (UINT16)sizeof (UINT16);\r
d1102dba 1601\r
1436aea4
MK
1602 case EFI_IFR_NUMERIC_SIZE_4:\r
1603 return (UINT16)sizeof (UINT32);\r
d1102dba 1604\r
1436aea4
MK
1605 case EFI_IFR_NUMERIC_SIZE_8:\r
1606 return (UINT16)sizeof (UINT64);\r
d1102dba 1607\r
1436aea4
MK
1608 default:\r
1609 ASSERT (FALSE);\r
1610 return 0;\r
1611 }\r
87bfeb11 1612\r
1436aea4
MK
1613 case EFI_IFR_ORDERED_LIST_OP:\r
1614 NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Header.Length;\r
1615 //\r
1616 // OneOfOption must follow the orderedlist opcode.\r
1617 //\r
1618 ASSERT (((EFI_IFR_OP_HEADER *)NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);\r
1619 switch (((EFI_IFR_ONE_OF_OPTION *)NextOpCodeData)->Type) {\r
1620 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1621 return (UINT16)sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
d1102dba 1622\r
1436aea4
MK
1623 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1624 return (UINT16)sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
d1102dba 1625\r
1436aea4
MK
1626 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1627 return (UINT16)sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
d1102dba 1628\r
1436aea4
MK
1629 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1630 return (UINT16)sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
d1102dba 1631\r
1436aea4
MK
1632 default:\r
1633 ASSERT (FALSE);\r
1634 return 0;\r
1635 }\r
87bfeb11 1636\r
1436aea4
MK
1637 case EFI_IFR_CHECKBOX_OP:\r
1638 return (UINT16)sizeof (BOOLEAN);\r
d1102dba 1639\r
1436aea4
MK
1640 case EFI_IFR_PASSWORD_OP:\r
1641 return (UINT16)((UINTN)((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize * sizeof (CHAR16));\r
4858527b 1642\r
1436aea4
MK
1643 case EFI_IFR_STRING_OP:\r
1644 return (UINT16)((UINTN)((EFI_IFR_STRING *)OpCodeData)->MaxSize * sizeof (CHAR16));\r
87bfeb11 1645\r
1436aea4
MK
1646 case EFI_IFR_DATE_OP:\r
1647 return (UINT16)sizeof (EFI_HII_DATE);\r
87bfeb11 1648\r
1436aea4
MK
1649 case EFI_IFR_TIME_OP:\r
1650 return (UINT16)sizeof (EFI_HII_TIME);\r
87bfeb11 1651\r
1436aea4
MK
1652 default:\r
1653 ASSERT (FALSE);\r
1654 return 0;\r
87bfeb11
ED
1655 }\r
1656}\r
1657\r
1658/**\r
4a429716 1659 Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for\r
87bfeb11
ED
1660 hex digits that appear between a '=' and a '&' in a config string.\r
1661\r
1662 If ConfigString is NULL, then ASSERT().\r
1663\r
1664 @param[in] ConfigString Pointer to a Null-terminated Unicode string.\r
1665\r
1666 @return Pointer to the Null-terminated Unicode result string.\r
1667\r
1668**/\r
1669EFI_STRING\r
1670EFIAPI\r
1671InternalLowerConfigString (\r
1672 IN EFI_STRING ConfigString\r
1673 )\r
1674{\r
1675 EFI_STRING String;\r
1676 BOOLEAN Lower;\r
1677\r
1678 ASSERT (ConfigString != NULL);\r
1679\r
1680 //\r
1681 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
1682 //\r
1683 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
1684 if (*String == L'=') {\r
1685 Lower = TRUE;\r
1686 } else if (*String == L'&') {\r
1687 Lower = FALSE;\r
1436aea4
MK
1688 } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
1689 *String = (CHAR16)(*String - L'A' + L'a');\r
87bfeb11
ED
1690 }\r
1691 }\r
1692\r
1693 return ConfigString;\r
1694}\r
1695\r
1696/**\r
1697 Allocates and returns a Null-terminated Unicode <ConfigHdr> string.\r
d1102dba 1698\r
87bfeb11
ED
1699 The format of a <ConfigHdr> is as follows:\r
1700\r
1701 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
1702\r
d1102dba 1703 @param[in] OpCodeData The opcode for the storage.\r
87bfeb11
ED
1704 @param[in] DriverHandle The driver handle which supports a Device Path Protocol\r
1705 that is the routing information PATH. Each byte of\r
1706 the Device Path associated with DriverHandle is converted\r
4a429716 1707 to a 2 Unicode character hexadecimal string.\r
87bfeb11
ED
1708\r
1709 @retval NULL DriverHandle does not support the Device Path Protocol.\r
1710 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string\r
1711\r
1712**/\r
1713EFI_STRING\r
1714ConstructConfigHdr (\r
1436aea4
MK
1715 IN UINT8 *OpCodeData,\r
1716 IN EFI_HANDLE DriverHandle\r
87bfeb11
ED
1717 )\r
1718{\r
1719 UINTN NameLength;\r
1720 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1721 UINTN DevicePathSize;\r
1722 CHAR16 *String;\r
1723 CHAR16 *ReturnString;\r
1724 UINTN Index;\r
1725 UINT8 *Buffer;\r
1726 CHAR16 *Name;\r
1727 CHAR8 *AsciiName;\r
b68ccac1 1728 UINTN NameSize;\r
87bfeb11 1729 EFI_GUID *Guid;\r
5ad66ec6 1730 UINTN MaxLen;\r
87bfeb11
ED
1731\r
1732 ASSERT (OpCodeData != NULL);\r
1733\r
1734 switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {\r
1436aea4
MK
1735 case EFI_IFR_VARSTORE_OP:\r
1736 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *)OpCodeData)->Guid;\r
1737 AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;\r
1738 break;\r
d1102dba 1739\r
1436aea4
MK
1740 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1741 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid;\r
1742 AsciiName = NULL;\r
1743 break;\r
d1102dba 1744\r
1436aea4
MK
1745 case EFI_IFR_VARSTORE_EFI_OP:\r
1746 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid;\r
1747 AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;\r
1748 break;\r
d1102dba 1749\r
1436aea4
MK
1750 default:\r
1751 ASSERT (FALSE);\r
1752 Guid = NULL;\r
1753 AsciiName = NULL;\r
1754 break;\r
87bfeb11
ED
1755 }\r
1756\r
1757 if (AsciiName != NULL) {\r
b68ccac1 1758 NameSize = AsciiStrSize (AsciiName);\r
1436aea4 1759 Name = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
87bfeb11 1760 ASSERT (Name != NULL);\r
b68ccac1 1761 AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);\r
87bfeb11
ED
1762 } else {\r
1763 Name = NULL;\r
1764 }\r
1765\r
1766 //\r
d1102dba 1767 // Compute the length of Name in Unicode characters.\r
87bfeb11
ED
1768 // If Name is NULL, then the length is 0.\r
1769 //\r
1770 NameLength = 0;\r
1771 if (Name != NULL) {\r
1772 NameLength = StrLen (Name);\r
1773 }\r
1774\r
1436aea4 1775 DevicePath = NULL;\r
87bfeb11
ED
1776 DevicePathSize = 0;\r
1777 //\r
1778 // Retrieve DevicePath Protocol associated with DriverHandle\r
1779 //\r
1780 if (DriverHandle != NULL) {\r
1781 DevicePath = DevicePathFromHandle (DriverHandle);\r
1782 if (DevicePath == NULL) {\r
1783 return NULL;\r
1784 }\r
1436aea4 1785\r
87bfeb11
ED
1786 //\r
1787 // Compute the size of the device path in bytes\r
1788 //\r
1789 DevicePathSize = GetDevicePathSize (DevicePath);\r
1790 }\r
1791\r
1792 //\r
1793 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
1794 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
1795 //\r
5ad66ec6
DB
1796 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
1797 String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
1798 if (String == NULL) {\r
1799 return NULL;\r
1800 }\r
1801\r
1802 //\r
1803 // Start with L"GUID="\r
1804 //\r
5ad66ec6
DB
1805 StrCpyS (String, MaxLen, L"GUID=");\r
1806 ReturnString = String;\r
1436aea4 1807 String += StrLen (String);\r
87bfeb11
ED
1808\r
1809 if (Guid != NULL) {\r
1810 //\r
1811 // Append Guid converted to <HexCh>32\r
1812 //\r
1813 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
9f4048f7
HW
1814 UnicodeValueToStringS (\r
1815 String,\r
1816 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1817 PREFIX_ZERO | RADIX_HEX,\r
1818 *(Buffer++),\r
1819 2\r
1820 );\r
1821 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1822 }\r
1823 }\r
d1102dba 1824\r
87bfeb11
ED
1825 //\r
1826 // Append L"&NAME="\r
1827 //\r
2d3e4cd1 1828 StrCatS (ReturnString, MaxLen, L"&NAME=");\r
87bfeb11
ED
1829 String += StrLen (String);\r
1830\r
1831 if (Name != NULL) {\r
1832 //\r
1833 // Append Name converted to <Char>NameLength\r
1834 //\r
1436aea4 1835 for ( ; *Name != L'\0'; Name++) {\r
9f4048f7
HW
1836 UnicodeValueToStringS (\r
1837 String,\r
1838 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1839 PREFIX_ZERO | RADIX_HEX,\r
1840 *Name,\r
1841 4\r
1842 );\r
1843 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1844 }\r
1845 }\r
1846\r
1847 //\r
1848 // Append L"&PATH="\r
1849 //\r
2d3e4cd1 1850 StrCatS (ReturnString, MaxLen, L"&PATH=");\r
87bfeb11
ED
1851 String += StrLen (String);\r
1852\r
1853 //\r
1854 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
1855 //\r
1856 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
9f4048f7
HW
1857 UnicodeValueToStringS (\r
1858 String,\r
1859 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1860 PREFIX_ZERO | RADIX_HEX,\r
1861 *(Buffer++),\r
1862 2\r
1863 );\r
1864 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1865 }\r
1866\r
1867 //\r
1868 // Null terminate the Unicode string\r
1869 //\r
1870 *String = L'\0';\r
1871\r
1872 //\r
1873 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
1874 //\r
1875 return InternalLowerConfigString (ReturnString);\r
1876}\r
1877\r
1878/**\r
1879 Generate the Config request element for one question.\r
1880\r
1881 @param Name The name info for one question.\r
1882 @param Offset The offset info for one question.\r
1883 @param Width The width info for one question.\r
1884\r
1885 @return Pointer to the Null-terminated Unicode request element string.\r
1886\r
1887**/\r
1888EFI_STRING\r
1889ConstructRequestElement (\r
1436aea4
MK
1890 IN CHAR16 *Name,\r
1891 IN UINT16 Offset,\r
1892 IN UINT16 Width\r
87bfeb11
ED
1893 )\r
1894{\r
1436aea4
MK
1895 CHAR16 *StringPtr;\r
1896 UINTN Length;\r
d1102dba 1897\r
87bfeb11
ED
1898 if (Name != NULL) {\r
1899 //\r
1900 // Add <BlockName> length for each Name\r
1901 //\r
1902 // <BlockName> ::= Name + \0\r
1903 // StrLen(Name) | 1\r
1904 //\r
1905 Length = StrLen (Name) + 1;\r
1906 } else {\r
1907 //\r
1908 // Add <BlockName> length for each Offset/Width pair\r
1909 //\r
1910 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0\r
1911 // | 7 | 4 | 7 | 4 | 1\r
1912 //\r
1913 Length = (7 + 4 + 7 + 4 + 1);\r
1914 }\r
1915\r
1916 //\r
1917 // Allocate buffer for the entire <ConfigRequest>\r
1918 //\r
1919 StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1920 ASSERT (StringPtr != NULL);\r
1921\r
1922 if (Name != NULL) {\r
1923 //\r
1924 // Append Name\0\r
1925 //\r
1926 UnicodeSPrint (\r
1927 StringPtr,\r
1928 (StrLen (Name) + 1) * sizeof (CHAR16),\r
1929 L"%s",\r
1930 Name\r
1436aea4 1931 );\r
87bfeb11
ED
1932 } else {\r
1933 //\r
1934 // Append OFFSET=XXXX&WIDTH=YYYY\0\r
1935 //\r
1936 UnicodeSPrint (\r
d1102dba
LG
1937 StringPtr,\r
1938 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),\r
1939 L"OFFSET=%04X&WIDTH=%04X",\r
1940 Offset,\r
87bfeb11 1941 Width\r
1436aea4 1942 );\r
87bfeb11
ED
1943 }\r
1944\r
1945 return StringPtr;\r
1946}\r
1947\r
1948/**\r
1949 Get string value for question's name field.\r
1950\r
1951 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
1952 @param NameId The string id for the name field.\r
1953\r
1954 @retval Name string.\r
1955\r
1956**/\r
1957CHAR16 *\r
1958GetNameFromId (\r
1436aea4
MK
1959 IN HII_DATABASE_RECORD *DatabaseRecord,\r
1960 IN EFI_STRING_ID NameId\r
87bfeb11
ED
1961 )\r
1962{\r
1963 CHAR16 *Name;\r
1964 CHAR8 *PlatformLanguage;\r
1965 CHAR8 *SupportedLanguages;\r
1966 CHAR8 *BestLanguage;\r
1967 UINTN StringSize;\r
1968 CHAR16 TempString;\r
1969 EFI_STATUS Status;\r
1970\r
1436aea4
MK
1971 Name = NULL;\r
1972 BestLanguage = NULL;\r
1973 PlatformLanguage = NULL;\r
87bfeb11
ED
1974 SupportedLanguages = NULL;\r
1975\r
1436aea4
MK
1976 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);\r
1977 SupportedLanguages = GetSupportedLanguages (DatabaseRecord->Handle);\r
87bfeb11
ED
1978\r
1979 //\r
1980 // Get the best matching language from SupportedLanguages\r
1981 //\r
1982 BestLanguage = GetBestLanguage (\r
d1102dba 1983 SupportedLanguages,\r
87bfeb11
ED
1984 FALSE, // RFC 4646 mode\r
1985 PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority\r
d1102dba 1986 SupportedLanguages, // Lowest priority\r
87bfeb11
ED
1987 NULL\r
1988 );\r
1989 if (BestLanguage == NULL) {\r
1990 BestLanguage = AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");\r
1991 ASSERT (BestLanguage != NULL);\r
1992 }\r
1993\r
1994 StringSize = 0;\r
1436aea4
MK
1995 Status = mPrivate.HiiString.GetString (\r
1996 &mPrivate.HiiString,\r
1997 BestLanguage,\r
1998 DatabaseRecord->Handle,\r
1999 NameId,\r
2000 &TempString,\r
2001 &StringSize,\r
2002 NULL\r
2003 );\r
87bfeb11
ED
2004 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2005 goto Done;\r
2006 }\r
2007\r
2008 Name = AllocateZeroPool (StringSize);\r
2009 if (Name == NULL) {\r
2010 goto Done;\r
2011 }\r
2012\r
2013 Status = mPrivate.HiiString.GetString (\r
1436aea4
MK
2014 &mPrivate.HiiString,\r
2015 BestLanguage,\r
2016 DatabaseRecord->Handle,\r
2017 NameId,\r
2018 Name,\r
2019 &StringSize,\r
2020 NULL\r
2021 );\r
87bfeb11
ED
2022\r
2023 if (EFI_ERROR (Status)) {\r
2024 FreePool (Name);\r
2025 Name = NULL;\r
2026 goto Done;\r
2027 }\r
2028\r
2029Done:\r
2030 if (SupportedLanguages != NULL) {\r
1436aea4 2031 FreePool (SupportedLanguages);\r
87bfeb11 2032 }\r
1436aea4 2033\r
87bfeb11
ED
2034 if (BestLanguage != NULL) {\r
2035 FreePool (BestLanguage);\r
2036 }\r
1436aea4 2037\r
87bfeb11
ED
2038 if (PlatformLanguage != NULL) {\r
2039 FreePool (PlatformLanguage);\r
2040 }\r
2041\r
2042 return Name;\r
2043}\r
2044\r
2045/**\r
2046 Base on the input parameter to generate the ConfigRequest string.\r
2047\r
2048 This is a internal function.\r
2049\r
2050 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
2051 @param KeywordStrId Keyword string id.\r
2052 @param OpCodeData The IFR data for this question.\r
2053 @param ConfigRequest Return the generate ConfigRequest string.\r
2054\r
2055 @retval EFI_SUCCESS Generate ConfigResp string success.\r
2056 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.\r
2057 @retval EFI_NOT_FOUND Not found the question which use this string id\r
2058 as the prompt string id.\r
2059**/\r
2060EFI_STATUS\r
2061ExtractConfigRequest (\r
1436aea4
MK
2062 IN HII_DATABASE_RECORD *DatabaseRecord,\r
2063 IN EFI_STRING_ID KeywordStrId,\r
2064 OUT UINT8 **OpCodeData,\r
2065 OUT EFI_STRING *ConfigRequest\r
d1102dba 2066 )\r
87bfeb11
ED
2067{\r
2068 LIST_ENTRY *Link;\r
2069 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2070 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
2071 EFI_IFR_QUESTION_HEADER *Header;\r
2072 UINT8 *Storage;\r
2073 UINT8 *OpCode;\r
2074 CHAR16 *Name;\r
2075 UINT16 Offset;\r
2076 UINT16 Width;\r
2077 CHAR16 *ConfigHdr;\r
2078 CHAR16 *RequestElement;\r
5ad66ec6 2079 UINTN MaxLen;\r
87bfeb11
ED
2080 CHAR16 *StringPtr;\r
2081\r
2082 ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);\r
2083\r
2084 OpCode = NULL;\r
2085 Name = NULL;\r
2086 Width = 0;\r
2087 Offset = 0;\r
2088\r
2089 PackageListNode = DatabaseRecord->PackageList;\r
2090\r
2091 //\r
2092 // Search the languages in the specified packagelist.\r
2093 //\r
2094 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
2095 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
2096\r
2097 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
2098 if (OpCode != NULL) {\r
2099 *OpCodeData = OpCode;\r
1436aea4 2100 Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));\r
87bfeb11
ED
2101 //\r
2102 // Header->VarStoreId == 0 means no storage for this question.\r
2103 //\r
2104 ASSERT (Header->VarStoreId != 0);\r
87000d77 2105 DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
d1102dba 2106\r
87bfeb11
ED
2107 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
2108 ASSERT (Storage != NULL);\r
2109\r
1436aea4 2110 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
87bfeb11
ED
2111 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
2112 } else {\r
2113 Offset = Header->VarStoreInfo.VarOffset;\r
1436aea4 2114 Width = GetWidth (OpCode);\r
87bfeb11 2115 }\r
1436aea4
MK
2116\r
2117 RequestElement = ConstructRequestElement (Name, Offset, Width);\r
2118 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);\r
cbbc454b 2119 ASSERT (ConfigHdr != NULL);\r
87bfeb11 2120\r
1436aea4 2121 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;\r
5ad66ec6 2122 *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
2123 if (*ConfigRequest == NULL) {\r
2124 FreePool (ConfigHdr);\r
2125 FreePool (RequestElement);\r
2126 return EFI_OUT_OF_RESOURCES;\r
2127 }\r
1436aea4 2128\r
87bfeb11
ED
2129 StringPtr = *ConfigRequest;\r
2130\r
5ad66ec6 2131 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
87bfeb11 2132\r
2d3e4cd1 2133 StrCatS (StringPtr, MaxLen, L"&");\r
87bfeb11 2134\r
2d3e4cd1 2135 StrCatS (StringPtr, MaxLen, RequestElement);\r
87bfeb11
ED
2136\r
2137 FreePool (ConfigHdr);\r
2138 FreePool (RequestElement);\r
2139\r
2140 return EFI_SUCCESS;\r
2141 }\r
2142 }\r
2143\r
2144 return EFI_NOT_FOUND;\r
2145}\r
2146\r
2147/**\r
2148 Base on the input parameter to generate the ConfigResp string.\r
2149\r
2150 This is a internal function.\r
2151\r
2152 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
2153 @param KeywordStrId Keyword string id.\r
2154 @param ValueElement The value for the question which use keyword string id\r
2155 as the prompt string id.\r
2156 @param OpCodeData The IFR data for this question.\r
2157 @param ConfigResp Return the generate ConfigResp string.\r
2158\r
2159 @retval EFI_SUCCESS Generate ConfigResp string success.\r
2160 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.\r
2161 @retval EFI_NOT_FOUND Not found the question which use this string id\r
2162 as the prompt string id.\r
2163**/\r
2164EFI_STATUS\r
2165ExtractConfigResp (\r
1436aea4
MK
2166 IN HII_DATABASE_RECORD *DatabaseRecord,\r
2167 IN EFI_STRING_ID KeywordStrId,\r
2168 IN EFI_STRING ValueElement,\r
2169 OUT UINT8 **OpCodeData,\r
2170 OUT EFI_STRING *ConfigResp\r
d1102dba 2171 )\r
87bfeb11
ED
2172{\r
2173 LIST_ENTRY *Link;\r
2174 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2175 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
2176 EFI_IFR_QUESTION_HEADER *Header;\r
2177 UINT8 *Storage;\r
2178 UINT8 *OpCode;\r
2179 CHAR16 *Name;\r
2180 UINT16 Offset;\r
2181 UINT16 Width;\r
2182 CHAR16 *ConfigHdr;\r
2183 CHAR16 *RequestElement;\r
5ad66ec6 2184 UINTN MaxLen;\r
87bfeb11
ED
2185 CHAR16 *StringPtr;\r
2186\r
2187 ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));\r
2188\r
2189 OpCode = NULL;\r
2190 Name = NULL;\r
2191 Width = 0;\r
2192 Offset = 0;\r
2193\r
2194 PackageListNode = DatabaseRecord->PackageList;\r
2195\r
2196 //\r
2197 // Search the languages in the specified packagelist.\r
2198 //\r
2199 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
2200 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
2201\r
2202 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
2203 if (OpCode != NULL) {\r
2204 *OpCodeData = OpCode;\r
1436aea4 2205 Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));\r
87bfeb11
ED
2206 //\r
2207 // Header->VarStoreId == 0 means no storage for this question.\r
2208 //\r
2209 ASSERT (Header->VarStoreId != 0);\r
87000d77 2210 DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
d1102dba 2211\r
87bfeb11
ED
2212 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
2213 ASSERT (Storage != NULL);\r
2214\r
1436aea4 2215 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
87bfeb11
ED
2216 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
2217 } else {\r
2218 Offset = Header->VarStoreInfo.VarOffset;\r
2219 Width = GetWidth (OpCode);\r
2220 }\r
87bfeb11 2221\r
1436aea4
MK
2222 RequestElement = ConstructRequestElement (Name, Offset, Width);\r
2223\r
2224 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);\r
cbbc454b 2225 ASSERT (ConfigHdr != NULL);\r
87bfeb11 2226\r
1436aea4 2227 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + StrLen (L"VALUE=") + StrLen (ValueElement) + 1;\r
5ad66ec6 2228 *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
2229 if (*ConfigResp == NULL) {\r
2230 FreePool (ConfigHdr);\r
2231 FreePool (RequestElement);\r
2232 return EFI_OUT_OF_RESOURCES;\r
2233 }\r
1436aea4 2234\r
87bfeb11
ED
2235 StringPtr = *ConfigResp;\r
2236\r
5ad66ec6 2237 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
87bfeb11 2238\r
2d3e4cd1 2239 StrCatS (StringPtr, MaxLen, L"&");\r
87bfeb11 2240\r
2d3e4cd1
DB
2241 StrCatS (StringPtr, MaxLen, RequestElement);\r
2242\r
2243 StrCatS (StringPtr, MaxLen, L"&");\r
2244\r
2245 StrCatS (StringPtr, MaxLen, L"VALUE=");\r
87bfeb11 2246\r
2d3e4cd1 2247 StrCatS (StringPtr, MaxLen, ValueElement);\r
87bfeb11
ED
2248\r
2249 FreePool (ConfigHdr);\r
2250 FreePool (RequestElement);\r
2251\r
2252 return EFI_SUCCESS;\r
2253 }\r
2254 }\r
2255\r
2256 return EFI_NOT_FOUND;\r
2257}\r
2258\r
2259/**\r
2260 Get the Value section from the Hii driver.\r
2261\r
2262 This is a internal function.\r
2263\r
2264 @param ConfigRequest The input ConfigRequest string.\r
2265 @param ValueElement The respond Value section from the hii driver.\r
2266\r
2267 @retval Misc value The error status return from ExtractConfig function.\r
2268 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated\r
2269 @retval EFI_SUCCESS Get the value section success.\r
2270\r
2271**/\r
2272EFI_STATUS\r
2273ExtractValueFromDriver (\r
1436aea4
MK
2274 IN CHAR16 *ConfigRequest,\r
2275 OUT CHAR16 **ValueElement\r
87bfeb11
ED
2276 )\r
2277{\r
1436aea4
MK
2278 EFI_STATUS Status;\r
2279 EFI_STRING Result;\r
2280 EFI_STRING Progress;\r
2281 CHAR16 *StringPtr;\r
2282 CHAR16 *StringEnd;\r
87bfeb11
ED
2283\r
2284 ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));\r
2285\r
2286 Status = mPrivate.ConfigRouting.ExtractConfig (\r
1436aea4
MK
2287 &mPrivate.ConfigRouting,\r
2288 (EFI_STRING)ConfigRequest,\r
2289 &Progress,\r
2290 &Result\r
2291 );\r
87bfeb11
ED
2292 if (EFI_ERROR (Status)) {\r
2293 return Status;\r
2294 }\r
2295\r
2296 //\r
2297 // Find Value Section and return it.\r
2298 //\r
2299 StringPtr = StrStr (Result, L"&VALUE=");\r
2300 ASSERT (StringPtr != NULL);\r
2301 StringEnd = StrStr (StringPtr + 1, L"&");\r
2302 if (StringEnd != NULL) {\r
2303 *StringEnd = L'\0';\r
2304 }\r
2305\r
2306 *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);\r
2307 if (*ValueElement == NULL) {\r
2308 return EFI_OUT_OF_RESOURCES;\r
2309 }\r
2310\r
2311 if (StringEnd != NULL) {\r
2312 *StringEnd = L'&';\r
2313 }\r
1436aea4 2314\r
87bfeb11
ED
2315 FreePool (Result);\r
2316\r
2317 return EFI_SUCCESS;\r
2318}\r
2319\r
2320/**\r
2321 Get EFI_STRING_ID info from the input device path, namespace and keyword.\r
2322\r
2323 This is a internal function.\r
2324\r
2325 @param DevicePath Input device path info.\r
2326 @param NameSpace NameSpace format string.\r
2327 @param KeywordData Keyword used to get string id.\r
2328 @param ProgressErr Return extra error type.\r
2329 @param KeywordStringId Return EFI_STRING_ID.\r
2330 @param DataBaseRecord DataBase record data for this driver.\r
2331\r
2332 @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.\r
2333 @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.\r
2334 @retval EFI_SUCCESS Find the EFI_STRING_ID.\r
2335\r
2336**/\r
2337EFI_STATUS\r
2338GetStringIdFromDatabase (\r
1436aea4
MK
2339 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
2340 IN CHAR8 **NameSpace,\r
2341 IN CHAR16 *KeywordData,\r
2342 OUT UINT32 *ProgressErr,\r
2343 OUT EFI_STRING_ID *KeywordStringId,\r
2344 OUT HII_DATABASE_RECORD **DataBaseRecord\r
2345 )\r
87bfeb11 2346{\r
1436aea4
MK
2347 HII_DATABASE_RECORD *Record;\r
2348 LIST_ENTRY *Link;\r
2349 BOOLEAN FindNameSpace;\r
2350 EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;\r
2351 UINT8 *DevicePathPkg;\r
2352 UINTN DevicePathSize;\r
87bfeb11
ED
2353\r
2354 ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));\r
2355\r
2356 FindNameSpace = FALSE;\r
2357\r
2358 if (*DevicePath != NULL) {\r
2359 //\r
2360 // Get DataBaseRecord from device path protocol.\r
2361 //\r
1436aea4 2362 Record = GetRecordFromDevicePath (*DevicePath);\r
87bfeb11
ED
2363 if (Record == NULL) {\r
2364 //\r
2365 // Can't find the DatabaseRecord base on the input device path info.\r
2366 // NEED TO CONFIRM the return ProgressErr.\r
2367 //\r
2368 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2369 return EFI_INVALID_PARAMETER;\r
2370 }\r
2371\r
2372 //\r
2373 // Get string id from the record.\r
2374 //\r
2375 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
2376 switch (*ProgressErr) {\r
1436aea4
MK
2377 case KEYWORD_HANDLER_NO_ERROR:\r
2378 *DataBaseRecord = Record;\r
2379 return EFI_SUCCESS;\r
87bfeb11 2380\r
1436aea4
MK
2381 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:\r
2382 return EFI_INVALID_PARAMETER;\r
87bfeb11 2383\r
1436aea4
MK
2384 default:\r
2385 ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);\r
2386 return EFI_NOT_FOUND;\r
87bfeb11
ED
2387 }\r
2388 } else {\r
2389 //\r
2390 // Find driver which matches the routing data.\r
2391 //\r
2392 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
2393 Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2394\r
2395 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
2396 if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {\r
2397 *DataBaseRecord = Record;\r
d1102dba 2398\r
87bfeb11 2399 if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {\r
1436aea4
MK
2400 DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));\r
2401 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);\r
2402 *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);\r
87bfeb11
ED
2403 if (*DevicePath == NULL) {\r
2404 return EFI_OUT_OF_RESOURCES;\r
2405 }\r
2406 } else {\r
2407 //\r
2408 // Need to verify this ASSERT.\r
2409 //\r
2410 ASSERT (FALSE);\r
2411 }\r
2412\r
2413 return EFI_SUCCESS;\r
2414 } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {\r
2415 return EFI_OUT_OF_RESOURCES;\r
2416 } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {\r
2417 FindNameSpace = TRUE;\r
d1102dba 2418 }\r
87bfeb11
ED
2419 }\r
2420\r
2421 //\r
2422 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.\r
2423 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.\r
2424 //\r
2425 if (FindNameSpace) {\r
2426 return EFI_NOT_FOUND;\r
2427 } else {\r
2428 return EFI_INVALID_PARAMETER;\r
2429 }\r
2430 }\r
2431}\r
2432\r
2433/**\r
4a429716 2434 Generate the KeywordResp String.\r
87bfeb11
ED
2435\r
2436 <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']\r
2437\r
2438 @param NameSpace NameSpace format string.\r
2439 @param DevicePath Input device path info.\r
2440 @param KeywordData Keyword used to get string id.\r
2441 @param ValueStr The value section for the keyword.\r
2442 @param ReadOnly Whether this value is readonly.\r
2443 @param KeywordResp Return the point to the KeywordResp string.\r
2444\r
2445 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2446 @retval EFI_SUCCESS Generate the KeywordResp string.\r
2447\r
2448**/\r
2449EFI_STATUS\r
2450GenerateKeywordResp (\r
1436aea4
MK
2451 IN CHAR8 *NameSpace,\r
2452 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2453 IN EFI_STRING KeywordData,\r
2454 IN EFI_STRING ValueStr,\r
2455 IN BOOLEAN ReadOnly,\r
2456 OUT EFI_STRING *KeywordResp\r
87bfeb11
ED
2457 )\r
2458{\r
1436aea4
MK
2459 UINTN RespStrLen;\r
2460 CHAR16 *RespStr;\r
2461 CHAR16 *PathHdr;\r
2462 CHAR16 *UnicodeNameSpace;\r
2463 UINTN NameSpaceLength;\r
87bfeb11
ED
2464\r
2465 ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));\r
2466\r
2467 //\r
2468 // 1. Calculate the string length.\r
2469 //\r
2470 //\r
2471 // 1.1 NameSpaceId size.\r
2472 // 'NAMESPACE='<String>\r
2473 //\r
1436aea4
MK
2474 NameSpaceLength = AsciiStrLen (NameSpace);\r
2475 RespStrLen = 10 + NameSpaceLength;\r
b68ccac1 2476 UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));\r
87bfeb11
ED
2477 if (UnicodeNameSpace == NULL) {\r
2478 return EFI_OUT_OF_RESOURCES;\r
2479 }\r
1436aea4 2480\r
b68ccac1 2481 AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);\r
87bfeb11
ED
2482\r
2483 //\r
2484 // 1.2 PathHdr size.\r
2485 // PATH=<UEFI binary Device Path represented as hex number>'&'\r
2486 // Attention: The output include the '&' at the end.\r
2487 //\r
2488 GenerateSubStr (\r
2489 L"&PATH=",\r
1436aea4
MK
2490 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),\r
2491 (VOID *)DevicePath,\r
87bfeb11
ED
2492 1,\r
2493 &PathHdr\r
2494 );\r
2495 RespStrLen += StrLen (PathHdr);\r
2496\r
2497 //\r
4a429716 2498 // 1.3 Keyword section.\r
87bfeb11
ED
2499 // 'KEYWORD='<String>[':'<DecCh>(1/4)]\r
2500 //\r
2501 RespStrLen += 8 + StrLen (KeywordData);\r
2502\r
2503 //\r
2504 // 1.4 Value section.\r
2505 // ValueStr = '&VALUE='<Number>\r
2506 //\r
2507 RespStrLen += StrLen (ValueStr);\r
2508\r
2509 //\r
2510 // 1.5 ReadOnly Section.\r
2511 // '&READONLY'\r
2512 //\r
2513 if (ReadOnly) {\r
2514 RespStrLen += 9;\r
2515 }\r
2516\r
2517 //\r
5ad66ec6 2518 // 2. Allocate the buffer and create the KeywordResp string include '\0'.\r
87bfeb11 2519 //\r
1436aea4 2520 RespStrLen += 1;\r
5ad66ec6 2521 *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));\r
87bfeb11
ED
2522 if (*KeywordResp == NULL) {\r
2523 if (UnicodeNameSpace != NULL) {\r
2524 FreePool (UnicodeNameSpace);\r
2525 }\r
2526\r
2527 return EFI_OUT_OF_RESOURCES;\r
2528 }\r
1436aea4 2529\r
87bfeb11
ED
2530 RespStr = *KeywordResp;\r
2531\r
2532 //\r
2533 // 2.1 Copy NameSpaceId section.\r
2534 //\r
5ad66ec6 2535 StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");\r
2d3e4cd1
DB
2536\r
2537 StrCatS (RespStr, RespStrLen, UnicodeNameSpace);\r
87bfeb11
ED
2538\r
2539 //\r
2540 // 2.2 Copy PathHdr section.\r
2541 //\r
2d3e4cd1 2542 StrCatS (RespStr, RespStrLen, PathHdr);\r
87bfeb11
ED
2543\r
2544 //\r
2545 // 2.3 Copy Keyword section.\r
2546 //\r
2d3e4cd1
DB
2547 StrCatS (RespStr, RespStrLen, L"KEYWORD=");\r
2548\r
2549 StrCatS (RespStr, RespStrLen, KeywordData);\r
87bfeb11
ED
2550\r
2551 //\r
2552 // 2.4 Copy the Value section.\r
2553 //\r
2d3e4cd1 2554 StrCatS (RespStr, RespStrLen, ValueStr);\r
87bfeb11
ED
2555\r
2556 //\r
2557 // 2.5 Copy ReadOnly section if exist.\r
2558 //\r
2559 if (ReadOnly) {\r
2d3e4cd1 2560 StrCatS (RespStr, RespStrLen, L"&READONLY");\r
87bfeb11
ED
2561 }\r
2562\r
87bfeb11
ED
2563 if (UnicodeNameSpace != NULL) {\r
2564 FreePool (UnicodeNameSpace);\r
2565 }\r
1436aea4 2566\r
87bfeb11
ED
2567 if (PathHdr != NULL) {\r
2568 FreePool (PathHdr);\r
2569 }\r
d1102dba 2570\r
87bfeb11
ED
2571 return EFI_SUCCESS;\r
2572}\r
2573\r
2574/**\r
2575 Merge the KeywordResp String to MultiKeywordResp string.\r
2576\r
2577 This is a internal function.\r
2578\r
2579 @param MultiKeywordResp The existed multikeywordresp string.\r
2580 @param KeywordResp The input keywordResp string.\r
2581\r
2582 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2583 @retval EFI_SUCCESS Generate the MultiKeywordResp string.\r
2584\r
2585**/\r
2586EFI_STATUS\r
2587MergeToMultiKeywordResp (\r
1436aea4
MK
2588 IN OUT EFI_STRING *MultiKeywordResp,\r
2589 IN EFI_STRING *KeywordResp\r
87bfeb11
ED
2590 )\r
2591{\r
2592 UINTN MultiKeywordRespLen;\r
2593 EFI_STRING StringPtr;\r
2594\r
2595 if (*MultiKeywordResp == NULL) {\r
2596 *MultiKeywordResp = *KeywordResp;\r
1436aea4 2597 *KeywordResp = NULL;\r
87bfeb11
ED
2598 return EFI_SUCCESS;\r
2599 }\r
2600\r
2601 MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);\r
2602\r
469293f8
JW
2603 StringPtr = ReallocatePool (\r
2604 StrSize (*MultiKeywordResp),\r
2605 MultiKeywordRespLen,\r
2606 *MultiKeywordResp\r
2607 );\r
87bfeb11
ED
2608 if (StringPtr == NULL) {\r
2609 return EFI_OUT_OF_RESOURCES;\r
2610 }\r
469293f8 2611\r
87bfeb11
ED
2612 *MultiKeywordResp = StringPtr;\r
2613\r
2d3e4cd1 2614 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");\r
87bfeb11 2615\r
2d3e4cd1 2616 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);\r
87bfeb11
ED
2617\r
2618 return EFI_SUCCESS;\r
2619}\r
2620\r
2621/**\r
d1102dba
LG
2622 Enumerate all keyword in the system.\r
2623\r
2624 If error occur when parse one keyword, just skip it and parse the next one.\r
87bfeb11
ED
2625\r
2626 This is a internal function.\r
2627\r
2628 @param NameSpace The namespace used to search the string.\r
2629 @param MultiResp Return the MultiKeywordResp string for the system.\r
6c20eda7 2630 @param ProgressErr Return the error status.\r
87bfeb11
ED
2631\r
2632 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2633 @retval EFI_SUCCESS Generate the MultiKeywordResp string.\r
2634 @retval EFI_NOT_FOUND No keyword found.\r
2635\r
2636**/\r
2637EFI_STATUS\r
2638EnumerateAllKeywords (\r
1436aea4
MK
2639 IN CHAR8 *NameSpace,\r
2640 OUT EFI_STRING *MultiResp,\r
2641 OUT UINT32 *ProgressErr\r
87bfeb11
ED
2642 )\r
2643{\r
2644 LIST_ENTRY *Link;\r
2645 LIST_ENTRY *StringLink;\r
2646 UINT8 *DevicePathPkg;\r
2647 UINT8 *DevicePath;\r
2648 HII_DATABASE_RECORD *DataBaseRecord;\r
87bfeb11
ED
2649 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2650 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
2651 CHAR8 *LocalNameSpace;\r
2652 EFI_STRING_ID NextStringId;\r
2653 EFI_STATUS Status;\r
c2400145 2654 UINT8 *OpCode;\r
87bfeb11
ED
2655 CHAR16 *ConfigRequest;\r
2656 CHAR16 *ValueElement;\r
2657 CHAR16 *KeywordResp;\r
2658 CHAR16 *MultiKeywordResp;\r
2659 CHAR16 *KeywordData;\r
2660 BOOLEAN ReadOnly;\r
6c20eda7 2661 BOOLEAN FindKeywordPackages;\r
87bfeb11 2662\r
1436aea4
MK
2663 DataBaseRecord = NULL;\r
2664 Status = EFI_SUCCESS;\r
2665 MultiKeywordResp = NULL;\r
2666 DevicePath = NULL;\r
2667 LocalNameSpace = NULL;\r
2668 ConfigRequest = NULL;\r
2669 ValueElement = NULL;\r
2670 KeywordResp = NULL;\r
6c20eda7 2671 FindKeywordPackages = FALSE;\r
87bfeb11
ED
2672\r
2673 if (NameSpace == NULL) {\r
2674 NameSpace = UEFI_CONFIG_LANG;\r
2675 }\r
2676\r
2677 //\r
2678 // Find driver which matches the routing data.\r
2679 //\r
2680 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
2681 DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2682 if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {\r
2683 DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
87bfeb11 2684 }\r
1436aea4 2685\r
87bfeb11
ED
2686 PackageListNode = DataBaseRecord->PackageList;\r
2687\r
2688 for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {\r
2689 StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
2690\r
2691 //\r
2692 // Check whether has keyword string package.\r
2693 //\r
1436aea4 2694 if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {\r
6c20eda7 2695 FindKeywordPackages = TRUE;\r
87bfeb11
ED
2696 //\r
2697 // Keep the NameSpace string.\r
2698 //\r
2699 LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
2700 if (LocalNameSpace == NULL) {\r
2701 return EFI_OUT_OF_RESOURCES;\r
2702 }\r
2703\r
2704 //\r
2705 // 1 means just begin the enumerate the valid string ids.\r
2706 // StringId == 1 is always used to save the language for this string package.\r
2707 // Any valid string start from 2. so here initial it to 1.\r
2708 //\r
2709 NextStringId = 1;\r
d1102dba 2710\r
87bfeb11
ED
2711 //\r
2712 // Enumerate all valid stringid in the package.\r
2713 //\r
2714 while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {\r
2715 //\r
2716 // 3.3 Construct the ConfigRequest string.\r
2717 //\r
2718 Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);\r
2719 if (EFI_ERROR (Status)) {\r
2720 //\r
2721 // If can't generate ConfigRequest for this question, skip it and start the next.\r
2722 //\r
2723 goto Error;\r
2724 }\r
d1102dba 2725\r
87bfeb11
ED
2726 //\r
2727 // 3.4 Extract Value for the input keyword.\r
2728 //\r
1436aea4 2729 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);\r
87bfeb11
ED
2730 if (EFI_ERROR (Status)) {\r
2731 if (Status != EFI_OUT_OF_RESOURCES) {\r
2732 //\r
2733 // If can't generate ConfigRequest for this question, skip it and start the next.\r
2734 //\r
2735 goto Error;\r
2736 }\r
1436aea4 2737\r
87bfeb11
ED
2738 //\r
2739 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
2740 //\r
2741 goto Done;\r
2742 }\r
2743\r
2744 //\r
2745 // Extract readonly flag from opcode.\r
2746 //\r
1436aea4 2747 ReadOnly = ExtractReadOnlyFromOpCode (OpCode);\r
87bfeb11
ED
2748\r
2749 //\r
2750 // 5. Generate KeywordResp string.\r
2751 //\r
2752 ASSERT (DevicePath != NULL);\r
1436aea4 2753 Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
87bfeb11
ED
2754 if (Status != EFI_SUCCESS) {\r
2755 //\r
2756 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
2757 //\r
2758 goto Done;\r
2759 }\r
d1102dba 2760\r
87bfeb11
ED
2761 //\r
2762 // 6. Merge to the MultiKeywordResp string.\r
2763 //\r
1436aea4 2764 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);\r
87bfeb11
ED
2765 if (EFI_ERROR (Status)) {\r
2766 goto Done;\r
2767 }\r
1436aea4 2768\r
87bfeb11
ED
2769Error:\r
2770 //\r
2771 // Clean the temp buffer to later use again.\r
2772 //\r
2773 if (ConfigRequest != NULL) {\r
2774 FreePool (ConfigRequest);\r
2775 ConfigRequest = NULL;\r
2776 }\r
1436aea4 2777\r
87bfeb11
ED
2778 if (ValueElement != NULL) {\r
2779 FreePool (ValueElement);\r
2780 ValueElement = NULL;\r
2781 }\r
1436aea4 2782\r
87bfeb11
ED
2783 if (KeywordResp != NULL) {\r
2784 FreePool (KeywordResp);\r
2785 KeywordResp = NULL;\r
d1102dba 2786 }\r
87bfeb11
ED
2787 }\r
2788\r
2789 if (LocalNameSpace != NULL) {\r
2790 FreePool (LocalNameSpace);\r
2791 LocalNameSpace = NULL;\r
2792 }\r
2793 }\r
d1102dba 2794 }\r
87bfeb11
ED
2795 }\r
2796\r
2797 //\r
4a429716 2798 // return the already get MultiKeywordString even error occurred.\r
87bfeb11
ED
2799 //\r
2800 if (MultiKeywordResp == NULL) {\r
2801 Status = EFI_NOT_FOUND;\r
6c20eda7
ED
2802 if (!FindKeywordPackages) {\r
2803 *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
2804 } else {\r
2805 *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
2806 }\r
87bfeb11
ED
2807 } else {\r
2808 Status = EFI_SUCCESS;\r
2809 }\r
1436aea4 2810\r
87bfeb11 2811 *MultiResp = MultiKeywordResp;\r
d1102dba 2812\r
87bfeb11
ED
2813Done:\r
2814 if (LocalNameSpace != NULL) {\r
2815 FreePool (LocalNameSpace);\r
2816 }\r
1436aea4 2817\r
87bfeb11
ED
2818 if (ConfigRequest != NULL) {\r
2819 FreePool (ConfigRequest);\r
2820 }\r
1436aea4 2821\r
87bfeb11
ED
2822 if (ValueElement != NULL) {\r
2823 FreePool (ValueElement);\r
2824 }\r
2825\r
2826 return Status;\r
2827}\r
2828\r
2829/**\r
2830\r
2831 This function accepts a <MultiKeywordResp> formatted string, finds the associated\r
2832 keyword owners, creates a <MultiConfigResp> string from it and forwards it to the\r
2833 EFI_HII_ROUTING_PROTOCOL.RouteConfig function.\r
d1102dba
LG
2834\r
2835 If there is an issue in resolving the contents of the KeywordString, then the\r
2836 function returns an error and also sets the Progress and ProgressErr with the\r
87bfeb11 2837 appropriate information about where the issue occurred and additional data about\r
d1102dba
LG
2838 the nature of the issue.\r
2839\r
87bfeb11
ED
2840 In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND\r
2841 error is generated during processing the second or later keyword element, the system\r
d1102dba 2842 storage associated with earlier keywords is not modified. All elements of the\r
87bfeb11
ED
2843 KeywordString must successfully pass all tests for format and access prior to making\r
2844 any modifications to storage.\r
d1102dba 2845\r
87bfeb11
ED
2846 In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString\r
2847 containing multiple keywords, the state of storage associated with earlier keywords\r
2848 is undefined.\r
2849\r
2850\r
2851 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
2852\r
d1102dba 2853 @param KeywordString A null-terminated string in <MultiKeywordResp> format.\r
87bfeb11 2854\r
d1102dba
LG
2855 @param Progress On return, points to a character in the KeywordString.\r
2856 Points to the string's NULL terminator if the request\r
2857 was successful. Points to the most recent '&' before\r
91af324d
DB
2858 the first failing name / value pair (or the beginning\r
2859 of the string if the failure is in the first name / value\r
2860 pair) if the request was not successful.\r
87bfeb11
ED
2861\r
2862 @param ProgressErr If during the processing of the KeywordString there was\r
d1102dba
LG
2863 a failure, this parameter gives additional information\r
2864 about the possible source of the problem. The various\r
87bfeb11
ED
2865 errors are defined in "Related Definitions" below.\r
2866\r
2867\r
2868 @retval EFI_SUCCESS The specified action was completed successfully.\r
2869\r
2870 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
2871 1. KeywordString is NULL.\r
d1102dba 2872 2. Parsing of the KeywordString resulted in an\r
87bfeb11
ED
2873 error. See Progress and ProgressErr for more data.\r
2874\r
d1102dba 2875 @retval EFI_NOT_FOUND An element of the KeywordString was not found.\r
87bfeb11
ED
2876 See ProgressErr for more data.\r
2877\r
d1102dba 2878 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
87bfeb11 2879 See ProgressErr for more data.\r
d1102dba
LG
2880\r
2881 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr\r
87bfeb11
ED
2882 for more data.\r
2883\r
2884 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr\r
2885 for more data.\r
2886\r
2887**/\r
2888EFI_STATUS\r
d1102dba 2889EFIAPI\r
87bfeb11 2890EfiConfigKeywordHandlerSetData (\r
1436aea4
MK
2891 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
2892 IN CONST EFI_STRING KeywordString,\r
2893 OUT EFI_STRING *Progress,\r
2894 OUT UINT32 *ProgressErr\r
87bfeb11
ED
2895 )\r
2896{\r
1436aea4
MK
2897 CHAR8 *NameSpace;\r
2898 EFI_STATUS Status;\r
2899 CHAR16 *StringPtr;\r
2900 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2901 CHAR16 *NextStringPtr;\r
2902 CHAR16 *KeywordData;\r
2903 EFI_STRING_ID KeywordStringId;\r
2904 UINT32 RetVal;\r
2905 HII_DATABASE_RECORD *DataBaseRecord;\r
2906 UINT8 *OpCode;\r
2907 CHAR16 *ConfigResp;\r
2908 CHAR16 *MultiConfigResp;\r
2909 CHAR16 *ValueElement;\r
2910 BOOLEAN ReadOnly;\r
2911 EFI_STRING InternalProgress;\r
2912 CHAR16 *TempString;\r
2913 CHAR16 *KeywordStartPos;\r
2914\r
2915 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {\r
87bfeb11
ED
2916 return EFI_INVALID_PARAMETER;\r
2917 }\r
2918\r
1436aea4
MK
2919 *Progress = KeywordString;\r
2920 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
2921 Status = EFI_SUCCESS;\r
87bfeb11
ED
2922 MultiConfigResp = NULL;\r
2923 NameSpace = NULL;\r
2924 DevicePath = NULL;\r
2925 KeywordData = NULL;\r
2926 ValueElement = NULL;\r
2927 ConfigResp = NULL;\r
580d230d 2928 KeywordStartPos = NULL;\r
87bfeb11
ED
2929 KeywordStringId = 0;\r
2930\r
9946c0a9
ED
2931 //\r
2932 // Use temp string to avoid changing input string buffer.\r
2933 //\r
2934 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);\r
2935 ASSERT (TempString != NULL);\r
2936 StringPtr = TempString;\r
2937\r
87bfeb11
ED
2938 while ((StringPtr != NULL) && (*StringPtr != L'\0')) {\r
2939 //\r
2940 // 1. Get NameSpace from NameSpaceId keyword.\r
2941 //\r
2942 Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);\r
2943 if (EFI_ERROR (Status)) {\r
2944 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
e74c4279 2945 goto Done;\r
87bfeb11 2946 }\r
1436aea4 2947\r
22950757 2948 ASSERT (NameSpace != NULL);\r
e74c4279
ED
2949 //\r
2950 // 1.1 Check whether the input namespace is valid.\r
2951 //\r
1436aea4 2952 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {\r
6c20eda7 2953 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
1436aea4 2954 Status = EFI_INVALID_PARAMETER;\r
e74c4279
ED
2955 goto Done;\r
2956 }\r
2957\r
87bfeb11
ED
2958 StringPtr = NextStringPtr;\r
2959\r
2960 //\r
2961 // 2. Get possible Device Path info from KeywordString.\r
2962 //\r
2963 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
2964 if (EFI_ERROR (Status)) {\r
2965 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2966 goto Done;\r
2967 }\r
1436aea4 2968\r
87bfeb11
ED
2969 StringPtr = NextStringPtr;\r
2970\r
2971 //\r
2972 // 3. Extract keyword from the KeywordRequest string.\r
2973 //\r
580d230d 2974 KeywordStartPos = StringPtr;\r
1436aea4 2975 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);\r
87bfeb11
ED
2976 if (EFI_ERROR (Status)) {\r
2977 //\r
2978 // Can't find Keyword base on the input device path info.\r
2979 //\r
2980 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
1436aea4 2981 Status = EFI_INVALID_PARAMETER;\r
87bfeb11
ED
2982 goto Done;\r
2983 }\r
1436aea4 2984\r
87bfeb11
ED
2985 StringPtr = NextStringPtr;\r
2986\r
2987 //\r
2988 // 4. Extract Value from the KeywordRequest string.\r
2989 //\r
2990 Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);\r
2991 if (EFI_ERROR (Status)) {\r
2992 //\r
2993 // Can't find Value base on the input device path info.\r
2994 //\r
2995 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
1436aea4 2996 Status = EFI_INVALID_PARAMETER;\r
87bfeb11
ED
2997 goto Done;\r
2998 }\r
1436aea4 2999\r
87bfeb11
ED
3000 StringPtr = NextStringPtr;\r
3001\r
3002 //\r
5654835b 3003 // 5. Find READONLY tag.\r
87bfeb11 3004 //\r
1436aea4
MK
3005 if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0)) {\r
3006 ReadOnly = TRUE;\r
5654835b 3007 StringPtr += StrLen (L"&READONLY");\r
87bfeb11
ED
3008 } else {\r
3009 ReadOnly = FALSE;\r
3010 }\r
3011\r
3012 //\r
3013 // 6. Get EFI_STRING_ID for the input keyword.\r
3014 //\r
3015 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
3016 if (EFI_ERROR (Status)) {\r
3017 *ProgressErr = RetVal;\r
3018 goto Done;\r
3019 }\r
3020\r
3021 //\r
3022 // 7. Construct the ConfigRequest string.\r
3023 //\r
3024 Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);\r
3025 if (EFI_ERROR (Status)) {\r
3026 goto Done;\r
3027 }\r
3028\r
3029 //\r
3030 // 8. Check the readonly flag.\r
3031 //\r
3032 if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {\r
5654835b
DB
3033 //\r
3034 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.\r
3035 // If not, the input KeywordString must be incorrect, return the error status to caller.\r
3036 //\r
3037 *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
1436aea4 3038 Status = EFI_INVALID_PARAMETER;\r
5654835b
DB
3039 goto Done;\r
3040 }\r
1436aea4 3041\r
5654835b 3042 if (ReadOnly) {\r
580d230d 3043 *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;\r
1436aea4 3044 Status = EFI_ACCESS_DENIED;\r
5654835b 3045 goto Done;\r
87bfeb11 3046 }\r
d1102dba 3047\r
87bfeb11
ED
3048 //\r
3049 // 9. Merge to the MultiKeywordResp string.\r
3050 //\r
1436aea4 3051 Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);\r
87bfeb11
ED
3052 if (EFI_ERROR (Status)) {\r
3053 goto Done;\r
3054 }\r
3055\r
3056 //\r
3057 // 10. Clean the temp buffer point.\r
3058 //\r
3059 FreePool (NameSpace);\r
3060 FreePool (DevicePath);\r
3061 FreePool (KeywordData);\r
3062 FreePool (ValueElement);\r
1436aea4
MK
3063 NameSpace = NULL;\r
3064 DevicePath = NULL;\r
3065 KeywordData = NULL;\r
87bfeb11
ED
3066 ValueElement = NULL;\r
3067 if (ConfigResp != NULL) {\r
3068 FreePool (ConfigResp);\r
3069 ConfigResp = NULL;\r
3070 }\r
1436aea4 3071\r
580d230d 3072 KeywordStartPos = NULL;\r
87bfeb11
ED
3073 }\r
3074\r
3075 //\r
3076 // 11. Set value to driver.\r
3077 //\r
1436aea4
MK
3078 Status = mPrivate.ConfigRouting.RouteConfig (\r
3079 &mPrivate.ConfigRouting,\r
3080 (EFI_STRING)MultiConfigResp,\r
3081 &InternalProgress\r
3082 );\r
87bfeb11
ED
3083 if (EFI_ERROR (Status)) {\r
3084 Status = EFI_DEVICE_ERROR;\r
3085 goto Done;\r
3086 }\r
d1102dba 3087\r
87bfeb11
ED
3088 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
3089\r
3090Done:\r
580d230d
ED
3091 if (KeywordStartPos != NULL) {\r
3092 *Progress = KeywordString + (KeywordStartPos - TempString);\r
3093 } else {\r
3094 *Progress = KeywordString + (StringPtr - TempString);\r
3095 }\r
3f4288fe 3096\r
9946c0a9
ED
3097 ASSERT (TempString != NULL);\r
3098 FreePool (TempString);\r
87bfeb11
ED
3099 if (NameSpace != NULL) {\r
3100 FreePool (NameSpace);\r
3101 }\r
1436aea4 3102\r
87bfeb11
ED
3103 if (DevicePath != NULL) {\r
3104 FreePool (DevicePath);\r
3105 }\r
1436aea4 3106\r
87bfeb11
ED
3107 if (KeywordData != NULL) {\r
3108 FreePool (KeywordData);\r
3109 }\r
1436aea4 3110\r
87bfeb11
ED
3111 if (ValueElement != NULL) {\r
3112 FreePool (ValueElement);\r
3113 }\r
1436aea4 3114\r
87bfeb11
ED
3115 if (ConfigResp != NULL) {\r
3116 FreePool (ConfigResp);\r
3117 }\r
1436aea4
MK
3118\r
3119 if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {\r
87bfeb11 3120 FreePool (MultiConfigResp);\r
3f4288fe 3121 }\r
580d230d 3122\r
87bfeb11
ED
3123 return Status;\r
3124}\r
3125\r
3126/**\r
3127\r
d1102dba 3128 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying\r
87bfeb11
ED
3129 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the\r
3130 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.\r
d1102dba 3131\r
87bfeb11
ED
3132 If there is an issue in resolving the contents of the KeywordString, then the function\r
3133 returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the\r
3134 appropriate information about where the issue occurred and additional data about the\r
3135 nature of the issue.\r
d1102dba 3136\r
87bfeb11
ED
3137 In the case when KeywordString is NULL, or contains multiple keywords, or when\r
3138 EFI_NOT_FOUND is generated while processing the keyword elements, the Results string\r
d1102dba 3139 contains values returned for all keywords processed prior to the keyword generating the\r
87bfeb11
ED
3140 error but no values for the keyword with error or any following keywords.\r
3141\r
d1102dba 3142\r
87bfeb11 3143 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
d1102dba 3144\r
87bfeb11
ED
3145 @param NameSpaceId A null-terminated string containing the platform configuration\r
3146 language to search through in the system. If a NULL is passed\r
3147 in, then it is assumed that any platform configuration language\r
3148 with the prefix of "x-UEFI-" are searched.\r
d1102dba 3149\r
87bfeb11 3150 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a\r
d1102dba
LG
3151 NULL is passed in the KeywordString field, all of the known\r
3152 keywords in the system for the NameSpaceId specified are\r
87bfeb11 3153 returned in the Results field.\r
d1102dba 3154\r
87bfeb11 3155 @param Progress On return, points to a character in the KeywordString. Points\r
d1102dba 3156 to the string's NULL terminator if the request was successful.\r
91af324d
DB
3157 Points to the most recent '&' before the first failing name / value\r
3158 pair (or the beginning of the string if the failure is in the first\r
3159 name / value pair) if the request was not successful.\r
d1102dba 3160\r
87bfeb11 3161 @param ProgressErr If during the processing of the KeywordString there was a\r
d1102dba 3162 failure, this parameter gives additional information about the\r
87bfeb11
ED
3163 possible source of the problem. See the definitions in SetData()\r
3164 for valid value definitions.\r
d1102dba 3165\r
87bfeb11 3166 @param Results A null-terminated string in <MultiKeywordResp> format is returned\r
d1102dba 3167 which has all the values filled in for the keywords in the\r
87bfeb11 3168 KeywordString. This is a callee-allocated field, and must be freed\r
d1102dba 3169 by the caller after being used.\r
87bfeb11
ED
3170\r
3171 @retval EFI_SUCCESS The specified action was completed successfully.\r
d1102dba 3172\r
87bfeb11 3173 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
4a429716 3174 1.Progress, ProgressErr, or Results is NULL.\r
87bfeb11
ED
3175 2.Parsing of the KeywordString resulted in an error. See\r
3176 Progress and ProgressErr for more data.\r
d1102dba 3177\r
87bfeb11
ED
3178\r
3179 @retval EFI_NOT_FOUND An element of the KeywordString was not found. See\r
3180 ProgressErr for more data.\r
3181\r
3182 @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr\r
3183 for more data.\r
3184\r
3185 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See\r
3186 ProgressErr for more data.\r
d1102dba 3187\r
87bfeb11
ED
3188 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for\r
3189 more data.\r
3190\r
3191 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr\r
3192 for more data.\r
3193\r
3194**/\r
3195EFI_STATUS\r
d1102dba 3196EFIAPI\r
87bfeb11
ED
3197EfiConfigKeywordHandlerGetData (\r
3198 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
e3917e22
MK
3199 IN CONST EFI_STRING NameSpaceId OPTIONAL,\r
3200 IN CONST EFI_STRING KeywordString OPTIONAL,\r
d1102dba 3201 OUT EFI_STRING *Progress,\r
87bfeb11
ED
3202 OUT UINT32 *ProgressErr,\r
3203 OUT EFI_STRING *Results\r
3204 )\r
3205{\r
1436aea4
MK
3206 CHAR8 *NameSpace;\r
3207 EFI_STATUS Status;\r
3208 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3209 HII_DATABASE_RECORD *DataBaseRecord;\r
3210 CHAR16 *StringPtr;\r
3211 CHAR16 *NextStringPtr;\r
3212 CHAR16 *KeywordData;\r
3213 EFI_STRING_ID KeywordStringId;\r
3214 UINT8 *OpCode;\r
3215 CHAR16 *ConfigRequest;\r
3216 CHAR16 *ValueElement;\r
3217 UINT32 RetVal;\r
3218 BOOLEAN ReadOnly;\r
3219 CHAR16 *KeywordResp;\r
3220 CHAR16 *MultiKeywordResp;\r
3221 CHAR16 *TempString;\r
87bfeb11 3222\r
1436aea4 3223 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {\r
87bfeb11
ED
3224 return EFI_INVALID_PARAMETER;\r
3225 }\r
3226\r
1436aea4
MK
3227 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
3228 Status = EFI_SUCCESS;\r
3229 DevicePath = NULL;\r
3230 NameSpace = NULL;\r
3231 KeywordData = NULL;\r
3232 ConfigRequest = NULL;\r
3233 StringPtr = KeywordString;\r
3234 ReadOnly = FALSE;\r
87bfeb11
ED
3235 MultiKeywordResp = NULL;\r
3236 KeywordStringId = 0;\r
1436aea4 3237 TempString = NULL;\r
87bfeb11 3238\r
9946c0a9
ED
3239 //\r
3240 // Use temp string to avoid changing input string buffer.\r
3241 //\r
3242 if (NameSpaceId != NULL) {\r
3243 TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);\r
3244 ASSERT (TempString != NULL);\r
3245 }\r
1436aea4 3246\r
87bfeb11
ED
3247 //\r
3248 // 1. Get NameSpace from NameSpaceId keyword.\r
3249 //\r
9946c0a9
ED
3250 Status = ExtractNameSpace (TempString, &NameSpace, NULL);\r
3251 if (TempString != NULL) {\r
3252 FreePool (TempString);\r
3253 TempString = NULL;\r
3254 }\r
1436aea4 3255\r
87bfeb11 3256 if (EFI_ERROR (Status)) {\r
6c20eda7 3257 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
87bfeb11
ED
3258 return Status;\r
3259 }\r
1436aea4 3260\r
e74c4279
ED
3261 //\r
3262 // 1.1 Check whether the input namespace is valid.\r
3263 //\r
1436aea4
MK
3264 if (NameSpace != NULL) {\r
3265 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {\r
6c20eda7 3266 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
22950757
DB
3267 return EFI_INVALID_PARAMETER;\r
3268 }\r
e74c4279 3269 }\r
d1102dba 3270\r
87bfeb11 3271 if (KeywordString != NULL) {\r
9946c0a9
ED
3272 //\r
3273 // Use temp string to avoid changing input string buffer.\r
3274 //\r
3275 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);\r
3276 ASSERT (TempString != NULL);\r
3277 StringPtr = TempString;\r
87bfeb11
ED
3278\r
3279 while (*StringPtr != L'\0') {\r
3280 //\r
3281 // 2. Get possible Device Path info from KeywordString.\r
3282 //\r
3283 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
3284 if (EFI_ERROR (Status)) {\r
3285 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
3286 goto Done;\r
3287 }\r
87bfeb11 3288\r
1436aea4 3289 StringPtr = NextStringPtr;\r
d1102dba 3290\r
87bfeb11
ED
3291 //\r
3292 // 3. Process Keyword section from the input keywordRequest string.\r
3293 //\r
3294 // 3.1 Extract keyword from the KeywordRequest string.\r
3295 //\r
1436aea4 3296 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);\r
87bfeb11
ED
3297 if (EFI_ERROR (Status)) {\r
3298 //\r
3299 // Can't find Keyword base on the input device path info.\r
3300 //\r
3301 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
1436aea4 3302 Status = EFI_INVALID_PARAMETER;\r
87bfeb11
ED
3303 goto Done;\r
3304 }\r
3305\r
3306 //\r
3307 // 3.2 Get EFI_STRING_ID for the input keyword.\r
3308 //\r
3309 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
3310 if (EFI_ERROR (Status)) {\r
3311 *ProgressErr = RetVal;\r
3312 goto Done;\r
3313 }\r
3314\r
3315 //\r
3316 // 3.3 Construct the ConfigRequest string.\r
3317 //\r
3318 Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);\r
3319 if (EFI_ERROR (Status)) {\r
3320 goto Done;\r
3321 }\r
d1102dba 3322\r
87bfeb11
ED
3323 //\r
3324 // 3.4 Extract Value for the input keyword.\r
3325 //\r
1436aea4 3326 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);\r
87bfeb11
ED
3327 if (EFI_ERROR (Status)) {\r
3328 if (Status != EFI_OUT_OF_RESOURCES) {\r
3329 Status = EFI_DEVICE_ERROR;\r
3330 }\r
1436aea4 3331\r
87bfeb11
ED
3332 goto Done;\r
3333 }\r
1436aea4 3334\r
87bfeb11
ED
3335 StringPtr = NextStringPtr;\r
3336\r
3337 //\r
3338 // 4. Process the possible filter section.\r
3339 //\r
3340 RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);\r
3341 if (RetVal != KEYWORD_HANDLER_NO_ERROR) {\r
3342 *ProgressErr = RetVal;\r
1436aea4 3343 Status = EFI_INVALID_PARAMETER;\r
87bfeb11
ED
3344 goto Done;\r
3345 }\r
87bfeb11 3346\r
1436aea4 3347 StringPtr = NextStringPtr;\r
87bfeb11
ED
3348\r
3349 //\r
3350 // 5. Generate KeywordResp string.\r
3351 //\r
1436aea4 3352 Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
87bfeb11
ED
3353 if (Status != EFI_SUCCESS) {\r
3354 goto Done;\r
3355 }\r
3356\r
3357 //\r
3358 // 6. Merge to the MultiKeywordResp string.\r
3359 //\r
1436aea4 3360 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);\r
87bfeb11
ED
3361 if (EFI_ERROR (Status)) {\r
3362 goto Done;\r
3363 }\r
3364\r
3365 //\r
3366 // 7. Update return value.\r
3367 //\r
3368 *Results = MultiKeywordResp;\r
3369\r
3370 //\r
3371 // 8. Clean the temp buffer.\r
3372 //\r
3373 FreePool (DevicePath);\r
3374 FreePool (KeywordData);\r
3375 FreePool (ValueElement);\r
3376 FreePool (ConfigRequest);\r
1436aea4
MK
3377 DevicePath = NULL;\r
3378 KeywordData = NULL;\r
3379 ValueElement = NULL;\r
87bfeb11
ED
3380 ConfigRequest = NULL;\r
3381 if (KeywordResp != NULL) {\r
3382 FreePool (KeywordResp);\r
3383 KeywordResp = NULL;\r
3384 }\r
3385 }\r
3386 } else {\r
3387 //\r
3388 // Enumerate all keyword in the system.\r
3389 //\r
1436aea4 3390 Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);\r
87bfeb11
ED
3391 if (EFI_ERROR (Status)) {\r
3392 goto Done;\r
3393 }\r
1436aea4 3394\r
87bfeb11
ED
3395 *Results = MultiKeywordResp;\r
3396 }\r
3397\r
3398 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
3399\r
3400Done:\r
3f4288fe
ED
3401 *Progress = KeywordString + (StringPtr - TempString);\r
3402\r
9946c0a9
ED
3403 if (TempString != NULL) {\r
3404 FreePool (TempString);\r
3405 }\r
1436aea4 3406\r
87bfeb11
ED
3407 if (NameSpace != NULL) {\r
3408 FreePool (NameSpace);\r
3409 }\r
1436aea4 3410\r
87bfeb11
ED
3411 if (DevicePath != NULL) {\r
3412 FreePool (DevicePath);\r
3413 }\r
1436aea4 3414\r
87bfeb11
ED
3415 if (KeywordData != NULL) {\r
3416 FreePool (KeywordData);\r
3417 }\r
3f4288fe 3418\r
87bfeb11
ED
3419 return Status;\r
3420}\r