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