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