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