]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / HiiDataBase / Dxe / Strings.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Strings.c\r
15\r
16Abstract:\r
17\r
18 This file contains the string processing code to the HII database.\r
19\r
20--*/\r
21\r
22\r
23#include "HiiDatabase.h"\r
24\r
1cc8ee78 25STATIC\r
878ddf1f 26VOID\r
27AsciiToUnicode (\r
28 IN UINT8 *Lang,\r
29 IN UINT16 *Language\r
30 )\r
31{\r
32 UINT8 Count;\r
33\r
34 //\r
35 // Convert the ASCII Lang variable to a Unicode Language variable\r
36 //\r
37 for (Count = 0; Count < 3; Count++) {\r
38 Language[Count] = (CHAR16) Lang[Count];\r
39 }\r
40}\r
41\r
42EFI_STATUS\r
43EFIAPI\r
44HiiTestString (\r
45 IN EFI_HII_PROTOCOL *This,\r
46 IN CHAR16 *StringToTest,\r
47 IN OUT UINT32 *FirstMissing,\r
48 OUT UINT32 *GlyphBufferSize\r
49 )\r
50/*++\r
51\r
52Routine Description:\r
53 Test if all of the characters in a string have corresponding font characters.\r
54 \r
55Arguments:\r
56\r
57Returns: \r
58\r
59--*/\r
60{\r
61 EFI_HII_GLOBAL_DATA *GlobalData;\r
62 EFI_HII_DATA *HiiData;\r
63 UINTN Count;\r
64 BOOLEAN Narrow;\r
65 UINTN Location;\r
66 UINT8 GlyphCol1[19];\r
67\r
68 if (This == NULL) {\r
69 return EFI_INVALID_PARAMETER;\r
70 }\r
71\r
72 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
73\r
74 GlobalData = HiiData->GlobalData;\r
75 Count = 0;\r
76 Narrow = TRUE;\r
77\r
78 ZeroMem (GlyphCol1, sizeof (GlyphCol1));\r
79\r
80 //\r
81 // Walk through the string until you hit the null terminator\r
82 //\r
83 for (; StringToTest[*FirstMissing] != 0x00; (*FirstMissing)++) {\r
84 Location = *FirstMissing;\r
85 //\r
86 // Rewind through the string looking for a glyph width identifier\r
87 //\r
88 for (; Location != 0; Location--) {\r
89 if (StringToTest[Location] == NARROW_CHAR || StringToTest[Location] == WIDE_CHAR) {\r
90 //\r
91 // We found something that identifies what glyph database to look in\r
92 //\r
93 if (StringToTest[Location] == WIDE_CHAR) {\r
94 Narrow = FALSE;\r
95 } else {\r
96 Narrow = TRUE;\r
97 }\r
98 }\r
99 }\r
100\r
101 if (Narrow) {\r
102 if (CompareMem (\r
103 GlobalData->NarrowGlyphs[StringToTest[*FirstMissing]].GlyphCol1,\r
104 &mUnknownGlyph,\r
105 NARROW_GLYPH_ARRAY_SIZE\r
106 ) == 0\r
107 ) {\r
108 //\r
109 // Break since this glyph isn't defined\r
110 //\r
111 return EFI_NOT_FOUND;\r
112 }\r
113 } else {\r
114 //\r
115 // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size\r
116 //\r
117 if (CompareMem (\r
118 GlobalData->WideGlyphs[StringToTest[*FirstMissing]].GlyphCol1,\r
119 &mUnknownGlyph,\r
120 WIDE_GLYPH_ARRAY_SIZE\r
121 ) == 0\r
122 ) {\r
123 //\r
124 // Break since this glyph isn't defined\r
125 //\r
126 return EFI_NOT_FOUND;\r
127 }\r
128 }\r
129\r
130 Count++;\r
131 }\r
132\r
133 if (Narrow) {\r
134 *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_NARROW_GLYPH));\r
135 } else {\r
136 *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_WIDE_GLYPH));\r
137 }\r
138\r
139 return EFI_SUCCESS;\r
140}\r
141\r
1cc8ee78 142STATIC\r
878ddf1f 143EFI_STATUS\r
144HiiNewString2 (\r
145 IN EFI_HII_PROTOCOL *This,\r
146 IN CHAR16 *Language,\r
147 IN EFI_HII_HANDLE Handle,\r
148 IN OUT STRING_REF *Reference,\r
149 IN CHAR16 *NewString,\r
150 IN BOOLEAN ResetStrings\r
151 )\r
152/*++\r
153\r
154Routine Description:\r
155\r
156 This function allows a new String to be added to an already existing String Package.\r
157 We will make a buffer the size of the package + EfiStrSize of the new string. We will\r
158 copy the string package that first gets changed and the following language packages until\r
159 we encounter the NULL string package. All this time we will ensure that the offsets have\r
160 been adjusted. \r
161\r
162Arguments:\r
163 \r
164 This - Pointer to the HII protocol.\r
165 Language - Pointer to buffer which contains the language code of this NewString.\r
166 Handle - Handle of the package instance to be processed.\r
167 Reference - The token number for the string. If 0, new string token to be returned through this parameter.\r
168 NewString - Buffer pointer for the new string. \r
169 ResetStrings - Indicate if we are resetting a string.\r
170 \r
171Returns: \r
172\r
173 EFI_SUCCESS - The string has been added or reset to Hii database.\r
174 EFI_INVALID_PARAMETER - Some parameter passed in is invalid.\r
175\r
176--*/\r
177{\r
178 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
179 EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;\r
180 EFI_HII_DATA *HiiData;\r
181 EFI_HII_STRING_PACK *StringPack;\r
182 EFI_HII_STRING_PACK *NewStringPack;\r
183 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
184 EFI_HII_PACKAGE_INSTANCE *NewBuffer;\r
185 UINT8 *Location;\r
186 UINT8 *StringLocation;\r
187 RELOFST *StringPointer;\r
188 UINTN Count;\r
189 UINTN Size;\r
190 UINTN Index;\r
191 UINTN SecondIndex;\r
192 BOOLEAN AddString;\r
193 EFI_STATUS Status;\r
194 UINTN Increment;\r
195 UINTN StringCount;\r
196 UINT32 TotalStringCount;\r
197 UINT32 OriginalStringCount;\r
198 RELOFST StringSize;\r
199 UINT32 Length;\r
200 RELOFST Offset;\r
201\r
202 if (This == NULL) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
205\r
206 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
207\r
208 HandleDatabase = HiiData->DatabaseHead;\r
209 PackageInstance = NULL;\r
210 AddString = FALSE;\r
211 Increment = 0;\r
212 StringCount = 0;\r
213 TotalStringCount = 0;\r
214 OriginalStringCount = 0;\r
215\r
216 //\r
217 // Check numeric value against the head of the database\r
218 //\r
219 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
220 //\r
221 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
222 //\r
223 if (Handle == HandleDatabase->Handle) {\r
224 PackageInstance = HandleDatabase->Buffer;\r
225 if (ResetStrings) {\r
226 TotalStringCount = HandleDatabase->NumberOfTokens;\r
227 }\r
228 break;\r
229 }\r
230 }\r
231 //\r
232 // No handle was found - error condition\r
233 //\r
234 if (PackageInstance == NULL) {\r
235 return EFI_INVALID_PARAMETER;\r
236 }\r
237\r
238 Status = ValidatePack (This, PackageInstance, &StringPackageInstance, &TotalStringCount);\r
239\r
240 //\r
241 // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value\r
242 //\r
243 Count = StringPackageInstance->IfrSize;\r
244\r
245 //\r
246 // This is the size of the complete series of string packs\r
247 //\r
248 Size = StringPackageInstance->StringSize;\r
249\r
250 //\r
251 // Based on if there is IFR data in this package instance, determine\r
252 // what the location is of the beginning of the string data.\r
253 //\r
254 if (StringPackageInstance->IfrSize > 0) {\r
255 Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;\r
256 } else {\r
257 Location = (UINT8 *) (&StringPackageInstance->IfrData);\r
258 }\r
259 //\r
260 // We allocate a buffer which is big enough for both adding and resetting string.\r
261 // The size is slightly larger than the real size of the packages when we are resetting a string.\r
262 //\r
263 NewBuffer = AllocateZeroPool (\r
264 sizeof (EFI_HII_PACKAGE_INSTANCE) -\r
265 2 * sizeof (VOID *) +\r
266 StringPackageInstance->IfrSize +\r
267 StringPackageInstance->StringSize +\r
268 sizeof (RELOFST) +\r
269 StrSize (NewString)\r
270 );\r
271 ASSERT (NewBuffer);\r
272\r
273 //\r
274 // Copy data to new buffer\r
275 //\r
276 NewBuffer->Handle = StringPackageInstance->Handle;\r
277 NewBuffer->IfrSize = StringPackageInstance->IfrSize;\r
278\r
279 //\r
280 // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string\r
281 // package to begin with.\r
282 //\r
283 NewBuffer->StringSize = StringPackageInstance->StringSize + StrSize (NewString) + sizeof (EFI_HII_STRING_PACK);\r
284\r
285 if (StringPackageInstance->IfrSize > 0) {\r
286 CopyMem (&NewBuffer->IfrData, &StringPackageInstance->IfrData, StringPackageInstance->IfrSize);\r
287 }\r
288\r
289 StringPack = (EFI_HII_STRING_PACK *) Location;\r
290\r
291 //\r
292 // There may be multiple instances packed together of strings\r
293 // so we must walk the self describing structures until we encounter\r
294 // what we are looking for. In the meantime, copy everything we encounter\r
295 // to the new buffer.\r
296 //\r
297 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
298 for (; Length != 0;) {\r
299 //\r
300 // If passed in Language ISO value is in this string pack's language string\r
301 // then we are dealing with the strings we want.\r
302 //\r
303 CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST));\r
304 Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language);\r
305\r
306 if (!EFI_ERROR (Status)) {\r
307 break;\r
308 }\r
309\r
310 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);\r
311\r
312 Count = Count + Length;\r
313 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
314 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
315 }\r
316 //\r
317 // Found the language pack to update on a particular handle\r
318 // We need to Copy the Contents of this pack and adjust the offset values associated\r
319 // with adding/changing a string. This is a particular piece of code that screams for\r
320 // it being prone to programming error.\r
321 //\r
322 //\r
323 // Copy the string package up to the string data\r
324 //\r
325 StringPointer = (RELOFST *) (StringPack + 1);\r
326 CopyMem (\r
327 ((CHAR8 *) (&NewBuffer->IfrData) + Count),\r
328 StringPack,\r
329 (UINTN) ((UINTN) (StringPointer) - (UINTN) (StringPack))\r
330 );\r
331\r
332 //\r
333 // Determine the number of StringPointers\r
334 //\r
335 if (!ResetStrings) {\r
336 CopyMem (&TotalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));\r
337 } else {\r
338 //\r
339 // If we are resetting the strings, use the original value when exported\r
340 //\r
341 CopyMem (&OriginalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));\r
342 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString -=\r
343 (\r
344 (RELOFST) (OriginalStringCount - TotalStringCount) *\r
345 sizeof (RELOFST)\r
346 );\r
347 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName -=\r
348 (\r
349 (RELOFST) (OriginalStringCount - TotalStringCount) *\r
350 sizeof (RELOFST)\r
351 );\r
352 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers = TotalStringCount;\r
353 *Reference = (STRING_REF) (TotalStringCount);\r
354 }\r
355 //\r
356 // If the token value is not valid, error out\r
357 //\r
358 if ((*Reference >= TotalStringCount) && !ResetStrings) {\r
359 gBS->FreePool (NewBuffer);\r
360 return EFI_INVALID_PARAMETER;\r
361 }\r
362 //\r
363 // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on\r
364 //\r
365 if (*Reference == 0) {\r
366 *Reference = (STRING_REF) (TotalStringCount);\r
367 AddString = TRUE;\r
368 }\r
369\r
370 if (AddString) {\r
371 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString += sizeof (RELOFST);\r
372 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName += sizeof (RELOFST);\r
373 ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers++;\r
374 }\r
375 //\r
376 // Increment offset by amount of copied data\r
377 //\r
378 Count = Count + ((UINTN) (StringPointer) - (UINTN) StringPack);\r
379\r
380 for (Index = 0; Index < TotalStringCount; Index++) {\r
381 //\r
382 // If we are pointing to the size of the changing string value\r
383 // then cache the old string value so you know what the difference is\r
384 //\r
385 if (Index == *Reference) {\r
386 CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));\r
387\r
388 StringLocation = ((UINT8 *) (StringPack) + Offset);\r
389 for (SecondIndex = 0;\r
390 (StringLocation[SecondIndex] != 0) || (StringLocation[SecondIndex + 1] != 0);\r
391 SecondIndex = SecondIndex + 2\r
392 )\r
393 ;\r
394 SecondIndex = SecondIndex + 2;\r
395\r
396 Size = SecondIndex;\r
397\r
398 //\r
399 // NewString is a passed in local string which is assumed to be aligned\r
400 //\r
401 Size = StrSize (NewString) - Size;\r
402 }\r
403 //\r
404 // If we are about to copy the offset of the string that follows the changed string make\r
405 // sure that the offsets are adjusted accordingly\r
406 //\r
407 if ((Index > *Reference) && !ResetStrings) {\r
408 CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));\r
409 Offset = (RELOFST) (Offset + Size);\r
410 CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));\r
411 }\r
412 //\r
413 // If we are adding a string that means we will have an extra string pointer that will affect all string offsets\r
414 //\r
415 if (AddString) {\r
416 CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));\r
417 Offset = (UINT32) (Offset + sizeof (RELOFST));\r
418 CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));\r
419 }\r
420 //\r
421 // If resetting the strings, we need to reduce the offset by the difference in the strings\r
422 //\r
423 if (ResetStrings) {\r
424 CopyMem (&Length, &StringPointer[Index], sizeof (RELOFST));\r
425 Length = Length - ((RELOFST) (OriginalStringCount - TotalStringCount) * sizeof (RELOFST));\r
426 CopyMem (&StringPointer[Index], &Length, sizeof (RELOFST));\r
427 }\r
428 //\r
429 // Notice that if the string was being added as a new token, we don't have to worry about the\r
430 // offsets changing in the other indexes\r
431 //\r
432 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringPointer[Index], sizeof (RELOFST));\r
433 Count = Count + sizeof (RELOFST);\r
434 StringCount++;\r
435 }\r
436 //\r
437 // If we are adding a new string the above for loop did not copy the offset for us\r
438 //\r
439 if (AddString) {\r
440 //\r
441 // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous\r
442 // offset's string and create an offset to our new string.\r
443 //\r
444 CopyMem (&Offset, &StringPointer[Index - 1], sizeof (RELOFST));\r
445 StringLocation = (UINT8 *) StringPack;\r
446 StringLocation = StringLocation + Offset - sizeof (RELOFST);\r
447\r
448 //\r
449 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues\r
450 //\r
451 for (Length = 0;\r
452 (StringLocation[Length] != 0) || (StringLocation[Length + 1] != 0);\r
453 Length = (RELOFST) (Length + 2)\r
454 )\r
455 ;\r
456 Length = (RELOFST) (Length + 2);\r
457\r
458 StringSize = (RELOFST) (Offset + Length);\r
459\r
460 //\r
461 // Copy the new string offset\r
462 //\r
463 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringSize, sizeof (RELOFST));\r
464 Count = Count + sizeof (RELOFST);\r
465\r
466 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
467 Length = Length + sizeof (RELOFST);\r
468 CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));\r
469 }\r
470 //\r
471 // Set Location to the First String\r
472 //\r
473 if (ResetStrings) {\r
474 Index = OriginalStringCount;\r
475 }\r
476 //\r
477 // Set Location to the First String\r
478 //\r
479 Location = (UINT8 *) &StringPointer[Index];\r
480 Index = 0;\r
481\r
482 //\r
483 // Keep copying strings until you run into two CHAR16's in a row that are NULL\r
484 //\r
485 do {\r
486 if ((*Reference == Increment) && !AddString) {\r
487 StringLocation = ((UINT8 *) (&NewBuffer->IfrData) + Count);\r
488 CopyMem (StringLocation, NewString, StrSize (NewString));\r
489\r
490 //\r
491 // Advance the destination location by Count number of bytes\r
492 //\r
493 Count = Count + StrSize (NewString);\r
494\r
495 //\r
496 // Add the difference between the new string and the old string to the length\r
497 //\r
498 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
499\r
500 //\r
501 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues\r
502 //\r
503 StringLocation = (UINT8 *) &Location[Index];\r
504 for (Offset = 0;\r
505 (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);\r
506 Offset = (RELOFST) (Offset + 2)\r
507 )\r
508 ;\r
509 Offset = (RELOFST) (Offset + 2);\r
510\r
511 Length = Length + (UINT32) StrSize (NewString) - Offset;\r
512\r
513 CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));\r
514 } else {\r
515 StringLocation = (UINT8 *) &Location[Index];\r
516 for (Offset = 0;\r
517 (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);\r
518 Offset = (RELOFST) (Offset + 2)\r
519 )\r
520 ;\r
521 Offset = (RELOFST) (Offset + 2);\r
522\r
523 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringLocation, Offset);\r
524\r
525 //\r
526 // Advance the destination location by Count number of bytes\r
527 //\r
528 Count = Count + Offset;\r
529 }\r
530 //\r
531 // Retrieve the number of characters to advance the index - should land at beginning of next string\r
532 //\r
533 Index = Index + Offset;\r
534 Increment++;\r
535 StringCount--;\r
536 Offset = 0;\r
537 } while (StringCount > 0);\r
538\r
539 //\r
540 // If we are adding a new string, then the above do/while will not suffice\r
541 //\r
542 if (AddString) {\r
543 Offset = (RELOFST) StrSize (NewString);\r
544 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), NewString, Offset);\r
545\r
546 Count = Count + StrSize (NewString);\r
547 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
548 Length = Length + (UINT32) StrSize (NewString);\r
549 CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));\r
550 }\r
551\r
552 if (ResetStrings) {\r
553 //\r
554 // Skip the remainder of strings in the string package\r
555 //\r
556 StringCount = OriginalStringCount - TotalStringCount;\r
557\r
558 while (StringCount > 0) {\r
559 StringLocation = (UINT8 *) &Location[Index];\r
560 for (Offset = 0;\r
561 (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);\r
562 Offset = (RELOFST) (Offset + 2)\r
563 )\r
564 ;\r
565 Offset = (RELOFST) (Offset + 2);\r
566 Index = Index + Offset;\r
567 StringCount--;\r
568\r
569 //\r
570 // Adjust the size of the string pack by the string size we just skipped.\r
571 // Also reduce the length by the size of a RelativeOffset value since we\r
572 // obviously would have skipped that as well.\r
573 //\r
574 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
575 Length = Length - Offset - sizeof (RELOFST);\r
576 CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));\r
577 }\r
578 }\r
579\r
580 StringPack = (EFI_HII_STRING_PACK *) &Location[Index];\r
581\r
582 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
583 for (; Length != 0;) {\r
584\r
585 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);\r
586\r
587 Count = Count + Length;\r
588 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
589 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
590 }\r
591 //\r
592 // Copy the null terminator to the new buffer\r
593 //\r
594 CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, sizeof (EFI_HII_STRING_PACK));\r
595\r
596 //\r
597 // Based on if there is IFR data in this package instance, determine\r
598 // what the location is of the beginning of the string data.\r
599 //\r
600 if (StringPackageInstance->IfrSize > 0) {\r
601 Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;\r
602 StringPack = (EFI_HII_STRING_PACK *) Location;\r
603 Location = (UINT8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize;\r
604 NewStringPack = (EFI_HII_STRING_PACK *) Location;\r
605 } else {\r
606 StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);\r
607 NewStringPack = (EFI_HII_STRING_PACK *) (&NewBuffer->IfrData);\r
608 }\r
609\r
610 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
611 for (; Length != 0;) {\r
612 //\r
613 // Since we updated the old version of the string data as we moved things over\r
614 // And we had a chicken-egg problem with the data we copied, let's post-fix the new\r
615 // buffer with accurate length data.\r
616 //\r
617 CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));\r
618 CopyMem (&NewStringPack->Header.Length, &StringPack->Header.Length, sizeof (UINT32));\r
619 CopyMem (&StringPack->Header.Length, &Count, sizeof (UINT32));\r
620\r
621 CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));\r
622 NewStringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (NewStringPack) + Count);\r
623 CopyMem (&Count, &StringPack->Header.Length, sizeof (UINT32));\r
624 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Count);\r
625 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
626 }\r
627\r
628 GetPackSize ((VOID *) ((CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize), &NewBuffer->StringSize, NULL);\r
629\r
630 //\r
631 // Search through the handles until the requested handle is found.\r
632 //\r
633 for (HandleDatabase = HiiData->DatabaseHead;\r
634 HandleDatabase->Handle != 0;\r
635 HandleDatabase = HandleDatabase->NextHandleDatabase\r
636 ) {\r
637 if (HandleDatabase->Handle == StringPackageInstance->Handle) {\r
638 //\r
639 // Free the previous buffer associated with this handle, and assign the new buffer to the handle\r
640 //\r
641 gBS->FreePool (HandleDatabase->Buffer);\r
642 HandleDatabase->Buffer = NewBuffer;\r
643 break;\r
644 }\r
645 }\r
646\r
647 return EFI_SUCCESS;\r
648}\r
649\r
650EFI_STATUS\r
651EFIAPI\r
652HiiNewString (\r
653 IN EFI_HII_PROTOCOL *This,\r
654 IN CHAR16 *Language,\r
655 IN EFI_HII_HANDLE Handle,\r
656 IN OUT STRING_REF *Reference,\r
657 IN CHAR16 *NewString\r
658 )\r
659/*++\r
660\r
661Routine Description:\r
662 This function allows a new String to be added to an already existing String Package.\r
663 We will make a buffer the size of the package + StrSize of the new string. We will\r
664 copy the string package that first gets changed and the following language packages until\r
665 we encounter the NULL string package. All this time we will ensure that the offsets have\r
666 been adjusted. \r
667\r
668Arguments:\r
669 \r
670Returns: \r
671\r
672--*/\r
673{\r
674 UINTN Index;\r
675 CHAR16 *LangCodes;\r
676 CHAR16 Lang[4];\r
677 STRING_REF OriginalValue;\r
678 EFI_STATUS Status;\r
679\r
680 //\r
681 // To avoid a warning 4 uninitialized variable warning\r
682 //\r
683 Status = EFI_SUCCESS;\r
684\r
685 Status = HiiGetPrimaryLanguages (\r
686 This,\r
687 Handle,\r
688 &LangCodes\r
689 );\r
690\r
691 if (!EFI_ERROR (Status)) {\r
692 OriginalValue = *Reference;\r
693\r
694 if (Language == NULL) {\r
695 for (Index = 0; LangCodes[Index] != 0; Index += 3) {\r
696 *Reference = OriginalValue;\r
697 CopyMem (Lang, &LangCodes[Index], 6);\r
698 Lang[3] = 0;\r
699 Status = HiiNewString2 (\r
700 This,\r
701 Lang,\r
702 Handle,\r
703 Reference,\r
704 NewString,\r
705 FALSE\r
706 );\r
707\r
708 }\r
709 } else {\r
710 Status = HiiNewString2 (\r
711 This,\r
712 Language,\r
713 Handle,\r
714 Reference,\r
715 NewString,\r
716 FALSE\r
717 );\r
718 }\r
719\r
720 gBS->FreePool (LangCodes);\r
721 }\r
722\r
723 return Status;\r
724}\r
725\r
726EFI_STATUS\r
727EFIAPI\r
728HiiResetStrings (\r
729 IN EFI_HII_PROTOCOL *This,\r
730 IN EFI_HII_HANDLE Handle\r
731 )\r
732/*++\r
733\r
734Routine Description:\r
735 \r
736 This function removes any new strings that were added after the initial string export for this handle.\r
737\r
738Arguments:\r
739\r
740Returns: \r
741\r
742--*/\r
743{\r
744 UINTN Index;\r
745 CHAR16 *LangCodes;\r
746 CHAR16 Lang[4];\r
747 STRING_REF Reference;\r
748 CHAR16 NewString;\r
749 EFI_STATUS Status;\r
750\r
751 Reference = 1;\r
752 NewString = 0;\r
753\r
754 HiiGetPrimaryLanguages (\r
755 This,\r
756 Handle,\r
757 &LangCodes\r
758 );\r
759\r
760 for (Index = 0; LangCodes[Index] != 0; Index += 3) {\r
761 CopyMem (Lang, &LangCodes[Index], 6);\r
762 Lang[3] = 0;\r
763 Status = HiiNewString2 (\r
764 This,\r
765 Lang,\r
766 Handle,\r
767 &Reference,\r
768 &NewString,\r
769 TRUE\r
770 );\r
1cc8ee78 771 ASSERT_EFI_ERROR (Status);\r
878ddf1f 772 }\r
773\r
774 gBS->FreePool (LangCodes);\r
775 return EFI_SUCCESS;\r
776}\r
777\r
778EFI_STATUS\r
779EFIAPI\r
780HiiGetString (\r
781 IN EFI_HII_PROTOCOL *This,\r
782 IN EFI_HII_HANDLE Handle,\r
783 IN STRING_REF Token,\r
784 IN BOOLEAN Raw,\r
785 IN CHAR16 *LanguageString,\r
786 IN OUT UINTN *BufferLengthTemp,\r
787 OUT EFI_STRING StringBuffer\r
788 )\r
789/*++\r
790\r
791Routine Description:\r
792 \r
793 This function extracts a string from a package already registered with the EFI HII database.\r
794\r
795Arguments:\r
796 This - A pointer to the EFI_HII_PROTOCOL instance.\r
797 Handle - The HII handle on which the string resides.\r
798 Token - The string token assigned to the string.\r
799 Raw - If TRUE, the string is returned unedited in the internal storage format described\r
800 above. If false, the string returned is edited by replacing <cr> with <space> \r
801 and by removing special characters such as the <wide> prefix.\r
802 LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language\r
803 identifier, indicating the language to print. If the LanguageString is empty (starts\r
804 with a NULL), the default system language will be used to determine the language.\r
805 BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too\r
806 small, this parameter is filled with the length of the buffer needed.\r
807 StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is\r
808 defined in String.\r
809\r
810Returns: \r
811 EFI_INVALID_PARAMETER - If input parameter is invalid.\r
812 EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.\r
813 EFI_SUCCESS - Operation is successful.\r
814 \r
815--*/\r
816{\r
817 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
818 EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;\r
819 EFI_HII_DATA *HiiData;\r
820 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
821 EFI_HII_STRING_PACK *StringPack;\r
822 RELOFST *StringPointer;\r
823 EFI_STATUS Status;\r
824 UINTN DataSize;\r
825 CHAR8 Lang[3];\r
826 CHAR16 Language[3];\r
827 UINT32 Length;\r
828 UINTN Count;\r
829 RELOFST Offset;\r
830 UINT16 *Local;\r
831 UINT16 Zero;\r
832 UINT16 Narrow;\r
833 UINT16 Wide;\r
834 UINT16 NoBreak;\r
835 BOOLEAN LangFound;\r
836 UINT16 *BufferLength = (UINT16 *) BufferLengthTemp;\r
837\r
838 if (This == NULL) {\r
839 return EFI_INVALID_PARAMETER;\r
840 }\r
841\r
842 LangFound = TRUE;\r
843\r
844 DataSize = sizeof (Lang);\r
845\r
846 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
847\r
848 PackageInstance = NULL;\r
849 Zero = 0;\r
850 Narrow = NARROW_CHAR;\r
851 Wide = WIDE_CHAR;\r
852 NoBreak = NON_BREAKING_CHAR;\r
853\r
854 //\r
855 // Check numeric value against the head of the database\r
856 //\r
857 for (HandleDatabase = HiiData->DatabaseHead;\r
858 HandleDatabase != NULL;\r
859 HandleDatabase = HandleDatabase->NextHandleDatabase\r
860 ) {\r
861 //\r
862 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
863 //\r
864 if (Handle == HandleDatabase->Handle) {\r
865 PackageInstance = HandleDatabase->Buffer;\r
866 break;\r
867 }\r
868 }\r
869 //\r
870 // No handle was found - error condition\r
871 //\r
872 if (PackageInstance == NULL) {\r
873 return EFI_INVALID_PARAMETER;\r
874 }\r
875\r
876 Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);\r
877\r
878 //\r
879 // If there is no specified language, assume the system default language\r
880 //\r
881 if (LanguageString == NULL) {\r
882 //\r
883 // Get system default language\r
884 //\r
885 Status = gRT->GetVariable (\r
886 (CHAR16 *) L"Lang",\r
887 &gEfiGlobalVariableGuid,\r
888 NULL,\r
889 &DataSize,\r
890 Lang\r
891 );\r
892\r
893 if (EFI_ERROR (Status)) {\r
894 //\r
895 // If Lang doesn't exist, just use the first language you find\r
896 //\r
897 LangFound = FALSE;\r
898 goto LangNotFound;\r
899 }\r
900 //\r
901 // Convert the ASCII Lang variable to a Unicode Language variable\r
902 //\r
903 AsciiToUnicode ((UINT8 *)Lang, Language);\r
904 } else {\r
905 //\r
906 // Copy input ISO value to Language variable\r
907 //\r
908 CopyMem (Language, LanguageString, 6);\r
909 }\r
910 //\r
911 // Based on if there is IFR data in this package instance, determine\r
912 // what the location is of the beginning of the string data.\r
913 //\r
914LangNotFound:\r
915 if (StringPackageInstance->IfrSize > 0) {\r
916 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);\r
917 } else {\r
918 StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);\r
919 }\r
920 //\r
921 // If Token is 0, extract entire string package\r
922 //\r
923 if (Token == 0) {\r
924 //\r
925 // Compute the entire string pack length, including all languages' and the terminating pack's.\r
926 //\r
927 Length = 0;\r
928 while (0 != StringPack->Header.Length) {\r
929 Length += StringPack->Header.Length;\r
930 StringPack = (VOID*)(((UINT8*)StringPack) + StringPack->Header.Length);\r
931 }\r
932 //\r
933 // Back to the start of package.\r
934 //\r
935 StringPack = (VOID*)(((UINT8*)StringPack) - Length); \r
936 //\r
937 // Terminating zero sub-pack.\r
938 //\r
939 Length += sizeof (EFI_HII_STRING_PACK); \r
940\r
941 //\r
942 // If trying to get the entire string package and have insufficient space. Return error.\r
943 //\r
944 if (Length > *BufferLength || StringBuffer == NULL) {\r
945 *BufferLength = (UINT16)Length;\r
946 return EFI_BUFFER_TOO_SMALL;\r
947 }\r
948 //\r
949 // Copy the Pack to the caller's buffer.\r
950 //\r
951 *BufferLength = (UINT16)Length;\r
952 CopyMem (StringBuffer, StringPack, Length);\r
953\r
954 return EFI_SUCCESS;\r
955 }\r
956 //\r
957 // There may be multiple instances packed together of strings\r
958 // so we must walk the self describing structures until we encounter\r
959 // what we are looking for, and then extract the string we are looking for\r
960 //\r
961 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
962 for (; Length != 0;) {\r
963 //\r
964 // If passed in Language ISO value is in this string pack's language string\r
965 // then we are dealing with the strings we want.\r
966 //\r
967 CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST));\r
968 Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language);\r
969\r
970 //\r
971 // If we cannot find the lang variable, we skip this check and use the first language available\r
972 //\r
973 if (LangFound) {\r
974 if (EFI_ERROR (Status)) {\r
975 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
976 CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
977 continue;\r
978 }\r
979 }\r
980\r
981 StringPointer = (RELOFST *) (StringPack + 1);\r
982\r
983 //\r
984 // We have the right string package - size it, and copy it to the StringBuffer\r
985 //\r
986 if (Token >= StringPack->NumStringPointers) {\r
987 return EFI_INVALID_PARAMETER;\r
988 } else {\r
989 CopyMem (&Offset, &StringPointer[Token], sizeof (RELOFST));\r
990 }\r
991 //\r
992 // Since StringPack is a packed structure, we need to determine the string's\r
993 // size safely, thus byte-wise. Post-increment the size to include the null-terminator\r
994 //\r
995 Local = (UINT16 *) ((CHAR8 *) (StringPack) + Offset);\r
996 for (Count = 0; CompareMem (&Local[Count], &Zero, 2); Count++)\r
997 ;\r
998 Count++;\r
999\r
1000 Count = Count * sizeof (CHAR16);;\r
1001\r
1002 if (*BufferLength >= Count && StringBuffer != NULL) {\r
1003 //\r
1004 // Copy the string to the user's buffer\r
1005 //\r
1006 if (Raw) {\r
1007 CopyMem (StringBuffer, Local, Count);\r
1008 } else {\r
1009 for (Count = 0; CompareMem (Local, &Zero, 2); Local++) {\r
1010 //\r
1011 // Skip "Narraw, Wide, NoBreak"\r
1012 //\r
1013 if (CompareMem (Local, &Narrow, 2) &&\r
1014 CompareMem (Local, &Wide, 2) && \r
1015 CompareMem (Local, &NoBreak, 2)) { \r
1016 CopyMem (&StringBuffer[Count++], Local, 2); \r
1017 } \r
1018 } \r
1019 //\r
1020 // Add "NULL" at the end.\r
1021 //\r
1022 CopyMem (&StringBuffer[Count], &Zero, 2);\r
1023 Count++;\r
1024 Count *= sizeof (CHAR16);\r
1025 }\r
1026\r
1027 *BufferLength = (UINT16) Count;\r
1028 return EFI_SUCCESS;\r
1029 } else {\r
1030 *BufferLength = (UINT16) Count;\r
1031 return EFI_BUFFER_TOO_SMALL;\r
1032 }\r
1033\r
1034 }\r
1035\r
1036 LangFound = FALSE;\r
1037 goto LangNotFound;\r
1038}\r
1039\r
1040EFI_STATUS\r
1041EFIAPI\r
1042HiiGetLine (\r
1043 IN EFI_HII_PROTOCOL *This,\r
1044 IN EFI_HII_HANDLE Handle,\r
1045 IN STRING_REF Token,\r
1046 IN OUT UINT16 *Index,\r
1047 IN UINT16 LineWidth,\r
1048 IN CHAR16 *LanguageString,\r
1049 IN OUT UINT16 *BufferLength,\r
1050 OUT EFI_STRING StringBuffer\r
1051 )\r
1052/*++\r
1053\r
1054Routine Description:\r
1055\r
1056 This function allows a program to extract a part of a string of not more than a given width. \r
1057 With repeated calls, this allows a calling program to extract "lines" of text that fit inside \r
1058 columns. The effort of measuring the fit of strings inside columns is localized to this call.\r
1059\r
1060Arguments:\r
1061\r
1062Returns: \r
1063\r
1064--*/\r
1065{\r
1066 UINTN Count;\r
1067 EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
1068 EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;\r
1069 EFI_HII_DATA *HiiData;\r
1070 EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
1071 EFI_HII_STRING_PACK *StringPack;\r
1072 RELOFST *StringPointer;\r
1073 CHAR16 *Location;\r
1074 EFI_STATUS Status;\r
1075 UINTN DataSize;\r
1076 CHAR8 Lang[3];\r
1077 CHAR16 Language[3];\r
1078\r
1079 if (This == NULL) {\r
1080 return EFI_INVALID_PARAMETER;\r
1081 }\r
1082\r
1083 HiiData = EFI_HII_DATA_FROM_THIS (This);\r
1084\r
1085 HandleDatabase = HiiData->DatabaseHead;\r
1086\r
1087 PackageInstance = NULL;\r
1088 DataSize = 4;\r
1089\r
1090 //\r
1091 // Check numeric value against the head of the database\r
1092 //\r
1093 for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
1094 //\r
1095 // Match the numeric value with the database entry - if matched, extract PackageInstance\r
1096 //\r
1097 if (Handle == HandleDatabase->Handle) {\r
1098 PackageInstance = HandleDatabase->Buffer;\r
1099 }\r
1100 }\r
1101 //\r
1102 // No handle was found - error condition\r
1103 //\r
1104 if (PackageInstance == NULL) {\r
1105 return EFI_INVALID_PARAMETER;\r
1106 }\r
1107\r
1108 Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);\r
1109\r
1110 //\r
1111 // If there is no specified language, assume the system default language\r
1112 //\r
1113 if (LanguageString == NULL) {\r
1114 //\r
1115 // Get system default language\r
1116 //\r
1117 Status = gRT->GetVariable (\r
1118 (CHAR16 *) L"Lang",\r
1119 &gEfiGlobalVariableGuid,\r
1120 NULL,\r
1121 &DataSize,\r
1122 Lang\r
1123 );\r
1124\r
1125 if (EFI_ERROR (Status)) {\r
1126 return Status;\r
1127 }\r
1128 //\r
1129 // Convert the ASCII Lang variable to a Unicode Language variable\r
1130 //\r
1131 AsciiToUnicode ((UINT8 *)Lang, Language);\r
1132 } else {\r
1133 //\r
1134 // Copy input ISO value to Language variable\r
1135 //\r
1136 CopyMem (Language, LanguageString, 6);\r
1137 }\r
1138 //\r
1139 // Based on if there is IFR data in this package instance, determine\r
1140 // what the location is of the beginning of the string data.\r
1141 //\r
1142 if (StringPackageInstance->IfrSize > 0) {\r
1143 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);\r
1144 } else {\r
1145 StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);\r
1146 }\r
1147\r
1148 StringPointer = (RELOFST *) (StringPack + 1);\r
1149\r
1150 //\r
1151 // There may be multiple instances packed together of strings\r
1152 // so we must walk the self describing structures until we encounter\r
1153 // what we are looking for, and then extract the string we are looking for\r
1154 //\r
1155 for (; StringPack->Header.Length != 0;) {\r
1156 //\r
1157 // If passed in Language ISO value is in this string pack's language string\r
1158 // then we are dealing with the strings we want.\r
1159 //\r
1160 Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language);\r
1161\r
1162 if (EFI_ERROR (Status)) {\r
1163 StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
1164 continue;\r
1165 }\r
1166\r
1167 Location = (CHAR16 *) ((CHAR8 *) (StringPack) + StringPointer[Token] +*Index * 2);\r
1168\r
1169 //\r
1170 // If the size of the remaining string is less than the LineWidth\r
1171 // then copy the entire thing\r
1172 //\r
1173 if (StrSize (Location) <= LineWidth) {\r
1174 if (*BufferLength >= StrSize (Location)) {\r
1175 StrCpy (StringBuffer, Location);\r
1176 return EFI_SUCCESS;\r
1177 } else {\r
1178 *BufferLength = (UINT16) StrSize (Location);\r
1179 return EFI_BUFFER_TOO_SMALL;\r
1180 }\r
1181 } else {\r
1182 //\r
1183 // Rewind the string from the maximum size until we see a space the break the line\r
1184 //\r
1185 for (Count = LineWidth; Location[Count] != 0x0020; Count--)\r
1186 ;\r
1187\r
1188 //\r
1189 // Put the index at the next character\r
1190 //\r
1191 *Index = (UINT16) (Count + 1);\r
1192\r
1193 if (*BufferLength >= Count) {\r
1194 StrnCpy (StringBuffer, Location, Count);\r
1195 return EFI_SUCCESS;\r
1196 } else {\r
1197 *BufferLength = (UINT16) Count;\r
1198 return EFI_BUFFER_TOO_SMALL;\r
1199 }\r
1200 }\r
1201 }\r
1202\r
1203 return EFI_SUCCESS;\r
1204}\r
1205\r
1206EFI_STATUS\r
1207HiiCompareLanguage (\r
1208 IN CHAR16 *LanguageStringLocation,\r
1209 IN CHAR16 *Language\r
1210 )\r
1211{\r
1212 UINT8 *Local;\r
1213 UINTN Index;\r
1214 CHAR16 *InputString;\r
1215 CHAR16 *OriginalInputString;\r
1216\r
1217 //\r
1218 // Allocate a temporary buffer for InputString\r
1219 //\r
1220 InputString = AllocateZeroPool (0x100);\r
1221\r
1222 ASSERT (InputString);\r
1223\r
1224 OriginalInputString = InputString;\r
1225\r
1226 Local = (UINT8 *) LanguageStringLocation;\r
1227\r
1228 //\r
1229 // Determine the size of this packed string safely (e.g. access by byte), post-increment\r
1230 // to include the null-terminator\r
1231 //\r
1232 for (Index = 0; Local[Index] != 0; Index = Index + 2)\r
1233 ;\r
1234 //\r
1235 // MARMAR Index = Index + 2;\r
1236 //\r
1237 // This is a packed structure that this location comes from, so let's make sure\r
1238 // the value is aligned by copying it to a local variable and working on it.\r
1239 //\r
1240 CopyMem (InputString, LanguageStringLocation, Index);\r
1241\r
1242 for (Index = 0; Index < 3; Index++) {\r
1243 InputString[Index] = (CHAR16) (InputString[Index] | 0x20);\r
1244 Language[Index] = (CHAR16) (Language[Index] | 0x20);\r
1245 }\r
1246 //\r
1247 // If the Language is the same return success\r
1248 //\r
1249 if (CompareMem (LanguageStringLocation, Language, 6) == 0) {\r
1250 gBS->FreePool (InputString);\r
1251 return EFI_SUCCESS;\r
1252 }\r
1253 //\r
1254 // Skip the first three letters that comprised the primary language,\r
1255 // see if what is being compared against is a secondary language\r
1256 //\r
1257 InputString = InputString + 3;\r
1258\r
1259 //\r
1260 // If the Language is not the same as the Primary language, see if there are any\r
1261 // secondary languages, and if there are see if we have a match. If not, return an error.\r
1262 //\r
1263 for (Index = 0; InputString[Index] != 0; Index = Index + 3) {\r
1264 //\r
1265 // Getting in here means we have a secondary language\r
1266 //\r
1267 if (CompareMem (&InputString[Index], Language, 6) == 0) {\r
1268 gBS->FreePool (InputString);\r
1269 return EFI_SUCCESS;\r
1270 }\r
1271 }\r
1272 //\r
1273 // If nothing was found, return the error\r
1274 //\r
1275 gBS->FreePool (OriginalInputString);\r
1276 return EFI_NOT_FOUND;\r
1277\r
1278}\r