3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file contains the string processing code to the HII database.
23 #include "HiiDatabase.h"
35 // Convert the ASCII Lang variable to a Unicode Language variable
37 for (Count
= 0; Count
< 3; Count
++) {
38 Language
[Count
] = (CHAR16
) Lang
[Count
];
45 IN EFI_HII_PROTOCOL
*This
,
46 IN CHAR16
*StringToTest
,
47 IN OUT UINT32
*FirstMissing
,
48 OUT UINT32
*GlyphBufferSize
53 Test if all of the characters in a string have corresponding font characters.
61 EFI_HII_GLOBAL_DATA
*GlobalData
;
62 EFI_HII_DATA
*HiiData
;
69 return EFI_INVALID_PARAMETER
;
72 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
74 GlobalData
= HiiData
->GlobalData
;
78 ZeroMem (GlyphCol1
, sizeof (GlyphCol1
));
81 // Walk through the string until you hit the null terminator
83 for (; StringToTest
[*FirstMissing
] != 0x00; (*FirstMissing
)++) {
84 Location
= *FirstMissing
;
86 // Rewind through the string looking for a glyph width identifier
88 for (; Location
!= 0; Location
--) {
89 if (StringToTest
[Location
] == NARROW_CHAR
|| StringToTest
[Location
] == WIDE_CHAR
) {
91 // We found something that identifies what glyph database to look in
93 if (StringToTest
[Location
] == WIDE_CHAR
) {
103 GlobalData
->NarrowGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
105 NARROW_GLYPH_ARRAY_SIZE
109 // Break since this glyph isn't defined
111 return EFI_NOT_FOUND
;
115 // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
118 GlobalData
->WideGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
120 WIDE_GLYPH_ARRAY_SIZE
124 // Break since this glyph isn't defined
126 return EFI_NOT_FOUND
;
134 *GlyphBufferSize
= (UINT32
) (Count
* sizeof (EFI_NARROW_GLYPH
));
136 *GlyphBufferSize
= (UINT32
) (Count
* sizeof (EFI_WIDE_GLYPH
));
145 IN EFI_HII_PROTOCOL
*This
,
147 IN EFI_HII_HANDLE Handle
,
148 IN OUT STRING_REF
*Reference
,
149 IN CHAR16
*NewString
,
150 IN BOOLEAN ResetStrings
156 This function allows a new String to be added to an already existing String Package.
157 We will make a buffer the size of the package + EfiStrSize of the new string. We will
158 copy the string package that first gets changed and the following language packages until
159 we encounter the NULL string package. All this time we will ensure that the offsets have
164 This - Pointer to the HII protocol.
165 Language - Pointer to buffer which contains the language code of this NewString.
166 Handle - Handle of the package instance to be processed.
167 Reference - The token number for the string. If 0, new string token to be returned through this parameter.
168 NewString - Buffer pointer for the new string.
169 ResetStrings - Indicate if we are resetting a string.
173 EFI_SUCCESS - The string has been added or reset to Hii database.
174 EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
178 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
179 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
180 EFI_HII_DATA
*HiiData
;
181 EFI_HII_STRING_PACK
*StringPack
;
182 EFI_HII_STRING_PACK
*NewStringPack
;
183 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
184 EFI_HII_PACKAGE_INSTANCE
*NewBuffer
;
186 UINT8
*StringLocation
;
187 RELOFST
*StringPointer
;
196 UINT32 TotalStringCount
;
197 UINT32 OriginalStringCount
;
203 return EFI_INVALID_PARAMETER
;
206 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
208 HandleDatabase
= HiiData
->DatabaseHead
;
209 PackageInstance
= NULL
;
213 TotalStringCount
= 0;
214 OriginalStringCount
= 0;
217 // Check numeric value against the head of the database
219 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
221 // Match the numeric value with the database entry - if matched, extract PackageInstance
223 if (Handle
== HandleDatabase
->Handle
) {
224 PackageInstance
= HandleDatabase
->Buffer
;
226 TotalStringCount
= HandleDatabase
->NumberOfTokens
;
232 // No handle was found - error condition
234 if (PackageInstance
== NULL
) {
235 return EFI_INVALID_PARAMETER
;
238 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, &TotalStringCount
);
241 // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
243 Count
= StringPackageInstance
->IfrSize
;
246 // This is the size of the complete series of string packs
248 Size
= StringPackageInstance
->StringSize
;
251 // Based on if there is IFR data in this package instance, determine
252 // what the location is of the beginning of the string data.
254 if (StringPackageInstance
->IfrSize
> 0) {
255 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
257 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
);
260 // We allocate a buffer which is big enough for both adding and resetting string.
261 // The size is slightly larger than the real size of the packages when we are resetting a string.
263 NewBuffer
= AllocateZeroPool (
264 sizeof (EFI_HII_PACKAGE_INSTANCE
) -
265 2 * sizeof (VOID
*) +
266 StringPackageInstance
->IfrSize
+
267 StringPackageInstance
->StringSize
+
274 // Copy data to new buffer
276 NewBuffer
->Handle
= StringPackageInstance
->Handle
;
277 NewBuffer
->IfrSize
= StringPackageInstance
->IfrSize
;
280 // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
281 // package to begin with.
283 NewBuffer
->StringSize
= StringPackageInstance
->StringSize
+ StrSize (NewString
) + sizeof (EFI_HII_STRING_PACK
);
285 if (StringPackageInstance
->IfrSize
> 0) {
286 CopyMem (&NewBuffer
->IfrData
, &StringPackageInstance
->IfrData
, StringPackageInstance
->IfrSize
);
289 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
292 // There may be multiple instances packed together of strings
293 // so we must walk the self describing structures until we encounter
294 // what we are looking for. In the meantime, copy everything we encounter
295 // to the new buffer.
297 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
298 for (; Length
!= 0;) {
300 // If passed in Language ISO value is in this string pack's language string
301 // then we are dealing with the strings we want.
303 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
304 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
306 if (!EFI_ERROR (Status
)) {
310 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
312 Count
= Count
+ Length
;
313 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
314 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
317 // Found the language pack to update on a particular handle
318 // We need to Copy the Contents of this pack and adjust the offset values associated
319 // with adding/changing a string. This is a particular piece of code that screams for
320 // it being prone to programming error.
323 // Copy the string package up to the string data
325 StringPointer
= (RELOFST
*) (StringPack
+ 1);
327 ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
),
329 (UINTN
) ((UINTN
) (StringPointer
) - (UINTN
) (StringPack
))
333 // Determine the number of StringPointers
336 CopyMem (&TotalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
339 // If we are resetting the strings, use the original value when exported
341 CopyMem (&OriginalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
342 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
-=
344 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
347 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
-=
349 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
352 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
= TotalStringCount
;
353 *Reference
= (STRING_REF
) (TotalStringCount
);
356 // If the token value is not valid, error out
358 if ((*Reference
>= TotalStringCount
) && !ResetStrings
) {
359 gBS
->FreePool (NewBuffer
);
360 return EFI_INVALID_PARAMETER
;
363 // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
365 if (*Reference
== 0) {
366 *Reference
= (STRING_REF
) (TotalStringCount
);
371 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
+= sizeof (RELOFST
);
372 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
+= sizeof (RELOFST
);
373 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
++;
376 // Increment offset by amount of copied data
378 Count
= Count
+ ((UINTN
) (StringPointer
) - (UINTN
) StringPack
);
380 for (Index
= 0; Index
< TotalStringCount
; Index
++) {
382 // If we are pointing to the size of the changing string value
383 // then cache the old string value so you know what the difference is
385 if (Index
== *Reference
) {
386 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
388 StringLocation
= ((UINT8
*) (StringPack
) + Offset
);
389 for (SecondIndex
= 0;
390 (StringLocation
[SecondIndex
] != 0) || (StringLocation
[SecondIndex
+ 1] != 0);
391 SecondIndex
= SecondIndex
+ 2
394 SecondIndex
= SecondIndex
+ 2;
399 // NewString is a passed in local string which is assumed to be aligned
401 Size
= StrSize (NewString
) - Size
;
404 // If we are about to copy the offset of the string that follows the changed string make
405 // sure that the offsets are adjusted accordingly
407 if ((Index
> *Reference
) && !ResetStrings
) {
408 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
409 Offset
= (RELOFST
) (Offset
+ Size
);
410 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
413 // If we are adding a string that means we will have an extra string pointer that will affect all string offsets
416 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
417 Offset
= (UINT32
) (Offset
+ sizeof (RELOFST
));
418 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
421 // If resetting the strings, we need to reduce the offset by the difference in the strings
424 CopyMem (&Length
, &StringPointer
[Index
], sizeof (RELOFST
));
425 Length
= Length
- ((RELOFST
) (OriginalStringCount
- TotalStringCount
) * sizeof (RELOFST
));
426 CopyMem (&StringPointer
[Index
], &Length
, sizeof (RELOFST
));
429 // Notice that if the string was being added as a new token, we don't have to worry about the
430 // offsets changing in the other indexes
432 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringPointer
[Index
], sizeof (RELOFST
));
433 Count
= Count
+ sizeof (RELOFST
);
437 // If we are adding a new string the above for loop did not copy the offset for us
441 // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
442 // offset's string and create an offset to our new string.
444 CopyMem (&Offset
, &StringPointer
[Index
- 1], sizeof (RELOFST
));
445 StringLocation
= (UINT8
*) StringPack
;
446 StringLocation
= StringLocation
+ Offset
- sizeof (RELOFST
);
449 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
452 (StringLocation
[Length
] != 0) || (StringLocation
[Length
+ 1] != 0);
453 Length
= (RELOFST
) (Length
+ 2)
456 Length
= (RELOFST
) (Length
+ 2);
458 StringSize
= (RELOFST
) (Offset
+ Length
);
461 // Copy the new string offset
463 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringSize
, sizeof (RELOFST
));
464 Count
= Count
+ sizeof (RELOFST
);
466 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
467 Length
= Length
+ sizeof (RELOFST
);
468 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
471 // Set Location to the First String
474 Index
= OriginalStringCount
;
477 // Set Location to the First String
479 Location
= (UINT8
*) &StringPointer
[Index
];
483 // Keep copying strings until you run into two CHAR16's in a row that are NULL
486 if ((*Reference
== Increment
) && !AddString
) {
487 StringLocation
= ((UINT8
*) (&NewBuffer
->IfrData
) + Count
);
488 CopyMem (StringLocation
, NewString
, StrSize (NewString
));
491 // Advance the destination location by Count number of bytes
493 Count
= Count
+ StrSize (NewString
);
496 // Add the difference between the new string and the old string to the length
498 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
501 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
503 StringLocation
= (UINT8
*) &Location
[Index
];
505 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
506 Offset
= (RELOFST
) (Offset
+ 2)
509 Offset
= (RELOFST
) (Offset
+ 2);
511 Length
= Length
+ (UINT32
) StrSize (NewString
) - Offset
;
513 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
515 StringLocation
= (UINT8
*) &Location
[Index
];
517 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
518 Offset
= (RELOFST
) (Offset
+ 2)
521 Offset
= (RELOFST
) (Offset
+ 2);
523 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringLocation
, Offset
);
526 // Advance the destination location by Count number of bytes
528 Count
= Count
+ Offset
;
531 // Retrieve the number of characters to advance the index - should land at beginning of next string
533 Index
= Index
+ Offset
;
537 } while (StringCount
> 0);
540 // If we are adding a new string, then the above do/while will not suffice
543 Offset
= (RELOFST
) StrSize (NewString
);
544 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), NewString
, Offset
);
546 Count
= Count
+ StrSize (NewString
);
547 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
548 Length
= Length
+ (UINT32
) StrSize (NewString
);
549 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
554 // Skip the remainder of strings in the string package
556 StringCount
= OriginalStringCount
- TotalStringCount
;
558 while (StringCount
> 0) {
559 StringLocation
= (UINT8
*) &Location
[Index
];
561 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
562 Offset
= (RELOFST
) (Offset
+ 2)
565 Offset
= (RELOFST
) (Offset
+ 2);
566 Index
= Index
+ Offset
;
570 // Adjust the size of the string pack by the string size we just skipped.
571 // Also reduce the length by the size of a RelativeOffset value since we
572 // obviously would have skipped that as well.
574 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
575 Length
= Length
- Offset
- sizeof (RELOFST
);
576 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
580 StringPack
= (EFI_HII_STRING_PACK
*) &Location
[Index
];
582 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
583 for (; Length
!= 0;) {
585 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
587 Count
= Count
+ Length
;
588 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
589 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
592 // Copy the null terminator to the new buffer
594 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, sizeof (EFI_HII_STRING_PACK
));
597 // Based on if there is IFR data in this package instance, determine
598 // what the location is of the beginning of the string data.
600 if (StringPackageInstance
->IfrSize
> 0) {
601 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
602 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
603 Location
= (UINT8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
;
604 NewStringPack
= (EFI_HII_STRING_PACK
*) Location
;
606 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
607 NewStringPack
= (EFI_HII_STRING_PACK
*) (&NewBuffer
->IfrData
);
610 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
611 for (; Length
!= 0;) {
613 // Since we updated the old version of the string data as we moved things over
614 // And we had a chicken-egg problem with the data we copied, let's post-fix the new
615 // buffer with accurate length data.
617 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
618 CopyMem (&NewStringPack
->Header
.Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
619 CopyMem (&StringPack
->Header
.Length
, &Count
, sizeof (UINT32
));
621 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
622 NewStringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (NewStringPack
) + Count
);
623 CopyMem (&Count
, &StringPack
->Header
.Length
, sizeof (UINT32
));
624 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Count
);
625 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
628 GetPackSize ((VOID
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
), &NewBuffer
->StringSize
, NULL
);
631 // Search through the handles until the requested handle is found.
633 for (HandleDatabase
= HiiData
->DatabaseHead
;
634 HandleDatabase
->Handle
!= 0;
635 HandleDatabase
= HandleDatabase
->NextHandleDatabase
637 if (HandleDatabase
->Handle
== StringPackageInstance
->Handle
) {
639 // Free the previous buffer associated with this handle, and assign the new buffer to the handle
641 gBS
->FreePool (HandleDatabase
->Buffer
);
642 HandleDatabase
->Buffer
= NewBuffer
;
653 IN EFI_HII_PROTOCOL
*This
,
655 IN EFI_HII_HANDLE Handle
,
656 IN OUT STRING_REF
*Reference
,
662 This function allows a new String to be added to an already existing String Package.
663 We will make a buffer the size of the package + StrSize of the new string. We will
664 copy the string package that first gets changed and the following language packages until
665 we encounter the NULL string package. All this time we will ensure that the offsets have
677 STRING_REF OriginalValue
;
681 // To avoid a warning 4 uninitialized variable warning
683 Status
= EFI_SUCCESS
;
685 Status
= HiiGetPrimaryLanguages (
691 if (!EFI_ERROR (Status
)) {
692 OriginalValue
= *Reference
;
694 if (Language
== NULL
) {
695 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
696 *Reference
= OriginalValue
;
697 CopyMem (Lang
, &LangCodes
[Index
], 6);
699 Status
= HiiNewString2 (
710 Status
= HiiNewString2 (
720 gBS
->FreePool (LangCodes
);
729 IN EFI_HII_PROTOCOL
*This
,
730 IN EFI_HII_HANDLE Handle
736 This function removes any new strings that were added after the initial string export for this handle.
747 STRING_REF Reference
;
754 HiiGetPrimaryLanguages (
760 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
761 CopyMem (Lang
, &LangCodes
[Index
], 6);
763 Status
= HiiNewString2 (
771 ASSERT_EFI_ERROR (Status
);
774 gBS
->FreePool (LangCodes
);
781 IN EFI_HII_PROTOCOL
*This
,
782 IN EFI_HII_HANDLE Handle
,
785 IN CHAR16
*LanguageString
,
786 IN OUT UINTN
*BufferLengthTemp
,
787 OUT EFI_STRING StringBuffer
793 This function extracts a string from a package already registered with the EFI HII database.
796 This - A pointer to the EFI_HII_PROTOCOL instance.
797 Handle - The HII handle on which the string resides.
798 Token - The string token assigned to the string.
799 Raw - If TRUE, the string is returned unedited in the internal storage format described
800 above. If false, the string returned is edited by replacing <cr> with <space>
801 and by removing special characters such as the <wide> prefix.
802 LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language
803 identifier, indicating the language to print. If the LanguageString is empty (starts
804 with a NULL), the default system language will be used to determine the language.
805 BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too
806 small, this parameter is filled with the length of the buffer needed.
807 StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is
811 EFI_INVALID_PARAMETER - If input parameter is invalid.
812 EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.
813 EFI_SUCCESS - Operation is successful.
817 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
818 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
819 EFI_HII_DATA
*HiiData
;
820 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
821 EFI_HII_STRING_PACK
*StringPack
;
822 RELOFST
*StringPointer
;
836 UINT16
*BufferLength
= (UINT16
*) BufferLengthTemp
;
839 return EFI_INVALID_PARAMETER
;
844 DataSize
= sizeof (Lang
);
846 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
848 PackageInstance
= NULL
;
850 Narrow
= NARROW_CHAR
;
852 NoBreak
= NON_BREAKING_CHAR
;
855 // Check numeric value against the head of the database
857 for (HandleDatabase
= HiiData
->DatabaseHead
;
858 HandleDatabase
!= NULL
;
859 HandleDatabase
= HandleDatabase
->NextHandleDatabase
862 // Match the numeric value with the database entry - if matched, extract PackageInstance
864 if (Handle
== HandleDatabase
->Handle
) {
865 PackageInstance
= HandleDatabase
->Buffer
;
870 // No handle was found - error condition
872 if (PackageInstance
== NULL
) {
873 return EFI_INVALID_PARAMETER
;
876 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
879 // If there is no specified language, assume the system default language
881 if (LanguageString
== NULL
) {
883 // Get system default language
885 Status
= gRT
->GetVariable (
887 &gEfiGlobalVariableGuid
,
893 if (EFI_ERROR (Status
)) {
895 // If Lang doesn't exist, just use the first language you find
901 // Convert the ASCII Lang variable to a Unicode Language variable
903 AsciiToUnicode ((UINT8
*)Lang
, Language
);
906 // Copy input ISO value to Language variable
908 CopyMem (Language
, LanguageString
, 6);
911 // Based on if there is IFR data in this package instance, determine
912 // what the location is of the beginning of the string data.
915 if (StringPackageInstance
->IfrSize
> 0) {
916 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
918 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
921 // If Token is 0, extract entire string package
925 // Compute the entire string pack length, including all languages' and the terminating pack's.
928 while (0 != StringPack
->Header
.Length
) {
929 Length
+= StringPack
->Header
.Length
;
930 StringPack
= (VOID
*)(((UINT8
*)StringPack
) + StringPack
->Header
.Length
);
933 // Back to the start of package.
935 StringPack
= (VOID
*)(((UINT8
*)StringPack
) - Length
);
937 // Terminating zero sub-pack.
939 Length
+= sizeof (EFI_HII_STRING_PACK
);
942 // If trying to get the entire string package and have insufficient space. Return error.
944 if (Length
> *BufferLength
|| StringBuffer
== NULL
) {
945 *BufferLength
= (UINT16
)Length
;
946 return EFI_BUFFER_TOO_SMALL
;
949 // Copy the Pack to the caller's buffer.
951 *BufferLength
= (UINT16
)Length
;
952 CopyMem (StringBuffer
, StringPack
, Length
);
957 // There may be multiple instances packed together of strings
958 // so we must walk the self describing structures until we encounter
959 // what we are looking for, and then extract the string we are looking for
961 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
962 for (; Length
!= 0;) {
964 // If passed in Language ISO value is in this string pack's language string
965 // then we are dealing with the strings we want.
967 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
968 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
971 // If we cannot find the lang variable, we skip this check and use the first language available
974 if (EFI_ERROR (Status
)) {
975 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
976 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
981 StringPointer
= (RELOFST
*) (StringPack
+ 1);
984 // We have the right string package - size it, and copy it to the StringBuffer
986 if (Token
>= StringPack
->NumStringPointers
) {
987 return EFI_INVALID_PARAMETER
;
989 CopyMem (&Offset
, &StringPointer
[Token
], sizeof (RELOFST
));
992 // Since StringPack is a packed structure, we need to determine the string's
993 // size safely, thus byte-wise. Post-increment the size to include the null-terminator
995 Local
= (UINT16
*) ((CHAR8
*) (StringPack
) + Offset
);
996 for (Count
= 0; CompareMem (&Local
[Count
], &Zero
, 2); Count
++)
1000 Count
= Count
* sizeof (CHAR16
);;
1002 if (*BufferLength
>= Count
&& StringBuffer
!= NULL
) {
1004 // Copy the string to the user's buffer
1007 CopyMem (StringBuffer
, Local
, Count
);
1009 for (Count
= 0; CompareMem (Local
, &Zero
, 2); Local
++) {
1011 // Skip "Narraw, Wide, NoBreak"
1013 if (CompareMem (Local
, &Narrow
, 2) &&
1014 CompareMem (Local
, &Wide
, 2) &&
1015 CompareMem (Local
, &NoBreak
, 2)) {
1016 CopyMem (&StringBuffer
[Count
++], Local
, 2);
1020 // Add "NULL" at the end.
1022 CopyMem (&StringBuffer
[Count
], &Zero
, 2);
1024 Count
*= sizeof (CHAR16
);
1027 *BufferLength
= (UINT16
) Count
;
1030 *BufferLength
= (UINT16
) Count
;
1031 return EFI_BUFFER_TOO_SMALL
;
1043 IN EFI_HII_PROTOCOL
*This
,
1044 IN EFI_HII_HANDLE Handle
,
1045 IN STRING_REF Token
,
1046 IN OUT UINT16
*Index
,
1047 IN UINT16 LineWidth
,
1048 IN CHAR16
*LanguageString
,
1049 IN OUT UINT16
*BufferLength
,
1050 OUT EFI_STRING StringBuffer
1054 Routine Description:
1056 This function allows a program to extract a part of a string of not more than a given width.
1057 With repeated calls, this allows a calling program to extract "lines" of text that fit inside
1058 columns. The effort of measuring the fit of strings inside columns is localized to this call.
1067 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
1068 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
1069 EFI_HII_DATA
*HiiData
;
1070 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
1071 EFI_HII_STRING_PACK
*StringPack
;
1072 RELOFST
*StringPointer
;
1080 return EFI_INVALID_PARAMETER
;
1083 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
1085 HandleDatabase
= HiiData
->DatabaseHead
;
1087 PackageInstance
= NULL
;
1091 // Check numeric value against the head of the database
1093 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
1095 // Match the numeric value with the database entry - if matched, extract PackageInstance
1097 if (Handle
== HandleDatabase
->Handle
) {
1098 PackageInstance
= HandleDatabase
->Buffer
;
1102 // No handle was found - error condition
1104 if (PackageInstance
== NULL
) {
1105 return EFI_INVALID_PARAMETER
;
1108 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
1111 // If there is no specified language, assume the system default language
1113 if (LanguageString
== NULL
) {
1115 // Get system default language
1117 Status
= gRT
->GetVariable (
1119 &gEfiGlobalVariableGuid
,
1125 if (EFI_ERROR (Status
)) {
1129 // Convert the ASCII Lang variable to a Unicode Language variable
1131 AsciiToUnicode ((UINT8
*)Lang
, Language
);
1134 // Copy input ISO value to Language variable
1136 CopyMem (Language
, LanguageString
, 6);
1139 // Based on if there is IFR data in this package instance, determine
1140 // what the location is of the beginning of the string data.
1142 if (StringPackageInstance
->IfrSize
> 0) {
1143 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
1145 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
1148 StringPointer
= (RELOFST
*) (StringPack
+ 1);
1151 // There may be multiple instances packed together of strings
1152 // so we must walk the self describing structures until we encounter
1153 // what we are looking for, and then extract the string we are looking for
1155 for (; StringPack
->Header
.Length
!= 0;) {
1157 // If passed in Language ISO value is in this string pack's language string
1158 // then we are dealing with the strings we want.
1160 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
);
1162 if (EFI_ERROR (Status
)) {
1163 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
1167 Location
= (CHAR16
*) ((CHAR8
*) (StringPack
) + StringPointer
[Token
] +*Index
* 2);
1170 // If the size of the remaining string is less than the LineWidth
1171 // then copy the entire thing
1173 if (StrSize (Location
) <= LineWidth
) {
1174 if (*BufferLength
>= StrSize (Location
)) {
1175 StrCpy (StringBuffer
, Location
);
1178 *BufferLength
= (UINT16
) StrSize (Location
);
1179 return EFI_BUFFER_TOO_SMALL
;
1183 // Rewind the string from the maximum size until we see a space the break the line
1185 for (Count
= LineWidth
; Location
[Count
] != 0x0020; Count
--)
1189 // Put the index at the next character
1191 *Index
= (UINT16
) (Count
+ 1);
1193 if (*BufferLength
>= Count
) {
1194 StrnCpy (StringBuffer
, Location
, Count
);
1197 *BufferLength
= (UINT16
) Count
;
1198 return EFI_BUFFER_TOO_SMALL
;
1207 HiiCompareLanguage (
1208 IN CHAR16
*LanguageStringLocation
,
1214 CHAR16
*InputString
;
1215 CHAR16
*OriginalInputString
;
1218 // Allocate a temporary buffer for InputString
1220 InputString
= AllocateZeroPool (0x100);
1222 ASSERT (InputString
);
1224 OriginalInputString
= InputString
;
1226 Local
= (UINT8
*) LanguageStringLocation
;
1229 // Determine the size of this packed string safely (e.g. access by byte), post-increment
1230 // to include the null-terminator
1232 for (Index
= 0; Local
[Index
] != 0; Index
= Index
+ 2)
1235 // MARMAR Index = Index + 2;
1237 // This is a packed structure that this location comes from, so let's make sure
1238 // the value is aligned by copying it to a local variable and working on it.
1240 CopyMem (InputString
, LanguageStringLocation
, Index
);
1242 for (Index
= 0; Index
< 3; Index
++) {
1243 InputString
[Index
] = (CHAR16
) (InputString
[Index
] | 0x20);
1244 Language
[Index
] = (CHAR16
) (Language
[Index
] | 0x20);
1247 // If the Language is the same return success
1249 if (CompareMem (LanguageStringLocation
, Language
, 6) == 0) {
1250 gBS
->FreePool (InputString
);
1254 // Skip the first three letters that comprised the primary language,
1255 // see if what is being compared against is a secondary language
1257 InputString
= InputString
+ 3;
1260 // If the Language is not the same as the Primary language, see if there are any
1261 // secondary languages, and if there are see if we have a match. If not, return an error.
1263 for (Index
= 0; InputString
[Index
] != 0; Index
= Index
+ 3) {
1265 // Getting in here means we have a secondary language
1267 if (CompareMem (&InputString
[Index
], Language
, 6) == 0) {
1268 gBS
->FreePool (InputString
);
1273 // If nothing was found, return the error
1275 gBS
->FreePool (OriginalInputString
);
1276 return EFI_NOT_FOUND
;