1 1.5 jmcneill /* $NetBSD: print.c,v 1.5 2021/09/30 19:02:48 jmcneill Exp $ */ 2 1.1 jakllsch 3 1.1 jakllsch /*++ 4 1.1 jakllsch 5 1.1 jakllsch Copyright (c) 1998 Intel Corporation 6 1.1 jakllsch 7 1.1 jakllsch Module Name: 8 1.1 jakllsch 9 1.1 jakllsch print.c 10 1.1 jakllsch 11 1.1 jakllsch Abstract: 12 1.1 jakllsch 13 1.1 jakllsch 14 1.1 jakllsch 15 1.1 jakllsch 16 1.1 jakllsch Revision History 17 1.1 jakllsch 18 1.1 jakllsch --*/ 19 1.1 jakllsch 20 1.1 jakllsch #include "lib.h" 21 1.1 jakllsch #include "efistdarg.h" // !!! 22 1.1 jakllsch 23 1.1 jakllsch // 24 1.1 jakllsch // Declare runtime functions 25 1.1 jakllsch // 26 1.1 jakllsch 27 1.1 jakllsch #ifdef RUNTIME_CODE 28 1.1 jakllsch #ifndef __GNUC__ 29 1.1 jakllsch #pragma RUNTIME_CODE(DbgPrint) 30 1.1 jakllsch 31 1.1 jakllsch // For debugging.. 32 1.1 jakllsch 33 1.1 jakllsch /* 34 1.1 jakllsch #pragma RUNTIME_CODE(_Print) 35 1.1 jakllsch #pragma RUNTIME_CODE(PFLUSH) 36 1.1 jakllsch #pragma RUNTIME_CODE(PSETATTR) 37 1.1 jakllsch #pragma RUNTIME_CODE(PPUTC) 38 1.1 jakllsch #pragma RUNTIME_CODE(PGETC) 39 1.1 jakllsch #pragma RUNTIME_CODE(PITEM) 40 1.1 jakllsch #pragma RUNTIME_CODE(ValueToHex) 41 1.1 jakllsch #pragma RUNTIME_CODE(ValueToString) 42 1.1 jakllsch #pragma RUNTIME_CODE(TimeToString) 43 1.1 jakllsch */ 44 1.1 jakllsch 45 1.1 jakllsch #endif /* !defined(__GNUC__) */ 46 1.1 jakllsch #endif 47 1.1 jakllsch 48 1.1 jakllsch // 49 1.1 jakllsch // 50 1.1 jakllsch // 51 1.1 jakllsch 52 1.1 jakllsch 53 1.1 jakllsch #define PRINT_STRING_LEN 200 54 1.1 jakllsch #define PRINT_ITEM_BUFFER_LEN 100 55 1.1 jakllsch 56 1.1 jakllsch typedef struct { 57 1.1 jakllsch BOOLEAN Ascii; 58 1.1 jakllsch UINTN Index; 59 1.1 jakllsch union { 60 1.2 jmcneill CONST CHAR16 *pw; 61 1.2 jmcneill CONST CHAR8 *pc; 62 1.1 jakllsch } un; 63 1.1 jakllsch } POINTER; 64 1.1 jakllsch 65 1.1 jakllsch #define pw un.pw 66 1.1 jakllsch #define pc un.pc 67 1.1 jakllsch 68 1.1 jakllsch typedef struct _pitem { 69 1.1 jakllsch 70 1.1 jakllsch POINTER Item; 71 1.1 jakllsch CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN]; 72 1.1 jakllsch UINTN Width; 73 1.1 jakllsch UINTN FieldWidth; 74 1.1 jakllsch UINTN *WidthParse; 75 1.1 jakllsch CHAR16 Pad; 76 1.1 jakllsch BOOLEAN PadBefore; 77 1.1 jakllsch BOOLEAN Comma; 78 1.1 jakllsch BOOLEAN Long; 79 1.1 jakllsch } PRINT_ITEM; 80 1.1 jakllsch 81 1.1 jakllsch 82 1.1 jakllsch typedef struct _pstate { 83 1.1 jakllsch // Input 84 1.1 jakllsch POINTER fmt; 85 1.1 jakllsch va_list args; 86 1.1 jakllsch 87 1.1 jakllsch // Output 88 1.1 jakllsch CHAR16 *Buffer; 89 1.1 jakllsch CHAR16 *End; 90 1.1 jakllsch CHAR16 *Pos; 91 1.1 jakllsch UINTN Len; 92 1.1 jakllsch 93 1.2 jmcneill UINTN Attr; 94 1.1 jakllsch UINTN RestoreAttr; 95 1.1 jakllsch 96 1.1 jakllsch UINTN AttrNorm; 97 1.1 jakllsch UINTN AttrHighlight; 98 1.1 jakllsch UINTN AttrError; 99 1.1 jakllsch 100 1.2 jmcneill INTN (EFIAPI *Output)(VOID *context, CHAR16 *str); 101 1.2 jmcneill INTN (EFIAPI *SetAttr)(VOID *context, UINTN attr); 102 1.2 jmcneill VOID *Context; 103 1.1 jakllsch 104 1.1 jakllsch // Current item being formatted 105 1.1 jakllsch struct _pitem *Item; 106 1.1 jakllsch } PRINT_STATE; 107 1.1 jakllsch 108 1.1 jakllsch // 109 1.1 jakllsch // Internal fucntions 110 1.1 jakllsch // 111 1.1 jakllsch 112 1.1 jakllsch STATIC 113 1.1 jakllsch UINTN 114 1.1 jakllsch _Print ( 115 1.1 jakllsch IN PRINT_STATE *ps 116 1.1 jakllsch ); 117 1.1 jakllsch 118 1.1 jakllsch STATIC 119 1.1 jakllsch UINTN 120 1.1 jakllsch _IPrint ( 121 1.1 jakllsch IN UINTN Column, 122 1.1 jakllsch IN UINTN Row, 123 1.1 jakllsch IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, 124 1.2 jmcneill IN CONST CHAR16 *fmt, 125 1.2 jmcneill IN CONST CHAR8 *fmta, 126 1.1 jakllsch IN va_list args 127 1.1 jakllsch ); 128 1.1 jakllsch 129 1.1 jakllsch STATIC 130 1.1 jakllsch INTN EFIAPI 131 1.1 jakllsch _DbgOut ( 132 1.1 jakllsch IN VOID *Context, 133 1.1 jakllsch IN CHAR16 *Buffer 134 1.1 jakllsch ); 135 1.1 jakllsch 136 1.1 jakllsch STATIC 137 1.1 jakllsch VOID 138 1.1 jakllsch PFLUSH ( 139 1.1 jakllsch IN OUT PRINT_STATE *ps 140 1.1 jakllsch ); 141 1.1 jakllsch 142 1.1 jakllsch STATIC 143 1.1 jakllsch VOID 144 1.1 jakllsch PPUTC ( 145 1.1 jakllsch IN OUT PRINT_STATE *ps, 146 1.1 jakllsch IN CHAR16 c 147 1.1 jakllsch ); 148 1.1 jakllsch 149 1.1 jakllsch STATIC 150 1.1 jakllsch VOID 151 1.1 jakllsch PITEM ( 152 1.1 jakllsch IN OUT PRINT_STATE *ps 153 1.1 jakllsch ); 154 1.1 jakllsch 155 1.1 jakllsch STATIC 156 1.1 jakllsch CHAR16 157 1.1 jakllsch PGETC ( 158 1.1 jakllsch IN POINTER *p 159 1.1 jakllsch ); 160 1.1 jakllsch 161 1.1 jakllsch STATIC 162 1.1 jakllsch VOID 163 1.1 jakllsch PSETATTR ( 164 1.1 jakllsch IN OUT PRINT_STATE *ps, 165 1.1 jakllsch IN UINTN Attr 166 1.1 jakllsch ); 167 1.1 jakllsch 168 1.1 jakllsch // 169 1.1 jakllsch // 170 1.1 jakllsch // 171 1.1 jakllsch 172 1.1 jakllsch INTN EFIAPI 173 1.1 jakllsch _SPrint ( 174 1.1 jakllsch IN VOID *Context, 175 1.1 jakllsch IN CHAR16 *Buffer 176 1.1 jakllsch ); 177 1.1 jakllsch 178 1.1 jakllsch INTN EFIAPI 179 1.1 jakllsch _PoolPrint ( 180 1.1 jakllsch IN VOID *Context, 181 1.1 jakllsch IN CHAR16 *Buffer 182 1.1 jakllsch ); 183 1.1 jakllsch 184 1.1 jakllsch INTN 185 1.1 jakllsch DbgPrint ( 186 1.2 jmcneill IN INTN mask, 187 1.2 jmcneill IN CONST CHAR8 *fmt, 188 1.1 jakllsch ... 189 1.1 jakllsch ) 190 1.1 jakllsch /*++ 191 1.1 jakllsch 192 1.1 jakllsch Routine Description: 193 1.1 jakllsch 194 1.1 jakllsch Prints a formatted unicode string to the default StandardError console 195 1.1 jakllsch 196 1.1 jakllsch Arguments: 197 1.1 jakllsch 198 1.1 jakllsch mask - Bit mask of debug string. If a bit is set in the 199 1.2 jmcneill mask that is also set in EFIDebug the string is 200 1.1 jakllsch printed; otherwise, the string is not printed 201 1.1 jakllsch 202 1.1 jakllsch fmt - Format string 203 1.1 jakllsch 204 1.1 jakllsch Returns: 205 1.1 jakllsch 206 1.1 jakllsch Length of string printed to the StandardError console 207 1.1 jakllsch 208 1.1 jakllsch --*/ 209 1.1 jakllsch { 210 1.1 jakllsch SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut; 211 1.1 jakllsch PRINT_STATE ps; 212 1.1 jakllsch va_list args; 213 1.1 jakllsch UINTN back; 214 1.1 jakllsch UINTN attr; 215 1.1 jakllsch UINTN SavedAttribute; 216 1.1 jakllsch 217 1.1 jakllsch 218 1.1 jakllsch if (!(EFIDebug & mask)) { 219 1.1 jakllsch return 0; 220 1.1 jakllsch } 221 1.1 jakllsch 222 1.1 jakllsch va_start (args, fmt); 223 1.1 jakllsch ZeroMem (&ps, sizeof(ps)); 224 1.1 jakllsch 225 1.2 jmcneill ps.Output = _DbgOut; 226 1.1 jakllsch ps.fmt.Ascii = TRUE; 227 1.1 jakllsch ps.fmt.pc = fmt; 228 1.1 jakllsch va_copy(ps.args, args); 229 1.2 jmcneill ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED); 230 1.1 jakllsch 231 1.1 jakllsch DbgOut = LibRuntimeDebugOut; 232 1.1 jakllsch 233 1.1 jakllsch if (!DbgOut) { 234 1.1 jakllsch DbgOut = ST->StdErr; 235 1.1 jakllsch } 236 1.1 jakllsch 237 1.1 jakllsch if (DbgOut) { 238 1.1 jakllsch ps.Attr = DbgOut->Mode->Attribute; 239 1.1 jakllsch ps.Context = DbgOut; 240 1.2 jmcneill ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN)) DbgOut->SetAttribute; 241 1.1 jakllsch } 242 1.1 jakllsch 243 1.1 jakllsch SavedAttribute = ps.Attr; 244 1.1 jakllsch 245 1.1 jakllsch back = (ps.Attr >> 4) & 0xf; 246 1.1 jakllsch ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back); 247 1.1 jakllsch ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back); 248 1.1 jakllsch ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back); 249 1.1 jakllsch 250 1.1 jakllsch attr = ps.AttrNorm; 251 1.1 jakllsch 252 1.1 jakllsch if (mask & D_WARN) { 253 1.1 jakllsch attr = ps.AttrHighlight; 254 1.1 jakllsch } 255 1.1 jakllsch 256 1.1 jakllsch if (mask & D_ERROR) { 257 1.1 jakllsch attr = ps.AttrError; 258 1.1 jakllsch } 259 1.1 jakllsch 260 1.1 jakllsch if (ps.SetAttr) { 261 1.1 jakllsch ps.Attr = attr; 262 1.2 jmcneill uefi_call_wrapper(ps.SetAttr, 2, ps.Context, attr); 263 1.1 jakllsch } 264 1.1 jakllsch 265 1.1 jakllsch _Print (&ps); 266 1.1 jakllsch 267 1.1 jakllsch va_end (ps.args); 268 1.1 jakllsch va_end (args); 269 1.1 jakllsch 270 1.1 jakllsch // 271 1.1 jakllsch // Restore original attributes 272 1.1 jakllsch // 273 1.1 jakllsch 274 1.1 jakllsch if (ps.SetAttr) { 275 1.2 jmcneill uefi_call_wrapper(ps.SetAttr, 2, ps.Context, SavedAttribute); 276 1.1 jakllsch } 277 1.2 jmcneill 278 1.1 jakllsch return 0; 279 1.1 jakllsch } 280 1.1 jakllsch 281 1.1 jakllsch STATIC 282 1.1 jakllsch INTN 283 1.1 jakllsch IsLocalPrint(void *func) 284 1.1 jakllsch { 285 1.1 jakllsch if (func == _DbgOut || func == _SPrint || func == _PoolPrint) 286 1.1 jakllsch return 1; 287 1.1 jakllsch return 0; 288 1.1 jakllsch } 289 1.1 jakllsch 290 1.1 jakllsch STATIC 291 1.1 jakllsch INTN EFIAPI 292 1.1 jakllsch _DbgOut ( 293 1.1 jakllsch IN VOID *Context, 294 1.1 jakllsch IN CHAR16 *Buffer 295 1.1 jakllsch ) 296 1.1 jakllsch // Append string worker for DbgPrint 297 1.1 jakllsch { 298 1.1 jakllsch SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut; 299 1.1 jakllsch 300 1.1 jakllsch DbgOut = Context; 301 1.1 jakllsch // if (!DbgOut && ST && ST->ConOut) { 302 1.1 jakllsch // DbgOut = ST->ConOut; 303 1.1 jakllsch // } 304 1.1 jakllsch 305 1.1 jakllsch if (DbgOut) { 306 1.1 jakllsch if (IsLocalPrint(DbgOut->OutputString)) 307 1.1 jakllsch DbgOut->OutputString(DbgOut, Buffer); 308 1.1 jakllsch else 309 1.1 jakllsch uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer); 310 1.1 jakllsch } 311 1.1 jakllsch 312 1.1 jakllsch return 0; 313 1.1 jakllsch } 314 1.1 jakllsch 315 1.1 jakllsch INTN EFIAPI 316 1.1 jakllsch _SPrint ( 317 1.1 jakllsch IN VOID *Context, 318 1.1 jakllsch IN CHAR16 *Buffer 319 1.1 jakllsch ) 320 1.5 jmcneill // Append string worker for UnicodeSPrint, PoolPrint and CatPrint 321 1.1 jakllsch { 322 1.1 jakllsch UINTN len; 323 1.1 jakllsch POOL_PRINT *spc; 324 1.1 jakllsch 325 1.1 jakllsch spc = Context; 326 1.1 jakllsch len = StrLen(Buffer); 327 1.1 jakllsch 328 1.1 jakllsch // 329 1.1 jakllsch // Is the string is over the max truncate it 330 1.1 jakllsch // 331 1.1 jakllsch 332 1.1 jakllsch if (spc->len + len > spc->maxlen) { 333 1.1 jakllsch len = spc->maxlen - spc->len; 334 1.1 jakllsch } 335 1.1 jakllsch 336 1.1 jakllsch // 337 1.1 jakllsch // Append the new text 338 1.1 jakllsch // 339 1.1 jakllsch 340 1.1 jakllsch CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16)); 341 1.1 jakllsch spc->len += len; 342 1.1 jakllsch 343 1.1 jakllsch // 344 1.1 jakllsch // Null terminate it 345 1.1 jakllsch // 346 1.1 jakllsch 347 1.1 jakllsch if (spc->len < spc->maxlen) { 348 1.1 jakllsch spc->str[spc->len] = 0; 349 1.1 jakllsch } else if (spc->maxlen) { 350 1.2 jmcneill spc->str[spc->maxlen] = 0; 351 1.1 jakllsch } 352 1.1 jakllsch 353 1.1 jakllsch return 0; 354 1.1 jakllsch } 355 1.1 jakllsch 356 1.1 jakllsch 357 1.1 jakllsch INTN EFIAPI 358 1.1 jakllsch _PoolPrint ( 359 1.1 jakllsch IN VOID *Context, 360 1.1 jakllsch IN CHAR16 *Buffer 361 1.1 jakllsch ) 362 1.1 jakllsch // Append string worker for PoolPrint and CatPrint 363 1.1 jakllsch { 364 1.1 jakllsch UINTN newlen; 365 1.1 jakllsch POOL_PRINT *spc; 366 1.1 jakllsch 367 1.1 jakllsch spc = Context; 368 1.1 jakllsch newlen = spc->len + StrLen(Buffer) + 1; 369 1.1 jakllsch 370 1.1 jakllsch // 371 1.1 jakllsch // Is the string is over the max, grow the buffer 372 1.1 jakllsch // 373 1.1 jakllsch 374 1.1 jakllsch if (newlen > spc->maxlen) { 375 1.1 jakllsch 376 1.1 jakllsch // 377 1.1 jakllsch // Grow the pool buffer 378 1.1 jakllsch // 379 1.1 jakllsch 380 1.1 jakllsch newlen += PRINT_STRING_LEN; 381 1.1 jakllsch spc->maxlen = newlen; 382 1.1 jakllsch spc->str = ReallocatePool ( 383 1.2 jmcneill spc->str, 384 1.2 jmcneill spc->len * sizeof(CHAR16), 385 1.1 jakllsch spc->maxlen * sizeof(CHAR16) 386 1.1 jakllsch ); 387 1.1 jakllsch 388 1.1 jakllsch if (!spc->str) { 389 1.1 jakllsch spc->len = 0; 390 1.1 jakllsch spc->maxlen = 0; 391 1.1 jakllsch } 392 1.1 jakllsch } 393 1.1 jakllsch 394 1.1 jakllsch // 395 1.1 jakllsch // Append the new text 396 1.1 jakllsch // 397 1.1 jakllsch 398 1.1 jakllsch return _SPrint (Context, Buffer); 399 1.1 jakllsch } 400 1.1 jakllsch 401 1.1 jakllsch 402 1.1 jakllsch 403 1.1 jakllsch VOID 404 1.1 jakllsch _PoolCatPrint ( 405 1.2 jmcneill IN CONST CHAR16 *fmt, 406 1.1 jakllsch IN va_list args, 407 1.1 jakllsch IN OUT POOL_PRINT *spc, 408 1.2 jmcneill IN INTN (EFIAPI *Output)(VOID *context, CHAR16 *str) 409 1.1 jakllsch ) 410 1.5 jmcneill // Dispatch function for UnicodeSPrint, PoolPrint, and CatPrint 411 1.1 jakllsch { 412 1.1 jakllsch PRINT_STATE ps; 413 1.1 jakllsch 414 1.1 jakllsch ZeroMem (&ps, sizeof(ps)); 415 1.1 jakllsch ps.Output = Output; 416 1.1 jakllsch ps.Context = spc; 417 1.1 jakllsch ps.fmt.pw = fmt; 418 1.1 jakllsch va_copy(ps.args, args); 419 1.1 jakllsch _Print (&ps); 420 1.1 jakllsch va_end(ps.args); 421 1.1 jakllsch } 422 1.1 jakllsch 423 1.1 jakllsch 424 1.1 jakllsch 425 1.1 jakllsch UINTN 426 1.5 jmcneill UnicodeVSPrint ( 427 1.2 jmcneill OUT CHAR16 *Str, 428 1.2 jmcneill IN UINTN StrSize, 429 1.2 jmcneill IN CONST CHAR16 *fmt, 430 1.2 jmcneill va_list args 431 1.1 jakllsch ) 432 1.1 jakllsch /*++ 433 1.1 jakllsch 434 1.1 jakllsch Routine Description: 435 1.1 jakllsch 436 1.2 jmcneill Prints a formatted unicode string to a buffer using a va_list 437 1.1 jakllsch 438 1.1 jakllsch Arguments: 439 1.1 jakllsch 440 1.1 jakllsch Str - Output buffer to print the formatted string into 441 1.1 jakllsch 442 1.1 jakllsch StrSize - Size of Str. String is truncated to this size. 443 1.1 jakllsch A size of 0 means there is no limit 444 1.1 jakllsch 445 1.1 jakllsch fmt - The format string 446 1.1 jakllsch 447 1.2 jmcneill args - va_list 448 1.2 jmcneill 449 1.2 jmcneill 450 1.1 jakllsch Returns: 451 1.1 jakllsch 452 1.1 jakllsch String length returned in buffer 453 1.1 jakllsch 454 1.1 jakllsch --*/ 455 1.1 jakllsch { 456 1.1 jakllsch POOL_PRINT spc; 457 1.1 jakllsch 458 1.1 jakllsch spc.str = Str; 459 1.1 jakllsch spc.maxlen = StrSize / sizeof(CHAR16) - 1; 460 1.1 jakllsch spc.len = 0; 461 1.1 jakllsch 462 1.1 jakllsch _PoolCatPrint (fmt, args, &spc, _SPrint); 463 1.2 jmcneill 464 1.2 jmcneill return spc.len; 465 1.2 jmcneill } 466 1.2 jmcneill 467 1.2 jmcneill UINTN 468 1.5 jmcneill UnicodeSPrint ( 469 1.2 jmcneill OUT CHAR16 *Str, 470 1.2 jmcneill IN UINTN StrSize, 471 1.2 jmcneill IN CONST CHAR16 *fmt, 472 1.2 jmcneill ... 473 1.2 jmcneill ) 474 1.2 jmcneill /*++ 475 1.2 jmcneill 476 1.2 jmcneill Routine Description: 477 1.2 jmcneill 478 1.2 jmcneill Prints a formatted unicode string to a buffer 479 1.2 jmcneill 480 1.2 jmcneill Arguments: 481 1.2 jmcneill 482 1.2 jmcneill Str - Output buffer to print the formatted string into 483 1.2 jmcneill 484 1.2 jmcneill StrSize - Size of Str. String is truncated to this size. 485 1.2 jmcneill A size of 0 means there is no limit 486 1.2 jmcneill 487 1.2 jmcneill fmt - The format string 488 1.2 jmcneill 489 1.2 jmcneill Returns: 490 1.2 jmcneill 491 1.2 jmcneill String length returned in buffer 492 1.2 jmcneill 493 1.2 jmcneill --*/ 494 1.2 jmcneill { 495 1.2 jmcneill va_list args; 496 1.2 jmcneill UINTN len; 497 1.2 jmcneill 498 1.2 jmcneill va_start (args, fmt); 499 1.5 jmcneill len = UnicodeVSPrint(Str, StrSize, fmt, args); 500 1.1 jakllsch va_end (args); 501 1.2 jmcneill 502 1.2 jmcneill return len; 503 1.1 jakllsch } 504 1.1 jakllsch 505 1.2 jmcneill CHAR16 * 506 1.2 jmcneill VPoolPrint ( 507 1.2 jmcneill IN CONST CHAR16 *fmt, 508 1.2 jmcneill va_list args 509 1.2 jmcneill ) 510 1.2 jmcneill /*++ 511 1.2 jmcneill 512 1.2 jmcneill Routine Description: 513 1.2 jmcneill 514 1.2 jmcneill Prints a formatted unicode string to allocated pool using va_list argument. 515 1.2 jmcneill The caller must free the resulting buffer. 516 1.2 jmcneill 517 1.2 jmcneill Arguments: 518 1.2 jmcneill 519 1.2 jmcneill fmt - The format string 520 1.2 jmcneill args - The arguments in va_list form 521 1.2 jmcneill 522 1.2 jmcneill Returns: 523 1.2 jmcneill 524 1.2 jmcneill Allocated buffer with the formatted string printed in it. 525 1.2 jmcneill The caller must free the allocated buffer. The buffer 526 1.2 jmcneill allocation is not packed. 527 1.2 jmcneill 528 1.2 jmcneill --*/ 529 1.2 jmcneill { 530 1.2 jmcneill POOL_PRINT spc; 531 1.2 jmcneill ZeroMem (&spc, sizeof(spc)); 532 1.2 jmcneill _PoolCatPrint (fmt, args, &spc, _PoolPrint); 533 1.2 jmcneill return spc.str; 534 1.2 jmcneill } 535 1.1 jakllsch 536 1.1 jakllsch CHAR16 * 537 1.1 jakllsch PoolPrint ( 538 1.2 jmcneill IN CONST CHAR16 *fmt, 539 1.1 jakllsch ... 540 1.1 jakllsch ) 541 1.1 jakllsch /*++ 542 1.1 jakllsch 543 1.1 jakllsch Routine Description: 544 1.1 jakllsch 545 1.1 jakllsch Prints a formatted unicode string to allocated pool. The caller 546 1.1 jakllsch must free the resulting buffer. 547 1.1 jakllsch 548 1.1 jakllsch Arguments: 549 1.1 jakllsch 550 1.1 jakllsch fmt - The format string 551 1.1 jakllsch 552 1.1 jakllsch Returns: 553 1.1 jakllsch 554 1.2 jmcneill Allocated buffer with the formatted string printed in it. 555 1.1 jakllsch The caller must free the allocated buffer. The buffer 556 1.1 jakllsch allocation is not packed. 557 1.1 jakllsch 558 1.1 jakllsch --*/ 559 1.1 jakllsch { 560 1.2 jmcneill va_list args; 561 1.2 jmcneill CHAR16 *pool; 562 1.1 jakllsch va_start (args, fmt); 563 1.2 jmcneill pool = VPoolPrint(fmt, args); 564 1.1 jakllsch va_end (args); 565 1.2 jmcneill return pool; 566 1.1 jakllsch } 567 1.1 jakllsch 568 1.1 jakllsch CHAR16 * 569 1.1 jakllsch CatPrint ( 570 1.1 jakllsch IN OUT POOL_PRINT *Str, 571 1.2 jmcneill IN CONST CHAR16 *fmt, 572 1.1 jakllsch ... 573 1.1 jakllsch ) 574 1.1 jakllsch /*++ 575 1.1 jakllsch 576 1.1 jakllsch Routine Description: 577 1.1 jakllsch 578 1.2 jmcneill Concatenates a formatted unicode string to allocated pool. 579 1.1 jakllsch The caller must free the resulting buffer. 580 1.1 jakllsch 581 1.1 jakllsch Arguments: 582 1.1 jakllsch 583 1.2 jmcneill Str - Tracks the allocated pool, size in use, and 584 1.1 jakllsch amount of pool allocated. 585 1.1 jakllsch 586 1.1 jakllsch fmt - The format string 587 1.1 jakllsch 588 1.1 jakllsch Returns: 589 1.1 jakllsch 590 1.2 jmcneill Allocated buffer with the formatted string printed in it. 591 1.1 jakllsch The caller must free the allocated buffer. The buffer 592 1.1 jakllsch allocation is not packed. 593 1.1 jakllsch 594 1.1 jakllsch --*/ 595 1.1 jakllsch { 596 1.1 jakllsch va_list args; 597 1.1 jakllsch 598 1.1 jakllsch va_start (args, fmt); 599 1.1 jakllsch _PoolCatPrint (fmt, args, Str, _PoolPrint); 600 1.1 jakllsch va_end (args); 601 1.1 jakllsch return Str->str; 602 1.1 jakllsch } 603 1.1 jakllsch 604 1.1 jakllsch 605 1.1 jakllsch 606 1.1 jakllsch UINTN 607 1.1 jakllsch Print ( 608 1.2 jmcneill IN CONST CHAR16 *fmt, 609 1.1 jakllsch ... 610 1.1 jakllsch ) 611 1.1 jakllsch /*++ 612 1.1 jakllsch 613 1.1 jakllsch Routine Description: 614 1.1 jakllsch 615 1.1 jakllsch Prints a formatted unicode string to the default console 616 1.1 jakllsch 617 1.1 jakllsch Arguments: 618 1.1 jakllsch 619 1.1 jakllsch fmt - Format string 620 1.1 jakllsch 621 1.1 jakllsch Returns: 622 1.1 jakllsch 623 1.1 jakllsch Length of string printed to the console 624 1.1 jakllsch 625 1.1 jakllsch --*/ 626 1.1 jakllsch { 627 1.1 jakllsch va_list args; 628 1.1 jakllsch UINTN back; 629 1.1 jakllsch 630 1.1 jakllsch va_start (args, fmt); 631 1.1 jakllsch back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args); 632 1.1 jakllsch va_end (args); 633 1.1 jakllsch return back; 634 1.1 jakllsch } 635 1.1 jakllsch 636 1.1 jakllsch UINTN 637 1.1 jakllsch VPrint ( 638 1.2 jmcneill IN CONST CHAR16 *fmt, 639 1.2 jmcneill va_list args 640 1.1 jakllsch ) 641 1.1 jakllsch /*++ 642 1.1 jakllsch 643 1.1 jakllsch Routine Description: 644 1.1 jakllsch 645 1.1 jakllsch Prints a formatted unicode string to the default console using a va_list 646 1.1 jakllsch 647 1.1 jakllsch Arguments: 648 1.1 jakllsch 649 1.1 jakllsch fmt - Format string 650 1.1 jakllsch args - va_list 651 1.1 jakllsch Returns: 652 1.1 jakllsch 653 1.1 jakllsch Length of string printed to the console 654 1.1 jakllsch 655 1.1 jakllsch --*/ 656 1.1 jakllsch { 657 1.1 jakllsch return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args); 658 1.1 jakllsch } 659 1.1 jakllsch 660 1.1 jakllsch 661 1.1 jakllsch UINTN 662 1.1 jakllsch PrintAt ( 663 1.2 jmcneill IN UINTN Column, 664 1.2 jmcneill IN UINTN Row, 665 1.2 jmcneill IN CONST CHAR16 *fmt, 666 1.1 jakllsch ... 667 1.1 jakllsch ) 668 1.1 jakllsch /*++ 669 1.1 jakllsch 670 1.1 jakllsch Routine Description: 671 1.1 jakllsch 672 1.2 jmcneill Prints a formatted unicode string to the default console, at 673 1.1 jakllsch the supplied cursor position 674 1.1 jakllsch 675 1.1 jakllsch Arguments: 676 1.1 jakllsch 677 1.1 jakllsch Column, Row - The cursor position to print the string at 678 1.1 jakllsch 679 1.1 jakllsch fmt - Format string 680 1.1 jakllsch 681 1.1 jakllsch Returns: 682 1.1 jakllsch 683 1.1 jakllsch Length of string printed to the console 684 1.1 jakllsch 685 1.1 jakllsch --*/ 686 1.1 jakllsch { 687 1.1 jakllsch va_list args; 688 1.1 jakllsch UINTN back; 689 1.1 jakllsch 690 1.1 jakllsch va_start (args, fmt); 691 1.1 jakllsch back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args); 692 1.1 jakllsch va_end (args); 693 1.1 jakllsch return back; 694 1.1 jakllsch } 695 1.1 jakllsch 696 1.1 jakllsch 697 1.1 jakllsch UINTN 698 1.1 jakllsch IPrint ( 699 1.1 jakllsch IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, 700 1.2 jmcneill IN CONST CHAR16 *fmt, 701 1.1 jakllsch ... 702 1.1 jakllsch ) 703 1.1 jakllsch /*++ 704 1.1 jakllsch 705 1.1 jakllsch Routine Description: 706 1.1 jakllsch 707 1.1 jakllsch Prints a formatted unicode string to the specified console 708 1.1 jakllsch 709 1.1 jakllsch Arguments: 710 1.1 jakllsch 711 1.1 jakllsch Out - The console to print the string too 712 1.1 jakllsch 713 1.1 jakllsch fmt - Format string 714 1.1 jakllsch 715 1.1 jakllsch Returns: 716 1.1 jakllsch 717 1.1 jakllsch Length of string printed to the console 718 1.1 jakllsch 719 1.1 jakllsch --*/ 720 1.1 jakllsch { 721 1.1 jakllsch va_list args; 722 1.1 jakllsch UINTN back; 723 1.1 jakllsch 724 1.1 jakllsch va_start (args, fmt); 725 1.1 jakllsch back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args); 726 1.1 jakllsch va_end (args); 727 1.1 jakllsch return back; 728 1.1 jakllsch } 729 1.1 jakllsch 730 1.1 jakllsch 731 1.1 jakllsch UINTN 732 1.1 jakllsch IPrintAt ( 733 1.1 jakllsch IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, 734 1.1 jakllsch IN UINTN Column, 735 1.1 jakllsch IN UINTN Row, 736 1.2 jmcneill IN CONST CHAR16 *fmt, 737 1.1 jakllsch ... 738 1.1 jakllsch ) 739 1.1 jakllsch /*++ 740 1.1 jakllsch 741 1.1 jakllsch Routine Description: 742 1.1 jakllsch 743 1.1 jakllsch Prints a formatted unicode string to the specified console, at 744 1.1 jakllsch the supplied cursor position 745 1.1 jakllsch 746 1.1 jakllsch Arguments: 747 1.1 jakllsch 748 1.2 jmcneill Out - The console to print the string to 749 1.1 jakllsch 750 1.1 jakllsch Column, Row - The cursor position to print the string at 751 1.1 jakllsch 752 1.1 jakllsch fmt - Format string 753 1.1 jakllsch 754 1.1 jakllsch Returns: 755 1.1 jakllsch 756 1.1 jakllsch Length of string printed to the console 757 1.1 jakllsch 758 1.1 jakllsch --*/ 759 1.1 jakllsch { 760 1.1 jakllsch va_list args; 761 1.1 jakllsch UINTN back; 762 1.1 jakllsch 763 1.1 jakllsch va_start (args, fmt); 764 1.2 jmcneill back = _IPrint (Column, Row, Out, fmt, NULL, args); 765 1.1 jakllsch va_end (args); 766 1.1 jakllsch return back; 767 1.1 jakllsch } 768 1.1 jakllsch 769 1.1 jakllsch 770 1.1 jakllsch UINTN 771 1.1 jakllsch _IPrint ( 772 1.1 jakllsch IN UINTN Column, 773 1.1 jakllsch IN UINTN Row, 774 1.1 jakllsch IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, 775 1.2 jmcneill IN CONST CHAR16 *fmt, 776 1.2 jmcneill IN CONST CHAR8 *fmta, 777 1.1 jakllsch IN va_list args 778 1.1 jakllsch ) 779 1.1 jakllsch // Display string worker for: Print, PrintAt, IPrint, IPrintAt 780 1.1 jakllsch { 781 1.1 jakllsch PRINT_STATE ps; 782 1.1 jakllsch UINTN back; 783 1.1 jakllsch 784 1.1 jakllsch ZeroMem (&ps, sizeof(ps)); 785 1.1 jakllsch ps.Context = Out; 786 1.2 jmcneill ps.Output = (INTN (EFIAPI *)(VOID *, CHAR16 *)) Out->OutputString; 787 1.2 jmcneill ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN)) Out->SetAttribute; 788 1.1 jakllsch ps.Attr = Out->Mode->Attribute; 789 1.2 jmcneill 790 1.1 jakllsch back = (ps.Attr >> 4) & 0xF; 791 1.1 jakllsch ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back); 792 1.1 jakllsch ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back); 793 1.1 jakllsch ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back); 794 1.1 jakllsch 795 1.1 jakllsch if (fmt) { 796 1.1 jakllsch ps.fmt.pw = fmt; 797 1.1 jakllsch } else { 798 1.1 jakllsch ps.fmt.Ascii = TRUE; 799 1.1 jakllsch ps.fmt.pc = fmta; 800 1.1 jakllsch } 801 1.1 jakllsch 802 1.1 jakllsch va_copy(ps.args, args); 803 1.1 jakllsch 804 1.1 jakllsch if (Column != (UINTN) -1) { 805 1.1 jakllsch uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row); 806 1.1 jakllsch } 807 1.1 jakllsch 808 1.1 jakllsch back = _Print (&ps); 809 1.1 jakllsch va_end(ps.args); 810 1.1 jakllsch return back; 811 1.1 jakllsch } 812 1.1 jakllsch 813 1.1 jakllsch 814 1.1 jakllsch UINTN 815 1.5 jmcneill AsciiPrint ( 816 1.2 jmcneill IN CONST CHAR8 *fmt, 817 1.1 jakllsch ... 818 1.1 jakllsch ) 819 1.1 jakllsch /*++ 820 1.1 jakllsch 821 1.1 jakllsch Routine Description: 822 1.1 jakllsch 823 1.1 jakllsch For those whom really can't deal with unicode, a print 824 1.1 jakllsch function that takes an ascii format string 825 1.1 jakllsch 826 1.1 jakllsch Arguments: 827 1.1 jakllsch 828 1.1 jakllsch fmt - ascii format string 829 1.1 jakllsch 830 1.1 jakllsch Returns: 831 1.1 jakllsch 832 1.1 jakllsch Length of string printed to the console 833 1.1 jakllsch 834 1.1 jakllsch --*/ 835 1.1 jakllsch 836 1.1 jakllsch { 837 1.1 jakllsch va_list args; 838 1.1 jakllsch UINTN back; 839 1.1 jakllsch 840 1.1 jakllsch va_start (args, fmt); 841 1.1 jakllsch back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args); 842 1.1 jakllsch va_end (args); 843 1.1 jakllsch return back; 844 1.1 jakllsch } 845 1.1 jakllsch 846 1.1 jakllsch 847 1.5 jmcneill UINTN 848 1.5 jmcneill AsciiVSPrint ( 849 1.5 jmcneill OUT CHAR8 *Str, 850 1.5 jmcneill IN UINTN StrSize, 851 1.5 jmcneill IN CONST CHAR8 *fmt, 852 1.5 jmcneill va_list args 853 1.5 jmcneill ) 854 1.5 jmcneill /*++ 855 1.5 jmcneill 856 1.5 jmcneill Routine Description: 857 1.5 jmcneill 858 1.5 jmcneill Prints a formatted ascii string to a buffer using a va_list 859 1.5 jmcneill 860 1.5 jmcneill Arguments: 861 1.5 jmcneill 862 1.5 jmcneill Str - Output buffer to print the formatted string into 863 1.5 jmcneill 864 1.5 jmcneill StrSize - Size of Str. String is truncated to this size. 865 1.5 jmcneill A size of 0 means there is no limit 866 1.5 jmcneill 867 1.5 jmcneill fmt - The format string 868 1.5 jmcneill 869 1.5 jmcneill args - va_list 870 1.5 jmcneill 871 1.5 jmcneill 872 1.5 jmcneill Returns: 873 1.5 jmcneill 874 1.5 jmcneill String length returned in buffer 875 1.5 jmcneill 876 1.5 jmcneill --*/ 877 1.5 jmcneill // Use UnicodeVSPrint() and convert back to ASCII 878 1.5 jmcneill { 879 1.5 jmcneill CHAR16 *UnicodeStr, *UnicodeFmt; 880 1.5 jmcneill UINTN i, Len; 881 1.5 jmcneill 882 1.5 jmcneill UnicodeStr = AllocatePool(StrSize * sizeof(CHAR16)); 883 1.5 jmcneill if (!UnicodeStr) 884 1.5 jmcneill return 0; 885 1.5 jmcneill 886 1.5 jmcneill UnicodeFmt = PoolPrint(L"%a", fmt); 887 1.5 jmcneill if (!UnicodeFmt) { 888 1.5 jmcneill FreePool(UnicodeStr); 889 1.5 jmcneill return 0; 890 1.5 jmcneill } 891 1.5 jmcneill 892 1.5 jmcneill Len = UnicodeVSPrint(UnicodeStr, StrSize, UnicodeFmt, args); 893 1.5 jmcneill FreePool(UnicodeFmt); 894 1.5 jmcneill 895 1.5 jmcneill // The strings are ASCII so just do a plain Unicode conversion 896 1.5 jmcneill for (i = 0; i < Len; i++) 897 1.5 jmcneill Str[i] = (CHAR8)UnicodeStr[i]; 898 1.5 jmcneill Str[Len] = 0; 899 1.5 jmcneill FreePool(UnicodeStr); 900 1.5 jmcneill 901 1.5 jmcneill return Len; 902 1.5 jmcneill } 903 1.5 jmcneill 904 1.5 jmcneill 905 1.1 jakllsch STATIC 906 1.1 jakllsch VOID 907 1.1 jakllsch PFLUSH ( 908 1.1 jakllsch IN OUT PRINT_STATE *ps 909 1.1 jakllsch ) 910 1.1 jakllsch { 911 1.1 jakllsch *ps->Pos = 0; 912 1.1 jakllsch if (IsLocalPrint(ps->Output)) 913 1.2 jmcneill ps->Output(ps->Context, ps->Buffer); 914 1.1 jakllsch else 915 1.1 jakllsch uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer); 916 1.1 jakllsch ps->Pos = ps->Buffer; 917 1.1 jakllsch } 918 1.1 jakllsch 919 1.1 jakllsch STATIC 920 1.1 jakllsch VOID 921 1.1 jakllsch PSETATTR ( 922 1.1 jakllsch IN OUT PRINT_STATE *ps, 923 1.1 jakllsch IN UINTN Attr 924 1.1 jakllsch ) 925 1.1 jakllsch { 926 1.1 jakllsch PFLUSH (ps); 927 1.1 jakllsch 928 1.1 jakllsch ps->RestoreAttr = ps->Attr; 929 1.1 jakllsch if (ps->SetAttr) { 930 1.1 jakllsch uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr); 931 1.1 jakllsch } 932 1.1 jakllsch 933 1.1 jakllsch ps->Attr = Attr; 934 1.2 jmcneill } 935 1.1 jakllsch 936 1.1 jakllsch STATIC 937 1.1 jakllsch VOID 938 1.1 jakllsch PPUTC ( 939 1.1 jakllsch IN OUT PRINT_STATE *ps, 940 1.1 jakllsch IN CHAR16 c 941 1.1 jakllsch ) 942 1.1 jakllsch { 943 1.1 jakllsch // if this is a newline, add a carraige return 944 1.1 jakllsch if (c == '\n') { 945 1.1 jakllsch PPUTC (ps, '\r'); 946 1.1 jakllsch } 947 1.1 jakllsch 948 1.1 jakllsch *ps->Pos = c; 949 1.1 jakllsch ps->Pos += 1; 950 1.1 jakllsch ps->Len += 1; 951 1.1 jakllsch 952 1.1 jakllsch // if at the end of the buffer, flush it 953 1.1 jakllsch if (ps->Pos >= ps->End) { 954 1.1 jakllsch PFLUSH(ps); 955 1.1 jakllsch } 956 1.1 jakllsch } 957 1.1 jakllsch 958 1.1 jakllsch 959 1.1 jakllsch STATIC 960 1.1 jakllsch CHAR16 961 1.1 jakllsch PGETC ( 962 1.1 jakllsch IN POINTER *p 963 1.1 jakllsch ) 964 1.1 jakllsch { 965 1.1 jakllsch CHAR16 c; 966 1.1 jakllsch 967 1.1 jakllsch c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index]; 968 1.1 jakllsch p->Index += 1; 969 1.1 jakllsch 970 1.1 jakllsch return c; 971 1.1 jakllsch } 972 1.1 jakllsch 973 1.1 jakllsch 974 1.1 jakllsch STATIC 975 1.1 jakllsch VOID 976 1.1 jakllsch PITEM ( 977 1.1 jakllsch IN OUT PRINT_STATE *ps 978 1.1 jakllsch ) 979 1.1 jakllsch { 980 1.1 jakllsch UINTN Len, i; 981 1.1 jakllsch PRINT_ITEM *Item; 982 1.1 jakllsch CHAR16 c; 983 1.1 jakllsch 984 1.1 jakllsch // Get the length of the item 985 1.1 jakllsch Item = ps->Item; 986 1.1 jakllsch Item->Item.Index = 0; 987 1.1 jakllsch while (Item->Item.Index < Item->FieldWidth) { 988 1.1 jakllsch c = PGETC(&Item->Item); 989 1.1 jakllsch if (!c) { 990 1.1 jakllsch Item->Item.Index -= 1; 991 1.1 jakllsch break; 992 1.1 jakllsch } 993 1.1 jakllsch } 994 1.1 jakllsch Len = Item->Item.Index; 995 1.1 jakllsch 996 1.1 jakllsch // if there is no item field width, use the items width 997 1.1 jakllsch if (Item->FieldWidth == (UINTN) -1) { 998 1.1 jakllsch Item->FieldWidth = Len; 999 1.1 jakllsch } 1000 1.1 jakllsch 1001 1.1 jakllsch // if item is larger then width, update width 1002 1.1 jakllsch if (Len > Item->Width) { 1003 1.1 jakllsch Item->Width = Len; 1004 1.1 jakllsch } 1005 1.1 jakllsch 1006 1.1 jakllsch 1007 1.1 jakllsch // if pad field before, add pad char 1008 1.1 jakllsch if (Item->PadBefore) { 1009 1.1 jakllsch for (i=Item->Width; i < Item->FieldWidth; i+=1) { 1010 1.1 jakllsch PPUTC (ps, ' '); 1011 1.1 jakllsch } 1012 1.1 jakllsch } 1013 1.1 jakllsch 1014 1.1 jakllsch // pad item 1015 1.1 jakllsch for (i=Len; i < Item->Width; i++) { 1016 1.1 jakllsch PPUTC (ps, Item->Pad); 1017 1.1 jakllsch } 1018 1.1 jakllsch 1019 1.1 jakllsch // add the item 1020 1.2 jmcneill Item->Item.Index=0; 1021 1.1 jakllsch while (Item->Item.Index < Len) { 1022 1.1 jakllsch PPUTC (ps, PGETC(&Item->Item)); 1023 1.1 jakllsch } 1024 1.1 jakllsch 1025 1.1 jakllsch // If pad at the end, add pad char 1026 1.1 jakllsch if (!Item->PadBefore) { 1027 1.1 jakllsch for (i=Item->Width; i < Item->FieldWidth; i+=1) { 1028 1.1 jakllsch PPUTC (ps, ' '); 1029 1.1 jakllsch } 1030 1.1 jakllsch } 1031 1.1 jakllsch } 1032 1.1 jakllsch 1033 1.1 jakllsch 1034 1.1 jakllsch STATIC 1035 1.1 jakllsch UINTN 1036 1.1 jakllsch _Print ( 1037 1.1 jakllsch IN PRINT_STATE *ps 1038 1.1 jakllsch ) 1039 1.1 jakllsch /*++ 1040 1.1 jakllsch 1041 1.1 jakllsch Routine Description: 1042 1.1 jakllsch 1043 1.1 jakllsch %w.lF - w = width 1044 1.1 jakllsch l = field width 1045 1.1 jakllsch F = format of arg 1046 1.1 jakllsch 1047 1.1 jakllsch Args F: 1048 1.1 jakllsch 0 - pad with zeros 1049 1.1 jakllsch - - justify on left (default is on right) 1050 1.2 jmcneill , - add comma's to field 1051 1.1 jakllsch * - width provided on stack 1052 1.1 jakllsch n - Set output attribute to normal (for this field only) 1053 1.1 jakllsch h - Set output attribute to highlight (for this field only) 1054 1.1 jakllsch e - Set output attribute to error (for this field only) 1055 1.1 jakllsch l - Value is 64 bits 1056 1.1 jakllsch 1057 1.1 jakllsch a - ascii string 1058 1.1 jakllsch s - unicode string 1059 1.1 jakllsch X - fixed 8 byte value in hex 1060 1.1 jakllsch x - hex value 1061 1.2 jmcneill d - value as signed decimal 1062 1.2 jmcneill u - value as unsigned decimal 1063 1.2 jmcneill f - value as floating point 1064 1.1 jakllsch c - Unicode char 1065 1.1 jakllsch t - EFI time structure 1066 1.1 jakllsch g - Pointer to GUID 1067 1.1 jakllsch r - EFI status code (result code) 1068 1.2 jmcneill D - pointer to Device Path with normal ending. 1069 1.1 jakllsch 1070 1.1 jakllsch N - Set output attribute to normal 1071 1.1 jakllsch H - Set output attribute to highlight 1072 1.1 jakllsch E - Set output attribute to error 1073 1.1 jakllsch % - Print a % 1074 1.2 jmcneill 1075 1.1 jakllsch Arguments: 1076 1.1 jakllsch 1077 1.1 jakllsch SystemTable - The system table 1078 1.1 jakllsch 1079 1.1 jakllsch Returns: 1080 1.1 jakllsch 1081 1.2 jmcneill Number of charactors written 1082 1.1 jakllsch 1083 1.1 jakllsch --*/ 1084 1.1 jakllsch { 1085 1.1 jakllsch CHAR16 c; 1086 1.1 jakllsch UINTN Attr; 1087 1.1 jakllsch PRINT_ITEM Item; 1088 1.1 jakllsch CHAR16 Buffer[PRINT_STRING_LEN]; 1089 1.1 jakllsch 1090 1.1 jakllsch ps->Len = 0; 1091 1.1 jakllsch ps->Buffer = Buffer; 1092 1.1 jakllsch ps->Pos = Buffer; 1093 1.1 jakllsch ps->End = Buffer + PRINT_STRING_LEN - 1; 1094 1.1 jakllsch ps->Item = &Item; 1095 1.1 jakllsch 1096 1.1 jakllsch ps->fmt.Index = 0; 1097 1.1 jakllsch while ((c = PGETC(&ps->fmt))) { 1098 1.1 jakllsch 1099 1.1 jakllsch if (c != '%') { 1100 1.1 jakllsch PPUTC ( ps, c ); 1101 1.2 jmcneill continue; 1102 1.1 jakllsch } 1103 1.1 jakllsch 1104 1.1 jakllsch // setup for new item 1105 1.1 jakllsch Item.FieldWidth = (UINTN) -1; 1106 1.1 jakllsch Item.Width = 0; 1107 1.1 jakllsch Item.WidthParse = &Item.Width; 1108 1.1 jakllsch Item.Pad = ' '; 1109 1.1 jakllsch Item.PadBefore = TRUE; 1110 1.1 jakllsch Item.Comma = FALSE; 1111 1.1 jakllsch Item.Long = FALSE; 1112 1.1 jakllsch Item.Item.Ascii = FALSE; 1113 1.1 jakllsch Item.Item.pw = NULL; 1114 1.1 jakllsch ps->RestoreAttr = 0; 1115 1.1 jakllsch Attr = 0; 1116 1.1 jakllsch 1117 1.1 jakllsch while ((c = PGETC(&ps->fmt))) { 1118 1.1 jakllsch 1119 1.1 jakllsch switch (c) { 1120 1.2 jmcneill 1121 1.1 jakllsch case '%': 1122 1.1 jakllsch // 1123 1.1 jakllsch // %% -> % 1124 1.1 jakllsch // 1125 1.2 jmcneill Item.Scratch[0] = '%'; 1126 1.2 jmcneill Item.Scratch[1] = 0; 1127 1.1 jakllsch Item.Item.pw = Item.Scratch; 1128 1.1 jakllsch break; 1129 1.1 jakllsch 1130 1.1 jakllsch case '0': 1131 1.1 jakllsch Item.Pad = '0'; 1132 1.1 jakllsch break; 1133 1.1 jakllsch 1134 1.1 jakllsch case '-': 1135 1.1 jakllsch Item.PadBefore = FALSE; 1136 1.1 jakllsch break; 1137 1.1 jakllsch 1138 1.1 jakllsch case ',': 1139 1.1 jakllsch Item.Comma = TRUE; 1140 1.1 jakllsch break; 1141 1.1 jakllsch 1142 1.1 jakllsch case '.': 1143 1.1 jakllsch Item.WidthParse = &Item.FieldWidth; 1144 1.1 jakllsch break; 1145 1.1 jakllsch 1146 1.1 jakllsch case '*': 1147 1.1 jakllsch *Item.WidthParse = va_arg(ps->args, UINTN); 1148 1.1 jakllsch break; 1149 1.2 jmcneill 1150 1.1 jakllsch case '1': 1151 1.1 jakllsch case '2': 1152 1.1 jakllsch case '3': 1153 1.1 jakllsch case '4': 1154 1.1 jakllsch case '5': 1155 1.1 jakllsch case '6': 1156 1.1 jakllsch case '7': 1157 1.1 jakllsch case '8': 1158 1.1 jakllsch case '9': 1159 1.1 jakllsch *Item.WidthParse = 0; 1160 1.1 jakllsch do { 1161 1.1 jakllsch *Item.WidthParse = *Item.WidthParse * 10 + c - '0'; 1162 1.1 jakllsch c = PGETC(&ps->fmt); 1163 1.1 jakllsch } while (c >= '0' && c <= '9') ; 1164 1.1 jakllsch ps->fmt.Index -= 1; 1165 1.1 jakllsch break; 1166 1.1 jakllsch 1167 1.1 jakllsch case 'a': 1168 1.1 jakllsch Item.Item.pc = va_arg(ps->args, CHAR8 *); 1169 1.1 jakllsch Item.Item.Ascii = TRUE; 1170 1.1 jakllsch if (!Item.Item.pc) { 1171 1.1 jakllsch Item.Item.pc = (CHAR8 *)"(null)"; 1172 1.1 jakllsch } 1173 1.1 jakllsch break; 1174 1.1 jakllsch 1175 1.1 jakllsch case 's': 1176 1.1 jakllsch Item.Item.pw = va_arg(ps->args, CHAR16 *); 1177 1.1 jakllsch if (!Item.Item.pw) { 1178 1.1 jakllsch Item.Item.pw = L"(null)"; 1179 1.1 jakllsch } 1180 1.1 jakllsch break; 1181 1.1 jakllsch 1182 1.1 jakllsch case 'c': 1183 1.2 jmcneill Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN); 1184 1.2 jmcneill Item.Scratch[1] = 0; 1185 1.1 jakllsch Item.Item.pw = Item.Scratch; 1186 1.1 jakllsch break; 1187 1.1 jakllsch 1188 1.1 jakllsch case 'l': 1189 1.1 jakllsch Item.Long = TRUE; 1190 1.1 jakllsch break; 1191 1.1 jakllsch 1192 1.1 jakllsch case 'X': 1193 1.1 jakllsch Item.Width = Item.Long ? 16 : 8; 1194 1.1 jakllsch Item.Pad = '0'; 1195 1.2 jmcneill #if __GNUC__ >= 7 1196 1.2 jmcneill __attribute__ ((fallthrough)); 1197 1.2 jmcneill #endif 1198 1.1 jakllsch case 'x': 1199 1.1 jakllsch ValueToHex ( 1200 1.2 jmcneill Item.Scratch, 1201 1.1 jakllsch Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32) 1202 1.1 jakllsch ); 1203 1.2 jmcneill Item.Item.pw = Item.Scratch; 1204 1.1 jakllsch 1205 1.1 jakllsch break; 1206 1.2 jmcneill 1207 1.1 jakllsch 1208 1.1 jakllsch case 'g': 1209 1.2 jmcneill GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *)); 1210 1.2 jmcneill Item.Item.pw = Item.Scratch; 1211 1.2 jmcneill break; 1212 1.2 jmcneill 1213 1.2 jmcneill case 'u': 1214 1.2 jmcneill ValueToString ( 1215 1.2 jmcneill Item.Scratch, 1216 1.2 jmcneill Item.Comma, 1217 1.2 jmcneill Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32) 1218 1.2 jmcneill ); 1219 1.1 jakllsch Item.Item.pw = Item.Scratch; 1220 1.1 jakllsch break; 1221 1.1 jakllsch 1222 1.1 jakllsch case 'd': 1223 1.2 jmcneill ValueToString ( 1224 1.2 jmcneill Item.Scratch, 1225 1.2 jmcneill Item.Comma, 1226 1.2 jmcneill Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32) 1227 1.2 jmcneill ); 1228 1.2 jmcneill Item.Item.pw = Item.Scratch; 1229 1.2 jmcneill break; 1230 1.2 jmcneill 1231 1.2 jmcneill case 'D': 1232 1.2 jmcneill { 1233 1.2 jmcneill EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *); 1234 1.2 jmcneill CHAR16 *dpstr = DevicePathToStr(dp); 1235 1.2 jmcneill StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN); 1236 1.2 jmcneill Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0'; 1237 1.2 jmcneill FreePool(dpstr); 1238 1.2 jmcneill 1239 1.1 jakllsch Item.Item.pw = Item.Scratch; 1240 1.2 jmcneill break; 1241 1.2 jmcneill } 1242 1.2 jmcneill 1243 1.2 jmcneill #ifndef __NetBSD__ 1244 1.2 jmcneill case 'f': 1245 1.2 jmcneill FloatToString ( 1246 1.2 jmcneill Item.Scratch, 1247 1.2 jmcneill Item.Comma, 1248 1.2 jmcneill va_arg(ps->args, double) 1249 1.1 jakllsch ); 1250 1.2 jmcneill Item.Item.pw = Item.Scratch; 1251 1.2 jmcneill break; 1252 1.2 jmcneill #endif 1253 1.2 jmcneill 1254 1.1 jakllsch case 't': 1255 1.2 jmcneill TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *)); 1256 1.1 jakllsch Item.Item.pw = Item.Scratch; 1257 1.1 jakllsch break; 1258 1.1 jakllsch 1259 1.1 jakllsch case 'r': 1260 1.2 jmcneill StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS)); 1261 1.1 jakllsch Item.Item.pw = Item.Scratch; 1262 1.1 jakllsch break; 1263 1.1 jakllsch 1264 1.1 jakllsch case 'n': 1265 1.1 jakllsch PSETATTR(ps, ps->AttrNorm); 1266 1.1 jakllsch break; 1267 1.1 jakllsch 1268 1.1 jakllsch case 'h': 1269 1.1 jakllsch PSETATTR(ps, ps->AttrHighlight); 1270 1.1 jakllsch break; 1271 1.1 jakllsch 1272 1.1 jakllsch case 'e': 1273 1.1 jakllsch PSETATTR(ps, ps->AttrError); 1274 1.1 jakllsch break; 1275 1.1 jakllsch 1276 1.1 jakllsch case 'N': 1277 1.1 jakllsch Attr = ps->AttrNorm; 1278 1.1 jakllsch break; 1279 1.1 jakllsch 1280 1.1 jakllsch case 'H': 1281 1.1 jakllsch Attr = ps->AttrHighlight; 1282 1.1 jakllsch break; 1283 1.1 jakllsch 1284 1.1 jakllsch case 'E': 1285 1.1 jakllsch Attr = ps->AttrError; 1286 1.1 jakllsch break; 1287 1.1 jakllsch 1288 1.1 jakllsch default: 1289 1.2 jmcneill Item.Scratch[0] = '?'; 1290 1.2 jmcneill Item.Scratch[1] = 0; 1291 1.1 jakllsch Item.Item.pw = Item.Scratch; 1292 1.1 jakllsch break; 1293 1.1 jakllsch } 1294 1.1 jakllsch 1295 1.1 jakllsch // if we have an Item 1296 1.1 jakllsch if (Item.Item.pw) { 1297 1.1 jakllsch PITEM (ps); 1298 1.1 jakllsch break; 1299 1.1 jakllsch } 1300 1.1 jakllsch 1301 1.1 jakllsch // if we have an Attr set 1302 1.1 jakllsch if (Attr) { 1303 1.1 jakllsch PSETATTR(ps, Attr); 1304 1.1 jakllsch ps->RestoreAttr = 0; 1305 1.1 jakllsch break; 1306 1.1 jakllsch } 1307 1.1 jakllsch } 1308 1.1 jakllsch 1309 1.1 jakllsch if (ps->RestoreAttr) { 1310 1.1 jakllsch PSETATTR(ps, ps->RestoreAttr); 1311 1.1 jakllsch } 1312 1.1 jakllsch } 1313 1.1 jakllsch 1314 1.1 jakllsch // Flush buffer 1315 1.1 jakllsch PFLUSH (ps); 1316 1.1 jakllsch return ps->Len; 1317 1.1 jakllsch } 1318 1.1 jakllsch 1319 1.1 jakllsch STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7', 1320 1.1 jakllsch '8','9','A','B','C','D','E','F'}; 1321 1.1 jakllsch 1322 1.1 jakllsch VOID 1323 1.1 jakllsch ValueToHex ( 1324 1.1 jakllsch IN CHAR16 *Buffer, 1325 1.1 jakllsch IN UINT64 v 1326 1.1 jakllsch ) 1327 1.1 jakllsch { 1328 1.1 jakllsch CHAR8 str[30], *p1; 1329 1.1 jakllsch CHAR16 *p2; 1330 1.1 jakllsch 1331 1.1 jakllsch if (!v) { 1332 1.1 jakllsch Buffer[0] = '0'; 1333 1.1 jakllsch Buffer[1] = 0; 1334 1.1 jakllsch return ; 1335 1.1 jakllsch } 1336 1.1 jakllsch 1337 1.1 jakllsch p1 = str; 1338 1.1 jakllsch p2 = Buffer; 1339 1.1 jakllsch 1340 1.1 jakllsch while (v) { 1341 1.2 jmcneill // Without the cast, the MSVC compiler may insert a reference to __allmull 1342 1.2 jmcneill *(p1++) = Hex[(UINTN)(v & 0xf)]; 1343 1.1 jakllsch v = RShiftU64 (v, 4); 1344 1.1 jakllsch } 1345 1.1 jakllsch 1346 1.1 jakllsch while (p1 != str) { 1347 1.1 jakllsch *(p2++) = *(--p1); 1348 1.1 jakllsch } 1349 1.1 jakllsch *p2 = 0; 1350 1.1 jakllsch } 1351 1.1 jakllsch 1352 1.1 jakllsch 1353 1.1 jakllsch VOID 1354 1.1 jakllsch ValueToString ( 1355 1.1 jakllsch IN CHAR16 *Buffer, 1356 1.1 jakllsch IN BOOLEAN Comma, 1357 1.1 jakllsch IN INT64 v 1358 1.1 jakllsch ) 1359 1.1 jakllsch { 1360 1.1 jakllsch STATIC CHAR8 ca[] = { 3, 1, 2 }; 1361 1.1 jakllsch CHAR8 str[40], *p1; 1362 1.1 jakllsch CHAR16 *p2; 1363 1.1 jakllsch UINTN c, r; 1364 1.1 jakllsch 1365 1.1 jakllsch if (!v) { 1366 1.1 jakllsch Buffer[0] = '0'; 1367 1.1 jakllsch Buffer[1] = 0; 1368 1.1 jakllsch return ; 1369 1.1 jakllsch } 1370 1.1 jakllsch 1371 1.1 jakllsch p1 = str; 1372 1.1 jakllsch p2 = Buffer; 1373 1.1 jakllsch 1374 1.1 jakllsch if (v < 0) { 1375 1.1 jakllsch *(p2++) = '-'; 1376 1.1 jakllsch v = -v; 1377 1.1 jakllsch } 1378 1.1 jakllsch 1379 1.1 jakllsch while (v) { 1380 1.1 jakllsch v = (INT64)DivU64x32 ((UINT64)v, 10, &r); 1381 1.1 jakllsch *(p1++) = (CHAR8)r + '0'; 1382 1.1 jakllsch } 1383 1.1 jakllsch 1384 1.5 jmcneill c = (UINTN) (Comma ? ca[(p1 - str) % 3] : 999) + 1; 1385 1.1 jakllsch while (p1 != str) { 1386 1.1 jakllsch 1387 1.1 jakllsch c -= 1; 1388 1.1 jakllsch if (!c) { 1389 1.1 jakllsch *(p2++) = ','; 1390 1.1 jakllsch c = 3; 1391 1.1 jakllsch } 1392 1.1 jakllsch 1393 1.1 jakllsch *(p2++) = *(--p1); 1394 1.1 jakllsch } 1395 1.1 jakllsch *p2 = 0; 1396 1.1 jakllsch } 1397 1.1 jakllsch 1398 1.2 jmcneill #ifndef __NetBSD__ 1399 1.2 jmcneill VOID 1400 1.2 jmcneill FloatToString ( 1401 1.2 jmcneill IN CHAR16 *Buffer, 1402 1.2 jmcneill IN BOOLEAN Comma, 1403 1.2 jmcneill IN double v 1404 1.2 jmcneill ) 1405 1.2 jmcneill { 1406 1.2 jmcneill /* 1407 1.2 jmcneill * Integer part. 1408 1.2 jmcneill */ 1409 1.2 jmcneill INTN i = (INTN)v; 1410 1.2 jmcneill ValueToString(Buffer, Comma, i); 1411 1.2 jmcneill 1412 1.2 jmcneill 1413 1.2 jmcneill /* 1414 1.2 jmcneill * Decimal point. 1415 1.2 jmcneill */ 1416 1.2 jmcneill UINTN x = StrLen(Buffer); 1417 1.2 jmcneill Buffer[x] = L'.'; 1418 1.2 jmcneill x++; 1419 1.2 jmcneill 1420 1.2 jmcneill 1421 1.2 jmcneill /* 1422 1.2 jmcneill * Keep fractional part. 1423 1.2 jmcneill */ 1424 1.2 jmcneill float f = (float)(v - i); 1425 1.2 jmcneill if (f < 0) f = -f; 1426 1.2 jmcneill 1427 1.2 jmcneill 1428 1.2 jmcneill /* 1429 1.2 jmcneill * Leading fractional zeroes. 1430 1.2 jmcneill */ 1431 1.2 jmcneill f *= 10.0; 1432 1.2 jmcneill while ( (f != 0) 1433 1.2 jmcneill && ((INTN)f == 0)) 1434 1.2 jmcneill { 1435 1.2 jmcneill Buffer[x] = L'0'; 1436 1.2 jmcneill x++; 1437 1.2 jmcneill f *= 10.0; 1438 1.2 jmcneill } 1439 1.2 jmcneill 1440 1.2 jmcneill 1441 1.2 jmcneill /* 1442 1.2 jmcneill * Fractional digits. 1443 1.2 jmcneill */ 1444 1.2 jmcneill while ((float)(INTN)f != f) 1445 1.2 jmcneill { 1446 1.2 jmcneill f *= 10; 1447 1.2 jmcneill } 1448 1.2 jmcneill ValueToString(Buffer + x, FALSE, (INTN)f); 1449 1.2 jmcneill return; 1450 1.2 jmcneill } 1451 1.2 jmcneill #endif 1452 1.2 jmcneill 1453 1.1 jakllsch VOID 1454 1.1 jakllsch TimeToString ( 1455 1.1 jakllsch OUT CHAR16 *Buffer, 1456 1.1 jakllsch IN EFI_TIME *Time 1457 1.1 jakllsch ) 1458 1.1 jakllsch { 1459 1.1 jakllsch UINTN Hour, Year; 1460 1.1 jakllsch CHAR16 AmPm; 1461 1.1 jakllsch 1462 1.1 jakllsch AmPm = 'a'; 1463 1.1 jakllsch Hour = Time->Hour; 1464 1.1 jakllsch if (Time->Hour == 0) { 1465 1.1 jakllsch Hour = 12; 1466 1.1 jakllsch } else if (Time->Hour >= 12) { 1467 1.1 jakllsch AmPm = 'p'; 1468 1.1 jakllsch if (Time->Hour >= 13) { 1469 1.1 jakllsch Hour -= 12; 1470 1.1 jakllsch } 1471 1.1 jakllsch } 1472 1.1 jakllsch 1473 1.1 jakllsch Year = Time->Year % 100; 1474 1.2 jmcneill 1475 1.1 jakllsch // bugbug: for now just print it any old way 1476 1.5 jmcneill UnicodeSPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c", 1477 1.1 jakllsch Time->Month, 1478 1.1 jakllsch Time->Day, 1479 1.1 jakllsch Year, 1480 1.1 jakllsch Hour, 1481 1.1 jakllsch Time->Minute, 1482 1.1 jakllsch AmPm 1483 1.1 jakllsch ); 1484 1.2 jmcneill } 1485 1.1 jakllsch 1486 1.1 jakllsch 1487 1.1 jakllsch 1488 1.1 jakllsch 1489 1.1 jakllsch VOID 1490 1.1 jakllsch DumpHex ( 1491 1.1 jakllsch IN UINTN Indent, 1492 1.1 jakllsch IN UINTN Offset, 1493 1.1 jakllsch IN UINTN DataSize, 1494 1.1 jakllsch IN VOID *UserData 1495 1.1 jakllsch ) 1496 1.1 jakllsch { 1497 1.1 jakllsch CHAR8 *Data, Val[50], Str[20], c; 1498 1.1 jakllsch UINTN Size, Index; 1499 1.2 jmcneill 1500 1.1 jakllsch UINTN ScreenCount; 1501 1.1 jakllsch UINTN TempColumn; 1502 1.1 jakllsch UINTN ScreenSize; 1503 1.1 jakllsch CHAR16 ReturnStr[1]; 1504 1.1 jakllsch 1505 1.1 jakllsch 1506 1.1 jakllsch uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize); 1507 1.1 jakllsch ScreenCount = 0; 1508 1.1 jakllsch ScreenSize -= 2; 1509 1.1 jakllsch 1510 1.1 jakllsch Data = UserData; 1511 1.1 jakllsch while (DataSize) { 1512 1.1 jakllsch Size = 16; 1513 1.1 jakllsch if (Size > DataSize) { 1514 1.1 jakllsch Size = DataSize; 1515 1.1 jakllsch } 1516 1.1 jakllsch 1517 1.1 jakllsch for (Index=0; Index < Size; Index += 1) { 1518 1.1 jakllsch c = Data[Index]; 1519 1.1 jakllsch Val[Index*3+0] = Hex[c>>4]; 1520 1.1 jakllsch Val[Index*3+1] = Hex[c&0xF]; 1521 1.1 jakllsch Val[Index*3+2] = (Index == 7)?'-':' '; 1522 1.1 jakllsch Str[Index] = (c < ' ' || c > 'z') ? '.' : c; 1523 1.1 jakllsch } 1524 1.1 jakllsch 1525 1.1 jakllsch Val[Index*3] = 0; 1526 1.1 jakllsch Str[Index] = 0; 1527 1.1 jakllsch Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str); 1528 1.1 jakllsch 1529 1.1 jakllsch Data += Size; 1530 1.1 jakllsch Offset += Size; 1531 1.1 jakllsch DataSize -= Size; 1532 1.1 jakllsch 1533 1.1 jakllsch ScreenCount++; 1534 1.1 jakllsch if (ScreenCount >= ScreenSize && ScreenSize != 0) { 1535 1.1 jakllsch // 1536 1.1 jakllsch // If ScreenSize == 0 we have the console redirected so don't 1537 1.1 jakllsch // block updates 1538 1.1 jakllsch // 1539 1.1 jakllsch ScreenCount = 0; 1540 1.1 jakllsch Print (L"Press Enter to continue :"); 1541 1.1 jakllsch Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16)); 1542 1.1 jakllsch Print (L"\n"); 1543 1.1 jakllsch } 1544 1.1 jakllsch 1545 1.1 jakllsch } 1546 1.1 jakllsch } 1547