]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Print.c
Add more check to make sure code run safely.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / GraphicsLite / Print.c
CommitLineData
3eb9473e 1/*++\r
2\r
4ac4deb7 3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
4ea9375a 4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Print.c\r
15\r
16Abstract:\r
17\r
18 Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very\r
19 simple implemenation of SPrint() and Print() to support debug. \r
20\r
21 You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a \r
22 time. This makes the implementation very simple.\r
23\r
24 VSPrint, Print, SPrint format specification has the follwoing form\r
25\r
26 %[flags][width]type\r
27\r
28 flags:\r
29 '-' - Left justify\r
30 '+' - Prefix a sign\r
31 ' ' - Prefix a blank\r
32 ',' - Place commas in numberss\r
33 '0' - Prefix for width with zeros\r
34 'l' - UINT64\r
35 'L' - UINT64\r
36\r
37 width:\r
38 '*' - Get width from a UINTN argumnet from the argument list\r
39 Decimal number that represents width of print\r
40\r
41 type:\r
42 'X' - argument is a UINTN hex number, prefix '0'\r
43 'x' - argument is a hex number\r
44 'd' - argument is a decimal number\r
45 'a' - argument is an ascii string \r
46 'S','s' - argument is an Unicode string\r
47 'g' - argument is a pointer to an EFI_GUID\r
48 't' - argument is a pointer to an EFI_TIME structure\r
49 'c' - argument is an ascii character\r
50 'r' - argument is EFI_STATUS\r
51 '%' - Print a %\r
52\r
53--*/\r
54\r
55#include "Tiano.h"\r
56#include "EfiDriverLib.h"\r
57#include "TianoCommon.h"\r
58#include "EfiCommonLib.h"\r
59#include "PrintWidth.h"\r
60#include "EfiPrintLib.h"\r
61#include "Print.h"\r
c7f33ca4 62#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
63#include EFI_PROTOCOL_DEFINITION (HiiFont)\r
64#else\r
3eb9473e 65#include EFI_PROTOCOL_DEFINITION (Hii)\r
c7f33ca4 66#endif\r
3eb9473e 67\r
68static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {\r
57d40fe2 69 {0x00, 0x00, 0x00, 0x00},\r
70 {0x98, 0x00, 0x00, 0x00},\r
71 {0x00, 0x98, 0x00, 0x00},\r
72 {0x98, 0x98, 0x00, 0x00},\r
73 {0x00, 0x00, 0x98, 0x00},\r
74 {0x98, 0x00, 0x98, 0x00},\r
75 {0x00, 0x98, 0x98, 0x00},\r
76 {0x98, 0x98, 0x98, 0x00},\r
77 {0x10, 0x10, 0x10, 0x00},\r
78 {0xff, 0x10, 0x10, 0x00},\r
79 {0x10, 0xff, 0x10, 0x00},\r
80 {0xff, 0xff, 0x10, 0x00},\r
81 {0x10, 0x10, 0xff, 0x00},\r
82 {0xf0, 0x10, 0xff, 0x00},\r
83 {0x10, 0xff, 0xff, 0x00},\r
84 {0xff, 0xff, 0xff, 0x00},\r
3eb9473e 85};\r
86\r
87\r
88UINTN\r
89_IPrint (\r
90 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
91 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,\r
92 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto,\r
93 IN UINTN X,\r
94 IN UINTN Y,\r
95 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,\r
96 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,\r
97 IN CHAR16 *fmt,\r
98 IN VA_LIST args\r
99 )\r
100/*++\r
101\r
102Routine Description:\r
103\r
104 Display string worker for: Print, PrintAt, IPrint, IPrintAt\r
105\r
106Arguments:\r
107\r
108 GraphicsOutput - Graphics output protocol interface\r
109\r
110 UgaDraw - UGA draw protocol interface\r
111 \r
112 Sto - Simple text out protocol interface\r
113 \r
114 X - X coordinate to start printing\r
115 \r
116 Y - Y coordinate to start printing\r
117 \r
118 Foreground - Foreground color\r
119 \r
120 Background - Background color\r
121 \r
122 fmt - Format string\r
123 \r
124 args - Print arguments\r
125\r
126Returns: \r
127\r
4ac4deb7 128 Length of string printed to the console\r
3eb9473e 129\r
130--*/\r
131{\r
132 VOID *Buffer;\r
133 EFI_STATUS Status;\r
3eb9473e 134 UINTN Index;\r
135 CHAR16 *UnicodeWeight;\r
3eb9473e 136 UINT32 HorizontalResolution;\r
137 UINT32 VerticalResolution;\r
138 UINT32 ColorDepth;\r
139 UINT32 RefreshRate;\r
140 UINTN BufferLen;\r
141 UINTN LineBufferLen;\r
c7f33ca4 142#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
143 EFI_HII_FONT_PROTOCOL *HiiFont;\r
144 EFI_IMAGE_OUTPUT *Blt;\r
145 EFI_FONT_DISPLAY_INFO *FontInfo; \r
146#else\r
147 EFI_HII_PROTOCOL *Hii;\r
148 UINT16 GlyphWidth;\r
149 UINT32 GlyphStatus;\r
150 UINT16 StringIndex;\r
151 EFI_NARROW_GLYPH *Glyph;\r
152 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LineBuffer;\r
153#endif\r
3eb9473e 154\r
155 //\r
156 // For now, allocate an arbitrarily long buffer\r
157 //\r
158 Buffer = EfiLibAllocateZeroPool (0x10000);\r
159 if (Buffer == NULL) {\r
4ac4deb7 160 return 0;\r
3eb9473e 161 }\r
162\r
163 if (GraphicsOutput != NULL) {\r
164 HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
165 VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r
166 } else {\r
167 UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);\r
168 }\r
169 ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));\r
170 \r
c7f33ca4 171#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
172 Blt = NULL;\r
173 FontInfo = NULL;\r
174 ASSERT (GraphicsOutput != NULL);\r
175 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);\r
176 if (EFI_ERROR (Status)) {\r
177 goto Error;\r
178 } \r
179#else \r
180 LineBuffer = NULL;\r
181 Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID**)&Hii);\r
182 if (EFI_ERROR (Status)) {\r
183 goto Error;\r
184 }\r
3eb9473e 185 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * GLYPH_HEIGHT;\r
186 LineBuffer = EfiLibAllocatePool (LineBufferLen);\r
187 if (LineBuffer == NULL) {\r
c7f33ca4 188 Status = EFI_OUT_OF_RESOURCES;\r
3eb9473e 189 goto Error;\r
c7f33ca4 190 } \r
191#endif\r
3eb9473e 192\r
193 VSPrint (Buffer, 0x10000, fmt, args);\r
194 \r
195 UnicodeWeight = (CHAR16 *) Buffer;\r
196\r
197 for (Index = 0; UnicodeWeight[Index] != 0; Index++) {\r
198 if (UnicodeWeight[Index] == CHAR_BACKSPACE ||\r
199 UnicodeWeight[Index] == CHAR_LINEFEED ||\r
200 UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {\r
201 UnicodeWeight[Index] = 0;\r
202 }\r
203 }\r
204\r
205 BufferLen = EfiStrLen (Buffer);\r
206\r
c7f33ca4 207#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
208 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;\r
209 if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {\r
210 Status = EFI_INVALID_PARAMETER;\r
211 goto Error;\r
212 }\r
213\r
214 Blt = (EFI_IMAGE_OUTPUT *) EfiLibAllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
215 if (Blt == NULL) {\r
216 Status = EFI_OUT_OF_RESOURCES;\r
217 goto Error;\r
218 }\r
219\r
220 Blt->Width = (UINT16) (HorizontalResolution);\r
221 Blt->Height = (UINT16) (VerticalResolution);\r
222 Blt->Image.Screen = GraphicsOutput;\r
223 \r
224 FontInfo = (EFI_FONT_DISPLAY_INFO *) EfiLibAllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
225 if (FontInfo == NULL) {\r
226 Status = EFI_OUT_OF_RESOURCES;\r
227 goto Error;\r
228 }\r
229 if (Foreground != NULL) {\r
230 EfiCopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
231 } else {\r
232 EfiCopyMem (\r
233 &FontInfo->ForegroundColor, \r
234 &mEfiColors[Sto->Mode->Attribute & 0x0f], \r
235 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
236 );\r
237 }\r
238 if (Background != NULL) {\r
239 EfiCopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
240 } else {\r
241 EfiCopyMem (\r
242 &FontInfo->BackgroundColor, \r
243 &mEfiColors[Sto->Mode->Attribute >> 4], \r
244 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
245 );\r
246 }\r
247\r
248 Status = HiiFont->StringToImage (\r
249 HiiFont,\r
250 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
251 Buffer,\r
252 FontInfo,\r
253 &Blt,\r
254 X,\r
255 Y,\r
256 NULL,\r
257 NULL,\r
258 NULL\r
259 );\r
260 \r
261#else\r
262 GlyphStatus = 0;\r
263\r
3eb9473e 264 if (GLYPH_WIDTH * GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {\r
265 Status = EFI_INVALID_PARAMETER;\r
266 goto Error;\r
267 }\r
268\r
269 for (Index = 0; Index < BufferLen; Index++) {\r
270 StringIndex = (UINT16) Index;\r
271 Status = Hii->GetGlyph (Hii, UnicodeWeight, &StringIndex, (UINT8 **) &Glyph, &GlyphWidth, &GlyphStatus);\r
272 if (EFI_ERROR (Status)) {\r
273 goto Error;\r
274 }\r
275\r
276 if (Foreground == NULL || Background == NULL) {\r
277 Status = Hii->GlyphToBlt (\r
278 Hii,\r
279 (UINT8 *) Glyph,\r
280 mEfiColors[Sto->Mode->Attribute & 0x0f],\r
281 mEfiColors[Sto->Mode->Attribute >> 4],\r
282 BufferLen,\r
283 GlyphWidth,\r
284 GLYPH_HEIGHT,\r
285 &LineBuffer[Index * GLYPH_WIDTH]\r
286 );\r
287 } else {\r
288 Status = Hii->GlyphToBlt (\r
289 Hii,\r
290 (UINT8 *) Glyph,\r
291 *Foreground,\r
292 *Background,\r
293 BufferLen,\r
294 GlyphWidth,\r
295 GLYPH_HEIGHT,\r
296 &LineBuffer[Index * GLYPH_WIDTH]\r
297 );\r
298 }\r
299 }\r
300\r
301 //\r
302 // Blt a character to the screen\r
303 //\r
304 if (GraphicsOutput != NULL) {\r
305 Status = GraphicsOutput->Blt (\r
306 GraphicsOutput,\r
307 LineBuffer,\r
308 EfiBltBufferToVideo,\r
309 0,\r
310 0,\r
311 X,\r
312 Y,\r
313 GLYPH_WIDTH * BufferLen,\r
314 GLYPH_HEIGHT,\r
315 GLYPH_WIDTH * BufferLen * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
316 );\r
317 } else {\r
318 Status = UgaDraw->Blt (\r
319 UgaDraw,\r
320 (EFI_UGA_PIXEL *) LineBuffer,\r
321 EfiUgaBltBufferToVideo,\r
322 0,\r
323 0,\r
324 X,\r
325 Y,\r
326 GLYPH_WIDTH * BufferLen,\r
327 GLYPH_HEIGHT,\r
328 GLYPH_WIDTH * BufferLen * sizeof (EFI_UGA_PIXEL)\r
329 );\r
330 }\r
331\r
c7f33ca4 332#endif\r
333\r
3eb9473e 334Error:\r
c7f33ca4 335#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
336 EfiLibSafeFreePool (Blt);\r
337 EfiLibSafeFreePool (FontInfo);\r
338#else\r
4ac4deb7 339 EfiLibSafeFreePool (LineBuffer);\r
c7f33ca4 340#endif \r
3eb9473e 341 gBS->FreePool (Buffer);\r
4ac4deb7
LG
342 \r
343 if (EFI_ERROR (Status)) {\r
344 return 0;\r
345 }\r
346\r
347 return BufferLen;\r
3eb9473e 348}\r
349\r
350\r
351UINTN\r
352PrintXY (\r
353 IN UINTN X,\r
354 IN UINTN Y,\r
355 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL\r
356 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL\r
357 IN CHAR_W *Fmt,\r
358 ...\r
359 )\r
360/*++\r
361\r
362Routine Description:\r
363\r
364 Prints a formatted unicode string to the default console\r
365\r
366Arguments:\r
367\r
368 X - X coordinate to start printing\r
369 \r
370 Y - Y coordinate to start printing\r
371 \r
372 ForeGround - Foreground color\r
373 \r
374 BackGround - Background color\r
375\r
376 Fmt - Format string\r
377\r
378 ... - Print arguments\r
379\r
380Returns:\r
381\r
382 Length of string printed to the console\r
383\r
384--*/\r
385{\r
386 EFI_HANDLE Handle;\r
387 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
388 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
389 EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto;\r
390 EFI_STATUS Status;\r
391 VA_LIST Args;\r
392\r
393 VA_START (Args, Fmt);\r
394\r
395 Handle = gST->ConsoleOutHandle;\r
396\r
397 Status = gBS->HandleProtocol (\r
398 Handle,\r
399 &gEfiGraphicsOutputProtocolGuid,\r
57d40fe2 400 (VOID **) &GraphicsOutput\r
3eb9473e 401 );\r
402\r
403 UgaDraw = NULL;\r
404 if (EFI_ERROR (Status)) {\r
405 GraphicsOutput = NULL;\r
406\r
407 Status = gBS->HandleProtocol (\r
408 Handle,\r
409 &gEfiUgaDrawProtocolGuid,\r
57d40fe2 410 (VOID **) &UgaDraw\r
3eb9473e 411 );\r
412\r
4ac4deb7
LG
413 if (EFI_ERROR (Status) || (UgaDraw != NULL)) {\r
414 return 0;\r
3eb9473e 415 }\r
416 }\r
417\r
4ac4deb7 418 Sto = NULL;\r
3eb9473e 419 Status = gBS->HandleProtocol (\r
420 Handle,\r
421 &gEfiSimpleTextOutProtocolGuid,\r
57d40fe2 422 (VOID **) &Sto\r
3eb9473e 423 );\r
424\r
4ac4deb7
LG
425 if (EFI_ERROR (Status) || (Sto != NULL)) {\r
426 return 0;\r
3eb9473e 427 }\r
428\r
429 return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);\r
430}\r
431\r
432\r
433UINTN\r
434SPrint (\r
435 OUT CHAR_W *Buffer,\r
436 IN UINTN BufferSize,\r
437 IN CONST CHAR_W *Format,\r
438 ...\r
439 )\r
440/*++\r
441\r
442Routine Description:\r
443\r
444 SPrint function to process format and place the results in Buffer.\r
445\r
446Arguments:\r
447\r
448 Buffer - Wide char buffer to print the results of the parsing of Format into.\r
449\r
450 BufferSize - Maximum number of characters to put into buffer. Zero means no \r
451 limit.\r
452\r
453 Format - Format string see file header for more details.\r
454\r
455 ... - Vararg list consumed by processing Format.\r
456\r
457Returns: \r
458\r
459 Number of characters printed.\r
460\r
461--*/\r
462{\r
463 UINTN Return;\r
464 VA_LIST Marker;\r
465\r
466 VA_START (Marker, Format);\r
467 Return = VSPrint (Buffer, BufferSize, Format, Marker);\r
468 VA_END (Marker);\r
469\r
470 return Return;\r
471}\r
472\r
473UINTN\r
c7f33ca4 474EFIAPI\r
3eb9473e 475VSPrint (\r
476 OUT CHAR_W *StartOfBuffer,\r
477 IN UINTN BufferSize,\r
478 IN CONST CHAR_W *FormatString,\r
479 IN VA_LIST Marker\r
480 )\r
481/*++\r
482\r
483Routine Description:\r
484\r
485 VSPrint function to process format and place the results in Buffer. Since a \r
486 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
487 this is the main print working routine\r
488\r
489Arguments:\r
490\r
491 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.\r
492\r
493 BufferSize - Maximum number of characters to put into buffer. Zero means \r
494 no limit.\r
495\r
496 FormatString - Unicode format string see file header for more details.\r
497\r
498 Marker - Vararg list consumed by processing Format.\r
499\r
500Returns: \r
501\r
502 Number of characters printed.\r
503\r
504--*/\r
505{\r
506 EFI_STATUS Status;\r
507 EFI_PRINT_PROTOCOL *PrintProtocol;\r
508\r
509 Status = gBS->LocateProtocol (\r
510 &gEfiPrintProtocolGuid,\r
511 NULL,\r
57d40fe2 512 (VOID **) &PrintProtocol\r
3eb9473e 513 );\r
514 if (EFI_ERROR (Status)) {\r
515 return 0;\r
516 } else {\r
517 return PrintProtocol->VSPrint (\r
518 StartOfBuffer,\r
519 BufferSize,\r
520 FormatString,\r
521 Marker\r
522 );\r
523 }\r
524}\r