]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportUI.c
MdeModulePkg/EbcDxe: Make the variable name follow rules
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcDebugger / EdbSupportUI.c
CommitLineData
e8a5ac7c 1/** @file\r
748edcd5 2\r
e8a5ac7c
DB
3Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
748edcd5
PB
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
748edcd5 12\r
e8a5ac7c 13**/\r
748edcd5
PB
14\r
15#include "Edb.h"\r
16\r
17VOID\r
18EFIAPI\r
19SetCursorPosition (\r
20 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
21 IN UINTN Column,\r
22 IN INTN Row,\r
23 IN UINTN LineLength,\r
24 IN UINTN TotalRow,\r
25 IN CHAR16 *Str,\r
26 IN UINTN StrPos,\r
27 IN UINTN Len\r
28 );\r
29\r
e8a5ac7c
DB
30/**\r
31\r
32 Function waits for a given event to fire, or for an optional timeout to expire.\r
33\r
34 @param Event - The event to wait for\r
35 @param Timeout - An optional timeout value in 100 ns units.\r
36\r
37 @retval EFI_SUCCESS - Event fired before Timeout expired.\r
38 @retval EFI_TIME_OUT - Timout expired before Event fired..\r
39\r
40**/\r
748edcd5
PB
41EFI_STATUS\r
42EFIAPI\r
43WaitForSingleEvent (\r
44 IN EFI_EVENT Event,\r
45 IN UINT64 Timeout OPTIONAL\r
46 )\r
748edcd5
PB
47{\r
48 EFI_STATUS Status;\r
49 UINTN Index;\r
50 EFI_EVENT TimerEvent;\r
51 EFI_EVENT WaitList[2];\r
52\r
53 if (Timeout) {\r
54 //\r
55 // Create a timer event\r
56 //\r
57 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
58 if (!EFI_ERROR (Status)) {\r
59 //\r
60 // Set the timer event\r
61 //\r
62 gBS->SetTimer (\r
63 TimerEvent,\r
64 TimerRelative,\r
65 Timeout\r
66 );\r
67\r
68 //\r
69 // Wait for the original event or the timer\r
70 //\r
71 WaitList[0] = Event;\r
72 WaitList[1] = TimerEvent;\r
73 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
74 gBS->CloseEvent (TimerEvent);\r
75\r
76 //\r
77 // If the timer expired, change the return to timed out\r
78 //\r
79 if (!EFI_ERROR (Status) && Index == 1) {\r
80 Status = EFI_TIMEOUT;\r
81 }\r
82 }\r
83 } else {\r
84 //\r
85 // No timeout... just wait on the event\r
86 //\r
87 Status = gBS->WaitForEvent (1, &Event, &Index);\r
88 ASSERT (!EFI_ERROR (Status));\r
89 ASSERT (Index == 0);\r
90 }\r
91\r
92 return Status;\r
93}\r
94\r
e8a5ac7c
DB
95/**\r
96\r
97 Move the cursor position one character backward.\r
98\r
99 @param LineLength Length of a line. Get it by calling QueryMode\r
100 @param Column Current column of the cursor position\r
101 @param Row Current row of the cursor position\r
102\r
103**/\r
748edcd5
PB
104VOID\r
105EFIAPI\r
106ConMoveCursorBackward (\r
107 IN UINTN LineLength,\r
108 IN OUT UINTN *Column,\r
109 IN OUT UINTN *Row\r
110 )\r
748edcd5
PB
111{\r
112 ASSERT (Column != NULL);\r
113 ASSERT (Row != NULL);\r
114 //\r
115 // If current column is 0, move to the last column of the previous line,\r
116 // otherwise, just decrement column.\r
117 //\r
118 if (*Column == 0) {\r
119 (*Column) = LineLength - 1;\r
120 //\r
121 // if (*Row > 0) {\r
122 //\r
123 (*Row)--;\r
124 //\r
125 // }\r
126 //\r
127 } else {\r
128 (*Column)--;\r
129 }\r
130}\r
131\r
e8a5ac7c
DB
132/**\r
133\r
134 Move the cursor position one character backward.\r
135\r
136 @param LineLength Length of a line. Get it by calling QueryMode\r
137 @param TotalRow Total row of a screen, get by calling QueryMode\r
138 @param Column Current column of the cursor position\r
139 @param Row Current row of the cursor position\r
140\r
141**/\r
748edcd5
PB
142VOID\r
143EFIAPI\r
144ConMoveCursorForward (\r
145 IN UINTN LineLength,\r
146 IN UINTN TotalRow,\r
147 IN OUT UINTN *Column,\r
148 IN OUT UINTN *Row\r
149 )\r
748edcd5
PB
150{\r
151 ASSERT (Column != NULL);\r
152 ASSERT (Row != NULL);\r
153 //\r
154 // If current column is at line end, move to the first column of the nest\r
155 // line, otherwise, just increment column.\r
156 //\r
157 (*Column)++;\r
158 if (*Column >= LineLength) {\r
159 (*Column) = 0;\r
160 if ((*Row) < TotalRow - 1) {\r
161 (*Row)++;\r
162 }\r
163 }\r
164}\r
165\r
166CHAR16 mBackupSpace[EFI_DEBUG_INPUS_BUFFER_SIZE];\r
167CHAR16 mInputBufferHistory[EFI_DEBUG_INPUS_BUFFER_SIZE];\r
168\r
169VOID\r
170EFIAPI\r
171Input (\r
172 IN CHAR16 *Prompt OPTIONAL,\r
173 OUT CHAR16 *InStr,\r
174 IN UINTN StrLength\r
175 )\r
176{\r
177 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
178 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;\r
179 BOOLEAN Done;\r
180 UINTN Column;\r
181 UINTN Row;\r
182 UINTN StartColumn;\r
183 UINTN Update;\r
184 UINTN Delete;\r
185 UINTN Len;\r
186 UINTN StrPos;\r
187 UINTN Index;\r
188 UINTN LineLength;\r
189 UINTN TotalRow;\r
190 UINTN SkipLength;\r
191 UINTN OutputLength;\r
192 UINTN TailRow;\r
193 UINTN TailColumn;\r
194 EFI_INPUT_KEY Key;\r
195 BOOLEAN InsertMode;\r
196 BOOLEAN NeedAdjust;\r
197 UINTN SubIndex;\r
198 CHAR16 *CommandStr;\r
199\r
200 ConOut = gST->ConOut;\r
201 ConIn = gST->ConIn;\r
202\r
203 ASSERT (ConOut != NULL);\r
204 ASSERT (ConIn != NULL);\r
205 ASSERT (InStr != NULL);\r
206\r
207 if (Prompt) {\r
208 ConOut->OutputString (ConOut, Prompt);\r
209 }\r
210 //\r
211 // Read a line from the console\r
212 //\r
213 Len = 0;\r
214 StrPos = 0;\r
215 OutputLength = 0;\r
216 Update = 0;\r
217 Delete = 0;\r
218 InsertMode = TRUE;\r
219 NeedAdjust = FALSE;\r
220\r
221 //\r
222 // If buffer is not large enough to hold a CHAR16, do nothing.\r
223 //\r
224 if (StrLength < 1) {\r
225 return ;\r
226 }\r
227 //\r
228 // Get the screen setting and the current cursor location\r
229 //\r
230 StartColumn = ConOut->Mode->CursorColumn;\r
231 Column = StartColumn;\r
232 Row = ConOut->Mode->CursorRow;\r
233 ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &LineLength, &TotalRow);\r
234 if (LineLength == 0) {\r
235 return ;\r
236 }\r
237\r
238 SetMem (InStr, StrLength * sizeof (CHAR16), 0);\r
239 Done = FALSE;\r
240 do {\r
241 //\r
242 // Read a key\r
243 //\r
244 WaitForSingleEvent (ConIn->WaitForKey, 0);\r
245 ConIn->ReadKeyStroke (ConIn, &Key);\r
246\r
247 switch (Key.UnicodeChar) {\r
248 case CHAR_CARRIAGE_RETURN:\r
249 //\r
250 // All done, print a newline at the end of the string\r
251 //\r
252 TailRow = Row + (Len - StrPos + Column) / LineLength;\r
253 TailColumn = (Len - StrPos + Column) % LineLength;\r
254 Done = TRUE;\r
255 break;\r
256\r
257 case CHAR_BACKSPACE:\r
258 if (StrPos) {\r
259 //\r
260 // If not move back beyond string beginning, move all characters behind\r
261 // the current position one character forward\r
262 //\r
263 StrPos -= 1;\r
264 Update = StrPos;\r
265 Delete = 1;\r
266 CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));\r
267\r
268 //\r
269 // Adjust the current column and row\r
270 //\r
271 ConMoveCursorBackward (LineLength, &Column, &Row);\r
272\r
273 NeedAdjust = TRUE;\r
274 }\r
275 break;\r
276\r
277 default:\r
278 if (Key.UnicodeChar >= ' ') {\r
279 //\r
280 // If we are at the buffer's end, drop the key\r
281 //\r
282 if (Len == StrLength - 1 && (InsertMode || StrPos == Len)) {\r
283 break;\r
284 }\r
285 //\r
286 // If in insert mode, move all characters behind the current position\r
287 // one character backward to make space for this character. Then store\r
288 // the character.\r
289 //\r
290 if (InsertMode) {\r
291 for (Index = Len; Index > StrPos; Index -= 1) {\r
292 InStr[Index] = InStr[Index - 1];\r
293 }\r
294 }\r
295\r
296 InStr[StrPos] = Key.UnicodeChar;\r
297 Update = StrPos;\r
298\r
299 StrPos += 1;\r
300 OutputLength = 1;\r
301 }\r
302 break;\r
303\r
304 case 0:\r
305 switch (Key.ScanCode) {\r
306 case SCAN_DELETE:\r
307 //\r
308 // Move characters behind current position one character forward\r
309 //\r
310 if (Len) {\r
311 Update = StrPos;\r
312 Delete = 1;\r
313 CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));\r
314\r
315 NeedAdjust = TRUE;\r
316 }\r
317 break;\r
318\r
319 case SCAN_LEFT:\r
320 //\r
321 // Adjust current cursor position\r
322 //\r
323 if (StrPos) {\r
324 StrPos -= 1;\r
325 ConMoveCursorBackward (LineLength, &Column, &Row);\r
326 }\r
327 break;\r
328\r
329 case SCAN_RIGHT:\r
330 //\r
331 // Adjust current cursor position\r
332 //\r
333 if (StrPos < Len) {\r
334 StrPos += 1;\r
335 ConMoveCursorForward (LineLength, TotalRow, &Column, &Row);\r
336 }\r
337 break;\r
338\r
339 case SCAN_HOME:\r
340 //\r
341 // Move current cursor position to the beginning of the command line\r
342 //\r
343 Row -= (StrPos + StartColumn) / LineLength;\r
344 Column = StartColumn;\r
345 StrPos = 0;\r
346 break;\r
347\r
348 case SCAN_END:\r
349 //\r
350 // Move current cursor position to the end of the command line\r
351 //\r
352 TailRow = Row + (Len - StrPos + Column) / LineLength;\r
353 TailColumn = (Len - StrPos + Column) % LineLength;\r
354 Row = TailRow;\r
355 Column = TailColumn;\r
356 StrPos = Len;\r
357 break;\r
358\r
359 case SCAN_ESC:\r
360 //\r
361 // Prepare to clear the current command line\r
362 //\r
363 InStr[0] = 0;\r
364 Update = 0;\r
365 Delete = Len;\r
366 Row -= (StrPos + StartColumn) / LineLength;\r
367 Column = StartColumn;\r
368 OutputLength = 0;\r
369\r
370 NeedAdjust = TRUE;\r
371 break;\r
372\r
373 case SCAN_INSERT:\r
374 //\r
375 // Toggle the SEnvInsertMode flag\r
376 //\r
377 InsertMode = (BOOLEAN)!InsertMode;\r
378 break;\r
379\r
380 case SCAN_UP:\r
381 case SCAN_DOWN:\r
382 //\r
383 // show history\r
384 //\r
385 CopyMem (InStr, mInputBufferHistory, StrLength * sizeof(CHAR16));\r
386 StrPos = StrLen (mInputBufferHistory);\r
387 Update = 0;\r
388 Delete = 0;\r
389 OutputLength = 0;\r
390\r
391 TailRow = Row + (StrPos + StartColumn) / LineLength;\r
392 TailColumn = (StrPos + StartColumn) % LineLength;\r
393 Row = TailRow;\r
394 Column = TailColumn;\r
395 NeedAdjust = FALSE;\r
396\r
397 ConOut->SetCursorPosition (ConOut, StartColumn, Row);\r
398 for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {\r
399 mBackupSpace[SubIndex] = L' ';\r
400 }\r
401 EDBPrint (mBackupSpace);\r
402 SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN)) * sizeof(CHAR16), 0);\r
403\r
404 ConOut->SetCursorPosition (ConOut, StartColumn, Row);\r
405 Len = StrPos;\r
406\r
407 break;\r
408\r
409 case SCAN_F1:\r
410 case SCAN_F2:\r
411 case SCAN_F3:\r
412 case SCAN_F4:\r
413 case SCAN_F5:\r
414 case SCAN_F6:\r
415 case SCAN_F7:\r
416 case SCAN_F8:\r
417 case SCAN_F9:\r
418 case SCAN_F10:\r
419 case SCAN_F11:\r
420 case SCAN_F12:\r
421 CommandStr = GetCommandNameByKey (Key);\r
422 if (CommandStr != NULL) {\r
423 StrnCpyS (InStr, StrLength, CommandStr, StrLength - 1);\r
424 return ;\r
425 }\r
426 break;\r
427 }\r
428 }\r
429\r
430 if (Done) {\r
431 break;\r
432 }\r
433 //\r
434 // If we need to update the output do so now\r
435 //\r
436 if (Update != -1) {\r
437 if (NeedAdjust) {\r
438 ConOut->SetCursorPosition (ConOut, Column, Row);\r
439 for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {\r
440 mBackupSpace[SubIndex] = L' ';\r
441 }\r
442 EDBPrint (mBackupSpace);\r
443 SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN)) * sizeof(CHAR16), 0);\r
444 ConOut->SetCursorPosition (ConOut, Column, Row);\r
445 NeedAdjust = FALSE;\r
446 }\r
447 EDBPrint (InStr + Update);\r
448 Len = StrLen (InStr);\r
449\r
450 if (Delete) {\r
451 SetMem (InStr + Len, Delete * sizeof (CHAR16), 0x00);\r
452 }\r
453\r
454 if (StrPos > Len) {\r
455 StrPos = Len;\r
456 }\r
457\r
458 Update = (UINTN) -1;\r
459\r
460 //\r
461 // After using print to reflect newly updates, if we're not using\r
462 // BACKSPACE and DELETE, we need to move the cursor position forward,\r
463 // so adjust row and column here.\r
464 //\r
465 if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {\r
466 //\r
467 // Calulate row and column of the tail of current string\r
468 //\r
469 TailRow = Row + (Len - StrPos + Column + OutputLength) / LineLength;\r
470 TailColumn = (Len - StrPos + Column + OutputLength) % LineLength;\r
471\r
472 //\r
473 // If the tail of string reaches screen end, screen rolls up, so if\r
474 // Row does not equal TailRow, Row should be decremented\r
475 //\r
476 // (if we are recalling commands using UPPER and DOWN key, and if the\r
477 // old command is too long to fit the screen, TailColumn must be 79.\r
478 //\r
479 if (TailColumn == 0 && TailRow >= TotalRow && (UINTN) Row != TailRow) {\r
480 Row--;\r
481 }\r
482 //\r
483 // Calculate the cursor position after current operation. If cursor\r
484 // reaches line end, update both row and column, otherwise, only\r
485 // column will be changed.\r
486 //\r
487 if (Column + OutputLength >= LineLength) {\r
488 SkipLength = OutputLength - (LineLength - Column);\r
489\r
490 Row += SkipLength / LineLength + 1;\r
491 if ((UINTN) Row > TotalRow - 1) {\r
492 Row = TotalRow - 1;\r
493 }\r
494\r
495 Column = SkipLength % LineLength;\r
496 } else {\r
497 Column += OutputLength;\r
498 }\r
499 }\r
500\r
501 Delete = 0;\r
502 }\r
503 //\r
504 // Set the cursor position for this key\r
505 //\r
506 SetCursorPosition (ConOut, Column, Row, LineLength, TotalRow, InStr, StrPos, Len);\r
507 } while (!Done);\r
508\r
509 CopyMem (mInputBufferHistory, InStr, StrLength * sizeof(CHAR16));\r
510\r
511 //\r
512 // Return the data to the caller\r
513 //\r
514 return ;\r
515}\r
516\r
517VOID\r
518EFIAPI\r
519SetCursorPosition (\r
520 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
521 IN UINTN Column,\r
522 IN INTN Row,\r
523 IN UINTN LineLength,\r
524 IN UINTN TotalRow,\r
525 IN CHAR16 *Str,\r
526 IN UINTN StrPos,\r
527 IN UINTN Len\r
528 )\r
529{\r
530 CHAR16 Backup;\r
531\r
532 ASSERT (ConOut != NULL);\r
533 ASSERT (Str != NULL);\r
534\r
535 Backup = 0;\r
536 if (Row >= 0) {\r
537 ConOut->SetCursorPosition (ConOut, Column, Row);\r
538 return ;\r
539 }\r
540\r
541 if (Len - StrPos > Column * Row) {\r
542 Backup = *(Str + StrPos + Column * Row);\r
543 *(Str + StrPos + Column * Row) = 0;\r
544 }\r
545\r
546 EDBPrint (L"%s", Str + StrPos);\r
547 if (Len - StrPos > Column * Row) {\r
548 *(Str + StrPos + Column * Row) = Backup;\r
549 }\r
550\r
551 ConOut->SetCursorPosition (ConOut, 0, 0);\r
552}\r
553\r
554BOOLEAN\r
555EFIAPI\r
556SetPageBreak (\r
557 VOID\r
558 )\r
559{\r
560 EFI_INPUT_KEY Key;\r
561 CHAR16 Str[3];\r
562 BOOLEAN OmitPrint;\r
563\r
564 //\r
565 // Check\r
566 //\r
567 if (!mDebuggerPrivate.EnablePageBreak) {\r
568 return FALSE;\r
569 }\r
570\r
571 gST->ConOut->OutputString (gST->ConOut, L"Press ENTER to continue, 'q' to exit:");\r
572\r
573 OmitPrint = FALSE;\r
574 //\r
575 // Wait for user input\r
576 //\r
577 Str[0] = ' ';\r
578 Str[1] = 0;\r
579 Str[2] = 0;\r
580 for (;;) {\r
581 WaitForSingleEvent (gST->ConIn->WaitForKey, 0);\r
582 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
583\r
584 //\r
585 // handle control keys\r
586 //\r
587 if (Key.UnicodeChar == CHAR_NULL) {\r
588 if (Key.ScanCode == SCAN_ESC) {\r
589 gST->ConOut->OutputString (gST->ConOut, L"\r\n");\r
590 OmitPrint = TRUE;\r
591 break;\r
592 }\r
593\r
594 continue;\r
595 }\r
596\r
597 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
598 gST->ConOut->OutputString (gST->ConOut, L"\r\n");\r
599 break;\r
600 }\r
601 //\r
602 // Echo input\r
603 //\r
604 Str[1] = Key.UnicodeChar;\r
605 if (Str[1] == CHAR_BACKSPACE) {\r
606 continue;\r
607 }\r
608\r
609 gST->ConOut->OutputString (gST->ConOut, Str);\r
610\r
611 if ((Str[1] == L'q') || (Str[1] == L'Q')) {\r
612 OmitPrint = TRUE;\r
613 } else {\r
614 OmitPrint = FALSE;\r
615 }\r
616\r
617 Str[0] = CHAR_BACKSPACE;\r
618 }\r
619\r
620 return OmitPrint;\r
621}\r
622\r
623UINTN\r
624EFIAPI\r
625EDBPrint (\r
626 IN CONST CHAR16 *Format,\r
627 ...\r
628 )\r
629{\r
630 UINTN Return;\r
631 VA_LIST Marker;\r
632 CHAR16 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];\r
633\r
634 VA_START (Marker, Format);\r
635 Return = UnicodeVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
636 VA_END (Marker);\r
637\r
638 if (gST->ConOut != NULL) {\r
639 //\r
640 // To be extra safe make sure ConOut has been initialized\r
641 //\r
642 gST->ConOut->OutputString (gST->ConOut, Buffer);\r
643 }\r
644\r
645 return Return;\r
646}\r
647\r
648UINTN\r
649EFIAPI\r
650EDBSPrint (\r
651 OUT CHAR16 *Buffer,\r
652 IN INTN BufferSize,\r
653 IN CONST CHAR16 *Format,\r
654 ...\r
655 )\r
656{\r
657 UINTN Return;\r
658 VA_LIST Marker;\r
659\r
660 ASSERT (BufferSize > 0);\r
661\r
662 VA_START (Marker, Format);\r
663 Return = UnicodeVSPrint (Buffer, (UINTN)BufferSize, Format, Marker);\r
664 VA_END (Marker);\r
665\r
666 return Return;\r
667}\r
668\r
669UINTN\r
670EFIAPI\r
671EDBSPrintWithOffset (\r
672 OUT CHAR16 *Buffer,\r
673 IN INTN BufferSize,\r
674 IN UINTN Offset,\r
675 IN CONST CHAR16 *Format,\r
676 ...\r
677 )\r
678{\r
679 UINTN Return;\r
680 VA_LIST Marker;\r
681\r
682 ASSERT (BufferSize - (Offset * sizeof(CHAR16)) > 0);\r
683\r
684 VA_START (Marker, Format);\r
685 Return = UnicodeVSPrint (Buffer + Offset, (UINTN)(BufferSize - (Offset * sizeof(CHAR16))), Format, Marker);\r
686 VA_END (Marker);\r
687\r
688 return Return;\r
689}\r