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.
18 Set the current coordinates of the cursor position.
20 @param ConOut Point to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
21 @param Column The position to set the cursor to.
22 @param Row The position to set the cursor to.
23 @param LineLength Length of a line.
24 @param TotalRow Total row of a screen.
25 @param Str Point to the string.
26 @param StrPos The position of the string.
27 @param Len The length of the string.
33 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
45 Function waits for a given event to fire, or for an optional timeout to expire.
47 @param Event - The event to wait for
48 @param Timeout - An optional timeout value in 100 ns units.
50 @retval EFI_SUCCESS - Event fired before Timeout expired.
51 @retval EFI_TIME_OUT - Timout expired before Event fired..
58 IN UINT64 Timeout OPTIONAL
64 EFI_EVENT WaitList
[2];
68 // Create a timer event
70 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
71 if (!EFI_ERROR (Status
)) {
73 // Set the timer event
82 // Wait for the original event or the timer
85 WaitList
[1] = TimerEvent
;
86 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
87 gBS
->CloseEvent (TimerEvent
);
90 // If the timer expired, change the return to timed out
92 if (!EFI_ERROR (Status
) && Index
== 1) {
98 // No timeout... just wait on the event
100 Status
= gBS
->WaitForEvent (1, &Event
, &Index
);
101 ASSERT (!EFI_ERROR (Status
));
110 Move the cursor position one character backward.
112 @param LineLength Length of a line. Get it by calling QueryMode
113 @param Column Current column of the cursor position
114 @param Row Current row of the cursor position
119 ConMoveCursorBackward (
121 IN OUT UINTN
*Column
,
125 ASSERT (Column
!= NULL
);
126 ASSERT (Row
!= NULL
);
128 // If current column is 0, move to the last column of the previous line,
129 // otherwise, just decrement column.
132 (*Column
) = LineLength
- 1;
147 Move the cursor position one character backward.
149 @param LineLength Length of a line. Get it by calling QueryMode
150 @param TotalRow Total row of a screen, get by calling QueryMode
151 @param Column Current column of the cursor position
152 @param Row Current row of the cursor position
157 ConMoveCursorForward (
160 IN OUT UINTN
*Column
,
164 ASSERT (Column
!= NULL
);
165 ASSERT (Row
!= NULL
);
167 // If current column is at line end, move to the first column of the nest
168 // line, otherwise, just increment column.
171 if (*Column
>= LineLength
) {
173 if ((*Row
) < TotalRow
- 1) {
179 CHAR16 mBackupSpace
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
180 CHAR16 mInputBufferHistory
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
186 @param Prompt The prompt string.
187 @param InStr Point to the input string.
188 @param StrLength The max length of string user can input.
194 IN CHAR16
*Prompt OPTIONAL
,
199 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
200 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*ConIn
;
222 ConOut
= gST
->ConOut
;
225 ASSERT (ConOut
!= NULL
);
226 ASSERT (ConIn
!= NULL
);
227 ASSERT (InStr
!= NULL
);
229 if (Prompt
!= NULL
) {
230 ConOut
->OutputString (ConOut
, Prompt
);
233 // Read a line from the console
244 // If buffer is not large enough to hold a CHAR16, do nothing.
250 // Get the screen setting and the current cursor location
252 StartColumn
= ConOut
->Mode
->CursorColumn
;
253 Column
= StartColumn
;
254 Row
= ConOut
->Mode
->CursorRow
;
255 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &LineLength
, &TotalRow
);
256 if (LineLength
== 0) {
260 SetMem (InStr
, StrLength
* sizeof (CHAR16
), 0);
266 WaitForSingleEvent (ConIn
->WaitForKey
, 0);
267 ConIn
->ReadKeyStroke (ConIn
, &Key
);
269 switch (Key
.UnicodeChar
) {
270 case CHAR_CARRIAGE_RETURN
:
272 // All done, print a newline at the end of the string
274 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
275 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
282 // If not move back beyond string beginning, move all characters behind
283 // the current position one character forward
288 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
291 // Adjust the current column and row
293 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
300 if (Key
.UnicodeChar
>= ' ') {
302 // If we are at the buffer's end, drop the key
304 if (Len
== StrLength
- 1 && (InsertMode
|| StrPos
== Len
)) {
308 // If in insert mode, move all characters behind the current position
309 // one character backward to make space for this character. Then store
313 for (Index
= Len
; Index
> StrPos
; Index
-= 1) {
314 InStr
[Index
] = InStr
[Index
- 1];
318 InStr
[StrPos
] = Key
.UnicodeChar
;
327 switch (Key
.ScanCode
) {
330 // Move characters behind current position one character forward
335 CopyMem (InStr
+ StrPos
, InStr
+ StrPos
+ 1, sizeof (CHAR16
) * (Len
- StrPos
));
343 // Adjust current cursor position
347 ConMoveCursorBackward (LineLength
, &Column
, &Row
);
353 // Adjust current cursor position
357 ConMoveCursorForward (LineLength
, TotalRow
, &Column
, &Row
);
363 // Move current cursor position to the beginning of the command line
365 Row
-= (StrPos
+ StartColumn
) / LineLength
;
366 Column
= StartColumn
;
372 // Move current cursor position to the end of the command line
374 TailRow
= Row
+ (Len
- StrPos
+ Column
) / LineLength
;
375 TailColumn
= (Len
- StrPos
+ Column
) % LineLength
;
383 // Prepare to clear the current command line
388 Row
-= (StrPos
+ StartColumn
) / LineLength
;
389 Column
= StartColumn
;
397 // Toggle the SEnvInsertMode flag
399 InsertMode
= (BOOLEAN
)!InsertMode
;
407 CopyMem (InStr
, mInputBufferHistory
, StrLength
* sizeof(CHAR16
));
408 StrPos
= StrLen (mInputBufferHistory
);
413 TailRow
= Row
+ (StrPos
+ StartColumn
) / LineLength
;
414 TailColumn
= (StrPos
+ StartColumn
) % LineLength
;
419 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
420 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
421 mBackupSpace
[SubIndex
] = L
' ';
423 EDBPrint (mBackupSpace
);
424 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (StartColumn
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
426 ConOut
->SetCursorPosition (ConOut
, StartColumn
, Row
);
443 CommandStr
= GetCommandNameByKey (Key
);
444 if (CommandStr
!= NULL
) {
445 StrnCpyS (InStr
, StrLength
, CommandStr
, StrLength
- 1);
456 // If we need to update the output do so now
460 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
461 for (SubIndex
= 0; SubIndex
< EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
); SubIndex
++) {
462 mBackupSpace
[SubIndex
] = L
' ';
464 EDBPrint (mBackupSpace
);
465 SetMem (mBackupSpace
, (EFI_DEBUG_INPUS_BUFFER_SIZE
- (Column
- EFI_DEBUG_PROMPT_COLUMN
)) * sizeof(CHAR16
), 0);
466 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
469 EDBPrint (InStr
+ Update
);
470 Len
= StrLen (InStr
);
473 SetMem (InStr
+ Len
, Delete
* sizeof (CHAR16
), 0x00);
483 // After using print to reflect newly updates, if we're not using
484 // BACKSPACE and DELETE, we need to move the cursor position forward,
485 // so adjust row and column here.
487 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
489 // Calulate row and column of the tail of current string
491 TailRow
= Row
+ (Len
- StrPos
+ Column
+ OutputLength
) / LineLength
;
492 TailColumn
= (Len
- StrPos
+ Column
+ OutputLength
) % LineLength
;
495 // If the tail of string reaches screen end, screen rolls up, so if
496 // Row does not equal TailRow, Row should be decremented
498 // (if we are recalling commands using UPPER and DOWN key, and if the
499 // old command is too long to fit the screen, TailColumn must be 79.
501 if (TailColumn
== 0 && TailRow
>= TotalRow
&& (UINTN
) Row
!= TailRow
) {
505 // Calculate the cursor position after current operation. If cursor
506 // reaches line end, update both row and column, otherwise, only
507 // column will be changed.
509 if (Column
+ OutputLength
>= LineLength
) {
510 SkipLength
= OutputLength
- (LineLength
- Column
);
512 Row
+= SkipLength
/ LineLength
+ 1;
513 if ((UINTN
) Row
> TotalRow
- 1) {
517 Column
= SkipLength
% LineLength
;
519 Column
+= OutputLength
;
526 // Set the cursor position for this key
528 SetCursorPosition (ConOut
, Column
, Row
, LineLength
, TotalRow
, InStr
, StrPos
, Len
);
531 CopyMem (mInputBufferHistory
, InStr
, StrLength
* sizeof(CHAR16
));
534 // Return the data to the caller
540 Set the current coordinates of the cursor position.
542 @param ConOut Point to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
543 @param Column The position to set the cursor to.
544 @param Row The position to set the cursor to.
545 @param LineLength Length of a line.
546 @param TotalRow Total row of a screen.
547 @param Str Point to the string.
548 @param StrPos The position of the string.
549 @param Len The length of the string.
555 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
,
567 ASSERT (ConOut
!= NULL
);
568 ASSERT (Str
!= NULL
);
572 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
576 if (Len
- StrPos
> Column
* Row
) {
577 Backup
= *(Str
+ StrPos
+ Column
* Row
);
578 *(Str
+ StrPos
+ Column
* Row
) = 0;
581 EDBPrint (L
"%s", Str
+ StrPos
);
582 if (Len
- StrPos
> Column
* Row
) {
583 *(Str
+ StrPos
+ Column
* Row
) = Backup
;
586 ConOut
->SetCursorPosition (ConOut
, 0, 0);
607 if (!mDebuggerPrivate
.EnablePageBreak
) {
611 gST
->ConOut
->OutputString (gST
->ConOut
, L
"Press ENTER to continue, 'q' to exit:");
615 // Wait for user input
621 WaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
622 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
625 // handle control keys
627 if (Key
.UnicodeChar
== CHAR_NULL
) {
628 if (Key
.ScanCode
== SCAN_ESC
) {
629 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
637 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
638 gST
->ConOut
->OutputString (gST
->ConOut
, L
"\r\n");
644 Str
[1] = Key
.UnicodeChar
;
645 if (Str
[1] == CHAR_BACKSPACE
) {
649 gST
->ConOut
->OutputString (gST
->ConOut
, Str
);
651 if ((Str
[1] == L
'q') || (Str
[1] == L
'Q')) {
657 Str
[0] = CHAR_BACKSPACE
;
664 Print a Unicode string to the output device.
666 @param Format A Null-terminated Unicode format string.
667 @param ... The variable argument list that contains pointers to Null-
668 terminated Unicode strings to be printed
674 IN CONST CHAR16
*Format
,
680 CHAR16 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
682 VA_START (Marker
, Format
);
683 Return
= UnicodeVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
686 if (gST
->ConOut
!= NULL
) {
688 // To be extra safe make sure ConOut has been initialized
690 gST
->ConOut
->OutputString (gST
->ConOut
, Buffer
);
697 Print a Unicode string to the output buffer.
699 @param Buffer A pointer to the output buffer for the produced Null-terminated
701 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
702 @param Format A Null-terminated Unicode format string.
703 @param ... The variable argument list that contains pointers to Null-
704 terminated Unicode strings to be printed
712 IN CONST CHAR16
*Format
,
719 ASSERT (BufferSize
> 0);
721 VA_START (Marker
, Format
);
722 Return
= UnicodeVSPrint (Buffer
, (UINTN
)BufferSize
, Format
, Marker
);
729 Print a Unicode string to the output buffer with specified offset..
731 @param Buffer A pointer to the output buffer for the produced Null-terminated
733 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
734 @param Offset The offset of the buffer.
735 @param Format A Null-terminated Unicode format string.
736 @param ... The variable argument list that contains pointers to Null-
737 terminated Unicode strings to be printed
742 EDBSPrintWithOffset (
746 IN CONST CHAR16
*Format
,
753 ASSERT (BufferSize
- (Offset
* sizeof(CHAR16
)) > 0);
755 VA_START (Marker
, Format
);
756 Return
= UnicodeVSPrint (Buffer
+ Offset
, (UINTN
)(BufferSize
- (Offset
* sizeof(CHAR16
))), Format
, Marker
);