3 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
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.
20 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
32 Function waits for a given event to fire, or for an optional timeout to expire.
34 @param Event - The event to wait for
35 @param Timeout - An optional timeout value in 100 ns units.
37 @retval EFI_SUCCESS - Event fired before Timeout expired.
38 @retval EFI_TIME_OUT - Timout expired before Event fired..
45 IN UINT64 Timeout OPTIONAL
51 EFI_EVENT WaitList
[2];
55 // Create a timer event
57 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
58 if (!EFI_ERROR (Status
)) {
60 // Set the timer event
69 // Wait for the original event or the timer
72 WaitList
[1] = TimerEvent
;
73 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
74 gBS
->CloseEvent (TimerEvent
);
77 // If the timer expired, change the return to timed out
79 if (!EFI_ERROR (Status
) && Index
== 1) {
85 // No timeout... just wait on the event
87 Status
= gBS
->WaitForEvent (1, &Event
, &Index
);
88 ASSERT (!EFI_ERROR (Status
));
97 Move the cursor position one character backward.
99 @param LineLength Length of a line. Get it by calling QueryMode
100 @param Column Current column of the cursor position
101 @param Row Current row of the cursor position
106 ConMoveCursorBackward (
108 IN OUT UINTN
*Column
,
112 ASSERT (Column
!= NULL
);
113 ASSERT (Row
!= NULL
);
115 // If current column is 0, move to the last column of the previous line,
116 // otherwise, just decrement column.
119 (*Column
) = LineLength
- 1;
134 Move the cursor position one character backward.
136 @param LineLength Length of a line. Get it by calling QueryMode
137 @param TotalRow Total row of a screen, get by calling QueryMode
138 @param Column Current column of the cursor position
139 @param Row Current row of the cursor position
144 ConMoveCursorForward (
147 IN OUT UINTN
*Column
,
151 ASSERT (Column
!= NULL
);
152 ASSERT (Row
!= NULL
);
154 // If current column is at line end, move to the first column of the nest
155 // line, otherwise, just increment column.
158 if (*Column
>= LineLength
) {
160 if ((*Row
) < TotalRow
- 1) {
166 CHAR16 mBackupSpace
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
167 CHAR16 mInputBufferHistory
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
172 IN CHAR16
*Prompt OPTIONAL
,
177 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
178 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*ConIn
;
200 ConOut
= gST
->ConOut
;
203 ASSERT (ConOut
!= NULL
);
204 ASSERT (ConIn
!= NULL
);
205 ASSERT (InStr
!= NULL
);
207 if (Prompt
!= NULL
) {
208 ConOut
->OutputString (ConOut
, Prompt
);
211 // Read a line from the console
222 // If buffer is not large enough to hold a CHAR16, do nothing.
228 // Get the screen setting and the current cursor location
230 StartColumn
= ConOut
->Mode
->CursorColumn
;
231 Column
= StartColumn
;
232 Row
= ConOut
->Mode
->CursorRow
;
233 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &LineLength
, &TotalRow
);
234 if (LineLength
== 0) {
238 SetMem (InStr
, StrLength
* sizeof (CHAR16
), 0);
244 WaitForSingleEvent (ConIn
->WaitForKey
, 0);
245 ConIn
->ReadKeyStroke (ConIn
, &Key
);
247 switch (Key
.UnicodeChar
) {
248 case CHAR_CARRIAGE_RETURN
:
250 // All done, print a newline at the end of the string
252 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
253 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
260 // If not move back beyond string beginning, move all characters behind
261 // the current position one character forward
266 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
269 // Adjust the current column and row
271 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
278 if (Key
.UnicodeChar
>= ' ') {
280 // If we are at the buffer's end, drop the key
282 if (Len
== StrLength
- 1 && (InsertMode
|| StrPos
== Len
)) {
286 // If in insert mode, move all characters behind the current position
287 // one character backward to make space for this character. Then store
291 for (Index
= Len
; Index
> StrPos
; Index
-= 1) {
292 InStr
[Index
] = InStr
[Index
- 1];
296 InStr
[StrPos
] = Key
.UnicodeChar
;
305 switch (Key
.ScanCode
) {
308 // Move characters behind current position one character forward
313 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
321 // Adjust current cursor position
325 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
331 // Adjust current cursor position
335 ConMoveCursorForward (LineLength
, TotalRow
, &Column
, &Row
);
341 // Move current cursor position to the beginning of the command line
343 Row
-= (StrPos
+ StartColumn
) / LineLength
;
344 Column
= StartColumn
;
350 // Move current cursor position to the end of the command line
352 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
353 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
361 // Prepare to clear the current command line
366 Row
-= (StrPos
+ StartColumn
) / LineLength
;
367 Column
= StartColumn
;
375 // Toggle the SEnvInsertMode flag
377 InsertMode
= (BOOLEAN
)!InsertMode
;
385 CopyMem (InStr
, mInputBufferHistory
, StrLength
* sizeof(CHAR16
));
386 StrPos
= StrLen (mInputBufferHistory
);
391 TailRow
= Row
+ (StrPos
+ StartColumn
) / LineLength
;
392 TailColumn
= (StrPos
+ StartColumn
) % LineLength
;
397 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
398 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
399 mBackupSpace
[SubIndex
] = L
' ';
401 EDBPrint (mBackupSpace
);
402 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
404 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
421 CommandStr
= GetCommandNameByKey (Key
);
422 if (CommandStr
!= NULL
) {
423 StrnCpyS (InStr
, StrLength
, CommandStr
, StrLength
- 1);
434 // If we need to update the output do so now
438 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
439 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
440 mBackupSpace
[SubIndex
] = L
' ';
442 EDBPrint (mBackupSpace
);
443 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
444 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
447 EDBPrint (InStr
+ Update
);
448 Len
= StrLen (InStr
);
451 SetMem (InStr
+ Len
, Delete
* sizeof (CHAR16
), 0x00);
461 // After using print to reflect newly updates, if we're not using
462 // BACKSPACE and DELETE, we need to move the cursor position forward,
463 // so adjust row and column here.
465 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
467 // Calulate row and column of the tail of current string
469 TailRow
= Row
+ (Len
- StrPos
+ Column
+ OutputLength
) / LineLength
;
470 TailColumn
= (Len
- StrPos
+ Column
+ OutputLength
) % LineLength
;
473 // If the tail of string reaches screen end, screen rolls up, so if
474 // Row does not equal TailRow, Row should be decremented
476 // (if we are recalling commands using UPPER and DOWN key, and if the
477 // old command is too long to fit the screen, TailColumn must be 79.
479 if (TailColumn
== 0 && TailRow
>= TotalRow
&& (UINTN
) Row
!= TailRow
) {
483 // Calculate the cursor position after current operation. If cursor
484 // reaches line end, update both row and column, otherwise, only
485 // column will be changed.
487 if (Column
+ OutputLength
>= LineLength
) {
488 SkipLength
= OutputLength
- (LineLength
- Column
);
490 Row
+= SkipLength
/ LineLength
+ 1;
491 if ((UINTN
) Row
> TotalRow
- 1) {
495 Column
= SkipLength
% LineLength
;
497 Column
+= OutputLength
;
504 // Set the cursor position for this key
506 SetCursorPosition (ConOut
, Column
, Row
, LineLength
, TotalRow
, InStr
, StrPos
, Len
);
509 CopyMem (mInputBufferHistory
, InStr
, StrLength
* sizeof(CHAR16
));
512 // Return the data to the caller
520 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
532 ASSERT (ConOut
!= NULL
);
533 ASSERT (Str
!= NULL
);
537 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
541 if (Len
- StrPos
> Column
* Row
) {
542 Backup
= *(Str
+ StrPos
+ Column
* Row
);
543 *(Str
+ StrPos
+ Column
* Row
) = 0;
546 EDBPrint (L
"%s", Str
+ StrPos
);
547 if (Len
- StrPos
> Column
* Row
) {
548 *(Str
+ StrPos
+ Column
* Row
) = Backup
;
551 ConOut
->SetCursorPosition (ConOut
, 0, 0);
567 if (!mDebuggerPrivate
.EnablePageBreak
) {
571 gST
->ConOut
->OutputString (gST
->ConOut
, L
"Press ENTER to continue, 'q' to exit:");
575 // Wait for user input
581 WaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
582 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
585 // handle control keys
587 if (Key
.UnicodeChar
== CHAR_NULL
) {
588 if (Key
.ScanCode
== SCAN_ESC
) {
589 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
597 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
598 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
604 Str
[1] = Key
.UnicodeChar
;
605 if (Str
[1] == CHAR_BACKSPACE
) {
609 gST
->ConOut
->OutputString (gST
->ConOut
, Str
);
611 if ((Str
[1] == L
'q') || (Str
[1] == L
'Q')) {
617 Str
[0] = CHAR_BACKSPACE
;
626 IN CONST CHAR16
*Format
,
632 CHAR16 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
634 VA_START (Marker
, Format
);
635 Return
= UnicodeVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
638 if (gST
->ConOut
!= NULL
) {
640 // To be extra safe make sure ConOut has been initialized
642 gST
->ConOut
->OutputString (gST
->ConOut
, Buffer
);
653 IN CONST CHAR16
*Format
,
660 ASSERT (BufferSize
> 0);
662 VA_START (Marker
, Format
);
663 Return
= UnicodeVSPrint (Buffer
, (UINTN
)BufferSize
, Format
, Marker
);
671 EDBSPrintWithOffset (
675 IN CONST CHAR16
*Format
,
682 ASSERT (BufferSize
- (Offset
* sizeof(CHAR16
)) > 0);
684 VA_START (Marker
, Format
);
685 Return
= UnicodeVSPrint (Buffer
+ Offset
, (UINTN
)(BufferSize
- (Offset
* sizeof(CHAR16
))), Format
, Marker
);