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   ASSERT ((Private->Attribute >> 4) < 8);
1003   Info->BackgroundColor    = mHiiEfiColors[Private->Attribute >> 4];
1004   Info->FontInfoMask       = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
1005   Info->FontInfo.FontStyle = 0;
1006   Info->FontInfo.FontSize  = EFI_GLYPH_HEIGHT;
1007   StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");
1008 
1009   *FontInfo = Info;
1010   if (FontInfoSize != NULL) {
1011     *FontInfoSize = InfoSize;
1012   }
1013   return EFI_SUCCESS;
1014 }
1015 
1016 
1017 /**
1018   Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or
1019   returns the system default according to the optional inputs.
1020 
1021   This is a internal function.
1022 
1023   @param  Private                 HII database driver private data.
1024   @param  StringInfo              Points to the string output information,
1025                                   including the color and font.
1026   @param  SystemInfo              If not NULL, points to system default font and color.
1027 
1028   @param  SystemInfoLen           If not NULL, output the length of default system
1029                                   info.
1030 
1031   @retval TRUE                    Yes, it points to system default.
1032   @retval FALSE                   No.
1033 
1034 **/
1035 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)1036 IsSystemFontInfo (
1037   IN  HII_DATABASE_PRIVATE_DATA      *Private,
1038   IN  EFI_FONT_DISPLAY_INFO          *StringInfo,
1039   OUT EFI_FONT_DISPLAY_INFO          **SystemInfo, OPTIONAL
1040   OUT UINTN                          *SystemInfoLen OPTIONAL
1041   )
1042 {
1043   EFI_STATUS                          Status;
1044   EFI_FONT_DISPLAY_INFO               *SystemDefault;
1045   UINTN                               DefaultLen;
1046   BOOLEAN                             Flag;
1047 
1048   ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1049 
1050   if (StringInfo == NULL && SystemInfo == NULL) {
1051     return TRUE;
1052   }
1053 
1054   SystemDefault = NULL;
1055   DefaultLen    = 0;
1056 
1057   Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
1058   ASSERT_EFI_ERROR (Status);
1059   ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
1060 
1061   //
1062   // Record the system default info.
1063   //
1064   if (SystemInfo != NULL) {
1065     *SystemInfo = SystemDefault;
1066   }
1067 
1068   if (SystemInfoLen != NULL) {
1069     *SystemInfoLen = DefaultLen;
1070   }
1071 
1072   if (StringInfo == NULL) {
1073     return TRUE;
1074   }
1075 
1076   Flag = FALSE;
1077   //
1078   // Check the FontInfoMask to see whether it is retrieving system info.
1079   //
1080   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) {
1081     if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) {
1082       goto Exit;
1083     }
1084   }
1085   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) {
1086     if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) {
1087       goto Exit;
1088     }
1089   }
1090   if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) {
1091     if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) {
1092       goto Exit;
1093     }
1094   }
1095   if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) {
1096     if (CompareMem (
1097           &StringInfo->ForegroundColor,
1098           &SystemDefault->ForegroundColor,
1099           sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1100           ) != 0) {
1101       goto Exit;
1102     }
1103   }
1104   if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) {
1105     if (CompareMem (
1106           &StringInfo->BackgroundColor,
1107           &SystemDefault->BackgroundColor,
1108           sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1109           ) != 0) {
1110       goto Exit;
1111     }
1112   }
1113 
1114   Flag = TRUE;
1115 
1116 Exit:
1117   if (SystemInfo == NULL) {
1118     if (SystemDefault != NULL) {
1119       FreePool (SystemDefault);
1120     }
1121   }
1122   return Flag;
1123 }
1124 
1125 
1126 /**
1127   This function checks whether EFI_FONT_INFO exists in current database. If
1128   FontInfoMask is specified, check what options can be used to make a match.
1129   Note that the masks relate to where the system default should be supplied
1130   are ignored by this function.
1131 
1132   @param  Private                 Hii database private structure.
1133   @param  FontInfo                Points to EFI_FONT_INFO structure.
1134   @param  FontInfoMask            If not NULL, describes what options can be used
1135                                   to make a match between the font requested and
1136                                   the font available. The caller must guarantee
1137                                   this mask is valid.
1138   @param  FontHandle              On entry, Points to the font handle returned by a
1139                                   previous  call to GetFontInfo() or NULL to start
1140                                   with the first font.
1141   @param  GlobalFontInfo          If not NULL, output the corresponding global font
1142                                   info.
1143 
1144   @retval TRUE                    Existed
1145   @retval FALSE                   Not existed
1146 
1147 **/
1148 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)1149 IsFontInfoExisted (
1150   IN  HII_DATABASE_PRIVATE_DATA *Private,
1151   IN  EFI_FONT_INFO             *FontInfo,
1152   IN  EFI_FONT_INFO_MASK        *FontInfoMask,   OPTIONAL
1153   IN  EFI_FONT_HANDLE           FontHandle,      OPTIONAL
1154   OUT HII_GLOBAL_FONT_INFO      **GlobalFontInfo OPTIONAL
1155   )
1156 {
1157   HII_GLOBAL_FONT_INFO          *GlobalFont;
1158   HII_GLOBAL_FONT_INFO          *GlobalFontBackup1;
1159   HII_GLOBAL_FONT_INFO          *GlobalFontBackup2;
1160   LIST_ENTRY                    *Link;
1161   EFI_FONT_INFO_MASK            Mask;
1162   BOOLEAN                       Matched;
1163   BOOLEAN                       VagueMatched1;
1164   BOOLEAN                       VagueMatched2;
1165 
1166   ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
1167   ASSERT (FontInfo != NULL);
1168 
1169   //
1170   // Matched flag represents an exactly match; VagueMatched1 represents a RESIZE
1171   // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
1172   //
1173   Matched           = FALSE;
1174   VagueMatched1     = FALSE;
1175   VagueMatched2     = FALSE;
1176 
1177   Mask              = 0;
1178   GlobalFontBackup1 = NULL;
1179   GlobalFontBackup2 = NULL;
1180 
1181   // The process of where the system default should be supplied instead of
1182   // the specified font info beyonds this function's scope.
1183   //
1184   if (FontInfoMask != NULL) {
1185     Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
1186   }
1187 
1188   //
1189   // If not NULL, FontHandle points to the next node of the last searched font
1190   // node by previous call.
1191   //
1192   if (FontHandle == NULL) {
1193     Link = Private->FontInfoList.ForwardLink;
1194   } else {
1195     Link = (LIST_ENTRY     *) FontHandle;
1196   }
1197 
1198   for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
1199     GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
1200     if (FontInfoMask == NULL) {
1201       if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
1202         if (GlobalFontInfo != NULL) {
1203           *GlobalFontInfo = GlobalFont;
1204         }
1205         return TRUE;
1206       }
1207     } else {
1208       //
1209       // Check which options could be used to make a match.
1210       //
1211       switch (Mask) {
1212       case EFI_FONT_INFO_ANY_FONT:
1213         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&
1214             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1215           Matched = TRUE;
1216         }
1217         break;
1218       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
1219         if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1220           Matched = TRUE;
1221         }
1222         break;
1223       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
1224         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1225           Matched = TRUE;
1226         }
1227         break;
1228       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
1229         Matched   = TRUE;
1230         break;
1231       //
1232       // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
1233       // remove some of the specified styles to meet the style requested.
1234       //
1235       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
1236         if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
1237           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1238             Matched           = TRUE;
1239           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1240             VagueMatched1     = TRUE;
1241             GlobalFontBackup1 = GlobalFont;
1242           }
1243         }
1244         break;
1245       //
1246       // If EFI_FONT_INFO_RESIZE is specified, then the system may attempt to
1247       // stretch or shrink a font to meet the size requested.
1248       //
1249       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
1250         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1251           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1252             Matched           = TRUE;
1253           } else {
1254             VagueMatched1     = TRUE;
1255             GlobalFontBackup1 = GlobalFont;
1256           }
1257         }
1258         break;
1259       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
1260         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1261           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1262             Matched           = TRUE;
1263           } else {
1264             VagueMatched1     = TRUE;
1265             GlobalFontBackup1 = GlobalFont;
1266           }
1267         } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1268           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1269             VagueMatched1     = TRUE;
1270             GlobalFontBackup1 = GlobalFont;
1271           } else {
1272             VagueMatched2     = TRUE;
1273             GlobalFontBackup2 = GlobalFont;
1274           }
1275         }
1276         break;
1277       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1278         if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1279           Matched           = TRUE;
1280         } else {
1281           VagueMatched1     = TRUE;
1282           GlobalFontBackup1 = GlobalFont;
1283         }
1284         break;
1285       case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1286         if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1287           Matched           = TRUE;
1288         } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1289           VagueMatched1     = TRUE;
1290           GlobalFontBackup1 = GlobalFont;
1291         }
1292         break;
1293       case EFI_FONT_INFO_ANY_STYLE:
1294         if ((CompareMem (
1295                GlobalFont->FontInfo->FontName,
1296                FontInfo->FontName,
1297                StrSize (FontInfo->FontName)
1298                ) == 0) &&
1299             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1300           Matched = TRUE;
1301         }
1302         break;
1303       case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
1304         if (CompareMem (
1305               GlobalFont->FontInfo->FontName,
1306               FontInfo->FontName,
1307               StrSize (FontInfo->FontName)
1308               ) == 0) {
1309           Matched = TRUE;
1310         }
1311         break;
1312       case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
1313         if (CompareMem (
1314               GlobalFont->FontInfo->FontName,
1315               FontInfo->FontName,
1316               StrSize (FontInfo->FontName)
1317               ) == 0) {
1318           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1319             Matched           = TRUE;
1320           } else {
1321             VagueMatched1     = TRUE;
1322             GlobalFontBackup1 = GlobalFont;
1323           }
1324         }
1325         break;
1326       case EFI_FONT_INFO_ANY_SIZE:
1327         if ((CompareMem (
1328                GlobalFont->FontInfo->FontName,
1329                FontInfo->FontName,
1330                StrSize (FontInfo->FontName)
1331                ) == 0) &&
1332             GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {
1333           Matched = TRUE;
1334         }
1335         break;
1336       case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
1337         if (CompareMem (
1338               GlobalFont->FontInfo->FontName,
1339               FontInfo->FontName,
1340               StrSize (FontInfo->FontName)
1341               ) == 0) {
1342           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1343             Matched           = TRUE;
1344           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1345             VagueMatched1     = TRUE;
1346             GlobalFontBackup1 = GlobalFont;
1347           }
1348         }
1349         break;
1350       case EFI_FONT_INFO_RESTYLE:
1351         if ((CompareMem (
1352                GlobalFont->FontInfo->FontName,
1353                FontInfo->FontName,
1354                StrSize (FontInfo->FontName)
1355                ) == 0) &&
1356             GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1357 
1358           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1359             Matched           = TRUE;
1360           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1361             VagueMatched1     = TRUE;
1362             GlobalFontBackup1 = GlobalFont;
1363           }
1364         }
1365         break;
1366       case EFI_FONT_INFO_RESIZE:
1367         if ((CompareMem (
1368                GlobalFont->FontInfo->FontName,
1369                FontInfo->FontName,
1370                StrSize (FontInfo->FontName)
1371                ) == 0) &&
1372             GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {
1373 
1374           if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1375             Matched           = TRUE;
1376           } else {
1377             VagueMatched1     = TRUE;
1378             GlobalFontBackup1 = GlobalFont;
1379           }
1380         }
1381         break;
1382       case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
1383         if (CompareMem (
1384               GlobalFont->FontInfo->FontName,
1385               FontInfo->FontName,
1386               StrSize (FontInfo->FontName)
1387               ) == 0) {
1388           if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
1389             if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1390               Matched           = TRUE;
1391             } else {
1392               VagueMatched1     = TRUE;
1393               GlobalFontBackup1 = GlobalFont;
1394             }
1395           } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
1396             if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {
1397               VagueMatched1     = TRUE;
1398               GlobalFontBackup1 = GlobalFont;
1399             } else {
1400               VagueMatched2     = TRUE;
1401               GlobalFontBackup2 = GlobalFont;
1402             }
1403           }
1404         }
1405         break;
1406       default:
1407         break;
1408       }
1409 
1410       if (Matched) {
1411         if (GlobalFontInfo != NULL) {
1412           *GlobalFontInfo = GlobalFont;
1413         }
1414         return TRUE;
1415       }
1416     }
1417   }
1418 
1419   if (VagueMatched1) {
1420     if (GlobalFontInfo != NULL) {
1421       *GlobalFontInfo = GlobalFontBackup1;
1422     }
1423     return TRUE;
1424   } else if (VagueMatched2) {
1425     if (GlobalFontInfo != NULL) {
1426       *GlobalFontInfo = GlobalFontBackup2;
1427     }
1428     return TRUE;
1429   }
1430 
1431   return FALSE;
1432 }
1433 
1434 
1435 /**
1436   Check whether the unicode represents a line break or not.
1437 
1438   This is a internal function. Please see Section 27.2.6 of the UEFI Specification
1439   for a description of the supported string format.
1440 
1441   @param  Char                    Unicode character
1442 
1443   @retval 0                       Yes, it forces a line break.
1444   @retval 1                       Yes, it presents a line break opportunity
1445   @retval 2                       Yes, it requires a line break happen before and after it.
1446   @retval -1                      No, it is not a link break.
1447 
1448 **/
1449 INT8
IsLineBreak(IN CHAR16 Char)1450 IsLineBreak (
1451   IN  CHAR16    Char
1452   )
1453 {
1454   switch (Char) {
1455     //
1456     // Mandatory line break characters, which force a line-break
1457     //
1458     case 0x000A:
1459     case 0x000C:
1460     case 0x000D:
1461     case 0x2028:
1462     case 0x2029:
1463       return 0;
1464     //
1465     // Space characters, which is taken as a line-break opportunity
1466     //
1467     case 0x0020:
1468     case 0x1680:
1469     case 0x2000:
1470     case 0x2001:
1471     case 0x2002:
1472     case 0x2003:
1473     case 0x2004:
1474     case 0x2005:
1475     case 0x2006:
1476     case 0x2008:
1477     case 0x2009:
1478     case 0x200A:
1479     case 0x205F:
1480     //
1481     // In-Word Break Opportunities
1482     //
1483     case 0x200B:
1484       return 1;
1485     //
1486     // A space which is not a line-break opportunity
1487     //
1488     case 0x00A0:
1489     case 0x202F:
1490     //
1491     // A hyphen which is not a line-break opportunity
1492     //
1493     case 0x2011:
1494       return -1;
1495     //
1496     // Hyphen characters which describe line break opportunities after the character
1497     //
1498     case 0x058A:
1499     case 0x2010:
1500     case 0x2012:
1501     case 0x2013:
1502     case 0x0F0B:
1503     case 0x1361:
1504     case 0x17D5:
1505       return 1;
1506     //
1507     // A hyphen which describes line break opportunities before and after them, but not between a pair of them
1508     //
1509     case 0x2014:
1510       return 2;
1511   }
1512   return -1;
1513 }
1514 
1515 
1516 /**
1517   Renders a string to a bitmap or to the display.
1518 
1519   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
1520   @param  Flags                   Describes how the string is to be drawn.
1521   @param  String                  Points to the null-terminated string to be
1522                                   displayed.
1523   @param  StringInfo              Points to the string output information,
1524                                   including the color and font.  If NULL, then the
1525                                   string will be output in the default system font
1526                                   and color.
1527   @param  Blt                     If this points to a non-NULL on entry, this
1528                                   points to the image, which is Width pixels   wide
1529                                   and Height pixels high. The string will be drawn
1530                                   onto this image and
1531                                   EFI_HII_OUT_FLAG_CLIP is implied. If this points
1532                                   to a NULL on entry, then a              buffer
1533                                   will be allocated to hold the generated image and
1534                                   the pointer updated on exit. It is the caller's
1535                                   responsibility to free this buffer.
1536   @param  BltX                    Specifies the offset from the left and top edge
1537                                   of the image of the first character cell in the
1538                                   image.
1539   @param  BltY                    Specifies the offset from the left and top edge
1540                                   of the image of the first character cell in the
1541                                   image.
1542   @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
1543                                   will point to an allocated buffer    containing
1544                                   row information and RowInfoArraySize will be
1545                                   updated to contain the        number of elements.
1546                                   This array describes the characters which were at
1547                                   least partially drawn and the heights of the
1548                                   rows. It is the caller's responsibility to free
1549                                   this buffer.
1550   @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
1551                                   contains the number of elements in RowInfoArray.
1552   @param  ColumnInfoArray         If this is non-NULL, then on return it will be
1553                                   filled with the horizontal offset for each
1554                                   character in the string on the row where it is
1555                                   displayed. Non-printing characters will     have
1556                                   the offset ~0. The caller is responsible to
1557                                   allocate a buffer large enough so that    there
1558                                   is one entry for each character in the string,
1559                                   not including the null-terminator. It is possible
1560                                   when character display is normalized that some
1561                                   character cells overlap.
1562 
1563   @retval EFI_SUCCESS             The string was successfully rendered.
1564   @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for
1565                                   RowInfoArray or Blt.
1566   @retval EFI_INVALID_PARAMETER   The String or Blt was NULL.
1567   @retval EFI_INVALID_PARAMETER Flags were invalid combination..
1568 
1569 **/
1570 EFI_STATUS
1571 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)1572 HiiStringToImage (
1573   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
1574   IN  EFI_HII_OUT_FLAGS              Flags,
1575   IN  CONST EFI_STRING               String,
1576   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
1577   IN  OUT EFI_IMAGE_OUTPUT           **Blt,
1578   IN  UINTN                          BltX,
1579   IN  UINTN                          BltY,
1580   OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
1581   OUT UINTN                          *RowInfoArraySize OPTIONAL,
1582   OUT UINTN                          *ColumnInfoArray  OPTIONAL
1583   )
1584 {
1585   EFI_STATUS                          Status;
1586   HII_DATABASE_PRIVATE_DATA           *Private;
1587   UINT8                               **GlyphBuf;
1588   EFI_HII_GLYPH_INFO                  *Cell;
1589   UINT8                               *Attributes;
1590   EFI_IMAGE_OUTPUT                    *Image;
1591   EFI_STRING                          StringPtr;
1592   EFI_STRING                          StringTmp;
1593   EFI_HII_ROW_INFO                    *RowInfo;
1594   UINTN                               LineWidth;
1595   UINTN                               LineHeight;
1596   UINTN                               LineOffset;
1597   UINTN                               LastLineHeight;
1598   UINTN                               BaseLineOffset;
1599   UINT16                              MaxRowNum;
1600   UINT16                              RowIndex;
1601   UINTN                               Index;
1602   UINTN                               NextIndex;
1603   UINTN                               Index1;
1604   EFI_FONT_DISPLAY_INFO               *StringInfoOut;
1605   EFI_FONT_DISPLAY_INFO               *SystemDefault;
1606   EFI_FONT_HANDLE                     FontHandle;
1607   EFI_STRING                          StringIn;
1608   EFI_STRING                          StringIn2;
1609   UINT16                              Height;
1610   UINT16                              BaseLine;
1611   EFI_FONT_INFO                       *FontInfo;
1612   BOOLEAN                             SysFontFlag;
1613   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Foreground;
1614   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Background;
1615   BOOLEAN                             Transparent;
1616   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;
1617   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BufferPtr;
1618   UINTN                               RowInfoSize;
1619   BOOLEAN                             LineBreak;
1620   UINTN                               StrLength;
1621   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *RowBufferPtr;
1622   HII_GLOBAL_FONT_INFO                *GlobalFont;
1623   UINT32                              PreInitBkgnd;
1624 
1625   //
1626   // Check incoming parameters.
1627   //
1628 
1629   if (This == NULL || String == NULL || Blt == NULL) {
1630     return EFI_INVALID_PARAMETER;
1631   }
1632   if (*Blt == NULL) {
1633     //
1634     // These two flag cannot be used if Blt is NULL upon entry.
1635     //
1636     if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
1637       return EFI_INVALID_PARAMETER;
1638     }
1639     if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
1640       return EFI_INVALID_PARAMETER;
1641     }
1642   }
1643   //
1644   // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
1645   //
1646   if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) ==  EFI_HII_OUT_FLAG_CLIP_CLEAN_X) {
1647     return EFI_INVALID_PARAMETER;
1648   }
1649   if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) ==  EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {
1650     return EFI_INVALID_PARAMETER;
1651   }
1652   //
1653   // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
1654   //
1655   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)) {
1656     return EFI_INVALID_PARAMETER;
1657   }
1658 
1659   if (*Blt == NULL) {
1660     //
1661     // Create a new bitmap and draw the string onto this image.
1662     //
1663     Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1664     if (Image == NULL) {
1665       return EFI_OUT_OF_RESOURCES;
1666     }
1667     Image->Width  = 800;
1668     Image->Height = 600;
1669     Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1670     if (Image->Image.Bitmap == NULL) {
1671       FreePool (Image);
1672       return EFI_OUT_OF_RESOURCES;
1673     }
1674 
1675     //
1676     // Other flags are not permitted when Blt is NULL.
1677     //
1678     Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
1679     *Blt = Image;
1680   }
1681 
1682   StrLength = StrLen(String);
1683   GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *));
1684   ASSERT (GlyphBuf != NULL);
1685   Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
1686   ASSERT (Cell != NULL);
1687   Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8));
1688   ASSERT (Attributes != NULL);
1689 
1690   RowInfo       = NULL;
1691   Status        = EFI_SUCCESS;
1692   StringIn2     = NULL;
1693   SystemDefault = NULL;
1694   StringIn      = NULL;
1695 
1696   //
1697   // Calculate the string output information, including specified color and font .
1698   // If StringInfo does not points to system font info, it must indicate an existing
1699   // EFI_FONT_INFO.
1700   //
1701   StringInfoOut = NULL;
1702   FontHandle    = NULL;
1703   Private       = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1704   SysFontFlag   = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
1705 
1706   if (SysFontFlag) {
1707     ASSERT (SystemDefault != NULL);
1708     FontInfo   = NULL;
1709     Height     = SystemDefault->FontInfo.FontSize;
1710     BaseLine   = SystemDefault->FontInfo.FontSize;
1711     Foreground = SystemDefault->ForegroundColor;
1712     Background = SystemDefault->BackgroundColor;
1713 
1714   } else {
1715     //
1716     //  StringInfo must not be NULL if it is not system info.
1717     //
1718     ASSERT (StringInfo != NULL);
1719     Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);
1720     if (Status == EFI_NOT_FOUND) {
1721       //
1722       // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
1723       // Use the system font instead. Still use the color specified by StringInfo.
1724       //
1725       SysFontFlag = TRUE;
1726       FontInfo    = NULL;
1727       Height      = SystemDefault->FontInfo.FontSize;
1728       BaseLine    = SystemDefault->FontInfo.FontSize;
1729       Foreground  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;
1730       Background  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;
1731 
1732     } else if (Status == EFI_SUCCESS) {
1733       FontInfo   = &StringInfoOut->FontInfo;
1734       IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont);
1735       Height     = GlobalFont->FontPackage->Height;
1736       BaseLine   = GlobalFont->FontPackage->BaseLine;
1737       Foreground = StringInfoOut->ForegroundColor;
1738       Background = StringInfoOut->BackgroundColor;
1739     } else {
1740       goto Exit;
1741     }
1742   }
1743 
1744   //
1745   // Use the maximum height of font as the base line.
1746   // And, use the maximum height as line height.
1747   //
1748   LineHeight     = Height;
1749   LastLineHeight = Height;
1750   BaseLineOffset = Height - BaseLine;
1751 
1752   //
1753   // Parse the string to be displayed to drop some ignored characters.
1754   //
1755 
1756   StringPtr = String;
1757 
1758   //
1759   // Ignore line-break characters only. Hyphens or dash character will be displayed
1760   // without line-break opportunity.
1761   //
1762   if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
1763     StringIn = AllocateZeroPool (StrSize (StringPtr));
1764     if (StringIn == NULL) {
1765       Status = EFI_OUT_OF_RESOURCES;
1766       goto Exit;
1767     }
1768     StringTmp = StringIn;
1769     while (*StringPtr != 0) {
1770       if (IsLineBreak (*StringPtr) == 0) {
1771         StringPtr++;
1772       } else {
1773         *StringTmp++ = *StringPtr++;
1774       }
1775     }
1776     *StringTmp = 0;
1777     StringPtr  = StringIn;
1778   }
1779   //
1780   // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
1781   // are not drawn. Otherwise they are replaced with Unicode character 0xFFFD.
1782   //
1783   StringIn2  = AllocateZeroPool (StrSize (StringPtr));
1784   if (StringIn2 == NULL) {
1785     Status = EFI_OUT_OF_RESOURCES;
1786     goto Exit;
1787   }
1788   Index     = 0;
1789   StringTmp = StringIn2;
1790   StrLength = StrLen(StringPtr);
1791   while (*StringPtr != 0 && Index < StrLength) {
1792     if (IsLineBreak (*StringPtr) == 0) {
1793       *StringTmp++ = *StringPtr++;
1794       Index++;
1795       continue;
1796     }
1797 
1798     Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
1799     if (Status == EFI_NOT_FOUND) {
1800       if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
1801         GlyphBuf[Index] = NULL;
1802         ZeroMem (&Cell[Index], sizeof (Cell[Index]));
1803         Status = EFI_SUCCESS;
1804       } else {
1805         //
1806         // Unicode 0xFFFD must exist in current hii database if this flag is not set.
1807         //
1808         Status = GetGlyphBuffer (
1809                    Private,
1810                    REPLACE_UNKNOWN_GLYPH,
1811                    FontInfo,
1812                    &GlyphBuf[Index],
1813                    &Cell[Index],
1814                    &Attributes[Index]
1815                    );
1816         if (EFI_ERROR (Status)) {
1817           Status = EFI_INVALID_PARAMETER;
1818         }
1819       }
1820     }
1821 
1822     if (EFI_ERROR (Status)) {
1823       goto Exit;
1824     }
1825 
1826     *StringTmp++ = *StringPtr++;
1827     Index++;
1828   }
1829   *StringTmp = 0;
1830   StringPtr  = StringIn2;
1831 
1832   //
1833   // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
1834   // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
1835   // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
1836   // Otherwise render this string to a new allocated image and output it.
1837   //
1838   Image     = *Blt;
1839   BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
1840   if (Image->Height < BltY) {
1841     //
1842     // the top edge of the image should be in Image resolution scope.
1843     //
1844     Status = EFI_INVALID_PARAMETER;
1845     goto Exit;
1846   }
1847   MaxRowNum = (UINT16) ((Image->Height - BltY) / Height);
1848   if ((Image->Height - BltY) % Height != 0) {
1849     LastLineHeight = (Image->Height - BltY) % Height;
1850     MaxRowNum++;
1851   }
1852 
1853   RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
1854   if (RowInfo == NULL) {
1855     Status = EFI_OUT_OF_RESOURCES;
1856     goto Exit;
1857   }
1858 
1859   //
1860   // Format the glyph buffer according to flags.
1861   //
1862   Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
1863 
1864   for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
1865     LineWidth      = 0;
1866     LineBreak      = FALSE;
1867 
1868     //
1869     // Clip the final row if the row's bottom-most on pixel cannot fit when
1870     // EFI_HII_OUT_FLAG_CLEAN_Y is set.
1871     //
1872     if (RowIndex == MaxRowNum - 1) {
1873       if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y && LastLineHeight < LineHeight ) {
1874         //
1875         // Don't draw at all if the row's bottom-most on pixel cannot fit.
1876         //
1877         break;
1878       }
1879       LineHeight = LastLineHeight;
1880     }
1881 
1882     //
1883     // Calculate how many characters there are in a row.
1884     //
1885     RowInfo[RowIndex].StartIndex = Index;
1886 
1887     while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
1888       if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
1889            IsLineBreak (StringPtr[Index]) == 0) {
1890         //
1891         // It forces a line break that ends this row.
1892         //
1893         Index++;
1894         LineBreak = TRUE;
1895         break;
1896       }
1897 
1898       //
1899       // If the glyph of the character is existing, then accumulate the actual printed width
1900       //
1901       LineWidth += (UINTN) Cell[Index].AdvanceX;
1902 
1903       Index++;
1904     }
1905 
1906     //
1907     // Record index of next char.
1908     //
1909     NextIndex = Index;
1910     //
1911     // Return to the previous char.
1912     //
1913     Index--;
1914     if (LineBreak && Index > 0 ) {
1915       //
1916       // Return the previous non line break char.
1917       //
1918       Index --;
1919     }
1920 
1921     //
1922     // If this character is the last character of a row, we need not
1923     // draw its (AdvanceX - Width - OffsetX) for next character.
1924     //
1925     LineWidth -= (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);
1926 
1927     //
1928     // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
1929     //
1930     if (LineWidth + BltX <= Image->Width ||
1931       (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) {
1932       //
1933       // Record right-most character in RowInfo even if it is partially displayed.
1934       //
1935       RowInfo[RowIndex].EndIndex       = Index;
1936       RowInfo[RowIndex].LineWidth      = LineWidth;
1937       RowInfo[RowIndex].LineHeight     = LineHeight;
1938       RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1939     } else {
1940       //
1941       // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
1942       // if its right-most on pixel cannot fit.
1943       //
1944       if (Index > RowInfo[RowIndex].StartIndex) {
1945         //
1946         // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
1947         //
1948         LineWidth -= (Cell[Index].Width + Cell[Index].OffsetX);
1949         LineWidth -= (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);
1950         RowInfo[RowIndex].EndIndex       = Index - 1;
1951         RowInfo[RowIndex].LineWidth      = LineWidth;
1952         RowInfo[RowIndex].LineHeight     = LineHeight;
1953         RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
1954       } else {
1955         //
1956         // There is no enough column to draw any character, so set current line width to zero.
1957         // And go to draw Next line if LineBreak is set.
1958         //
1959         RowInfo[RowIndex].LineWidth      = 0;
1960         goto NextLine;
1961       }
1962     }
1963 
1964     //
1965     // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
1966     // opportunity prior to a character whose right-most extent would exceed Width.
1967     // Search the right-most line-break opportunity here.
1968     //
1969     if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP &&
1970         (RowInfo[RowIndex].LineWidth + BltX > Image->Width || StringPtr[NextIndex] != 0) &&
1971         !LineBreak) {
1972       if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
1973         LineWidth = RowInfo[RowIndex].LineWidth;
1974         for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
1975           if (Index1 == RowInfo[RowIndex].EndIndex) {
1976             LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
1977           } else {
1978             LineWidth -= Cell[Index1].AdvanceX;
1979           }
1980           if (IsLineBreak (StringPtr[Index1]) > 0) {
1981             LineBreak = TRUE;
1982             if (Index1 > RowInfo[RowIndex].StartIndex) {
1983               RowInfo[RowIndex].EndIndex = Index1 - 1;
1984             }
1985             //
1986             // relocate to the character after the right-most line break opportunity of this line
1987             //
1988             NextIndex = Index1 + 1;
1989             break;
1990           }
1991           //
1992           // If don't find a line break opportunity from EndIndex to StartIndex,
1993           // then jump out.
1994           //
1995           if (Index1 == RowInfo[RowIndex].StartIndex)
1996             break;
1997         }
1998 
1999         //
2000         // Update LineWidth to the real width
2001         //
2002         if (IsLineBreak (StringPtr[Index1]) > 0) {
2003           if (Index1 == RowInfo[RowIndex].StartIndex) {
2004             LineWidth = 0;
2005           } else {
2006             LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2007           }
2008           RowInfo[RowIndex].LineWidth = LineWidth;
2009         }
2010       }
2011       //
2012       // If no line-break opportunity can be found, then the text will
2013       // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
2014       //
2015       if (!LineBreak) {
2016         LineWidth = RowInfo[RowIndex].LineWidth;
2017         Index1    = RowInfo[RowIndex].EndIndex;
2018         if (LineWidth + BltX > Image->Width) {
2019           if (Index1 > RowInfo[RowIndex].StartIndex) {
2020             //
2021             // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
2022             //
2023             LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
2024             LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
2025             RowInfo[RowIndex].EndIndex       = Index1 - 1;
2026             RowInfo[RowIndex].LineWidth      = LineWidth;
2027           } else {
2028             //
2029             // There is no enough column to draw any character, so set current line width to zero.
2030             // And go to draw Next line if LineBreak is set.
2031             //
2032             RowInfo[RowIndex].LineWidth = 0;
2033             goto NextLine;
2034           }
2035         }
2036       }
2037     }
2038 
2039     //
2040     // LineWidth can't exceed Image width.
2041     //
2042     if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {
2043       RowInfo[RowIndex].LineWidth = Image->Width - BltX;
2044     }
2045 
2046     //
2047     // Draw it to screen or existing bitmap depending on whether
2048     // EFI_HII_DIRECT_TO_SCREEN is set.
2049     //
2050     LineOffset = 0;
2051     if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
2052       BltBuffer = NULL;
2053       if (RowInfo[RowIndex].LineWidth != 0) {
2054         BltBuffer = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2055         if (BltBuffer == NULL) {
2056           Status = EFI_OUT_OF_RESOURCES;
2057           goto Exit;
2058         }
2059         //
2060         // Initialize the background color.
2061         //
2062         PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
2063         SetMem32 (BltBuffer,RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),PreInitBkgnd);
2064         //
2065         // Set BufferPtr to Origin by adding baseline to the starting position.
2066         //
2067         BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;
2068       }
2069       for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2070         if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2071           //
2072           // Only BLT these character which have corresponding glyph in font database.
2073           //
2074           GlyphToImage (
2075             GlyphBuf[Index1],
2076             Foreground,
2077             Background,
2078             (UINT16) RowInfo[RowIndex].LineWidth,
2079             BaseLine,
2080             RowInfo[RowIndex].LineWidth - LineOffset,
2081             RowInfo[RowIndex].LineHeight,
2082             Transparent,
2083             &Cell[Index1],
2084             Attributes[Index1],
2085             &BufferPtr
2086           );
2087         }
2088         if (ColumnInfoArray != NULL) {
2089           if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2090               || RowInfo[RowIndex].LineWidth == 0) {
2091             *ColumnInfoArray = (UINTN) ~0;
2092           } else {
2093             *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2094           }
2095           ColumnInfoArray++;
2096         }
2097         LineOffset += Cell[Index1].AdvanceX;
2098       }
2099 
2100       if (BltBuffer != NULL) {
2101         Status = Image->Image.Screen->Blt (
2102                                         Image->Image.Screen,
2103                                         BltBuffer,
2104                                         EfiBltBufferToVideo,
2105                                         0,
2106                                         0,
2107                                         BltX,
2108                                         BltY,
2109                                         RowInfo[RowIndex].LineWidth,
2110                                         RowInfo[RowIndex].LineHeight,
2111                                         0
2112                                         );
2113         if (EFI_ERROR (Status)) {
2114           FreePool (BltBuffer);
2115           goto Exit;
2116         }
2117 
2118         FreePool (BltBuffer);
2119       }
2120     } else {
2121       //
2122       // Save the starting position for calculate the starting position of next row.
2123       //
2124       RowBufferPtr = BufferPtr;
2125       //
2126       // Set BufferPtr to Origin by adding baseline to the starting position.
2127       //
2128       BufferPtr = BufferPtr + BaseLine * Image->Width;
2129       for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
2130         if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {
2131           //
2132           // Only BLT these character which have corresponding glyph in font database.
2133           //
2134           GlyphToImage (
2135             GlyphBuf[Index1],
2136             Foreground,
2137             Background,
2138             Image->Width,
2139             BaseLine,
2140             RowInfo[RowIndex].LineWidth - LineOffset,
2141             RowInfo[RowIndex].LineHeight,
2142             Transparent,
2143             &Cell[Index1],
2144             Attributes[Index1],
2145             &BufferPtr
2146           );
2147         }
2148         if (ColumnInfoArray != NULL) {
2149           if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0)
2150               || RowInfo[RowIndex].LineWidth == 0) {
2151             *ColumnInfoArray = (UINTN) ~0;
2152           } else {
2153             *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
2154           }
2155           ColumnInfoArray++;
2156         }
2157         LineOffset += Cell[Index1].AdvanceX;
2158       }
2159 
2160       //
2161       // Jump to starting position of next row.
2162       //
2163       if (RowIndex == 0) {
2164         BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;
2165       } else {
2166         BufferPtr = RowBufferPtr + LineHeight * Image->Width;
2167       }
2168     }
2169 
2170 NextLine:
2171     //
2172     // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down
2173     //
2174     BltY += RowInfo[RowIndex].LineHeight;
2175 
2176     RowIndex++;
2177     Index = NextIndex;
2178 
2179     if (!LineBreak) {
2180       //
2181       // If there is not a mandatory line break or line break opportunity, only render one line to image
2182       //
2183       break;
2184     }
2185   }
2186 
2187   //
2188   // Write output parameters.
2189   //
2190   RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
2191   if (RowInfoArray != NULL) {
2192     if (RowInfoSize > 0) {
2193       *RowInfoArray = AllocateZeroPool (RowInfoSize);
2194       if (*RowInfoArray == NULL) {
2195         Status = EFI_OUT_OF_RESOURCES;
2196         goto Exit;
2197       }
2198       CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
2199     } else {
2200       *RowInfoArray = NULL;
2201     }
2202   }
2203   if (RowInfoArraySize != NULL) {
2204     *RowInfoArraySize = RowIndex;
2205   }
2206 
2207   Status = EFI_SUCCESS;
2208 
2209 Exit:
2210 
2211   for (Index = 0; Index < StrLength; Index++) {
2212     if (GlyphBuf[Index] != NULL) {
2213       FreePool (GlyphBuf[Index]);
2214     }
2215   }
2216   if (StringIn != NULL) {
2217     FreePool (StringIn);
2218   }
2219   if (StringIn2 != NULL) {
2220     FreePool (StringIn2);
2221   }
2222   if (StringInfoOut != NULL) {
2223     FreePool (StringInfoOut);
2224   }
2225   if (RowInfo != NULL) {
2226     FreePool (RowInfo);
2227   }
2228   if (SystemDefault != NULL) {
2229     FreePool (SystemDefault);
2230   }
2231   if (GlyphBuf != NULL) {
2232     FreePool (GlyphBuf);
2233   }
2234   if (Cell != NULL) {
2235     FreePool (Cell);
2236   }
2237   if (Attributes != NULL) {
2238     FreePool (Attributes);
2239   }
2240 
2241   return Status;
2242 }
2243 
2244 
2245 /**
2246   Render a string to a bitmap or the screen containing the contents of the specified string.
2247 
2248   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2249   @param  Flags                   Describes how the string is to be drawn.
2250   @param  PackageList             The package list in the HII database to search
2251                                   for the specified string.
2252   @param  StringId                The string's id, which is unique within
2253                                   PackageList.
2254   @param  Language                Points to the language for the retrieved string.
2255                                   If NULL, then the current system language is
2256                                   used.
2257   @param  StringInfo              Points to the string output information,
2258                                   including the color and font.  If NULL, then the
2259                                   string will be output in the default system font
2260                                   and color.
2261   @param  Blt                     If this points to a non-NULL on entry, this
2262                                   points to the image, which is Width pixels   wide
2263                                   and Height pixels high. The string will be drawn
2264                                   onto this image and
2265                                   EFI_HII_OUT_FLAG_CLIP is implied. If this points
2266                                   to a NULL on entry, then a              buffer
2267                                   will be allocated to hold the generated image and
2268                                   the pointer updated on exit. It is the caller's
2269                                   responsibility to free this buffer.
2270   @param  BltX                    Specifies the offset from the left and top edge
2271                                   of the image of the first character cell in the
2272                                   image.
2273   @param  BltY                    Specifies the offset from the left and top edge
2274                                   of the image of the first character cell in the
2275                                   image.
2276   @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
2277                                   will point to an allocated buffer    containing
2278                                   row information and RowInfoArraySize will be
2279                                   updated to contain the        number of elements.
2280                                   This array describes the characters which were at
2281                                   least partially drawn and the heights of the
2282                                   rows. It is the caller's responsibility to free
2283                                   this buffer.
2284   @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
2285                                   contains the number of elements in RowInfoArray.
2286   @param  ColumnInfoArray         If this is non-NULL, then on return it will be
2287                                   filled with the horizontal offset for each
2288                                   character in the string on the row where it is
2289                                   displayed. Non-printing characters will     have
2290                                   the offset ~0. The caller is responsible to
2291                                   allocate a buffer large enough so that    there
2292                                   is one entry for each character in the string,
2293                                   not including the null-terminator. It is possible
2294                                   when character display is normalized that some
2295                                   character cells overlap.
2296 
2297   @retval EFI_SUCCESS            The string was successfully rendered.
2298   @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for
2299                                  RowInfoArray or Blt.
2300   @retval EFI_INVALID_PARAMETER  The Blt or PackageList was NULL.
2301   @retval EFI_INVALID_PARAMETER  Flags were invalid combination.
2302   @retval EFI_NOT_FOUND          The specified PackageList is not in the Database or the string id is not
2303                                  in the specified PackageList.
2304 
2305 **/
2306 EFI_STATUS
2307 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)2308 HiiStringIdToImage (
2309   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2310   IN  EFI_HII_OUT_FLAGS              Flags,
2311   IN  EFI_HII_HANDLE                 PackageList,
2312   IN  EFI_STRING_ID                  StringId,
2313   IN  CONST CHAR8*                   Language,
2314   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
2315   IN  OUT EFI_IMAGE_OUTPUT           **Blt,
2316   IN  UINTN                          BltX,
2317   IN  UINTN                          BltY,
2318   OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
2319   OUT UINTN                          *RowInfoArraySize OPTIONAL,
2320   OUT UINTN                          *ColumnInfoArray  OPTIONAL
2321   )
2322 {
2323   EFI_STATUS                          Status;
2324   HII_DATABASE_PRIVATE_DATA           *Private;
2325   EFI_HII_STRING_PROTOCOL             *HiiString;
2326   EFI_STRING                          String;
2327   UINTN                               StringSize;
2328   UINTN                               FontLen;
2329   UINTN                               NameSize;
2330   EFI_FONT_INFO                       *StringFontInfo;
2331   EFI_FONT_DISPLAY_INFO               *NewStringInfo;
2332   CHAR8                               TempSupportedLanguages;
2333   CHAR8                               *SupportedLanguages;
2334   UINTN                               SupportedLanguagesSize;
2335   CHAR8                               *CurrentLanguage;
2336   CHAR8                               *BestLanguage;
2337 
2338   if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
2339     return EFI_INVALID_PARAMETER;
2340   }
2341 
2342   if (!IsHiiHandleValid (PackageList)) {
2343     return EFI_NOT_FOUND;
2344   }
2345 
2346   //
2347   // Initialize string pointers to be NULL
2348   //
2349   SupportedLanguages = NULL;
2350   CurrentLanguage    = NULL;
2351   BestLanguage       = NULL;
2352   String             = NULL;
2353   StringFontInfo     = NULL;
2354   NewStringInfo      = NULL;
2355 
2356   //
2357   // Get the string to be displayed.
2358   //
2359   Private   = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2360   HiiString = &Private->HiiString;
2361 
2362   //
2363   // Get the size of supported language.
2364   //
2365   SupportedLanguagesSize = 0;
2366   Status = HiiString->GetLanguages (
2367                         HiiString,
2368                         PackageList,
2369                         &TempSupportedLanguages,
2370                         &SupportedLanguagesSize
2371                         );
2372   if (Status != EFI_BUFFER_TOO_SMALL) {
2373     return Status;
2374   }
2375 
2376   SupportedLanguages = AllocatePool (SupportedLanguagesSize);
2377   if (SupportedLanguages == NULL) {
2378     return EFI_OUT_OF_RESOURCES;
2379   }
2380 
2381   Status = HiiString->GetLanguages (
2382                         HiiString,
2383                         PackageList,
2384                         SupportedLanguages,
2385                         &SupportedLanguagesSize
2386                         );
2387   if (EFI_ERROR (Status)) {
2388     goto Exit;
2389   }
2390 
2391   if (Language == NULL) {
2392     Language = "";
2393   }
2394   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLanguage, NULL);
2395   BestLanguage = GetBestLanguage (
2396                    SupportedLanguages,
2397                    FALSE,
2398                    Language,
2399                    (CurrentLanguage == NULL) ? CurrentLanguage : "",
2400                    (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
2401                    NULL
2402                    );
2403   if (BestLanguage == NULL) {
2404     Status = EFI_NOT_FOUND;
2405     goto Exit;
2406   }
2407 
2408   StringSize = MAX_STRING_LENGTH;
2409   String = (EFI_STRING) AllocateZeroPool (StringSize);
2410   if (String == NULL) {
2411     Status = EFI_OUT_OF_RESOURCES;
2412     goto Exit;
2413   }
2414 
2415   Status = HiiString->GetString (
2416                         HiiString,
2417                         BestLanguage,
2418                         PackageList,
2419                         StringId,
2420                         String,
2421                         &StringSize,
2422                         &StringFontInfo
2423                         );
2424   if (Status == EFI_BUFFER_TOO_SMALL) {
2425     FreePool (String);
2426     String = (EFI_STRING) AllocateZeroPool (StringSize);
2427     if (String == NULL) {
2428       Status = EFI_OUT_OF_RESOURCES;
2429       goto Exit;
2430     }
2431     Status = HiiString->GetString (
2432                           HiiString,
2433                           BestLanguage,
2434                           PackageList,
2435                           StringId,
2436                           String,
2437                           &StringSize,
2438                           NULL
2439                           );
2440   }
2441 
2442   if (EFI_ERROR (Status)) {
2443     goto Exit;
2444   }
2445 
2446   //
2447   // When StringInfo specifies that string will be output in the system default font and color,
2448   // use particular stringfontinfo described in string package instead if exists.
2449   // StringFontInfo equals NULL means system default font attaches with the string block.
2450   //
2451   if (StringFontInfo != NULL && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, NULL, NULL)) {
2452     NameSize = StrSize (StringFontInfo->FontName);
2453     FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
2454     NewStringInfo = AllocateZeroPool (FontLen);
2455     if (NewStringInfo == NULL) {
2456       Status = EFI_OUT_OF_RESOURCES;
2457       goto Exit;
2458     }
2459     NewStringInfo->FontInfoMask       = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;
2460     NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;
2461     NewStringInfo->FontInfo.FontSize  = StringFontInfo->FontSize;
2462     StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);
2463 
2464     Status = HiiStringToImage (
2465                This,
2466                Flags,
2467                String,
2468                NewStringInfo,
2469                Blt,
2470                BltX,
2471                BltY,
2472                RowInfoArray,
2473                RowInfoArraySize,
2474                ColumnInfoArray
2475                );
2476     goto Exit;
2477   }
2478 
2479   Status = HiiStringToImage (
2480            This,
2481            Flags,
2482            String,
2483            StringInfo,
2484            Blt,
2485            BltX,
2486            BltY,
2487            RowInfoArray,
2488            RowInfoArraySize,
2489            ColumnInfoArray
2490            );
2491 
2492 Exit:
2493   if (SupportedLanguages != NULL) {
2494     FreePool (SupportedLanguages);
2495   }
2496   if (CurrentLanguage != NULL) {
2497     FreePool (CurrentLanguage);
2498   }
2499   if (BestLanguage != NULL) {
2500     FreePool (BestLanguage);
2501   }
2502   if (String != NULL) {
2503     FreePool (String);
2504   }
2505   if (StringFontInfo != NULL) {
2506     FreePool (StringFontInfo);
2507   }
2508   if (NewStringInfo != NULL) {
2509     FreePool (NewStringInfo);
2510   }
2511 
2512   return Status;
2513 }
2514 
2515 
2516 /**
2517   Convert the glyph for a single character into a bitmap.
2518 
2519   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2520   @param  Char                    Character to retrieve.
2521   @param  StringInfo              Points to the string font and color information
2522                                   or NULL if the string should use the default
2523                                   system font and color.
2524   @param  Blt                     Thus must point to a NULL on entry. A buffer will
2525                                   be allocated to hold the output and the pointer
2526                                   updated on exit. It is the caller's
2527                                   responsibility to free this buffer.
2528   @param  Baseline                Number of pixels from the bottom of the bitmap to
2529                                   the baseline.
2530 
2531   @retval EFI_SUCCESS             Glyph bitmap created.
2532   @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer Blt.
2533   @retval EFI_WARN_UNKNOWN_GLYPH  The glyph was unknown and was replaced with the
2534                                   glyph for Unicode character 0xFFFD.
2535   @retval EFI_INVALID_PARAMETER   Blt is NULL or *Blt is not NULL.
2536 
2537 **/
2538 EFI_STATUS
2539 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)2540 HiiGetGlyph (
2541   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2542   IN  CHAR16                         Char,
2543   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo,
2544   OUT EFI_IMAGE_OUTPUT               **Blt,
2545   OUT UINTN                          *Baseline OPTIONAL
2546   )
2547 {
2548   EFI_STATUS                         Status;
2549   HII_DATABASE_PRIVATE_DATA          *Private;
2550   EFI_IMAGE_OUTPUT                   *Image;
2551   UINT8                              *GlyphBuffer;
2552   EFI_FONT_DISPLAY_INFO              *SystemDefault;
2553   EFI_FONT_DISPLAY_INFO              *StringInfoOut;
2554   BOOLEAN                            Default;
2555   EFI_FONT_HANDLE                    FontHandle;
2556   EFI_STRING                         String;
2557   EFI_HII_GLYPH_INFO                 Cell;
2558   EFI_FONT_INFO                      *FontInfo;
2559   UINT8                              Attributes;
2560   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Foreground;
2561   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Background;
2562   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer;
2563   UINT16                             BaseLine;
2564 
2565   if (This == NULL || Blt == NULL || *Blt != NULL) {
2566     return EFI_INVALID_PARAMETER;
2567   }
2568 
2569   Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2570 
2571   Default       = FALSE;
2572   Image         = NULL;
2573   SystemDefault = NULL;
2574   FontHandle    = NULL;
2575   String        = NULL;
2576   GlyphBuffer   = NULL;
2577   StringInfoOut = NULL;
2578   FontInfo      = NULL;
2579 
2580   ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2581   ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2582 
2583   Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
2584 
2585   if (!Default) {
2586     //
2587     // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
2588     // the specified color and font.
2589     //
2590     String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);
2591     if (String == NULL) {
2592       Status = EFI_OUT_OF_RESOURCES;
2593       goto Exit;
2594     }
2595     *String = Char;
2596     *(String + 1) = 0;
2597 
2598     Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
2599     if (EFI_ERROR (Status)) {
2600       goto Exit;
2601     }
2602     ASSERT (StringInfoOut != NULL);
2603     FontInfo   = &StringInfoOut->FontInfo;
2604     Foreground = StringInfoOut->ForegroundColor;
2605     Background = StringInfoOut->BackgroundColor;
2606   } else {
2607     ASSERT (SystemDefault != NULL);
2608     Foreground = SystemDefault->ForegroundColor;
2609     Background = SystemDefault->BackgroundColor;
2610   }
2611 
2612   Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
2613   if (EFI_ERROR (Status)) {
2614     goto Exit;
2615   }
2616 
2617   Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
2618   if (Image == NULL) {
2619     Status = EFI_OUT_OF_RESOURCES;
2620     goto Exit;
2621   }
2622   Image->Width   = Cell.Width;
2623   Image->Height  = Cell.Height;
2624 
2625   if (Image->Width * Image->Height > 0) {
2626     Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
2627     if (Image->Image.Bitmap == NULL) {
2628       FreePool (Image);
2629       Status = EFI_OUT_OF_RESOURCES;
2630       goto Exit;
2631     }
2632 
2633     //
2634     // Set BaseLine to the char height.
2635     //
2636     BaseLine  = (UINT16) (Cell.Height + Cell.OffsetY);
2637     //
2638     // Set BltBuffer to the position of Origin.
2639     //
2640     BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;
2641     GlyphToImage (
2642       GlyphBuffer,
2643       Foreground,
2644       Background,
2645       Image->Width,
2646       BaseLine,
2647       Cell.Width + Cell.OffsetX,
2648       BaseLine - Cell.OffsetY,
2649       FALSE,
2650       &Cell,
2651       Attributes,
2652       &BltBuffer
2653       );
2654   }
2655 
2656   *Blt = Image;
2657   if (Baseline != NULL) {
2658     *Baseline = Cell.OffsetY;
2659   }
2660 
2661   Status = EFI_SUCCESS;
2662 
2663 Exit:
2664 
2665   if (Status == EFI_NOT_FOUND) {
2666     //
2667     // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
2668     //
2669     if (Char != REPLACE_UNKNOWN_GLYPH) {
2670       Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
2671       if (!EFI_ERROR (Status)) {
2672         Status = EFI_WARN_UNKNOWN_GLYPH;
2673       }
2674     } else {
2675       Status = EFI_WARN_UNKNOWN_GLYPH;
2676     }
2677   }
2678 
2679   if (SystemDefault != NULL) {
2680    FreePool (SystemDefault);
2681   }
2682   if (StringInfoOut != NULL) {
2683     FreePool (StringInfoOut);
2684   }
2685   if (String != NULL) {
2686     FreePool (String);
2687   }
2688   if (GlyphBuffer != NULL) {
2689     FreePool (GlyphBuffer);
2690   }
2691 
2692   return Status;
2693 }
2694 
2695 
2696 /**
2697   This function iterates through fonts which match the specified font, using
2698   the specified criteria. If String is non-NULL, then all of the characters in
2699   the string must exist in order for a candidate font to be returned.
2700 
2701   @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
2702   @param  FontHandle              On entry, points to the font handle returned by a
2703                                    previous call to GetFontInfo() or NULL to start
2704                                   with the  first font. On return, points to the
2705                                   returned font handle or points to NULL if there
2706                                   are no more matching fonts.
2707   @param  StringInfoIn            Upon entry, points to the font to return information
2708                                   about. If NULL, then the information about the system
2709                                   default font will be returned.
2710   @param  StringInfoOut           Upon return, contains the matching font's information.
2711                                   If NULL, then no information is returned. This buffer
2712                                   is allocated with a call to the Boot Service AllocatePool().
2713                                   It is the caller's responsibility to call the Boot
2714                                   Service FreePool() when the caller no longer requires
2715                                   the contents of StringInfoOut.
2716   @param  String                  Points to the string which will be tested to
2717                                   determine  if all characters are available. If
2718                                   NULL, then any font  is acceptable.
2719 
2720   @retval EFI_SUCCESS             Matching font returned successfully.
2721   @retval EFI_NOT_FOUND           No matching font was found.
2722   @retval EFI_INVALID_PARAMETER  StringInfoIn->FontInfoMask is an invalid combination.
2723   @retval EFI_OUT_OF_RESOURCES    There were insufficient resources to complete the
2724                                   request.
2725 
2726 **/
2727 EFI_STATUS
2728 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)2729 HiiGetFontInfo (
2730   IN  CONST EFI_HII_FONT_PROTOCOL    *This,
2731   IN  OUT   EFI_FONT_HANDLE          *FontHandle,
2732   IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfoIn, OPTIONAL
2733   OUT       EFI_FONT_DISPLAY_INFO    **StringInfoOut,
2734   IN  CONST EFI_STRING               String OPTIONAL
2735   )
2736 {
2737   HII_DATABASE_PRIVATE_DATA          *Private;
2738   EFI_STATUS                         Status;
2739   EFI_FONT_DISPLAY_INFO              *SystemDefault;
2740   EFI_FONT_DISPLAY_INFO              InfoOut;
2741   UINTN                              StringInfoOutLen;
2742   EFI_FONT_INFO                      *FontInfo;
2743   HII_GLOBAL_FONT_INFO               *GlobalFont;
2744   EFI_STRING                         StringIn;
2745   EFI_FONT_HANDLE                    LocalFontHandle;
2746 
2747   if (This == NULL) {
2748     return EFI_INVALID_PARAMETER;
2749   }
2750 
2751   StringInfoOutLen = 0;
2752   FontInfo        = NULL;
2753   SystemDefault   = NULL;
2754   LocalFontHandle = NULL;
2755   if (FontHandle != NULL) {
2756     LocalFontHandle = *FontHandle;
2757   }
2758 
2759   Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2760 
2761   //
2762   // Already searched to the end of the whole list, return directly.
2763   //
2764   if (LocalFontHandle == &Private->FontInfoList) {
2765     LocalFontHandle = NULL;
2766     Status = EFI_NOT_FOUND;
2767     goto Exit;
2768   }
2769 
2770   //
2771   // Get default system display info, if StringInfoIn points to
2772   // system display info, return it directly.
2773   //
2774   if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
2775     //
2776     // System font is the first node. When handle is not NULL, system font can not
2777     // be found any more.
2778     //
2779     if (LocalFontHandle == NULL) {
2780       if (StringInfoOut != NULL) {
2781         *StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault);
2782         if (*StringInfoOut == NULL) {
2783           Status = EFI_OUT_OF_RESOURCES;
2784           LocalFontHandle = NULL;
2785           goto Exit;
2786         }
2787       }
2788 
2789       LocalFontHandle = Private->FontInfoList.ForwardLink;
2790       Status = EFI_SUCCESS;
2791       goto Exit;
2792     } else {
2793       LocalFontHandle = NULL;
2794       Status = EFI_NOT_FOUND;
2795       goto Exit;
2796     }
2797   }
2798 
2799   //
2800   // StringInfoIn must not be NULL if it is not system default font info.
2801   //
2802   ASSERT (StringInfoIn != NULL);
2803   //
2804   // Check the font information mask to make sure it is valid.
2805   //
2806   if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT  | EFI_FONT_INFO_ANY_FONT))  ==
2807        (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT))   ||
2808       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE  | EFI_FONT_INFO_ANY_SIZE))  ==
2809        (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE))   ||
2810       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
2811        (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
2812       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE    | EFI_FONT_INFO_ANY_SIZE))  ==
2813        (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE))     ||
2814       ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE   | EFI_FONT_INFO_ANY_STYLE)) ==
2815        (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {
2816     return EFI_INVALID_PARAMETER;
2817   }
2818 
2819   //
2820   // Parse the font information mask to find a matching font.
2821   //
2822 
2823   CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
2824 
2825   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
2826     Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
2827   } else {
2828     Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);
2829   }
2830   if (EFI_ERROR (Status)) {
2831     goto Exit;
2832   }
2833 
2834   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
2835     InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
2836   }
2837   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
2838     InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
2839   }
2840   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
2841     InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
2842   }
2843   if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
2844     InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
2845   }
2846 
2847   ASSERT (FontInfo != NULL);
2848   FontInfo->FontSize  = InfoOut.FontInfo.FontSize;
2849   FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
2850 
2851   if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
2852     //
2853     // Test to guarantee all characters are available in the found font.
2854     //
2855     if (String != NULL) {
2856       StringIn = String;
2857       while (*StringIn != 0) {
2858         Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
2859         if (EFI_ERROR (Status)) {
2860           LocalFontHandle = NULL;
2861           goto Exit;
2862         }
2863         StringIn++;
2864       }
2865     }
2866     //
2867     // Write to output parameter
2868     //
2869     if (StringInfoOut != NULL) {
2870       StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
2871       *StringInfoOut   = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);
2872       if (*StringInfoOut == NULL) {
2873         Status = EFI_OUT_OF_RESOURCES;
2874         LocalFontHandle = NULL;
2875         goto Exit;
2876       }
2877 
2878       CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
2879       CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
2880     }
2881 
2882     LocalFontHandle = GlobalFont->Entry.ForwardLink;
2883     Status = EFI_SUCCESS;
2884     goto Exit;
2885   }
2886 
2887   Status = EFI_NOT_FOUND;
2888 
2889 Exit:
2890 
2891   if (FontHandle != NULL) {
2892     *FontHandle = LocalFontHandle;
2893   }
2894 
2895   if (SystemDefault != NULL) {
2896    FreePool (SystemDefault);
2897   }
2898   if (FontInfo != NULL) {
2899    FreePool (FontInfo);
2900   }
2901   return Status;
2902 }
2903 
2904 
2905