3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
40 IN UINT64 Timeout OPTIONAL
45 Function waits for a given event to fire, or for an optional timeout to expire.
48 Event - The event to wait for
50 Timeout - An optional timeout value in 100 ns units.
54 EFI_SUCCESS - Event fired before Timeout expired.
55 EFI_TIME_OUT - Timout expired before Event fired..
62 EFI_EVENT WaitList
[2];
66 // Create a timer event
68 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
69 if (!EFI_ERROR (Status
)) {
71 // Set the timer event
80 // Wait for the original event or the timer
83 WaitList
[1] = TimerEvent
;
84 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
85 gBS
->CloseEvent (TimerEvent
);
88 // If the timer expired, change the return to timed out
90 if (!EFI_ERROR (Status
) && Index
== 1) {
96 // No timeout... just wait on the event
98 Status
= gBS
->WaitForEvent (1, &Event
, &Index
);
99 ASSERT (!EFI_ERROR (Status
));
108 ConMoveCursorBackward (
110 IN OUT UINTN
*Column
,
116 Move the cursor position one character backward.
119 LineLength Length of a line. Get it by calling QueryMode
120 Column Current column of the cursor position
121 Row Current row of the cursor position
127 ASSERT (Column
!= NULL
);
128 ASSERT (Row
!= NULL
);
130 // If current column is 0, move to the last column of the previous line,
131 // otherwise, just decrement column.
134 (*Column
) = LineLength
- 1;
149 ConMoveCursorForward (
152 IN OUT UINTN
*Column
,
158 Move the cursor position one character backward.
161 LineLength Length of a line. Get it by calling QueryMode
162 TotalRow Total row of a screen, get by calling QueryMode
163 Column Current column of the cursor position
164 Row Current row of the cursor position
170 ASSERT (Column
!= NULL
);
171 ASSERT (Row
!= NULL
);
173 // If current column is at line end, move to the first column of the nest
174 // line, otherwise, just increment column.
177 if (*Column
>= LineLength
) {
179 if ((*Row
) < TotalRow
- 1) {
185 CHAR16 mBackupSpace
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
186 CHAR16 mInputBufferHistory
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
191 IN CHAR16
*Prompt OPTIONAL
,
196 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
197 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*ConIn
;
219 ConOut
= gST
->ConOut
;
222 ASSERT (ConOut
!= NULL
);
223 ASSERT (ConIn
!= NULL
);
224 ASSERT (InStr
!= NULL
);
227 ConOut
->OutputString (ConOut
, Prompt
);
230 // Read a line from the console
241 // If buffer is not large enough to hold a CHAR16, do nothing.
247 // Get the screen setting and the current cursor location
249 StartColumn
= ConOut
->Mode
->CursorColumn
;
250 Column
= StartColumn
;
251 Row
= ConOut
->Mode
->CursorRow
;
252 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &LineLength
, &TotalRow
);
253 if (LineLength
== 0) {
257 SetMem (InStr
, StrLength
* sizeof (CHAR16
), 0);
263 WaitForSingleEvent (ConIn
->WaitForKey
, 0);
264 ConIn
->ReadKeyStroke (ConIn
, &Key
);
266 switch (Key
.UnicodeChar
) {
267 case CHAR_CARRIAGE_RETURN
:
269 // All done, print a newline at the end of the string
271 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
272 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
279 // If not move back beyond string beginning, move all characters behind
280 // the current position one character forward
285 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
288 // Adjust the current column and row
290 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
297 if (Key
.UnicodeChar
>= ' ') {
299 // If we are at the buffer's end, drop the key
301 if (Len
== StrLength
- 1 && (InsertMode
|| StrPos
== Len
)) {
305 // If in insert mode, move all characters behind the current position
306 // one character backward to make space for this character. Then store
310 for (Index
= Len
; Index
> StrPos
; Index
-= 1) {
311 InStr
[Index
] = InStr
[Index
- 1];
315 InStr
[StrPos
] = Key
.UnicodeChar
;
324 switch (Key
.ScanCode
) {
327 // Move characters behind current position one character forward
332 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
340 // Adjust current cursor position
344 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
350 // Adjust current cursor position
354 ConMoveCursorForward (LineLength
, TotalRow
, &Column
, &Row
);
360 // Move current cursor position to the beginning of the command line
362 Row
-= (StrPos
+ StartColumn
) / LineLength
;
363 Column
= StartColumn
;
369 // Move current cursor position to the end of the command line
371 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
372 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
380 // Prepare to clear the current command line
385 Row
-= (StrPos
+ StartColumn
) / LineLength
;
386 Column
= StartColumn
;
394 // Toggle the SEnvInsertMode flag
396 InsertMode
= (BOOLEAN
)!InsertMode
;
404 CopyMem (InStr
, mInputBufferHistory
, StrLength
* sizeof(CHAR16
));
405 StrPos
= StrLen (mInputBufferHistory
);
410 TailRow
= Row
+ (StrPos
+ StartColumn
) / LineLength
;
411 TailColumn
= (StrPos
+ StartColumn
) % LineLength
;
416 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
417 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
418 mBackupSpace
[SubIndex
] = L
' ';
420 EDBPrint (mBackupSpace
);
421 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
423 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
440 CommandStr
= GetCommandNameByKey (Key
);
441 if (CommandStr
!= NULL
) {
442 StrnCpyS (InStr
, StrLength
, CommandStr
, StrLength
- 1);
453 // If we need to update the output do so now
457 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
458 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
459 mBackupSpace
[SubIndex
] = L
' ';
461 EDBPrint (mBackupSpace
);
462 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
463 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
466 EDBPrint (InStr
+ Update
);
467 Len
= StrLen (InStr
);
470 SetMem (InStr
+ Len
, Delete
* sizeof (CHAR16
), 0x00);
480 // After using print to reflect newly updates, if we're not using
481 // BACKSPACE and DELETE, we need to move the cursor position forward,
482 // so adjust row and column here.
484 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
486 // Calulate row and column of the tail of current string
488 TailRow
= Row
+ (Len
- StrPos
+ Column
+ OutputLength
) / LineLength
;
489 TailColumn
= (Len
- StrPos
+ Column
+ OutputLength
) % LineLength
;
492 // If the tail of string reaches screen end, screen rolls up, so if
493 // Row does not equal TailRow, Row should be decremented
495 // (if we are recalling commands using UPPER and DOWN key, and if the
496 // old command is too long to fit the screen, TailColumn must be 79.
498 if (TailColumn
== 0 && TailRow
>= TotalRow
&& (UINTN
) Row
!= TailRow
) {
502 // Calculate the cursor position after current operation. If cursor
503 // reaches line end, update both row and column, otherwise, only
504 // column will be changed.
506 if (Column
+ OutputLength
>= LineLength
) {
507 SkipLength
= OutputLength
- (LineLength
- Column
);
509 Row
+= SkipLength
/ LineLength
+ 1;
510 if ((UINTN
) Row
> TotalRow
- 1) {
514 Column
= SkipLength
% LineLength
;
516 Column
+= OutputLength
;
523 // Set the cursor position for this key
525 SetCursorPosition (ConOut
, Column
, Row
, LineLength
, TotalRow
, InStr
, StrPos
, Len
);
528 CopyMem (mInputBufferHistory
, InStr
, StrLength
* sizeof(CHAR16
));
531 // Return the data to the caller
539 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
551 ASSERT (ConOut
!= NULL
);
552 ASSERT (Str
!= NULL
);
556 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
560 if (Len
- StrPos
> Column
* Row
) {
561 Backup
= *(Str
+ StrPos
+ Column
* Row
);
562 *(Str
+ StrPos
+ Column
* Row
) = 0;
565 EDBPrint (L
"%s", Str
+ StrPos
);
566 if (Len
- StrPos
> Column
* Row
) {
567 *(Str
+ StrPos
+ Column
* Row
) = Backup
;
570 ConOut
->SetCursorPosition (ConOut
, 0, 0);
586 if (!mDebuggerPrivate
.EnablePageBreak
) {
590 gST
->ConOut
->OutputString (gST
->ConOut
, L
"Press ENTER to continue, 'q' to exit:");
594 // Wait for user input
600 WaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
601 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
604 // handle control keys
606 if (Key
.UnicodeChar
== CHAR_NULL
) {
607 if (Key
.ScanCode
== SCAN_ESC
) {
608 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
616 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
617 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
623 Str
[1] = Key
.UnicodeChar
;
624 if (Str
[1] == CHAR_BACKSPACE
) {
628 gST
->ConOut
->OutputString (gST
->ConOut
, Str
);
630 if ((Str
[1] == L
'q') || (Str
[1] == L
'Q')) {
636 Str
[0] = CHAR_BACKSPACE
;
645 IN CONST CHAR16
*Format
,
651 CHAR16 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
653 VA_START (Marker
, Format
);
654 Return
= UnicodeVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
657 if (gST
->ConOut
!= NULL
) {
659 // To be extra safe make sure ConOut has been initialized
661 gST
->ConOut
->OutputString (gST
->ConOut
, Buffer
);
672 IN CONST CHAR16
*Format
,
679 ASSERT (BufferSize
> 0);
681 VA_START (Marker
, Format
);
682 Return
= UnicodeVSPrint (Buffer
, (UINTN
)BufferSize
, Format
, Marker
);
690 EDBSPrintWithOffset (
694 IN CONST CHAR16
*Format
,
701 ASSERT (BufferSize
- (Offset
* sizeof(CHAR16
)) > 0);
703 VA_START (Marker
, Format
);
704 Return
= UnicodeVSPrint (Buffer
+ Offset
, (UINTN
)(BufferSize
- (Offset
* sizeof(CHAR16
))), Format
, Marker
);