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