TianoCore EDK2 master
Loading...
Searching...
No Matches
EdbSupportUI.c
Go to the documentation of this file.
1
9#include "Edb.h"
10
24VOID
25EFIAPI
28 IN UINTN Column,
29 IN INTN Row,
30 IN UINTN LineLength,
31 IN UINTN TotalRow,
32 IN CHAR16 *Str,
33 IN UINTN StrPos,
34 IN UINTN Len
35 );
36
49EFIAPI
51 IN EFI_EVENT Event,
52 IN UINT64 Timeout OPTIONAL
53 )
54{
55 EFI_STATUS Status;
56 UINTN Index;
57 EFI_EVENT TimerEvent;
58 EFI_EVENT WaitList[2];
59
60 if (Timeout != 0) {
61 //
62 // Create a timer event
63 //
64 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
65 if (!EFI_ERROR (Status)) {
66 //
67 // Set the timer event
68 //
69 gBS->SetTimer (
70 TimerEvent,
72 Timeout
73 );
74
75 //
76 // Wait for the original event or the timer
77 //
78 WaitList[0] = Event;
79 WaitList[1] = TimerEvent;
80 Status = gBS->WaitForEvent (2, WaitList, &Index);
81 gBS->CloseEvent (TimerEvent);
82
83 //
84 // If the timer expired, change the return to timed out
85 //
86 if (!EFI_ERROR (Status) && (Index == 1)) {
87 Status = EFI_TIMEOUT;
88 }
89 }
90 } else {
91 //
92 // No timeout... just wait on the event
93 //
94 Status = gBS->WaitForEvent (1, &Event, &Index);
95 ASSERT (!EFI_ERROR (Status));
96 ASSERT (Index == 0);
97 }
98
99 return Status;
100}
101
111VOID
112EFIAPI
114 IN UINTN LineLength,
115 IN OUT UINTN *Column,
116 IN OUT UINTN *Row
117 )
118{
119 ASSERT (Column != NULL);
120 ASSERT (Row != NULL);
121 //
122 // If current column is 0, move to the last column of the previous line,
123 // otherwise, just decrement column.
124 //
125 if (*Column == 0) {
126 (*Column) = LineLength - 1;
127 //
128 // if (*Row > 0) {
129 //
130 (*Row)--;
131 //
132 // }
133 //
134 } else {
135 (*Column)--;
136 }
137}
138
149VOID
150EFIAPI
152 IN UINTN LineLength,
153 IN UINTN TotalRow,
154 IN OUT UINTN *Column,
155 IN OUT UINTN *Row
156 )
157{
158 ASSERT (Column != NULL);
159 ASSERT (Row != NULL);
160 //
161 // If current column is at line end, move to the first column of the nest
162 // line, otherwise, just increment column.
163 //
164 (*Column)++;
165 if (*Column >= LineLength) {
166 (*Column) = 0;
167 if ((*Row) < TotalRow - 1) {
168 (*Row)++;
169 }
170 }
171}
172
173CHAR16 mBackupSpace[EFI_DEBUG_INPUS_BUFFER_SIZE];
174CHAR16 mInputBufferHistory[EFI_DEBUG_INPUS_BUFFER_SIZE];
175
185VOID
186EFIAPI
188 IN CHAR16 *Prompt OPTIONAL,
189 OUT CHAR16 *InStr,
190 IN UINTN StrLength
191 )
192{
195 BOOLEAN Done;
196 UINTN Column;
197 UINTN Row;
198 UINTN StartColumn;
199 UINTN Update;
200 UINTN Delete;
201 UINTN Len;
202 UINTN StrPos;
203 UINTN Index;
204 UINTN LineLength;
205 UINTN TotalRow;
206 UINTN SkipLength;
207 UINTN OutputLength;
208 UINTN TailRow;
209 UINTN TailColumn;
210 EFI_INPUT_KEY Key;
211 BOOLEAN InsertMode;
212 BOOLEAN NeedAdjust;
213 UINTN SubIndex;
214 CHAR16 *CommandStr;
215
216 ConOut = gST->ConOut;
217 ConIn = gST->ConIn;
218
219 ASSERT (ConOut != NULL);
220 ASSERT (ConIn != NULL);
221 ASSERT (InStr != NULL);
222
223 if (Prompt != NULL) {
224 ConOut->OutputString (ConOut, Prompt);
225 }
226
227 //
228 // Read a line from the console
229 //
230 Len = 0;
231 StrPos = 0;
232 OutputLength = 0;
233 Update = 0;
234 Delete = 0;
235 InsertMode = TRUE;
236 NeedAdjust = FALSE;
237
238 //
239 // If buffer is not large enough to hold a CHAR16, do nothing.
240 //
241 if (StrLength < 1) {
242 return;
243 }
244
245 //
246 // Get the screen setting and the current cursor location
247 //
248 StartColumn = ConOut->Mode->CursorColumn;
249 Column = StartColumn;
250 Row = ConOut->Mode->CursorRow;
251 ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &LineLength, &TotalRow);
252 if (LineLength == 0) {
253 return;
254 }
255
256 SetMem (InStr, StrLength * sizeof (CHAR16), 0);
257 Done = FALSE;
258 do {
259 //
260 // Read a key
261 //
262 WaitForSingleEvent (ConIn->WaitForKey, 0);
263 ConIn->ReadKeyStroke (ConIn, &Key);
264
265 switch (Key.UnicodeChar) {
266 case CHAR_CARRIAGE_RETURN:
267 //
268 // All done, print a newline at the end of the string
269 //
270 TailRow = Row + (Len - StrPos + Column) / LineLength;
271 TailColumn = (Len - StrPos + Column) % LineLength;
272 Done = TRUE;
273 break;
274
275 case CHAR_BACKSPACE:
276 if (StrPos != 0) {
277 //
278 // If not move back beyond string beginning, move all characters behind
279 // the current position one character forward
280 //
281 StrPos -= 1;
282 Update = StrPos;
283 Delete = 1;
284 CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));
285
286 //
287 // Adjust the current column and row
288 //
289 ConMoveCursorBackward (LineLength, &Column, &Row);
290
291 NeedAdjust = TRUE;
292 }
293
294 break;
295
296 default:
297 if (Key.UnicodeChar >= ' ') {
298 //
299 // If we are at the buffer's end, drop the key
300 //
301 if ((Len == StrLength - 1) && (InsertMode || (StrPos == Len))) {
302 break;
303 }
304
305 //
306 // If in insert mode, move all characters behind the current position
307 // one character backward to make space for this character. Then store
308 // the character.
309 //
310 if (InsertMode) {
311 for (Index = Len; Index > StrPos; Index -= 1) {
312 InStr[Index] = InStr[Index - 1];
313 }
314 }
315
316 InStr[StrPos] = Key.UnicodeChar;
317 Update = StrPos;
318
319 StrPos += 1;
320 OutputLength = 1;
321 }
322
323 break;
324
325 case 0:
326 switch (Key.ScanCode) {
327 case SCAN_DELETE:
328 //
329 // Move characters behind current position one character forward
330 //
331 if (Len != 0) {
332 Update = StrPos;
333 Delete = 1;
334 CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));
335
336 NeedAdjust = TRUE;
337 }
338
339 break;
340
341 case SCAN_LEFT:
342 //
343 // Adjust current cursor position
344 //
345 if (StrPos != 0) {
346 StrPos -= 1;
347 ConMoveCursorBackward (LineLength, &Column, &Row);
348 }
349
350 break;
351
352 case SCAN_RIGHT:
353 //
354 // Adjust current cursor position
355 //
356 if (StrPos < Len) {
357 StrPos += 1;
358 ConMoveCursorForward (LineLength, TotalRow, &Column, &Row);
359 }
360
361 break;
362
363 case SCAN_HOME:
364 //
365 // Move current cursor position to the beginning of the command line
366 //
367 Row -= (StrPos + StartColumn) / LineLength;
368 Column = StartColumn;
369 StrPos = 0;
370 break;
371
372 case SCAN_END:
373 //
374 // Move current cursor position to the end of the command line
375 //
376 TailRow = Row + (Len - StrPos + Column) / LineLength;
377 TailColumn = (Len - StrPos + Column) % LineLength;
378 Row = TailRow;
379 Column = TailColumn;
380 StrPos = Len;
381 break;
382
383 case SCAN_ESC:
384 //
385 // Prepare to clear the current command line
386 //
387 InStr[0] = 0;
388 Update = 0;
389 Delete = Len;
390 Row -= (StrPos + StartColumn) / LineLength;
391 Column = StartColumn;
392 OutputLength = 0;
393
394 NeedAdjust = TRUE;
395 break;
396
397 case SCAN_INSERT:
398 //
399 // Toggle the SEnvInsertMode flag
400 //
401 InsertMode = (BOOLEAN) !InsertMode;
402 break;
403
404 case SCAN_UP:
405 case SCAN_DOWN:
406 //
407 // show history
408 //
409 CopyMem (InStr, mInputBufferHistory, StrLength * sizeof (CHAR16));
410 StrPos = StrLen (mInputBufferHistory);
411 Update = 0;
412 Delete = 0;
413 OutputLength = 0;
414
415 TailRow = Row + (StrPos + StartColumn) / LineLength;
416 TailColumn = (StrPos + StartColumn) % LineLength;
417 Row = TailRow;
418 Column = TailColumn;
419 NeedAdjust = FALSE;
420
421 ConOut->SetCursorPosition (ConOut, StartColumn, Row);
422 for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {
423 mBackupSpace[SubIndex] = L' ';
424 }
425
426 EDBPrint (mBackupSpace);
427 SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN)) * sizeof (CHAR16), 0);
428
429 ConOut->SetCursorPosition (ConOut, StartColumn, Row);
430 Len = StrPos;
431
432 break;
433
434 case SCAN_F1:
435 case SCAN_F2:
436 case SCAN_F3:
437 case SCAN_F4:
438 case SCAN_F5:
439 case SCAN_F6:
440 case SCAN_F7:
441 case SCAN_F8:
442 case SCAN_F9:
443 case SCAN_F10:
444 case SCAN_F11:
445 case SCAN_F12:
446 CommandStr = GetCommandNameByKey (Key);
447 if (CommandStr != NULL) {
448 StrnCpyS (InStr, StrLength, CommandStr, StrLength - 1);
449 return;
450 }
451
452 break;
453 }
454 }
455
456 if (Done) {
457 break;
458 }
459
460 //
461 // If we need to update the output do so now
462 //
463 if (Update != -1) {
464 if (NeedAdjust) {
465 ConOut->SetCursorPosition (ConOut, Column, Row);
466 for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {
467 mBackupSpace[SubIndex] = L' ';
468 }
469
470 EDBPrint (mBackupSpace);
471 SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN)) * sizeof (CHAR16), 0);
472 ConOut->SetCursorPosition (ConOut, Column, Row);
473 NeedAdjust = FALSE;
474 }
475
476 EDBPrint (InStr + Update);
477 Len = StrLen (InStr);
478
479 if (Delete != 0) {
480 SetMem (InStr + Len, Delete * sizeof (CHAR16), 0x00);
481 }
482
483 if (StrPos > Len) {
484 StrPos = Len;
485 }
486
487 Update = (UINTN)-1;
488
489 //
490 // After using print to reflect newly updates, if we're not using
491 // BACKSPACE and DELETE, we need to move the cursor position forward,
492 // so adjust row and column here.
493 //
494 if ((Key.UnicodeChar != CHAR_BACKSPACE) && !((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_DELETE))) {
495 //
496 // Calulate row and column of the tail of current string
497 //
498 TailRow = Row + (Len - StrPos + Column + OutputLength) / LineLength;
499 TailColumn = (Len - StrPos + Column + OutputLength) % LineLength;
500
501 //
502 // If the tail of string reaches screen end, screen rolls up, so if
503 // Row does not equal TailRow, Row should be decremented
504 //
505 // (if we are recalling commands using UPPER and DOWN key, and if the
506 // old command is too long to fit the screen, TailColumn must be 79.
507 //
508 if ((TailColumn == 0) && (TailRow >= TotalRow) && ((UINTN)Row != TailRow)) {
509 Row--;
510 }
511
512 //
513 // Calculate the cursor position after current operation. If cursor
514 // reaches line end, update both row and column, otherwise, only
515 // column will be changed.
516 //
517 if (Column + OutputLength >= LineLength) {
518 SkipLength = OutputLength - (LineLength - Column);
519
520 Row += SkipLength / LineLength + 1;
521 if ((UINTN)Row > TotalRow - 1) {
522 Row = TotalRow - 1;
523 }
524
525 Column = SkipLength % LineLength;
526 } else {
527 Column += OutputLength;
528 }
529 }
530
531 Delete = 0;
532 }
533
534 //
535 // Set the cursor position for this key
536 //
537 SetCursorPosition (ConOut, Column, Row, LineLength, TotalRow, InStr, StrPos, Len);
538 } while (!Done);
539
540 CopyMem (mInputBufferHistory, InStr, StrLength * sizeof (CHAR16));
541
542 //
543 // Return the data to the caller
544 //
545 return;
546}
547
561VOID
562EFIAPI
565 IN UINTN Column,
566 IN INTN Row,
567 IN UINTN LineLength,
568 IN UINTN TotalRow,
569 IN CHAR16 *Str,
570 IN UINTN StrPos,
571 IN UINTN Len
572 )
573{
574 CHAR16 Backup;
575
576 ASSERT (ConOut != NULL);
577 ASSERT (Str != NULL);
578
579 Backup = 0;
580 if (Row >= 0) {
581 ConOut->SetCursorPosition (ConOut, Column, Row);
582 return;
583 }
584
585 if (Len - StrPos > Column * Row) {
586 Backup = *(Str + StrPos + Column * Row);
587 *(Str + StrPos + Column * Row) = 0;
588 }
589
590 EDBPrint (L"%s", Str + StrPos);
591 if (Len - StrPos > Column * Row) {
592 *(Str + StrPos + Column * Row) = Backup;
593 }
594
595 ConOut->SetCursorPosition (ConOut, 0, 0);
596}
597
603BOOLEAN
604EFIAPI
606 VOID
607 )
608{
609 EFI_INPUT_KEY Key;
610 CHAR16 Str[3];
611 BOOLEAN OmitPrint;
612
613 //
614 // Check
615 //
616 if (!mDebuggerPrivate.EnablePageBreak) {
617 return FALSE;
618 }
619
620 gST->ConOut->OutputString (gST->ConOut, L"Press ENTER to continue, 'q' to exit:");
621
622 OmitPrint = FALSE;
623 //
624 // Wait for user input
625 //
626 Str[0] = ' ';
627 Str[1] = 0;
628 Str[2] = 0;
629 for ( ; ;) {
631 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
632
633 //
634 // handle control keys
635 //
636 if (Key.UnicodeChar == CHAR_NULL) {
637 if (Key.ScanCode == SCAN_ESC) {
638 gST->ConOut->OutputString (gST->ConOut, L"\r\n");
639 OmitPrint = TRUE;
640 break;
641 }
642
643 continue;
644 }
645
646 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
647 gST->ConOut->OutputString (gST->ConOut, L"\r\n");
648 break;
649 }
650
651 //
652 // Echo input
653 //
654 Str[1] = Key.UnicodeChar;
655 if (Str[1] == CHAR_BACKSPACE) {
656 continue;
657 }
658
659 gST->ConOut->OutputString (gST->ConOut, Str);
660
661 if ((Str[1] == L'q') || (Str[1] == L'Q')) {
662 OmitPrint = TRUE;
663 } else {
664 OmitPrint = FALSE;
665 }
666
667 Str[0] = CHAR_BACKSPACE;
668 }
669
670 return OmitPrint;
671}
672
681UINTN
682EFIAPI
684 IN CONST CHAR16 *Format,
685 ...
686 )
687{
688 UINTN Return;
689 VA_LIST Marker;
690 CHAR16 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
691
692 VA_START (Marker, Format);
693 Return = UnicodeVSPrint (Buffer, sizeof (Buffer), Format, Marker);
694 VA_END (Marker);
695
696 if (gST->ConOut != NULL) {
697 //
698 // To be extra safe make sure ConOut has been initialized
699 //
700 gST->ConOut->OutputString (gST->ConOut, Buffer);
701 }
702
703 return Return;
704}
705
717UINTN
718EFIAPI
720 OUT CHAR16 *Buffer,
721 IN INTN BufferSize,
722 IN CONST CHAR16 *Format,
723 ...
724 )
725{
726 UINTN Return;
727 VA_LIST Marker;
728
729 ASSERT (BufferSize > 0);
730
731 VA_START (Marker, Format);
732 Return = UnicodeVSPrint (Buffer, (UINTN)BufferSize, Format, Marker);
733 VA_END (Marker);
734
735 return Return;
736}
737
750UINTN
751EFIAPI
753 OUT CHAR16 *Buffer,
754 IN INTN BufferSize,
755 IN UINTN Offset,
756 IN CONST CHAR16 *Format,
757 ...
758 )
759{
760 UINTN Return;
761 VA_LIST Marker;
762
763 ASSERT (BufferSize - (Offset * sizeof (CHAR16)) > 0);
764
765 VA_START (Marker, Format);
766 Return = UnicodeVSPrint (Buffer + Offset, (UINTN)(BufferSize - (Offset * sizeof (CHAR16))), Format, Marker);
767 VA_END (Marker);
768
769 return Return;
770}
UINT64 UINTN
INT64 INTN
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:310
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
CHAR16 * GetCommandNameByKey(IN EFI_INPUT_KEY CommandKey)
Definition: EdbCommand.c:634
UINTN EFIAPI EDBSPrint(OUT CHAR16 *Buffer, IN INTN BufferSize, IN CONST CHAR16 *Format,...)
Definition: EdbSupportUI.c:719
BOOLEAN EFIAPI SetPageBreak(VOID)
Definition: EdbSupportUI.c:605
VOID EFIAPI ConMoveCursorBackward(IN UINTN LineLength, IN OUT UINTN *Column, IN OUT UINTN *Row)
Definition: EdbSupportUI.c:113
UINTN EFIAPI EDBPrint(IN CONST CHAR16 *Format,...)
Definition: EdbSupportUI.c:683
VOID EFIAPI Input(IN CHAR16 *Prompt OPTIONAL, OUT CHAR16 *InStr, IN UINTN StrLength)
Definition: EdbSupportUI.c:187
UINTN EFIAPI EDBSPrintWithOffset(OUT CHAR16 *Buffer, IN INTN BufferSize, IN UINTN Offset, IN CONST CHAR16 *Format,...)
Definition: EdbSupportUI.c:752
EFI_STATUS EFIAPI WaitForSingleEvent(IN EFI_EVENT Event, IN UINT64 Timeout OPTIONAL)
Definition: EdbSupportUI.c:50
VOID EFIAPI SetCursorPosition(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut, IN UINTN Column, IN INTN Row, IN UINTN LineLength, IN UINTN TotalRow, IN CHAR16 *Str, IN UINTN StrPos, IN UINTN Len)
Definition: EdbSupportUI.c:563
VOID EFIAPI ConMoveCursorForward(IN UINTN LineLength, IN UINTN TotalRow, IN OUT UINTN *Column, IN OUT UINTN *Row)
Definition: EdbSupportUI.c:151
UINTN EFIAPI UnicodeVSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString, IN VA_LIST Marker)
Definition: PrintLib.c:287
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define VA_END(Marker)
Definition: Base.h:691
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
@ TimerRelative
Definition: UefiSpec.h:539
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
Definition: UefiSpec.h:2053
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
Definition: UefiSpec.h:2064