1 /** @file
2 Implementation for EFI_HII_FONT_PROTOCOL.
3 
4 
5 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 
11 #include "HiiDatabase.h"
12 
13 EFI_GRAPHICS_OUTPUT_BLT_PIXEL        mHiiEfiColors[16] = {
14   //
15   // B     G     R
16   //
17   {0x00, 0x00, 0x00, 0x00},  // BLACK
18   {0x98, 0x00, 0x00, 0x00},  // BLUE
19   {0x00, 0x98, 0x00, 0x00},  // GREEN
20   {0x98, 0x98, 0x00, 0x00},  // CYAN
21   {0x00, 0x00, 0x98, 0x00},  // RED
22   {0x98, 0x00, 0x98, 0x00},  // MAGENTA
23   {0x00, 0x98, 0x98, 0x00},  // BROWN
24   {0x98, 0x98, 0x98, 0x00},  // LIGHTGRAY
25   {0x30, 0x30, 0x30, 0x00},  // DARKGRAY - BRIGHT BLACK
26   {0xff, 0x00, 0x00, 0x00},  // LIGHTBLUE
27   {0x00, 0xff, 0x00, 0x00},  // LIGHTGREEN
28   {0xff, 0xff, 0x00, 0x00},  // LIGHTCYAN
29   {0x00, 0x00, 0xff, 0x00},  // LIGHTRED
30   {0xff, 0x00, 0xff, 0x00},  // LIGHTMAGENTA
31   {0x00, 0xff, 0xff, 0x00},  // YELLOW
32   {0xff, 0xff, 0xff, 0x00},  // WHITE
33 };
34 
35 
36 /**
37   Insert a character cell information to the list specified by GlyphInfoList.
38 
39   This is a internal function.
40 
41   @param  CharValue               Unicode character value, which identifies a glyph
42                                   block.
43   @param  GlyphInfoList           HII_GLYPH_INFO list head.
44   @param  Cell                    Incoming character cell information.
45 
46   @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.
47   @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
48                                   task.
49 
50 **/
51 EFI_STATUS
NewCell(IN CHAR16 CharValue,IN LIST_ENTRY * GlyphInfoList,IN EFI_HII_GLYPH_INFO * Cell)52 NewCell (
53   IN  CHAR16                         CharValue,
54   IN  LIST_ENTRY                     *GlyphInfoList,
55   IN  EFI_HII_GLYPH_INFO             *Cell
56   )
57 {
58   HII_GLYPH_INFO           *GlyphInfo;
59 
60   ASSERT (Cell != NULL && GlyphInfoList != NULL);
61 
62   GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO));
63   if (GlyphInfo == NULL) {
64     return EFI_OUT_OF_RESOURCES;
65   }
66 
67   //
68   // GlyphInfoList stores a list of default character cell information, each is
69   // identified by "CharId".
70   //
71   GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;
72   GlyphInfo->CharId    = CharValue;
73   if (Cell->AdvanceX == 0) {
74     Cell->AdvanceX = Cell->Width;
75   }
76   CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));
77   InsertTailList (GlyphInfoList, &GlyphInfo->Entry);
78 
79   return EFI_SUCCESS;
80 }
81 
82 
83 /**
84   Get a character cell information from the list specified by GlyphInfoList.
85 
86   This is a internal function.
87 
88   @param  CharValue               Unicode character value, which identifies a glyph
89                                   block.
90   @param  GlyphInfoList           HII_GLYPH_INFO list head.
91   @param  Cell                    Buffer which stores output character cell
92                                   information.
93 
94   @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.
95   @retval EFI_NOT_FOUND           The character info specified by CharValue does
96                                   not exist.
97 
98 **/
99 EFI_STATUS
GetCell(IN CHAR16 CharValue,IN LIST_ENTRY * GlyphInfoList,OUT EFI_HII_GLYPH_INFO * Cell)100 GetCell (
101   IN  CHAR16                         CharValue,
102   IN  LIST_ENTRY                     *GlyphInfoList,
103   OUT EFI_HII_GLYPH_INFO             *Cell
104   )
105 {
106   HII_GLYPH_INFO           *GlyphInfo;
107   LIST_ENTRY               *Link;
108 
109   ASSERT (Cell != NULL && GlyphInfoList != NULL);
110 
111   //
112   // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,
113   // the value of "CharId" of a default character cell which is used for a
114   // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be
115   // less or equal to the value of "CharValueCurrent" of this default block.
116   //
117   // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph
118   // with CharValue equals "7" uses the GlyphInfo with CharId = 7;
119   // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.
120   //
121   for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {
122     GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);
123     if (GlyphInfo->CharId <= CharValue) {
124       CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));
125       return EFI_SUCCESS;
126     }
127   }
128 
129   return EFI_NOT_FOUND;
130 }
131 
132 
133 /**
134   Convert the glyph for a single character into a bitmap.
135 
136   This is a internal function.
137 
138   @param  Private                 HII database driver private data.
139   @param  Char                    Character to retrieve.
140   @param  StringInfo              Points to the string font and color information
141                                   or NULL  if the string should use the default
142                                   system font and color.
143   @param  GlyphBuffer             Buffer to store the retrieved bitmap data.
144   @param  Cell                    Points to EFI_HII_GLYPH_INFO structure.
145   @param  Attributes              If not NULL, output the glyph attributes if any.
146 
147   @retval EFI_SUCCESS             Glyph bitmap outputted.
148   @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer GlyphBuffer.
149   @retval EFI_NOT_FOUND           The glyph was unknown can not be found.
150   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
151 
152 **/
153 EFI_STATUS
GetGlyphBuffer(IN HII_DATABASE_PRIVATE_DATA * Private,IN CHAR16 Char,IN EFI_FONT_INFO * StringInfo,OUT UINT8 ** GlyphBuffer,OUT EFI_HII_GLYPH_INFO * Cell,OUT UINT8 * Attributes OPTIONAL)154 GetGlyphBuffer (
155   IN  HII_DATABASE_PRIVATE_DATA      *Private,
156   IN  CHAR16                         Char,
157   IN  EFI_FONT_INFO                  *StringInfo,
158   OUT UINT8                          **GlyphBuffer,
159   OUT EFI_HII_GLYPH_INFO             *Cell,
160   OUT UINT8                          *Attributes OPTIONAL
161   )
162 {
163   HII_DATABASE_RECORD                *Node;
164   LIST_ENTRY                         *Link;
165   HII_SIMPLE_FONT_PACKAGE_INSTANCE   *SimpleFont;
166   LIST_ENTRY                         *Link1;
167   UINT16                             Index;
168   EFI_NARROW_GLYPH                   Narrow;
169   EFI_WIDE_GLYPH                     Wide;
170   HII_GLOBAL_FONT_INFO               *GlobalFont;
171   UINTN                              HeaderSize;
172   EFI_NARROW_GLYPH                   *NarrowPtr;
173   EFI_WIDE_GLYPH                     *WidePtr;
174 
175   if (GlyphBuffer == NULL || Cell == NULL) {
176     return EFI_INVALID_PARAMETER;
177   }
178   if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
179     return EFI_INVALID_PARAMETER;
180   }
181 
182   ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));
183 
184   //
185   // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather
186   // than system default font and color.
187   // If NULL, try to find the character in simplified font packages since
188   // default system font is the fixed font (narrow or wide glyph).
189   //
190   if (StringInfo != NULL) {
191     if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {
192       return EFI_INVALID_PARAMETER;
193     }
194     if (Attributes != NULL) {
195       *Attributes = PROPORTIONAL_GLYPH;
196     }
197     return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);
198   } else {
199     HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);
200 
201     for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
202       Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
203       for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;
204            Link1 != &Node->PackageList->SimpleFontPkgHdr;
205            Link1 = Link1->ForwardLink
206           ) {
207         SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
208         //
209         // Search the narrow glyph array
210         //
211         NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize);
212         for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {
213           CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH));
214           if (Narrow.UnicodeWeight == Char) {
215             *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT);
216             if (*GlyphBuffer == NULL) {
217               return EFI_OUT_OF_RESOURCES;
218             }
219             Cell->Width    = EFI_GLYPH_WIDTH;
220             Cell->Height   = EFI_GLYPH_HEIGHT;
221             Cell->AdvanceX = Cell->Width;
222             CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);
223             if (Attributes != NULL) {
224               *Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH);
225             }
226             return EFI_SUCCESS;
227           }
228         }
229         //
230         // Search the wide glyph array
231         //
232         WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);
233         for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {
234           CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));
235           if (Wide.UnicodeWeight == Char) {
236             *GlyphBuffer    = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);
237             if (*GlyphBuffer == NULL) {
238               return EFI_OUT_OF_RESOURCES;
239             }
240             Cell->Width    = EFI_GLYPH_WIDTH * 2;
241             Cell->Height   = EFI_GLYPH_HEIGHT;
242             Cell->AdvanceX = Cell->Width;
243             CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);
244             CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);
245             if (Attributes != NULL) {
246               *Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE);
247             }
248             return EFI_SUCCESS;
249           }
250         }
251       }
252     }
253   }
254 
255   return EFI_NOT_FOUND;
256 }
257 
258 /**
259   Convert bitmap data of the glyph to blt structure.
260 
261   This is a internal function.
262 
263   @param GlyphBuffer     Buffer points to bitmap data of glyph.
264   @param  Foreground     The color of the "on" pixels in the glyph in the
265                          bitmap.
266   @param  Background     The color of the "off" pixels in the glyph in the
267                          bitmap.
268   @param  ImageWidth     Width of the whole image in pixels.
269   @param  RowWidth       The width of the text on the line, in pixels.
270   @param  RowHeight      The height of the line, in pixels.
271   @param  Transparent    If TRUE, the Background color is ignored and all
272                          "off" pixels in the character's drawn will use the
273                          pixel value from BltBuffer.
274   @param  Origin         On input, points to the origin of the to be
275                          displayed character, on output, points to the
276                          next glyph's origin.
277 
278 **/
279 VOID
NarrowGlyphToBlt(IN UINT8 * GlyphBuffer,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,IN UINT16 ImageWidth,IN UINTN RowWidth,IN UINTN RowHeight,IN BOOLEAN Transparent,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL ** Origin)280 NarrowGlyphToBlt (
281   IN     UINT8                         *GlyphBuffer,
282   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
283   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
284   IN     UINT16                        ImageWidth,
285   IN     UINTN                         RowWidth,
286   IN     UINTN                         RowHeight,
287   IN     BOOLEAN                       Transparent,
288   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
289   )
290 {
291   UINT8                                Xpos;
292   UINT8                                Ypos;
293   UINT8                                Height;
294   UINT8                                Width;
295   EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *Buffer;
296 
297   ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
298 
299   Height = EFI_GLYPH_HEIGHT;
300   Width  = EFI_GLYPH_WIDTH;
301 
302   //
303   // Move position to the left-top corner of char.
304   //
305   Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth;
306 
307   //
308   // Char may be partially displayed when CLIP_X or CLIP_Y is not set.
309   //
310   if (RowHeight < Height) {
311     Height = (UINT8) RowHeight;
312   }
313   if (RowWidth < Width) {
314     Width = (UINT8) RowWidth;
315   }
316 
317   for (Ypos = 0; Ypos < Height; Ypos++) {
318     for (Xpos = 0; Xpos < Width; Xpos++) {
319       if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) {
320         Buffer[Ypos * ImageWidth + Xpos] = Foreground;
321       } else {
322         if (!Transparent) {
323           Buffer[Ypos * ImageWidth + Xpos] = Background;
324         }
325       }
326     }
327   }
328 
329   *Origin = *Origin + EFI_GLYPH_WIDTH;
330 }
331 
332 
333 /**
334   Convert bitmap data of the glyph to blt structure.
335 
336   This is a internal function.
337 
338   @param  GlyphBuffer             Buffer points to bitmap data of glyph.
339   @param  Foreground              The color of the "on" pixels in the glyph in the
340                                   bitmap.
341   @param  Background              The color of the "off" pixels in the glyph in the
342                                   bitmap.
343   @param  ImageWidth              Width of the whole image in pixels.
344   @param  BaseLine                BaseLine in the line.
345   @param  RowWidth                The width of the text on the line, in pixels.
346   @param  RowHeight               The height of the line, in pixels.
347   @param  Transparent             If TRUE, the Background color is ignored and all
348                                   "off" pixels in the character's drawn will use the
349                                   pixel value from BltBuffer.
350   @param  Cell                    Points to EFI_HII_GLYPH_INFO structure.
351   @param  Attributes              The attribute of incoming glyph in GlyphBuffer.
352   @param  Origin                  On input, points to the origin of the to be
353                                   displayed character, on output, points to the
354                                   next glyph's origin.
355 
356 
357 **/
358 VOID
GlyphToBlt(IN UINT8 * GlyphBuffer,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,IN UINT16 ImageWidth,IN UINT16 BaseLine,IN UINTN RowWidth,IN UINTN RowHeight,IN BOOLEAN Transparent,IN CONST EFI_HII_GLYPH_INFO * Cell,IN UINT8 Attributes,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL ** Origin)359 GlyphToBlt (
360   IN     UINT8                         *GlyphBuffer,
361   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
362   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
363   IN     UINT16                        ImageWidth,
364   IN     UINT16                        BaseLine,
365   IN     UINTN                         RowWidth,
366   IN     UINTN                         RowHeight,
367   IN     BOOLEAN                       Transparent,
368   IN     CONST EFI_HII_GLYPH_INFO      *Cell,
369   IN     UINT8                         Attributes,
370   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
371   )
372 {
373   UINT16                                Xpos;
374   UINT16                                Ypos;
375   UINT8                                 Data;
376   UINT16                                Index;
377   UINT16                                YposOffset;
378   UINTN                                 OffsetY;
379   EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer;
380 
381   ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
382 
383   //
384   // Only adjust origin position if char has no bitmap.
385   //
386   if (GlyphBuffer == NULL) {
387     *Origin = *Origin + Cell->AdvanceX;
388     return;
389   }
390   //
391   // Move position to the left-top corner of char.
392   //
393   BltBuffer  = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth;
394   YposOffset = (UINT16) (BaseLine - (Cell->OffsetY + Cell->Height));
395 
396   //
397   // Since non-spacing key will be printed OR'd with the previous glyph, don't
398   // write 0.
399   //
400   if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
401     Transparent = TRUE;
402   }
403 
404   //
405   // The glyph's upper left hand corner pixel is the most significant bit of the
406   // first bitmap byte.
407   //
408   for (Ypos = 0; Ypos < Cell->Height && (((UINT32) Ypos + YposOffset) < RowHeight); Ypos++) {
409     OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos);
410 
411     //
412     // All bits in these bytes are meaningful.
413     //
414     for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) {
415       Data  = *(GlyphBuffer + OffsetY + Xpos);
416       for (Index = 0; Index < 8 && (((UINT32) Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
417         if ((Data & (1 << (8 - Index - 1))) != 0) {
418           BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
419         } else {
420           if (!Transparent) {
421             BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
422           }
423         }
424       }
425     }
426 
427     if (Cell->Width % 8 != 0) {
428       //
429       // There are some padding bits in this byte. Ignore them.
430       //
431       Data  = *(GlyphBuffer + OffsetY + Xpos);
432       for (Index = 0; Index < Cell->Width % 8 && (((UINT32) Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
433         if ((Data & (1 << (8 - Index - 1))) != 0) {
434           BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
435         } else {
436           if (!Transparent) {
437             BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
438           }
439         }
440       }
441     } // end of if (Width % 8...)
442 
443   } // end of for (Ypos=0...)
444 
445   *Origin = *Origin + Cell->AdvanceX;
446 }
447 
448 
449 /**
450   Convert bitmap data of the glyph to blt structure.
451 
452   This is a internal function.
453 
454   @param  GlyphBuffer             Buffer points to bitmap data of glyph.
455   @param  Foreground              The color of the "on" pixels in the glyph in the
456                                   bitmap.
457   @param  Background              The color of the "off" pixels in the glyph in the
458                                   bitmap.
459   @param  ImageWidth              Width of the whole image in pixels.
460   @param  BaseLine                BaseLine in the line.
461   @param  RowWidth                The width of the text on the line, in pixels.
462   @param  RowHeight               The height of the line, in pixels.
463   @param  Transparent             If TRUE, the Background color is ignored and all
464                                   "off" pixels in the character's drawn will use the
465                                   pixel value from BltBuffer.
466   @param  Cell                    Points to EFI_HII_GLYPH_INFO structure.
467   @param  Attributes              The attribute of incoming glyph in GlyphBuffer.
468   @param  Origin                  On input, points to the origin of the to be
469                                   displayed character, on output, points to the
470                                   next glyph's origin.
471 
472   @return Points to the address of next origin node in BltBuffer.
473 
474 **/
475 VOID
GlyphToImage(IN UINT8 * GlyphBuffer,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,IN UINT16 ImageWidth,IN UINT16 BaseLine,IN UINTN RowWidth,IN UINTN RowHeight,IN BOOLEAN Transparent,IN CONST EFI_HII_GLYPH_INFO * Cell,IN UINT8 Attributes,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL ** Origin)476 GlyphToImage (
477   IN     UINT8                         *GlyphBuffer,
478   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
479   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
480   IN     UINT16                        ImageWidth,
481   IN     UINT16                        BaseLine,
482   IN     UINTN                         RowWidth,
483   IN     UINTN                         RowHeight,
484   IN     BOOLEAN                       Transparent,
485   IN     CONST EFI_HII_GLYPH_INFO      *Cell,
486   IN     UINT8                         Attributes,
487   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
488   )
489 {
490   EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *Buffer;
491 
492   ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
493 
494   Buffer = *Origin;
495 
496   if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
497     //
498     // This character is a non-spacing key, print it OR'd with the previous glyph.
499     // without advancing cursor.
500     //
501     Buffer -= Cell->AdvanceX;
502     GlyphToBlt (
503       GlyphBuffer,
504       Foreground,
505       Background,
506       ImageWidth,
507       BaseLine,
508       RowWidth,
509       RowHeight,
510       Transparent,
511       Cell,
512       Attributes,
513       &Buffer
514       );
515 
516   } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {
517     //
518     // This character is wide glyph, i.e. 16 pixels * 19 pixels.
519     // Draw it as two narrow glyphs.
520     //
521     NarrowGlyphToBlt (
522       GlyphBuffer,
523       Foreground,
524       Background,
525       ImageWidth,
526       RowWidth,
527       RowHeight,
528       Transparent,
529       Origin
530       );
531 
532     NarrowGlyphToBlt (
533       GlyphBuffer + EFI_GLYPH_HEIGHT,
534       Foreground,
535       Background,
536       ImageWidth,
537       RowWidth,
538       RowHeight,
539       Transparent,
540       Origin
541       );
542 
543   } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {
544     //
545     // This character is narrow glyph, i.e. 8 pixels * 19 pixels.
546     //
547     NarrowGlyphToBlt (
548       GlyphBuffer,
549       Foreground,
550       Background,
551       ImageWidth,
552       RowWidth,
553       RowHeight,
554       Transparent,
555       Origin
556       );
557 
558   } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {
559     //
560     // This character is proportional glyph, i.e. Cell->Width * Cell->Height pixels.
561     //
562     GlyphToBlt (
563       GlyphBuffer,
564       Foreground,
565       Background,
566       ImageWidth,
567       BaseLine,
568       RowWidth,
569       RowHeight,
570       Transparent,
571       Cell,
572       Attributes,
573       Origin
574       );
575   }
576 }
577 
578 
579 /**
580   Write the output parameters of FindGlyphBlock().
581 
582   This is a internal function.
583 
584   @param  BufferIn                Buffer which stores the bitmap data of the found
585                                   block.
586   @param  BufferLen               Length of BufferIn.
587   @param  InputCell               Buffer which stores cell information of the
588                                   encoded bitmap.
589   @param  GlyphBuffer             Output the corresponding bitmap data of the found
590                                   block. It is the caller's responsibility to free
591                                   this buffer.
592   @param  Cell                    Output cell information of the encoded bitmap.
593   @param  GlyphBufferLen          If not NULL, output the length of GlyphBuffer.
594 
595   @retval EFI_SUCCESS             The operation is performed successfully.
596   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
597   @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
598                                   task.
599 
600 **/
601 EFI_STATUS
WriteOutputParam(IN UINT8 * BufferIn,IN UINTN BufferLen,IN EFI_HII_GLYPH_INFO * InputCell,OUT UINT8 ** GlyphBuffer,OPTIONAL OUT EFI_HII_GLYPH_INFO * Cell,OPTIONAL OUT UINTN * GlyphBufferLen OPTIONAL)602 WriteOutputParam (
603   IN  UINT8                          *BufferIn,
604   IN  UINTN                          BufferLen,
605   IN  EFI_HII_GLYPH_INFO             *InputCell,
606   OUT UINT8                          **GlyphBuffer, OPTIONAL
607   OUT EFI_HII_GLYPH_INFO             *Cell, OPTIONAL
608   OUT UINTN                          *GlyphBufferLen OPTIONAL
609   )
610 {
611   if (BufferIn == NULL || InputCell == NULL) {
612     return EFI_INVALID_PARAMETER;
613   }
614 
615   if (Cell != NULL) {
616     CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
617   }
618 
619   if (GlyphBuffer != NULL && BufferLen > 0) {
620     *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);
621     if (*GlyphBuffer == NULL) {
622       return EFI_OUT_OF_RESOURCES;
623     }
624     CopyMem (*GlyphBuffer, BufferIn, BufferLen);
625   }
626 
627   if (GlyphBufferLen != NULL) {
628     *GlyphBufferLen = BufferLen;
629   }
630 
631   return EFI_SUCCESS;
632 }
633 
634 
635 /**
636   Parse all glyph blocks to find a glyph block specified by CharValue.
637   If CharValue = (CHAR16) (-1), collect all default character cell information
638   within this font package and backup its information.
639 
640   @param  FontPackage             Hii string package instance.
641   @param  CharValue               Unicode character value, which identifies a glyph
642                                   block.
643   @param  GlyphBuffer             Output the corresponding bitmap data of the found
644                                   block. It is the caller's responsibility to free
645                                   this buffer.
646   @param  Cell                    Output cell information of the encoded bitmap.
647   @param  GlyphBufferLen          If not NULL, output the length of GlyphBuffer.
648 
649   @retval EFI_SUCCESS             The bitmap data is retrieved successfully.
650   @retval EFI_NOT_FOUND           The specified CharValue does not exist in current
651                                   database.
652   @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
653                                   task.
654 
655 **/
656 EFI_STATUS
FindGlyphBlock(IN HII_FONT_PACKAGE_INSTANCE * FontPackage,IN CHAR16 CharValue,OUT UINT8 ** GlyphBuffer,OPTIONAL OUT EFI_HII_GLYPH_INFO * Cell,OPTIONAL OUT UINTN * GlyphBufferLen OPTIONAL)657 FindGlyphBlock (
658   IN  HII_FONT_PACKAGE_INSTANCE      *FontPackage,
659   IN  CHAR16                         CharValue,
660   OUT UINT8                          **GlyphBuffer, OPTIONAL
661   OUT EFI_HII_GLYPH_INFO             *Cell, OPTIONAL
662   OUT UINTN                          *GlyphBufferLen OPTIONAL
663   )
664 {
665   EFI_STATUS                          Status;
666   UINT8                               *BlockPtr;
667   UINT16                              CharCurrent;
668   UINT16                              Length16;
669   UINT32                              Length32;
670   EFI_HII_GIBT_GLYPHS_BLOCK           Glyphs;
671   UINTN                               BufferLen;
672   UINT16                              Index;
673   EFI_HII_GLYPH_INFO                  DefaultCell;
674   EFI_HII_GLYPH_INFO                  LocalCell;
675   INT16                               MinOffsetY;
676   UINT16                              BaseLine;
677 
678   ASSERT (FontPackage != NULL);
679   ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
680   BaseLine  = 0;
681   MinOffsetY = 0;
682 
683   if (CharValue == (CHAR16) (-1)) {
684     //
685     // Collect the cell information specified in font package fixed header.
686     // Use CharValue =0 to represent this particular cell.
687     //
688     Status = NewCell (
689                0,
690                &FontPackage->GlyphInfoList,
691                (EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32))
692                );
693     if (EFI_ERROR (Status)) {
694       return Status;
695     }
696     CopyMem (
697       &LocalCell,
698       (UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32),
699       sizeof (EFI_HII_GLYPH_INFO)
700       );
701   }
702 
703   BlockPtr    = FontPackage->GlyphBlock;
704   CharCurrent = 1;
705   BufferLen   = 0;
706 
707   while (*BlockPtr != EFI_HII_GIBT_END) {
708     switch (*BlockPtr) {
709     case EFI_HII_GIBT_DEFAULTS:
710       //
711       // Collect all default character cell information specified by
712       // EFI_HII_GIBT_DEFAULTS.
713       //
714       if (CharValue == (CHAR16) (-1)) {
715         Status = NewCell (
716                    CharCurrent,
717                    &FontPackage->GlyphInfoList,
718                    (EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))
719                    );
720         if (EFI_ERROR (Status)) {
721           return Status;
722         }
723         CopyMem (
724           &LocalCell,
725           BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
726           sizeof (EFI_HII_GLYPH_INFO)
727           );
728         if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
729           BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);
730         }
731         if (MinOffsetY > LocalCell.OffsetY) {
732           MinOffsetY = LocalCell.OffsetY;
733         }
734       }
735       BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);
736       break;
737 
738     case EFI_HII_GIBT_DUPLICATE:
739       if (CharCurrent == CharValue) {
740         CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));
741         CharCurrent = 1;
742         BlockPtr    = FontPackage->GlyphBlock;
743         continue;
744       }
745       CharCurrent++;
746       BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);
747       break;
748 
749     case EFI_HII_GIBT_EXT1:
750       BlockPtr += *(UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
751       break;
752     case EFI_HII_GIBT_EXT2:
753       CopyMem (
754         &Length16,
755         (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
756         sizeof (UINT16)
757         );
758       BlockPtr += Length16;
759       break;
760     case EFI_HII_GIBT_EXT4:
761       CopyMem (
762         &Length32,
763         (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
764         sizeof (UINT32)
765         );
766       BlockPtr += Length32;
767       break;
768 
769     case EFI_HII_GIBT_GLYPH:
770       CopyMem (
771         &LocalCell,
772         BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
773         sizeof (EFI_HII_GLYPH_INFO)
774         );
775       if (CharValue == (CHAR16) (-1)) {
776         if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
777           BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);
778         }
779         if (MinOffsetY > LocalCell.OffsetY) {
780           MinOffsetY = LocalCell.OffsetY;
781         }
782       }
783       BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
784       if (CharCurrent == CharValue) {
785         return WriteOutputParam (
786                  (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8)),
787                  BufferLen,
788                  &LocalCell,
789                  GlyphBuffer,
790                  Cell,
791                  GlyphBufferLen
792                  );
793       }
794       CharCurrent++;
795       BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;
796       break;
797 
798     case EFI_HII_GIBT_GLYPHS:
799       BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);
800       CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));
801       BlockPtr += sizeof (EFI_HII_GLYPH_INFO);
802       CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));
803       BlockPtr += sizeof (UINT16);
804 
805       if (CharValue == (CHAR16) (-1)) {
806         if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) {
807           BaseLine = (UINT16) (Glyphs.Cell.Height + Glyphs.Cell.OffsetY);
808         }
809         if (MinOffsetY > Glyphs.Cell.OffsetY) {
810           MinOffsetY = Glyphs.Cell.OffsetY;
811         }
812       }
813 
814       BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);
815       for (Index = 0; Index < Glyphs.Count; Index++) {
816         if (CharCurrent + Index == CharValue) {
817           return WriteOutputParam (
818                    BlockPtr,
819                    BufferLen,
820                    &Glyphs.Cell,
821                    GlyphBuffer,
822                    Cell,
823                    GlyphBufferLen
824                    );
825         }
826         BlockPtr += BufferLen;
827       }
828       CharCurrent = (UINT16) (CharCurrent + Glyphs.Count);
829       break;
830 
831     case EFI_HII_GIBT_GLYPH_DEFAULT:
832       Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
833       if (EFI_ERROR (Status)) {
834         return Status;
835       }
836       if (CharValue == (CHAR16) (-1)) {
837         if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
838           BaseLine = (UINT16) (DefaultCell.Height + DefaultCell.OffsetY);
839         }
840         if (MinOffsetY > DefaultCell.OffsetY) {
841           MinOffsetY = DefaultCell.OffsetY;
842         }
843       }
844       BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
845 
846       if (CharCurrent == CharValue) {
847         return WriteOutputParam (
848                  BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
849                  BufferLen,
850                  &DefaultCell,
851                  GlyphBuffer,
852                  Cell,
853                  GlyphBufferLen
854                  );
855       }
856       CharCurrent++;
857       BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;
858       break;
859 
860     case EFI_HII_GIBT_GLYPHS_DEFAULT:
861       CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
862       Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
863       if (EFI_ERROR (Status)) {
864         return Status;
865       }
866       if (CharValue == (CHAR16) (-1)) {
867         if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
868           BaseLine = (UINT16) (DefaultCell.Height + DefaultCell.OffsetY);
869         }
870         if (MinOffsetY > DefaultCell.OffsetY) {
871           MinOffsetY = DefaultCell.OffsetY;
872         }
873       }
874       BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
875       BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);
876       for (Index = 0; Index < Length16; Index++) {
877         if (CharCurrent + Index == CharValue) {
878           return WriteOutputParam (
879                    BlockPtr,
880                    BufferLen,
881                    &DefaultCell,
882                    GlyphBuffer,
883                    Cell,
884                    GlyphBufferLen
885                    );
886         }
887         BlockPtr += BufferLen;
888       }
889       CharCurrent = (UINT16) (CharCurrent + Length16);
890       break;
891 
892     case EFI_HII_GIBT_SKIP1:
893       CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));
894       BlockPtr    += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);
895       break;
896     case EFI_HII_GIBT_SKIP2:
897       CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
898       CharCurrent = (UINT16) (CharCurrent + Length16);
899       BlockPtr    += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);
900       break;
901     default:
902       ASSERT (FALSE);
903       break;
904     }
905 
906     if (CharValue < CharCurrent) {
907       return EFI_NOT_FOUND;
908     }
909   }
910 
911   if (CharValue == (CHAR16) (-1)) {
912     FontPackage->BaseLine = BaseLine;
913     FontPackage->Height   = (UINT16) (BaseLine - MinOffsetY);
914     return EFI_SUCCESS;
915   }
916 
917   return EFI_NOT_FOUND;
918 }
919 
920 
921 /**
922   Copy a Font Name to a new created EFI_FONT_INFO structure.
923 
924   This is a internal function.
925 
926   @param  FontName                NULL-terminated string.
927   @param  FontInfo                a new EFI_FONT_INFO which stores the FontName.
928                                   It's caller's responsibility to free this buffer.
929 
930   @retval EFI_SUCCESS             FontInfo is allocated and copied with FontName.
931   @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
932                                   task.
933 
934 **/
935 EFI_STATUS
SaveFontName(IN EFI_STRING FontName,OUT EFI_FONT_INFO ** FontInfo)936 SaveFontName (
937   IN  EFI_STRING                       FontName,
938   OUT EFI_FONT_INFO                    **FontInfo
939   )
940 {
941   UINTN         FontInfoLen;
942   UINTN         NameSize;
943 
944   ASSERT (FontName != NULL && FontInfo != NULL);
945 
946   NameSize = StrSize (FontName);
947   FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;
948   *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);
949   if (*FontInfo == NULL) {
950     return EFI_OUT_OF_RESOURCES;
951   }
952 
953   StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), FontName);
954   return EFI_SUCCESS;
955 }
956 
957 
958 /**
959   Retrieve system default font and color.
960 
961   @param  Private                 HII database driver private data.
962   @param  FontInfo                Points to system default font output-related
963                                   information. It's caller's responsibility to free
964                                   this buffer.
965   @param  FontInfoSize            If not NULL, output the size of buffer FontInfo.
966 
967   @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.
968   @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
969                                   task.
970   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
971 
972 **/
973 EFI_STATUS
GetSystemFont(IN HII_DATABASE_PRIVATE_DATA * Private,OUT EFI_FONT_DISPLAY_INFO ** FontInfo,OUT UINTN * FontInfoSize OPTIONAL)974 GetSystemFont (
975   IN  HII_DATABASE_PRIVATE_DATA      *Private,
976   OUT EFI_FONT_DISPLAY_INFO          **FontInfo,
977   OUT UINTN                          *FontInfoSize OPTIONAL
978   )
979 {
980   EFI_FONT_DISPLAY_INFO              *Info;
981   UINTN                              InfoSize;
982   UINTN                              NameSize;
983 
984   if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
985     return EFI_INVALID_PARAMETER;
986   }
987   if (FontInfo == NULL) {
988     return EFI_INVALID_PARAMETER;
989   }
990 
991   //
992   // The standard font always has the name "sysdefault".
993   //
994   NameSize = StrSize (L"sysdefault");
995   InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
996   Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);
997   if (Info == NULL) {
998     return EFI_OUT_OF_RESOURCES;
999   }
1000 
1001   Info->ForegroundColor    = mHiiEfiColors[Private->Attribute & 0x0f];
1002   Info->BackgroundColor    = mHiiEfiColors[Private->Attribute >> 4];
1003   Info->FontInfoMask       = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
1004   Info->FontInfo.FontStyle = 0;
1005   Info->FontInfo.FontSize  = EFI_GLYPH_HEIGHT;
1006   StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");
1007 
1008   *FontInfo = Info;
1009   if (FontInfoSize != NULL) {
1010     *FontInfoSize = InfoSize;
1011   }
1012   return EFI_SUCCESS;
1013 }
1014 
1015 
1016 /**
1017   Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or
1018   returns the system default according to the optional inputs.
1019 
1020   This is a internal function.
1021 
1022   @param  Private                 HII database driver private data.
1023   @param  StringInfo              Points to the string output information,
1024                                   including the color and font.
1025   @param  SystemInfo              If not NULL, points to system default font and color.
1026 
1027   @param  SystemInfoLen           If not NULL, output the length of default system
1028                                   info.
1029 
1030   @retval TRUE                    Yes, it points to system default.
1031   @retval FALSE                   No.
1032 
1033 **/
1034 BOOLEAN
IsSystemFontInfo(IN HII_DATABASE_PRIVATE_DATA * Private,IN EFI_FONT_DISPLAY_INFO * StringInfo,OUT EFI_FONT_DISPLAY_INFO ** SystemInfo,OPTIONAL OUT UINTN * SystemInfoLen OPTIONAL)1035 IsSystemFontInfo (
1036   IN  HII_DATABASE_PRIVATE_DATA      *Private,
1037   IN  EFI_FONT_DISPLAY_INFO          *StringInfo,
1038   OUT EFI_FONT_DISPLAY_INFO          **SystemInfo, OPTIONAL
1039   OUT UINTN                          *SystemInfoLen OPTIONAL
1040   )
1041 {
1042   EFI_STATUS                          Status;
1043   EFI_FONT_DISPLAY_INFO               *SystemDefault;
1044   UINTN                               DefaultLen;
1045   BOOLEAN                             Flag;
1046 
1047   ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1048 
1049   if (StringInfo == NULL && SystemInfo == NULL) {
1050     return TRUE;
1051   }
1052 
1053   SystemDefault = NULL;
1054   DefaultLen    = 0;
1055 
1056   Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
1057   ASSERT_EFI_ERROR (Status);
1058   ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
1059 
1060   //
1061   // Record the system default info.
1062   //
1063   if (SystemInfo != NULL) {
1064     *SystemInfo = SystemDefault;
1065   }
1066 
1067   if (SystemInfoLen != NULL) {
1068     *SystemInfoLen = DefaultLen;
1069   }
1070 
1071   if (StringInfo == NULL) {
1072     return TRUE;
1073   }
1074 
1075   Flag = FALSE;
1076   //
1077   // Check the FontInfoMask to see whether it is retrieving system info.
1078   //
1079   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) {
1080     if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) {
1081       goto Exit;
1082     }
1083   }
1084   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) {
1085     if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) {
1086       goto Exit;
1087     }
1088   }
1089   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) {
1090     if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) {
1091       goto Exit;
1092     }
1093   }
1094   if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) {
1095     if (CompareMem (
1096           &StringInfo->ForegroundColor,
1097           &SystemDefault->ForegroundColor,
1098           sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1099           ) != 0) {
1100       goto Exit;
1101     }
1102   }
1103   if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) {
1104     if (CompareMem (
1105           &StringInfo->BackgroundColor,
1106           &SystemDefault->BackgroundColor,
1107           sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1108           ) != 0) {
1109       goto Exit;
1110     }
1111   }
1112 
1113   Flag = TRUE;
1114 
1115 Exit:
1116   if (SystemInfo == NULL) {
1117     if (SystemDefault != NULL) {
1118       FreePool (SystemDefault);
1119     }
1120   }
1121   return Flag;
1122 }
1123 
1124 
1125 /**
1126   This function checks whether EFI_FONT_INFO exists in current database. If
1127   FontInfoMask is specified, check what options can be used to make a match.
1128   Note that the masks relate to where the system default should be supplied
1129   are ignored by this function.
1130 
1131   @param  Private                 Hii database private structure.
1132   @param  FontInfo                Points to EFI_FONT_INFO structure.
1133   @param  FontInfoMask            If not NULL, describes what options can be used
1134                                   to make a match between the font requested and
1135                                   the font available. The caller must guarantee
1136                                   this mask is valid.
1137   @param  FontHandle              On entry, Points to the font handle returned by a
1138                                   previous  call to GetFontInfo() or NULL to start
1139                                   with the first font.
1140   @param  GlobalFontInfo          If not NULL, output the corresponding global font
1141                                   info.
1142 
1143   @retval TRUE                    Existed
1144   @retval FALSE                   Not existed
1145 
1146 **/
1147 BOOLEAN
IsFontInfoExisted(IN HII_DATABASE_PRIVATE_DATA * Private,IN EFI_FONT_INFO * FontInfo,IN EFI_FONT_INFO_MASK * FontInfoMask,OPTIONAL IN EFI_FONT_HANDLE FontHandle,OPTIONAL OUT HII_GLOBAL_FONT_INFO ** GlobalFontInfo OPTIONAL)1148 IsFontInfoExisted (
1149   IN  HII_DATABASE_PRIVATE_DATA *Private,
1150   IN  EFI_FONT_INFO             *FontInfo,
1151   IN  EFI_FONT_INFO_MASK        *FontInfoMask,   OPTIONAL
1152   IN  EFI_FONT_HANDLE           FontHandle,      OPTIONAL
1153   OUT HII_GLOBAL_FONT_INFO      **GlobalFontInfo OPTIONAL
1154   )
1155 {
1156   HII_GLOBAL_FONT_INFO          *GlobalFont;
1157   HII_GLOBAL_FONT_INFO          *GlobalFontBackup1;
1158   HII_GLOBAL_FONT_INFO          *GlobalFontBackup2;
1159   LIST_ENTRY                    *Link;
1160   EFI_FONT_INFO_MASK            Mask;
1161   BOOLEAN                       Matched;
1162   BOOLEAN                       VagueMatched1;
1163   BOOLEAN                       VagueMatched2;
1164 
1165   ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1166   ASSERT (FontInfo != NULL);
1167 
1168   //
1169   // Matched flag represents an exactly match; VagueMatched1 represents a RESIZE
1170   // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
1171   //
1172   Matched           = FALSE;
1173   VagueMatched1     = FALSE;
1174   VagueMatched2     = FALSE;
1175 
1176   Mask              = 0;
1177   GlobalFontBackup1 = NULL;
1178   GlobalFontBackup2 = NULL;
1179 
1180   // The process of where the system default should be supplied instead of
1181   // the specified font info beyonds this function's scope.
1182   //
1183   if (FontInfoMask != NULL) {
1184     Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
1185   }
1186 
1187   //
1188   // If not NULL, FontHandle points to the next node of the last searched font
1189   // node by previous call.
1190   //
1191   if (FontHandle == NULL) {
1192     Link = Private->FontInfoList.ForwardLink;
1193   } else {
1194     Link = (LIST_ENTRY     *) FontHandle;
1195   }
1196 
1197   for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
1198     GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
1199     if (FontInfoMask == NULL) {
1200       if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
1201         if (GlobalFontInfo != NULL) {
1202           *GlobalFontInfo = GlobalFont;
1203         }
1204         return TRUE;
1205       }
1206     } else {
1207       //
1208       // Check which options could be used to make a match.
1209       //
1210       switch (Mask) {
1211       case EFI_FONT_INFO_ANY_FONT:
1212         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&
1213             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1214           Matched = TRUE;
1215         }
1216         break;
1217       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
1218         if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1219           Matched = TRUE;
1220         }
1221         break;
1222       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
1223         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1224           Matched = TRUE;
1225         }
1226         break;
1227       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
1228         Matched   = TRUE;
1229         break;
1230       //
1231       // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
1232       // remove some of the specified styles to meet the style requested.
1233       //
1234       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
1235         if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1236           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1237             Matched           = TRUE;
1238           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1239             VagueMatched1     = TRUE;
1240             GlobalFontBackup1 = GlobalFont;
1241           }
1242         }
1243         break;
1244       //
1245       // If EFI_FONT_INFO_RESIZE is specified, then the system may attempt to
1246       // stretch or shrink a font to meet the size requested.
1247       //
1248       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
1249         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1250           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1251             Matched           = TRUE;
1252           } else {
1253             VagueMatched1     = TRUE;
1254             GlobalFontBackup1 = GlobalFont;
1255           }
1256         }
1257         break;
1258       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
1259         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1260           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1261             Matched           = TRUE;
1262           } else {
1263             VagueMatched1     = TRUE;
1264             GlobalFontBackup1 = GlobalFont;
1265           }
1266         } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1267           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1268             VagueMatched1     = TRUE;
1269             GlobalFontBackup1 = GlobalFont;
1270           } else {
1271             VagueMatched2     = TRUE;
1272             GlobalFontBackup2 = GlobalFont;
1273           }
1274         }
1275         break;
1276       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1277         if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1278           Matched           = TRUE;
1279         } else {
1280           VagueMatched1     = TRUE;
1281           GlobalFontBackup1 = GlobalFont;
1282         }
1283         break;
1284       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1285         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1286           Matched           = TRUE;
1287         } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1288           VagueMatched1     = TRUE;
1289           GlobalFontBackup1 = GlobalFont;
1290         }
1291         break;
1292       case EFI_FONT_INFO_ANY_STYLE:
1293         if ((CompareMem (
1294                GlobalFont->FontInfo->FontName,
1295                FontInfo->FontName,
1296                StrSize (FontInfo->FontName)
1297                ) == 0) &&
1298             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1299           Matched = TRUE;
1300         }
1301         break;
1302       case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
1303         if (CompareMem (
1304               GlobalFont->FontInfo->FontName,
1305               FontInfo->FontName,
1306               StrSize (FontInfo->FontName)
1307               ) == 0) {
1308           Matched = TRUE;
1309         }
1310         break;
1311       case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1312         if (CompareMem (
1313               GlobalFont->FontInfo->FontName,
1314               FontInfo->FontName,
1315               StrSize (FontInfo->FontName)
1316               ) == 0) {
1317           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1318             Matched           = TRUE;
1319           } else {
1320             VagueMatched1     = TRUE;
1321             GlobalFontBackup1 = GlobalFont;
1322           }
1323         }
1324         break;
1325       case EFI_FONT_INFO_ANY_SIZE:
1326         if ((CompareMem (
1327                GlobalFont->FontInfo->FontName,
1328                FontInfo->FontName,
1329                StrSize (FontInfo->FontName)
1330                ) == 0) &&
1331             GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {
1332           Matched = TRUE;
1333         }
1334         break;
1335       case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1336         if (CompareMem (
1337               GlobalFont->FontInfo->FontName,
1338               FontInfo->FontName,
1339               StrSize (FontInfo->FontName)
1340               ) == 0) {
1341           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1342             Matched           = TRUE;
1343           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1344             VagueMatched1     = TRUE;
1345             GlobalFontBackup1 = GlobalFont;
1346           }
1347         }
1348         break;
1349       case EFI_FONT_INFO_RESTYLE:
1350         if ((CompareMem (
1351                GlobalFont->FontInfo->FontName,
1352                FontInfo->FontName,
1353                StrSize (FontInfo->FontName)
1354                ) == 0) &&
1355             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1356 
1357           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1358             Matched           = TRUE;
1359           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1360             VagueMatched1     = TRUE;
1361             GlobalFontBackup1 = GlobalFont;
1362           }
1363         }
1364         break;
1365       case EFI_FONT_INFO_RESIZE:
1366         if ((CompareMem (
1367                GlobalFont->FontInfo->FontName,
1368                FontInfo->FontName,
1369                StrSize (FontInfo->FontName)
1370                ) == 0) &&
1371             GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {
1372 
1373           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1374             Matched           = TRUE;
1375           } else {
1376             VagueMatched1     = TRUE;
1377             GlobalFontBackup1 = GlobalFont;
1378           }
1379         }
1380         break;
1381       case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
1382         if (CompareMem (
1383               GlobalFont->FontInfo->FontName,
1384               FontInfo->FontName,
1385               StrSize (FontInfo->FontName)
1386               ) == 0) {
1387           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1388             if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1389               Matched           = TRUE;
1390             } else {
1391               VagueMatched1     = TRUE;
1392               GlobalFontBackup1 = GlobalFont;
1393             }
1394           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1395             if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1396               VagueMatched1     = TRUE;
1397               GlobalFontBackup1 = GlobalFont;
1398             } else {
1399               VagueMatched2     = TRUE;
1400               GlobalFontBackup2 = GlobalFont;
1401             }
1402           }
1403         }
1404         break;
1405       default:
1406         break;
1407       }
1408 
1409       if (Matched) {
1410         if (GlobalFontInfo != NULL) {
1411           *GlobalFontInfo = GlobalFont;
1412         }
1413         return TRUE;
1414       }
1415     }
1416   }
1417 
1418   if (VagueMatched1) {
1419     if (GlobalFontInfo != NULL) {
1420       *GlobalFontInfo = GlobalFontBackup1;
1421     }
1422     return TRUE;
1423   } else if (VagueMatched2) {
1424     if (GlobalFontInfo != NULL) {
1425       *GlobalFontInfo = GlobalFontBackup2;
1426     }
1427     return TRUE;
1428   }
1429 
1430   return FALSE;
1431 }
1432 
1433 
1434 /**
1435   Check whether the unicode represents a line break or not.
1436 
1437   This is a internal function. Please see Section 27.2.6 of the UEFI Specification
1438   for a description of the supported string format.
1439 
1440   @param  Char                    Unicode character
1441 
1442   @retval 0                       Yes, it forces a line break.
1443   @retval 1                       Yes, it presents a line break opportunity
1444   @retval 2                       Yes, it requires a line break happen before and after it.
1445   @retval -1                      No, it is not a link break.
1446 
1447 **/
1448 INT8
IsLineBreak(IN CHAR16 Char)1449 IsLineBreak (
1450   IN  CHAR16    Char
1451   )
1452 {
1453   switch (Char) {
1454     //
1455     // Mandatory line break characters, which force a line-break
1456     //
1457     case 0x000A:
1458     case 0x000C:
1459     case 0x000D:
1460     case 0x2028:
1461     case 0x2029:
1462       return 0;
1463     //
1464     // Space characters, which is taken as a line-break opportunity
1465     //
1466     case 0x0020:
1467     case 0x1680:
1468     case 0x2000:
1469     case 0x2001:
1470     case 0x2002:
1471     case 0x2003:
1472     case 0x2004:
1473     case 0x2005:
1474     case 0x2006:
1475     case 0x2008:
1476     case 0x2009:
1477     case 0x200A:
1478     case 0x205F:
1479     //
1480     // In-Word Break Opportunities
1481     //
1482     case 0x200B:
1483       return 1;
1484     //
1485     // A space which is not a line-break opportunity
1486     //
1487     case 0x00A0:
1488     case 0x202F:
1489     //
1490     // A hyphen which is not a line-break opportunity
1491     //
1492     case 0x2011:
1493       return -1;
1494     //
1495     // Hyphen characters which describe line break opportunities after the character
1496     //
1497     case 0x058A:
1498     case 0x2010:
1499     case 0x2012:
1500     case 0x2013:
1501     case 0x0F0B:
1502     case 0x1361:
1503     case 0x17D5:
1504       return 1;
1505     //
1506     // A hyphen which describes line break opportunities before and after them, but not between a pair of them
1507     //
1508     case 0x2014:
1509       return 2;
1510   }
1511   return -1;
1512 }
1513 
1514 
1515 /**
1516   Renders a string to a bitmap or to the display.
1517 
1518   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
1519   @param  Flags                   Describes how the string is to be drawn.
1520   @param  String                  Points to the null-terminated string to be
1521                                   displayed.
1522   @param  StringInfo              Points to the string output information,
1523                                   including the color and font.  If NULL, then the
1524                                   string will be output in the default system font
1525                                   and color.
1526   @param  Blt                     If this points to a non-NULL on entry, this
1527                                   points to the image, which is Width pixels   wide
1528                                   and Height pixels high. The string will be drawn
1529                                   onto this image and
1530                                   EFI_HII_OUT_FLAG_CLIP is implied. If this points
1531                                   to a NULL on entry, then a              buffer
1532                                   will be allocated to hold the generated image and
1533                                   the pointer updated on exit. It is the caller's
1534                                   responsibility to free this buffer.
1535   @param  BltX                    Specifies the offset from the left and top edge
1536                                   of the image of the first character cell in the
1537                                   image.
1538   @param  BltY                    Specifies the offset from the left and top edge
1539                                   of the image of the first character cell in the
1540                                   image.
1541   @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
1542                                   will point to an allocated buffer    containing
1543                                   row information and RowInfoArraySize will be
1544                                   updated to contain the        number of elements.
1545                                   This array describes the characters which were at
1546                                   least partially drawn and the heights of the
1547                                   rows. It is the caller's responsibility to free
1548                                   this buffer.
1549   @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
1550                                   contains the number of elements in RowInfoArray.
1551   @param  ColumnInfoArray         If this is non-NULL, then on return it will be
1552                                   filled with the horizontal offset for each
1553                                   character in the string on the row where it is
1554                                   displayed. Non-printing characters will     have
1555                                   the offset ~0. The caller is responsible to
1556                                   allocate a buffer large enough so that    there
1557                                   is one entry for each character in the string,
1558                                   not including the null-terminator. It is possible
1559                                   when character display is normalized that some
1560                                   character cells overlap.
1561 
1562   @retval EFI_SUCCESS             The string was successfully rendered.
1563   @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for
1564                                   RowInfoArray or Blt.
1565   @retval EFI_INVALID_PARAMETER   The String or Blt was NULL.
1566   @retval EFI_INVALID_PARAMETER Flags were invalid combination..
1567 
1568 **/
1569 EFI_STATUS
1570 EFIAPI
HiiStringToImage(IN CONST EFI_HII_FONT_PROTOCOL * This,IN EFI_HII_OUT_FLAGS Flags,IN CONST EFI_STRING String,IN CONST EFI_FONT_DISPLAY_INFO * StringInfo OPTIONAL,IN OUT EFI_IMAGE_OUTPUT ** Blt,IN UINTN BltX,IN UINTN BltY,OUT EFI_HII_ROW_INFO ** RowInfoArray OPTIONAL,OUT UINTN * RowInfoArraySize OPTIONAL,OUT UINTN * ColumnInfoArray OPTIONAL)1571 HiiStringToImage (
1572   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
1573   IN  EFI_HII_OUT_FLAGS              Flags,
1574   IN  CONST EFI_STRING               String,
1575   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
1576   IN  OUT EFI_IMAGE_OUTPUT           **Blt,
1577   IN  UINTN                          BltX,
1578   IN  UINTN                          BltY,
1579   OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
1580   OUT UINTN                          *RowInfoArraySize OPTIONAL,
1581   OUT UINTN                          *ColumnInfoArray  OPTIONAL
1582   )
1583 {
1584   EFI_STATUS                          Status;
1585   HII_DATABASE_PRIVATE_DATA           *Private;
1586   UINT8                               **GlyphBuf;
1587   EFI_HII_GLYPH_INFO                  *Cell;
1588   UINT8                               *Attributes;
1589   EFI_IMAGE_OUTPUT                    *Image;
1590   EFI_STRING                          StringPtr;
1591   EFI_STRING                          StringTmp;
1592   EFI_HII_ROW_INFO                    *RowInfo;
1593   UINTN                               LineWidth;
1594   UINTN                               LineHeight;
1595   UINTN                               LineOffset;
1596   UINTN                               LastLineHeight;
1597   UINTN                               BaseLineOffset;
1598   UINT16                              MaxRowNum;
1599   UINT16                              RowIndex;
1600   UINTN                               Index;
1601   UINTN                               NextIndex;
1602   UINTN                               Index1;
1603   EFI_FONT_DISPLAY_INFO               *StringInfoOut;
1604   EFI_FONT_DISPLAY_INFO               *SystemDefault;
1605   EFI_FONT_HANDLE                     FontHandle;
1606   EFI_STRING                          StringIn;
1607   EFI_STRING                          StringIn2;
1608   UINT16                              Height;
1609   UINT16                              BaseLine;
1610   EFI_FONT_INFO                       *FontInfo;
1611   BOOLEAN                             SysFontFlag;
1612   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Foreground;
1613   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Background;
1614   BOOLEAN                             Transparent;
1615   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;
1616   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BufferPtr;
1617   UINTN                               RowInfoSize;
1618   BOOLEAN                             LineBreak;
1619   UINTN                               StrLength;
1620   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *RowBufferPtr;
1621   HII_GLOBAL_FONT_INFO                *GlobalFont;
1622   UINT32                              PreInitBkgnd;
1623 
1624   //
1625   // Check incoming parameters.
1626   //
1627 
1628   if (This == NULL || String == NULL || Blt == NULL) {
1629     return EFI_INVALID_PARAMETER;
1630   }
1631   if (*Blt == NULL) {
1632     //
1633     // These two flag cannot be used if Blt is NULL upon entry.
1634     //
1635     if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
1636       return EFI_INVALID_PARAMETER;
1637     }
1638     if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
1639       return EFI_INVALID_PARAMETER;
1640     }
1641   }
1642   //
1643   // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
1644   //
1645   if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) ==  EFI_HII_OUT_FLAG_CLIP_CLEAN_X) {
1646     return EFI_INVALID_PARAMETER;
1647   }
1648   if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) ==  EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {
1649     return EFI_INVALID_PARAMETER;
1650   }
1651   //
1652   // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
1653   //
1654   if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) ==  (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) {
1655     return EFI_INVALID_PARAMETER;
1656   }
1657 
1658   if (*Blt == NULL) {
1659     //
1660     // Create a new bitmap and draw the string onto this image.
1661     //
1662     Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1663     if (Image == NULL) {
1664       return EFI_OUT_OF_RESOURCES;
1665     }
1666     Image->Width  = 800;
1667     Image->Height = 600;
1668     Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1669     if (Image->Image.Bitmap == NULL) {
1670       FreePool (Image);
1671       return EFI_OUT_OF_RESOURCES;
1672     }
1673 
1674     //
1675     // Other flags are not permitted when Blt is NULL.
1676     //
1677     Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
1678     *Blt = Image;
1679   }
1680 
1681   StrLength = StrLen(String);
1682   GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *));
1683   ASSERT (GlyphBuf != NULL);
1684   Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
1685   ASSERT (Cell != NULL);
1686   Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8));
1687   ASSERT (Attributes != NULL);
1688 
1689   RowInfo       = NULL;
1690   Status        = EFI_SUCCESS;
1691   StringIn2     = NULL;
1692   SystemDefault = NULL;
1693   StringIn      = NULL;
1694 
1695   //
1696   // Calculate the string output information, including specified color and font .
1697   // If StringInfo does not points to system font info, it must indicate an existing
1698   // EFI_FONT_INFO.
1699   //
1700   StringInfoOut = NULL;
1701   FontHandle    = NULL;
1702   Private       = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1703   SysFontFlag   = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
1704 
1705   if (SysFontFlag) {
1706     ASSERT (SystemDefault != NULL);
1707     FontInfo   = NULL;
1708     Height     = SystemDefault->FontInfo.FontSize;
1709     BaseLine   = SystemDefault->FontInfo.FontSize;
1710     Foreground = SystemDefault->ForegroundColor;
1711     Background = SystemDefault->BackgroundColor;
1712 
1713   } else {
1714     //
1715     //  StringInfo must not be NULL if it is not system info.
1716     //
1717     ASSERT (StringInfo != NULL);
1718     Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);
1719     if (Status == EFI_NOT_FOUND) {
1720       //
1721       // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
1722       // Use the system font instead. Still use the color specified by StringInfo.
1723       //
1724       SysFontFlag = TRUE;
1725       FontInfo    = NULL;
1726       Height      = SystemDefault->FontInfo.FontSize;
1727       BaseLine    = SystemDefault->FontInfo.FontSize;
1728       Foreground  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;
1729       Background  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;
1730 
1731     } else if (Status == EFI_SUCCESS) {
1732       FontInfo   = &StringInfoOut->FontInfo;
1733       IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont);
1734       Height     = GlobalFont->FontPackage->Height;
1735       BaseLine   = GlobalFont->FontPackage->BaseLine;
1736       Foreground = StringInfoOut->ForegroundColor;
1737       Background = StringInfoOut->BackgroundColor;
1738     } else {
1739       goto Exit;
1740     }
1741   }
1742 
1743   //
1744   // Use the maximum height of font as the base line.
1745   // And, use the maximum height as line height.
1746   //
1747   LineHeight     = Height;
1748   LastLineHeight = Height;
1749   BaseLineOffset = Height - BaseLine;
1750 
1751   //
1752   // Parse the string to be displayed to drop some ignored characters.
1753   //
1754 
1755   StringPtr = String;
1756 
1757   //
1758   // Ignore line-break characters only. Hyphens or dash character will be displayed
1759   // without line-break opportunity.
1760   //
1761   if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
1762     StringIn = AllocateZeroPool (StrSize (StringPtr));
1763     if (StringIn == NULL) {
1764       Status = EFI_OUT_OF_RESOURCES;
1765       goto Exit;
1766     }
1767     StringTmp = StringIn;
1768     while (*StringPtr != 0) {
1769       if (IsLineBreak (*StringPtr) == 0) {
1770         StringPtr++;
1771       } else {
1772         *StringTmp++ = *StringPtr++;
1773       }
1774     }
1775     *StringTmp = 0;
1776     StringPtr  = StringIn;
1777   }
1778   //
1779   // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
1780   // are not drawn. Otherwise they are replaced with Unicode character 0xFFFD.
1781   //
1782   StringIn2  = AllocateZeroPool (StrSize (StringPtr));
1783   if (StringIn2 == NULL) {
1784     Status = EFI_OUT_OF_RESOURCES;
1785     goto Exit;
1786   }
1787   Index     = 0;
1788   StringTmp = StringIn2;
1789   StrLength = StrLen(StringPtr);
1790   while (*StringPtr != 0 && Index < StrLength) {
1791     if (IsLineBreak (*StringPtr) == 0) {
1792       *StringTmp++ = *StringPtr++;
1793       Index++;
1794       continue;
1795     }
1796 
1797     Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
1798     if (Status == EFI_NOT_FOUND) {
1799       if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
1800         GlyphBuf[Index] = NULL;
1801         ZeroMem (&Cell[Index], sizeof (Cell[Index]));
1802         Status = EFI_SUCCESS;
1803       } else {
1804         //
1805         // Unicode 0xFFFD must exist in current hii database if this flag is not set.
1806         //
1807         Status = GetGlyphBuffer (
1808                    Private,
1809                    REPLACE_UNKNOWN_GLYPH,
1810                    FontInfo,
1811                    &GlyphBuf[Index],
1812                    &Cell[Index],
1813                    &Attributes[Index]
1814                    );
1815         if (EFI_ERROR (Status)) {
1816           Status = EFI_INVALID_PARAMETER;
1817         }
1818       }
1819     }
1820 
1821     if (EFI_ERROR (Status)) {
1822       goto Exit;
1823     }
1824 
1825     *StringTmp++ = *StringPtr++;
1826     Index++;
1827   }
1828   *StringTmp = 0;
1829   StringPtr  = StringIn2;
1830 
1831   //
1832   // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
1833   // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
1834   // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
1835   // Otherwise render this string to a new allocated image and output it.
1836   //
1837   Image     = *Blt;
1838   BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
1839   if (Image->Height < BltY) {
1840     //
1841     // the top edge of the image should be in Image resolution scope.
1842     //
1843     Status = EFI_INVALID_PARAMETER;
1844     goto Exit;
1845   }
1846   MaxRowNum = (UINT16) ((Image->Height - BltY) / Height);
1847   if ((Image->Height - BltY) % Height != 0) {
1848     LastLineHeight = (Image->Height - BltY) % Height;
1849     MaxRowNum++;
1850   }
1851 
1852   RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
1853   if (RowInfo == NULL) {
1854     Status = EFI_OUT_OF_RESOURCES;
1855     goto Exit;
1856   }
1857 
1858   //
1859   // Format the glyph buffer according to flags.
1860   //
1861   Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
1862 
1863   for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
1864     LineWidth      = 0;
1865     LineBreak      = FALSE;
1866 
1867     //
1868     // Clip the final row if the row's bottom-most on pixel cannot fit when
1869     // EFI_HII_OUT_FLAG_CLEAN_Y is set.
1870     //
1871     if (RowIndex == MaxRowNum - 1) {
1872       if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y && LastLineHeight < LineHeight ) {
1873         //
1874         // Don't draw at all if the row's bottom-most on pixel cannot fit.
1875         //
1876         break;
1877       }
1878       LineHeight = LastLineHeight;
1879     }
1880 
1881     //
1882     // Calculate how many characters there are in a row.
1883     //
1884     RowInfo[RowIndex].StartIndex = Index;
1885 
1886     while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
1887       if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
1888            IsLineBreak (StringPtr[Index]) == 0) {
1889         //
1890         // It forces a line break that ends this row.
1891         //
1892         Index++;
1893         LineBreak = TRUE;
1894         break;
1895       }
1896 
1897       //
1898       // If the glyph of the character is existing, then accumulate the actual printed width
1899       //
1900       LineWidth += (UINTN) Cell[Index].AdvanceX;
1901 
1902       Index++;
1903     }
1904 
1905     //
1906     // Record index of next char.
1907     //
1908     NextIndex = Index;
1909     //
1910     // Return to the previous char.
1911     //
1912     Index--;
1913     if (LineBreak && Index > 0 ) {
1914       //
1915       // Return the previous non line break char.
1916       //
1917       Index --;
1918     }
1919 
1920     //
1921     // If this character is the last character of a row, we need not
1922     // draw its (AdvanceX - Width - OffsetX) for next character.
1923     //
1924     LineWidth -= (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);
1925 
1926     //
1927     // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
1928     //
1929     if (LineWidth + BltX <= Image->Width ||
1930       (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) {
1931       //
1932       // Record right-most character in RowInfo even if it is partially displayed.
1933       //
1934       RowInfo[RowIndex].EndIndex       = Index;
1935       RowInfo[RowIndex].LineWidth      = LineWidth;
1936       RowInfo[RowIndex].LineHeight     = LineHeight;
1937       RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1938     } else {
1939       //
1940       // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
1941       // if its right-most on pixel cannot fit.
1942       //
1943       if (Index > RowInfo[RowIndex].StartIndex) {
1944         //
1945         // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
1946         //
1947         LineWidth -= (Cell[Index].Width + Cell[Index].OffsetX);
1948         LineWidth -= (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);
1949         RowInfo[RowIndex].EndIndex       = Index - 1;
1950         RowInfo[RowIndex].LineWidth      = LineWidth;
1951         RowInfo[RowIndex].LineHeight     = LineHeight;
1952         RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1953       } else {
1954         //
1955         // There is no enough column to draw any character, so set current line width to zero.
1956         // And go to draw Next line if LineBreak is set.
1957         //
1958         RowInfo[RowIndex].LineWidth      = 0;
1959         goto NextLine;
1960       }
1961     }
1962 
1963     //
1964     // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
1965     // opportunity prior to a character whose right-most extent would exceed Width.
1966     // Search the right-most line-break opportunity here.
1967     //
1968     if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP &&
1969         (RowInfo[RowIndex].LineWidth + BltX > Image->Width || StringPtr[NextIndex] != 0) &&
1970         !LineBreak) {
1971       if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
1972         LineWidth = RowInfo[RowIndex].LineWidth;
1973         for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
1974           if (Index1 == RowInfo[RowIndex].EndIndex) {
1975             LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
1976           } else {
1977             LineWidth -= Cell[Index1].AdvanceX;
1978           }
1979           if (IsLineBreak (StringPtr[Index1]) > 0) {
1980             LineBreak = TRUE;
1981             if (Index1 > RowInfo[RowIndex].StartIndex) {
1982               RowInfo[RowIndex].EndIndex = Index1 - 1;
1983             }
1984             //
1985             // relocate to the character after the right-most line break opportunity of this line
1986             //
1987             NextIndex = Index1 + 1;
1988             break;
1989           }
1990           //
1991           // If don't find a line break opportunity from EndIndex to StartIndex,
1992           // then jump out.
1993           //
1994           if (Index1 == RowInfo[RowIndex].StartIndex)
1995             break;
1996         }
1997 
1998         //
1999         // Update LineWidth to the real width
2000         //
2001         if (IsLineBreak (StringPtr[Index1]) > 0) {
2002           if (Index1 == RowInfo[RowIndex].StartIndex) {
2003             LineWidth = 0;
2004           } else {
2005             LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2006           }
2007           RowInfo[RowIndex].LineWidth = LineWidth;
2008         }
2009       }
2010       //
2011       // If no line-break opportunity can be found, then the text will
2012       // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
2013       //
2014       if (!LineBreak) {
2015         LineWidth = RowInfo[RowIndex].LineWidth;
2016         Index1    = RowInfo[RowIndex].EndIndex;
2017         if (LineWidth + BltX > Image->Width) {
2018           if (Index1 > RowInfo[RowIndex].StartIndex) {
2019             //
2020             // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
2021             //
2022             LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
2023             LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2024             RowInfo[RowIndex].EndIndex       = Index1 - 1;
2025             RowInfo[RowIndex].LineWidth      = LineWidth;
2026           } else {
2027             //
2028             // There is no enough column to draw any character, so set current line width to zero.
2029             // And go to draw Next line if LineBreak is set.
2030             //
2031             RowInfo[RowIndex].LineWidth = 0;
2032             goto NextLine;
2033           }
2034         }
2035       }
2036     }
2037 
2038     //
2039     // LineWidth can't exceed Image width.
2040     //
2041     if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {
2042       RowInfo[RowIndex].LineWidth = Image->Width - BltX;
2043     }
2044 
2045     //
2046     // Draw it to screen or existing bitmap depending on whether
2047     // EFI_HII_DIRECT_TO_SCREEN is set.
2048     //
2049     LineOffset = 0;
2050     if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
2051       BltBuffer = NULL;
2052       if (RowInfo[RowIndex].LineWidth != 0) {
2053         BltBuffer = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2054         if (BltBuffer == NULL) {
2055           Status = EFI_OUT_OF_RESOURCES;
2056           goto Exit;
2057         }
2058         //
2059         // Initialize the background color.
2060         //
2061         PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
2062         SetMem32 (BltBuffer,RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),PreInitBkgnd);
2063         //
2064         // Set BufferPtr to Origin by adding baseline to the starting position.
2065         //
2066         BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;
2067       }
2068       for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2069         if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2070           //
2071           // Only BLT these character which have corresponding glyph in font database.
2072           //
2073           GlyphToImage (
2074             GlyphBuf[Index1],
2075             Foreground,
2076             Background,
2077             (UINT16) RowInfo[RowIndex].LineWidth,
2078             BaseLine,
2079             RowInfo[RowIndex].LineWidth - LineOffset,
2080             RowInfo[RowIndex].LineHeight,
2081             Transparent,
2082             &Cell[Index1],
2083             Attributes[Index1],
2084             &BufferPtr
2085           );
2086         }
2087         if (ColumnInfoArray != NULL) {
2088           if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2089               || RowInfo[RowIndex].LineWidth == 0) {
2090             *ColumnInfoArray = (UINTN) ~0;
2091           } else {
2092             *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2093           }
2094           ColumnInfoArray++;
2095         }
2096         LineOffset += Cell[Index1].AdvanceX;
2097       }
2098 
2099       if (BltBuffer != NULL) {
2100         Status = Image->Image.Screen->Blt (
2101                                         Image->Image.Screen,
2102                                         BltBuffer,
2103                                         EfiBltBufferToVideo,
2104                                         0,
2105                                         0,
2106                                         BltX,
2107                                         BltY,
2108                                         RowInfo[RowIndex].LineWidth,
2109                                         RowInfo[RowIndex].LineHeight,
2110                                         0
2111                                         );
2112         if (EFI_ERROR (Status)) {
2113           FreePool (BltBuffer);
2114           goto Exit;
2115         }
2116 
2117         FreePool (BltBuffer);
2118       }
2119     } else {
2120       //
2121       // Save the starting position for calculate the starting position of next row.
2122       //
2123       RowBufferPtr = BufferPtr;
2124       //
2125       // Set BufferPtr to Origin by adding baseline to the starting position.
2126       //
2127       BufferPtr = BufferPtr + BaseLine * Image->Width;
2128       for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2129         if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2130           //
2131           // Only BLT these character which have corresponding glyph in font database.
2132           //
2133           GlyphToImage (
2134             GlyphBuf[Index1],
2135             Foreground,
2136             Background,
2137             Image->Width,
2138             BaseLine,
2139             RowInfo[RowIndex].LineWidth - LineOffset,
2140             RowInfo[RowIndex].LineHeight,
2141             Transparent,
2142             &Cell[Index1],
2143             Attributes[Index1],
2144             &BufferPtr
2145           );
2146         }
2147         if (ColumnInfoArray != NULL) {
2148           if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2149               || RowInfo[RowIndex].LineWidth == 0) {
2150             *ColumnInfoArray = (UINTN) ~0;
2151           } else {
2152             *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2153           }
2154           ColumnInfoArray++;
2155         }
2156         LineOffset += Cell[Index1].AdvanceX;
2157       }
2158 
2159       //
2160       // Jump to starting position of next row.
2161       //
2162       if (RowIndex == 0) {
2163         BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;
2164       } else {
2165         BufferPtr = RowBufferPtr + LineHeight * Image->Width;
2166       }
2167     }
2168 
2169 NextLine:
2170     //
2171     // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down
2172     //
2173     BltY += RowInfo[RowIndex].LineHeight;
2174 
2175     RowIndex++;
2176     Index = NextIndex;
2177 
2178     if (!LineBreak) {
2179       //
2180       // If there is not a mandatory line break or line break opportunity, only render one line to image
2181       //
2182       break;
2183     }
2184   }
2185 
2186   //
2187   // Write output parameters.
2188   //
2189   RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
2190   if (RowInfoArray != NULL) {
2191     if (RowInfoSize > 0) {
2192       *RowInfoArray = AllocateZeroPool (RowInfoSize);
2193       if (*RowInfoArray == NULL) {
2194         Status = EFI_OUT_OF_RESOURCES;
2195         goto Exit;
2196       }
2197       CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
2198     } else {
2199       *RowInfoArray = NULL;
2200     }
2201   }
2202   if (RowInfoArraySize != NULL) {
2203     *RowInfoArraySize = RowIndex;
2204   }
2205 
2206   Status = EFI_SUCCESS;
2207 
2208 Exit:
2209 
2210   for (Index = 0; Index < StrLength; Index++) {
2211     if (GlyphBuf[Index] != NULL) {
2212       FreePool (GlyphBuf[Index]);
2213     }
2214   }
2215   if (StringIn != NULL) {
2216     FreePool (StringIn);
2217   }
2218   if (StringIn2 != NULL) {
2219     FreePool (StringIn2);
2220   }
2221   if (StringInfoOut != NULL) {
2222     FreePool (StringInfoOut);
2223   }
2224   if (RowInfo != NULL) {
2225     FreePool (RowInfo);
2226   }
2227   if (SystemDefault != NULL) {
2228     FreePool (SystemDefault);
2229   }
2230   if (GlyphBuf != NULL) {
2231     FreePool (GlyphBuf);
2232   }
2233   if (Cell != NULL) {
2234     FreePool (Cell);
2235   }
2236   if (Attributes != NULL) {
2237     FreePool (Attributes);
2238   }
2239 
2240   return Status;
2241 }
2242 
2243 
2244 /**
2245   Render a string to a bitmap or the screen containing the contents of the specified string.
2246 
2247   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2248   @param  Flags                   Describes how the string is to be drawn.
2249   @param  PackageList             The package list in the HII database to search
2250                                   for the specified string.
2251   @param  StringId                The string's id, which is unique within
2252                                   PackageList.
2253   @param  Language                Points to the language for the retrieved string.
2254                                   If NULL, then the current system language is
2255                                   used.
2256   @param  StringInfo              Points to the string output information,
2257                                   including the color and font.  If NULL, then the
2258                                   string will be output in the default system font
2259                                   and color.
2260   @param  Blt                     If this points to a non-NULL on entry, this
2261                                   points to the image, which is Width pixels   wide
2262                                   and Height pixels high. The string will be drawn
2263                                   onto this image and
2264                                   EFI_HII_OUT_FLAG_CLIP is implied. If this points
2265                                   to a NULL on entry, then a              buffer
2266                                   will be allocated to hold the generated image and
2267                                   the pointer updated on exit. It is the caller's
2268                                   responsibility to free this buffer.
2269   @param  BltX                    Specifies the offset from the left and top edge
2270                                   of the image of the first character cell in the
2271                                   image.
2272   @param  BltY                    Specifies the offset from the left and top edge
2273                                   of the image of the first character cell in the
2274                                   image.
2275   @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
2276                                   will point to an allocated buffer    containing
2277                                   row information and RowInfoArraySize will be
2278                                   updated to contain the        number of elements.
2279                                   This array describes the characters which were at
2280                                   least partially drawn and the heights of the
2281                                   rows. It is the caller's responsibility to free
2282                                   this buffer.
2283   @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
2284                                   contains the number of elements in RowInfoArray.
2285   @param  ColumnInfoArray         If this is non-NULL, then on return it will be
2286                                   filled with the horizontal offset for each
2287                                   character in the string on the row where it is
2288                                   displayed. Non-printing characters will     have
2289                                   the offset ~0. The caller is responsible to
2290                                   allocate a buffer large enough so that    there
2291                                   is one entry for each character in the string,
2292                                   not including the null-terminator. It is possible
2293                                   when character display is normalized that some
2294                                   character cells overlap.
2295 
2296   @retval EFI_SUCCESS            The string was successfully rendered.
2297   @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for
2298                                  RowInfoArray or Blt.
2299   @retval EFI_INVALID_PARAMETER  The Blt or PackageList was NULL.
2300   @retval EFI_INVALID_PARAMETER  Flags were invalid combination.
2301   @retval EFI_NOT_FOUND          The specified PackageList is not in the Database or the string id is not
2302                                  in the specified PackageList.
2303 
2304 **/
2305 EFI_STATUS
2306 EFIAPI
HiiStringIdToImage(IN CONST EFI_HII_FONT_PROTOCOL * This,IN EFI_HII_OUT_FLAGS Flags,IN EFI_HII_HANDLE PackageList,IN EFI_STRING_ID StringId,IN CONST CHAR8 * Language,IN CONST EFI_FONT_DISPLAY_INFO * StringInfo OPTIONAL,IN OUT EFI_IMAGE_OUTPUT ** Blt,IN UINTN BltX,IN UINTN BltY,OUT EFI_HII_ROW_INFO ** RowInfoArray OPTIONAL,OUT UINTN * RowInfoArraySize OPTIONAL,OUT UINTN * ColumnInfoArray OPTIONAL)2307 HiiStringIdToImage (
2308   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2309   IN  EFI_HII_OUT_FLAGS              Flags,
2310   IN  EFI_HII_HANDLE                 PackageList,
2311   IN  EFI_STRING_ID                  StringId,
2312   IN  CONST CHAR8*                   Language,
2313   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
2314   IN  OUT EFI_IMAGE_OUTPUT           **Blt,
2315   IN  UINTN                          BltX,
2316   IN  UINTN                          BltY,
2317   OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
2318   OUT UINTN                          *RowInfoArraySize OPTIONAL,
2319   OUT UINTN                          *ColumnInfoArray  OPTIONAL
2320   )
2321 {
2322   EFI_STATUS                          Status;
2323   HII_DATABASE_PRIVATE_DATA           *Private;
2324   EFI_HII_STRING_PROTOCOL             *HiiString;
2325   EFI_STRING                          String;
2326   UINTN                               StringSize;
2327   UINTN                               FontLen;
2328   UINTN                               NameSize;
2329   EFI_FONT_INFO                       *StringFontInfo;
2330   EFI_FONT_DISPLAY_INFO               *NewStringInfo;
2331   CHAR8                               TempSupportedLanguages;
2332   CHAR8                               *SupportedLanguages;
2333   UINTN                               SupportedLanguagesSize;
2334   CHAR8                               *CurrentLanguage;
2335   CHAR8                               *BestLanguage;
2336 
2337   if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
2338     return EFI_INVALID_PARAMETER;
2339   }
2340 
2341   if (!IsHiiHandleValid (PackageList)) {
2342     return EFI_NOT_FOUND;
2343   }
2344 
2345   //
2346   // Initialize string pointers to be NULL
2347   //
2348   SupportedLanguages = NULL;
2349   CurrentLanguage    = NULL;
2350   BestLanguage       = NULL;
2351   String             = NULL;
2352   StringFontInfo     = NULL;
2353   NewStringInfo      = NULL;
2354 
2355   //
2356   // Get the string to be displayed.
2357   //
2358   Private   = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2359   HiiString = &Private->HiiString;
2360 
2361   //
2362   // Get the size of supported language.
2363   //
2364   SupportedLanguagesSize = 0;
2365   Status = HiiString->GetLanguages (
2366                         HiiString,
2367                         PackageList,
2368                         &TempSupportedLanguages,
2369                         &SupportedLanguagesSize
2370                         );
2371   if (Status != EFI_BUFFER_TOO_SMALL) {
2372     return Status;
2373   }
2374 
2375   SupportedLanguages = AllocatePool (SupportedLanguagesSize);
2376   if (SupportedLanguages == NULL) {
2377     return EFI_OUT_OF_RESOURCES;
2378   }
2379 
2380   Status = HiiString->GetLanguages (
2381                         HiiString,
2382                         PackageList,
2383                         SupportedLanguages,
2384                         &SupportedLanguagesSize
2385                         );
2386   if (EFI_ERROR (Status)) {
2387     goto Exit;
2388   }
2389 
2390   if (Language == NULL) {
2391     Language = "";
2392   }
2393   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLanguage, NULL);
2394   BestLanguage = GetBestLanguage (
2395                    SupportedLanguages,
2396                    FALSE,
2397                    Language,
2398                    (CurrentLanguage == NULL) ? CurrentLanguage : "",
2399                    (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
2400                    NULL
2401                    );
2402   if (BestLanguage == NULL) {
2403     Status = EFI_NOT_FOUND;
2404     goto Exit;
2405   }
2406 
2407   StringSize = MAX_STRING_LENGTH;
2408   String = (EFI_STRING) AllocateZeroPool (StringSize);
2409   if (String == NULL) {
2410     Status = EFI_OUT_OF_RESOURCES;
2411     goto Exit;
2412   }
2413 
2414   Status = HiiString->GetString (
2415                         HiiString,
2416                         BestLanguage,
2417                         PackageList,
2418                         StringId,
2419                         String,
2420                         &StringSize,
2421                         &StringFontInfo
2422                         );
2423   if (Status == EFI_BUFFER_TOO_SMALL) {
2424     FreePool (String);
2425     String = (EFI_STRING) AllocateZeroPool (StringSize);
2426     if (String == NULL) {
2427       Status = EFI_OUT_OF_RESOURCES;
2428       goto Exit;
2429     }
2430     Status = HiiString->GetString (
2431                           HiiString,
2432                           BestLanguage,
2433                           PackageList,
2434                           StringId,
2435                           String,
2436                           &StringSize,
2437                           NULL
2438                           );
2439   }
2440 
2441   if (EFI_ERROR (Status)) {
2442     goto Exit;
2443   }
2444 
2445   //
2446   // When StringInfo specifies that string will be output in the system default font and color,
2447   // use particular stringfontinfo described in string package instead if exists.
2448   // StringFontInfo equals NULL means system default font attaches with the string block.
2449   //
2450   if (StringFontInfo != NULL && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, NULL, NULL)) {
2451     NameSize = StrSize (StringFontInfo->FontName);
2452     FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
2453     NewStringInfo = AllocateZeroPool (FontLen);
2454     if (NewStringInfo == NULL) {
2455       Status = EFI_OUT_OF_RESOURCES;
2456       goto Exit;
2457     }
2458     NewStringInfo->FontInfoMask       = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;
2459     NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;
2460     NewStringInfo->FontInfo.FontSize  = StringFontInfo->FontSize;
2461     StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);
2462 
2463     Status = HiiStringToImage (
2464                This,
2465                Flags,
2466                String,
2467                NewStringInfo,
2468                Blt,
2469                BltX,
2470                BltY,
2471                RowInfoArray,
2472                RowInfoArraySize,
2473                ColumnInfoArray
2474                );
2475     goto Exit;
2476   }
2477 
2478   Status = HiiStringToImage (
2479            This,
2480            Flags,
2481            String,
2482            StringInfo,
2483            Blt,
2484            BltX,
2485            BltY,
2486            RowInfoArray,
2487            RowInfoArraySize,
2488            ColumnInfoArray
2489            );
2490 
2491 Exit:
2492   if (SupportedLanguages != NULL) {
2493     FreePool (SupportedLanguages);
2494   }
2495   if (CurrentLanguage != NULL) {
2496     FreePool (CurrentLanguage);
2497   }
2498   if (BestLanguage != NULL) {
2499     FreePool (BestLanguage);
2500   }
2501   if (String != NULL) {
2502     FreePool (String);
2503   }
2504   if (StringFontInfo != NULL) {
2505     FreePool (StringFontInfo);
2506   }
2507   if (NewStringInfo != NULL) {
2508     FreePool (NewStringInfo);
2509   }
2510 
2511   return Status;
2512 }
2513 
2514 
2515 /**
2516   Convert the glyph for a single character into a bitmap.
2517 
2518   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2519   @param  Char                    Character to retrieve.
2520   @param  StringInfo              Points to the string font and color information
2521                                   or NULL if the string should use the default
2522                                   system font and color.
2523   @param  Blt                     Thus must point to a NULL on entry. A buffer will
2524                                   be allocated to hold the output and the pointer
2525                                   updated on exit. It is the caller's
2526                                   responsibility to free this buffer.
2527   @param  Baseline                Number of pixels from the bottom of the bitmap to
2528                                   the baseline.
2529 
2530   @retval EFI_SUCCESS             Glyph bitmap created.
2531   @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer Blt.
2532   @retval EFI_WARN_UNKNOWN_GLYPH  The glyph was unknown and was replaced with the
2533                                   glyph for Unicode character 0xFFFD.
2534   @retval EFI_INVALID_PARAMETER   Blt is NULL or *Blt is not NULL.
2535 
2536 **/
2537 EFI_STATUS
2538 EFIAPI
HiiGetGlyph(IN CONST EFI_HII_FONT_PROTOCOL * This,IN CHAR16 Char,IN CONST EFI_FONT_DISPLAY_INFO * StringInfo,OUT EFI_IMAGE_OUTPUT ** Blt,OUT UINTN * Baseline OPTIONAL)2539 HiiGetGlyph (
2540   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2541   IN  CHAR16                         Char,
2542   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo,
2543   OUT EFI_IMAGE_OUTPUT               **Blt,
2544   OUT UINTN                          *Baseline OPTIONAL
2545   )
2546 {
2547   EFI_STATUS                         Status;
2548   HII_DATABASE_PRIVATE_DATA          *Private;
2549   EFI_IMAGE_OUTPUT                   *Image;
2550   UINT8                              *GlyphBuffer;
2551   EFI_FONT_DISPLAY_INFO              *SystemDefault;
2552   EFI_FONT_DISPLAY_INFO              *StringInfoOut;
2553   BOOLEAN                            Default;
2554   EFI_FONT_HANDLE                    FontHandle;
2555   EFI_STRING                         String;
2556   EFI_HII_GLYPH_INFO                 Cell;
2557   EFI_FONT_INFO                      *FontInfo;
2558   UINT8                              Attributes;
2559   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Foreground;
2560   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Background;
2561   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer;
2562   UINT16                             BaseLine;
2563 
2564   if (This == NULL || Blt == NULL || *Blt != NULL) {
2565     return EFI_INVALID_PARAMETER;
2566   }
2567 
2568   Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2569 
2570   Default       = FALSE;
2571   Image         = NULL;
2572   SystemDefault = NULL;
2573   FontHandle    = NULL;
2574   String        = NULL;
2575   GlyphBuffer   = NULL;
2576   StringInfoOut = NULL;
2577   FontInfo      = NULL;
2578 
2579   ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2580   ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2581 
2582   Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
2583 
2584   if (!Default) {
2585     //
2586     // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
2587     // the specified color and font.
2588     //
2589     String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);
2590     if (String == NULL) {
2591       Status = EFI_OUT_OF_RESOURCES;
2592       goto Exit;
2593     }
2594     *String = Char;
2595     *(String + 1) = 0;
2596 
2597     Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
2598     if (EFI_ERROR (Status)) {
2599       goto Exit;
2600     }
2601     ASSERT (StringInfoOut != NULL);
2602     FontInfo   = &StringInfoOut->FontInfo;
2603     Foreground = StringInfoOut->ForegroundColor;
2604     Background = StringInfoOut->BackgroundColor;
2605   } else {
2606     ASSERT (SystemDefault != NULL);
2607     Foreground = SystemDefault->ForegroundColor;
2608     Background = SystemDefault->BackgroundColor;
2609   }
2610 
2611   Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
2612   if (EFI_ERROR (Status)) {
2613     goto Exit;
2614   }
2615 
2616   Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
2617   if (Image == NULL) {
2618     Status = EFI_OUT_OF_RESOURCES;
2619     goto Exit;
2620   }
2621   Image->Width   = Cell.Width;
2622   Image->Height  = Cell.Height;
2623 
2624   if (Image->Width * Image->Height > 0) {
2625     Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2626     if (Image->Image.Bitmap == NULL) {
2627       FreePool (Image);
2628       Status = EFI_OUT_OF_RESOURCES;
2629       goto Exit;
2630     }
2631 
2632     //
2633     // Set BaseLine to the char height.
2634     //
2635     BaseLine  = (UINT16) (Cell.Height + Cell.OffsetY);
2636     //
2637     // Set BltBuffer to the position of Origin.
2638     //
2639     BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;
2640     GlyphToImage (
2641       GlyphBuffer,
2642       Foreground,
2643       Background,
2644       Image->Width,
2645       BaseLine,
2646       Cell.Width + Cell.OffsetX,
2647       BaseLine - Cell.OffsetY,
2648       FALSE,
2649       &Cell,
2650       Attributes,
2651       &BltBuffer
2652       );
2653   }
2654 
2655   *Blt = Image;
2656   if (Baseline != NULL) {
2657     *Baseline = Cell.OffsetY;
2658   }
2659 
2660   Status = EFI_SUCCESS;
2661 
2662 Exit:
2663 
2664   if (Status == EFI_NOT_FOUND) {
2665     //
2666     // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
2667     //
2668     if (Char != REPLACE_UNKNOWN_GLYPH) {
2669       Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
2670       if (!EFI_ERROR (Status)) {
2671         Status = EFI_WARN_UNKNOWN_GLYPH;
2672       }
2673     } else {
2674       Status = EFI_WARN_UNKNOWN_GLYPH;
2675     }
2676   }
2677 
2678   if (SystemDefault != NULL) {
2679    FreePool (SystemDefault);
2680   }
2681   if (StringInfoOut != NULL) {
2682     FreePool (StringInfoOut);
2683   }
2684   if (String != NULL) {
2685     FreePool (String);
2686   }
2687   if (GlyphBuffer != NULL) {
2688     FreePool (GlyphBuffer);
2689   }
2690 
2691   return Status;
2692 }
2693 
2694 
2695 /**
2696   This function iterates through fonts which match the specified font, using
2697   the specified criteria. If String is non-NULL, then all of the characters in
2698   the string must exist in order for a candidate font to be returned.
2699 
2700   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2701   @param  FontHandle              On entry, points to the font handle returned by a
2702                                    previous call to GetFontInfo() or NULL to start
2703                                   with the  first font. On return, points to the
2704                                   returned font handle or points to NULL if there
2705                                   are no more matching fonts.
2706   @param  StringInfoIn            Upon entry, points to the font to return information
2707                                   about. If NULL, then the information about the system
2708                                   default font will be returned.
2709   @param  StringInfoOut           Upon return, contains the matching font's information.
2710                                   If NULL, then no information is returned. This buffer
2711                                   is allocated with a call to the Boot Service AllocatePool().
2712                                   It is the caller's responsibility to call the Boot
2713                                   Service FreePool() when the caller no longer requires
2714                                   the contents of StringInfoOut.
2715   @param  String                  Points to the string which will be tested to
2716                                   determine  if all characters are available. If
2717                                   NULL, then any font  is acceptable.
2718 
2719   @retval EFI_SUCCESS             Matching font returned successfully.
2720   @retval EFI_NOT_FOUND           No matching font was found.
2721   @retval EFI_INVALID_PARAMETER  StringInfoIn->FontInfoMask is an invalid combination.
2722   @retval EFI_OUT_OF_RESOURCES    There were insufficient resources to complete the
2723                                   request.
2724 
2725 **/
2726 EFI_STATUS
2727 EFIAPI
HiiGetFontInfo(IN CONST EFI_HII_FONT_PROTOCOL * This,IN OUT EFI_FONT_HANDLE * FontHandle,IN CONST EFI_FONT_DISPLAY_INFO * StringInfoIn,OPTIONAL OUT EFI_FONT_DISPLAY_INFO ** StringInfoOut,IN CONST EFI_STRING String OPTIONAL)2728 HiiGetFontInfo (
2729   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2730   IN  OUT   EFI_FONT_HANDLE          *FontHandle,
2731   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfoIn, OPTIONAL
2732   OUT       EFI_FONT_DISPLAY_INFO    **StringInfoOut,
2733   IN  CONST EFI_STRING               String OPTIONAL
2734   )
2735 {
2736   HII_DATABASE_PRIVATE_DATA          *Private;
2737   EFI_STATUS                         Status;
2738   EFI_FONT_DISPLAY_INFO              *SystemDefault;
2739   EFI_FONT_DISPLAY_INFO              InfoOut;
2740   UINTN                              StringInfoOutLen;
2741   EFI_FONT_INFO                      *FontInfo;
2742   HII_GLOBAL_FONT_INFO               *GlobalFont;
2743   EFI_STRING                         StringIn;
2744   EFI_FONT_HANDLE                    LocalFontHandle;
2745 
2746   if (This == NULL) {
2747     return EFI_INVALID_PARAMETER;
2748   }
2749 
2750   StringInfoOutLen = 0;
2751   FontInfo        = NULL;
2752   SystemDefault   = NULL;
2753   LocalFontHandle = NULL;
2754   if (FontHandle != NULL) {
2755     LocalFontHandle = *FontHandle;
2756   }
2757 
2758   Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2759 
2760   //
2761   // Already searched to the end of the whole list, return directly.
2762   //
2763   if (LocalFontHandle == &Private->FontInfoList) {
2764     LocalFontHandle = NULL;
2765     Status = EFI_NOT_FOUND;
2766     goto Exit;
2767   }
2768 
2769   //
2770   // Get default system display info, if StringInfoIn points to
2771   // system display info, return it directly.
2772   //
2773   if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
2774     //
2775     // System font is the first node. When handle is not NULL, system font can not
2776     // be found any more.
2777     //
2778     if (LocalFontHandle == NULL) {
2779       if (StringInfoOut != NULL) {
2780         *StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault);
2781         if (*StringInfoOut == NULL) {
2782           Status = EFI_OUT_OF_RESOURCES;
2783           LocalFontHandle = NULL;
2784           goto Exit;
2785         }
2786       }
2787 
2788       LocalFontHandle = Private->FontInfoList.ForwardLink;
2789       Status = EFI_SUCCESS;
2790       goto Exit;
2791     } else {
2792       LocalFontHandle = NULL;
2793       Status = EFI_NOT_FOUND;
2794       goto Exit;
2795     }
2796   }
2797 
2798   //
2799   // StringInfoIn must not be NULL if it is not system default font info.
2800   //
2801   ASSERT (StringInfoIn != NULL);
2802   //
2803   // Check the font information mask to make sure it is valid.
2804   //
2805   if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT  | EFI_FONT_INFO_ANY_FONT))  ==
2806        (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT))   ||
2807       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE  | EFI_FONT_INFO_ANY_SIZE))  ==
2808        (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE))   ||
2809       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
2810        (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
2811       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE    | EFI_FONT_INFO_ANY_SIZE))  ==
2812        (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE))     ||
2813       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE   | EFI_FONT_INFO_ANY_STYLE)) ==
2814        (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {
2815     return EFI_INVALID_PARAMETER;
2816   }
2817 
2818   //
2819   // Parse the font information mask to find a matching font.
2820   //
2821 
2822   CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
2823 
2824   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
2825     Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
2826   } else {
2827     Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);
2828   }
2829   if (EFI_ERROR (Status)) {
2830     goto Exit;
2831   }
2832 
2833   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
2834     InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
2835   }
2836   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
2837     InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
2838   }
2839   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
2840     InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
2841   }
2842   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
2843     InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
2844   }
2845 
2846   ASSERT (FontInfo != NULL);
2847   FontInfo->FontSize  = InfoOut.FontInfo.FontSize;
2848   FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
2849 
2850   if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
2851     //
2852     // Test to guarantee all characters are available in the found font.
2853     //
2854     if (String != NULL) {
2855       StringIn = String;
2856       while (*StringIn != 0) {
2857         Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
2858         if (EFI_ERROR (Status)) {
2859           LocalFontHandle = NULL;
2860           goto Exit;
2861         }
2862         StringIn++;
2863       }
2864     }
2865     //
2866     // Write to output parameter
2867     //
2868     if (StringInfoOut != NULL) {
2869       StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
2870       *StringInfoOut   = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);
2871       if (*StringInfoOut == NULL) {
2872         Status = EFI_OUT_OF_RESOURCES;
2873         LocalFontHandle = NULL;
2874         goto Exit;
2875       }
2876 
2877       CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
2878       CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
2879     }
2880 
2881     LocalFontHandle = GlobalFont->Entry.ForwardLink;
2882     Status = EFI_SUCCESS;
2883     goto Exit;
2884   }
2885 
2886   Status = EFI_NOT_FOUND;
2887 
2888 Exit:
2889 
2890   if (FontHandle != NULL) {
2891     *FontHandle = LocalFontHandle;
2892   }
2893 
2894   if (SystemDefault != NULL) {
2895    FreePool (SystemDefault);
2896   }
2897   if (FontInfo != NULL) {
2898    FreePool (FontInfo);
2899   }
2900   return Status;
2901 }
2902 
2903 
2904