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