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