1f33c8020SAxel Dörfler /* 246af4e77SAxel Dörfler * Copyright 2005-2010, Axel Dörfler, axeld@pinc-software.de. 3f33c8020SAxel Dörfler * Distributed under the terms of the MIT License. 446af4e77SAxel Dörfler * 546af4e77SAxel Dörfler * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 646af4e77SAxel Dörfler * Distributed under the terms of the NewOS License. 7f33c8020SAxel Dörfler */ 8f33c8020SAxel Dörfler 9f33c8020SAxel Dörfler 10f33c8020SAxel Dörfler #include "blue_screen.h" 11f33c8020SAxel Dörfler 1267f20716SAxel Dörfler #include <KernelExport.h> 13f33c8020SAxel Dörfler #include <frame_buffer_console.h> 14f33c8020SAxel Dörfler #include <console.h> 156eba0636SMichael Lotz #include <debug.h> 16f33c8020SAxel Dörfler #include <arch/debug_console.h> 17*e7d7b1e2SRene Gollent #include <safemode.h> 18f33c8020SAxel Dörfler 19f33c8020SAxel Dörfler #include <string.h> 20f33c8020SAxel Dörfler #include <stdio.h> 21f33c8020SAxel Dörfler 22855ab2b3SAxel Dörfler #include "debug_commands.h" 23855ab2b3SAxel Dörfler 24f33c8020SAxel Dörfler 25f33c8020SAxel Dörfler #define USE_SCROLLING 0 26f33c8020SAxel Dörfler #define NO_CLEAR 1 27f33c8020SAxel Dörfler 2867f20716SAxel Dörfler #define MAX_ARGS 8 2967f20716SAxel Dörfler 3067f20716SAxel Dörfler #define FMASK 0x0f 3167f20716SAxel Dörfler #define BMASK 0x70 3267f20716SAxel Dörfler 3367f20716SAxel Dörfler typedef enum { 3467f20716SAxel Dörfler CONSOLE_STATE_NORMAL = 0, 3567f20716SAxel Dörfler CONSOLE_STATE_GOT_ESCAPE, 3667f20716SAxel Dörfler CONSOLE_STATE_SEEN_BRACKET, 3767f20716SAxel Dörfler CONSOLE_STATE_NEW_ARG, 3867f20716SAxel Dörfler CONSOLE_STATE_PARSING_ARG, 3967f20716SAxel Dörfler } console_state; 4067f20716SAxel Dörfler 4170c3e1a4SAxel Dörfler typedef enum { 4270c3e1a4SAxel Dörfler LINE_ERASE_WHOLE, 4370c3e1a4SAxel Dörfler LINE_ERASE_LEFT, 4470c3e1a4SAxel Dörfler LINE_ERASE_RIGHT 4570c3e1a4SAxel Dörfler } erase_line_mode; 4670c3e1a4SAxel Dörfler 47f33c8020SAxel Dörfler struct screen_info { 48f33c8020SAxel Dörfler int32 columns; 49f33c8020SAxel Dörfler int32 rows; 50f33c8020SAxel Dörfler int32 x, y; 51f33c8020SAxel Dörfler uint8 attr; 5267f20716SAxel Dörfler bool bright_attr; 5367f20716SAxel Dörfler bool reverse_attr; 54855ab2b3SAxel Dörfler int32 in_command_rows; 55855ab2b3SAxel Dörfler bool paging; 56fec23a53SMichael Lotz bool paging_timeout; 5733965e02SAxel Dörfler bool boot_debug_output; 58855ab2b3SAxel Dörfler bool ignore_output; 5967f20716SAxel Dörfler 6067f20716SAxel Dörfler // state machine 6167f20716SAxel Dörfler console_state state; 6267f20716SAxel Dörfler int32 arg_count; 6367f20716SAxel Dörfler int32 args[MAX_ARGS]; 64f33c8020SAxel Dörfler } sScreen; 65f33c8020SAxel Dörfler 66f33c8020SAxel Dörfler console_module_info *sModule; 67f33c8020SAxel Dörfler 68f33c8020SAxel Dörfler 69f33c8020SAxel Dörfler static inline void 70f33c8020SAxel Dörfler hide_cursor(void) 71f33c8020SAxel Dörfler { 72f33c8020SAxel Dörfler sModule->move_cursor(-1, -1); 73f33c8020SAxel Dörfler } 74f33c8020SAxel Dörfler 75f33c8020SAxel Dörfler 76f33c8020SAxel Dörfler static inline void 77f33c8020SAxel Dörfler update_cursor(int32 x, int32 y) 78f33c8020SAxel Dörfler { 79f33c8020SAxel Dörfler sModule->move_cursor(x, y); 80f33c8020SAxel Dörfler } 81f33c8020SAxel Dörfler 82f33c8020SAxel Dörfler 8367f20716SAxel Dörfler static inline void 8467f20716SAxel Dörfler move_cursor(int32 x, int32 y) 8567f20716SAxel Dörfler { 8667f20716SAxel Dörfler sScreen.x = x; 8767f20716SAxel Dörfler sScreen.y = y; 8867f20716SAxel Dörfler update_cursor(x, y); 8967f20716SAxel Dörfler } 9067f20716SAxel Dörfler 9167f20716SAxel Dörfler 92f33c8020SAxel Dörfler #if USE_SCROLLING 93f33c8020SAxel Dörfler 94855ab2b3SAxel Dörfler /*! Scroll from the cursor line up to the top of the scroll region up one 95855ab2b3SAxel Dörfler line. 96855ab2b3SAxel Dörfler */ 97f33c8020SAxel Dörfler static void 98f33c8020SAxel Dörfler scroll_up(void) 99f33c8020SAxel Dörfler { 100f33c8020SAxel Dörfler // move the screen up one 101f33c8020SAxel Dörfler sModule->blit(0, 1, sScreen.columns, sScreen.rows - 1, 0, 0); 102f33c8020SAxel Dörfler 103f33c8020SAxel Dörfler // clear the bottom line 104f33c8020SAxel Dörfler sModule->fill_glyph(0, 0, sScreen.columns, 1, ' ', sScreen.attr); 105f33c8020SAxel Dörfler } 106f33c8020SAxel Dörfler #endif 107f33c8020SAxel Dörfler 108f33c8020SAxel Dörfler 109f33c8020SAxel Dörfler static void 110f33c8020SAxel Dörfler next_line(void) 111f33c8020SAxel Dörfler { 112f937627dSIngo Weinhold bool abortCommand = false; 113f937627dSIngo Weinhold 114a39bfc19SAxel Dörfler #if USE_SCROLLING 115a39bfc19SAxel Dörfler // TODO: scrolling is usually too slow; we could probably just remove it 116a39bfc19SAxel Dörfler if (sScreen.y == sScreen.rows - 1) 117a39bfc19SAxel Dörfler scroll_up(); 118a39bfc19SAxel Dörfler else 119a39bfc19SAxel Dörfler sScreen.y++; 120a39bfc19SAxel Dörfler #else 121855ab2b3SAxel Dörfler if (in_command_invocation()) 122855ab2b3SAxel Dörfler sScreen.in_command_rows++; 123855ab2b3SAxel Dörfler else 124855ab2b3SAxel Dörfler sScreen.in_command_rows = 0; 125855ab2b3SAxel Dörfler 126a39bfc19SAxel Dörfler if (sScreen.paging && ((sScreen.in_command_rows > 0 127a39bfc19SAxel Dörfler && ((sScreen.in_command_rows + 3) % sScreen.rows) == 0) 128a39bfc19SAxel Dörfler || (sScreen.boot_debug_output && sScreen.y == sScreen.rows - 1))) { 129fec23a53SMichael Lotz if (sScreen.paging_timeout) 130fec23a53SMichael Lotz spin(1000 * 1000 * 3); 131fec23a53SMichael Lotz else { 132a39bfc19SAxel Dörfler // Use the paging mechanism: either, we're in the debugger, and a 133a39bfc19SAxel Dörfler // command is being executed, or we're currently showing boot debug 134a39bfc19SAxel Dörfler // output 135f937627dSIngo Weinhold const char *text = in_command_invocation() 136f937627dSIngo Weinhold ? "Press key to continue, Q to quit, S to skip output" 137bc2836bbSMichael Lotz : "Press key to continue, S to skip output, P to disable paging"; 138855ab2b3SAxel Dörfler int32 length = strlen(text); 139855ab2b3SAxel Dörfler if (sScreen.x + length > sScreen.columns) { 140855ab2b3SAxel Dörfler // make sure we don't overwrite too much 141855ab2b3SAxel Dörfler text = "P"; 142855ab2b3SAxel Dörfler length = 1; 143855ab2b3SAxel Dörfler } 144855ab2b3SAxel Dörfler 145855ab2b3SAxel Dörfler for (int32 i = 0; i < length; i++) { 146a39bfc19SAxel Dörfler // yellow on black (or reverse, during boot) 147855ab2b3SAxel Dörfler sModule->put_glyph(sScreen.columns - length + i, sScreen.y, 148a39bfc19SAxel Dörfler text[i], sScreen.boot_debug_output ? 0x6f : 0xf6); 149855ab2b3SAxel Dörfler } 150855ab2b3SAxel Dörfler 1516eba0636SMichael Lotz char c = kgetc(); 152f937627dSIngo Weinhold if (c == 's') { 153855ab2b3SAxel Dörfler sScreen.ignore_output = true; 154bc2836bbSMichael Lotz } else if (c == 'q' && in_command_invocation()) { 155bc2836bbSMichael Lotz abortCommand = true; 15673aa393dSIngo Weinhold sScreen.ignore_output = true; 157bc2836bbSMichael Lotz } else if (c == 'p' && !in_command_invocation()) 158bc2836bbSMichael Lotz sScreen.paging = false; 159fec23a53SMichael Lotz else if (c == 't' && !in_command_invocation()) 160fec23a53SMichael Lotz sScreen.paging_timeout = true; 161855ab2b3SAxel Dörfler 162855ab2b3SAxel Dörfler // remove on screen text again 163855ab2b3SAxel Dörfler sModule->fill_glyph(sScreen.columns - length, sScreen.y, length, 164855ab2b3SAxel Dörfler 1, ' ', sScreen.attr); 165855ab2b3SAxel Dörfler } 166ab542128SMichael Lotz 167ab542128SMichael Lotz if (sScreen.in_command_rows > 0) 168ab542128SMichael Lotz sScreen.in_command_rows += 2; 169fec23a53SMichael Lotz } 170a39bfc19SAxel Dörfler if (sScreen.y == sScreen.rows - 1) { 171f33c8020SAxel Dörfler sScreen.y = 0; 172855ab2b3SAxel Dörfler sModule->fill_glyph(0, 0, sScreen.columns, 2, ' ', sScreen.attr); 173a39bfc19SAxel Dörfler } else 174f33c8020SAxel Dörfler sScreen.y++; 175a39bfc19SAxel Dörfler #endif 176f33c8020SAxel Dörfler 177f33c8020SAxel Dörfler #if NO_CLEAR 178855ab2b3SAxel Dörfler if (sScreen.y + 2 < sScreen.rows) { 179855ab2b3SAxel Dörfler sModule->fill_glyph(0, (sScreen.y + 2) % sScreen.rows, sScreen.columns, 180855ab2b3SAxel Dörfler 1, ' ', sScreen.attr); 181855ab2b3SAxel Dörfler } 182f33c8020SAxel Dörfler #endif 183f33c8020SAxel Dörfler sScreen.x = 0; 184f937627dSIngo Weinhold 185f937627dSIngo Weinhold if (abortCommand) { 186f937627dSIngo Weinhold abort_debugger_command(); 187f937627dSIngo Weinhold // should not return 188f937627dSIngo Weinhold } 189f33c8020SAxel Dörfler } 190f33c8020SAxel Dörfler 191f33c8020SAxel Dörfler 192f33c8020SAxel Dörfler static void 19370c3e1a4SAxel Dörfler erase_line(erase_line_mode mode) 19470c3e1a4SAxel Dörfler { 19570c3e1a4SAxel Dörfler switch (mode) { 19670c3e1a4SAxel Dörfler case LINE_ERASE_WHOLE: 197855ab2b3SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.columns, 1, ' ', 198855ab2b3SAxel Dörfler sScreen.attr); 19970c3e1a4SAxel Dörfler break; 20070c3e1a4SAxel Dörfler case LINE_ERASE_LEFT: 201855ab2b3SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.x + 1, 1, ' ', 202855ab2b3SAxel Dörfler sScreen.attr); 20370c3e1a4SAxel Dörfler break; 20470c3e1a4SAxel Dörfler case LINE_ERASE_RIGHT: 205855ab2b3SAxel Dörfler sModule->fill_glyph(sScreen.x, sScreen.y, sScreen.columns 206855ab2b3SAxel Dörfler - sScreen.x, 1, ' ', sScreen.attr); 20770c3e1a4SAxel Dörfler break; 20870c3e1a4SAxel Dörfler } 20970c3e1a4SAxel Dörfler } 21070c3e1a4SAxel Dörfler 21170c3e1a4SAxel Dörfler 21270c3e1a4SAxel Dörfler static void 213f33c8020SAxel Dörfler back_space(void) 214f33c8020SAxel Dörfler { 215f33c8020SAxel Dörfler if (sScreen.x <= 0) 216f33c8020SAxel Dörfler return; 217f33c8020SAxel Dörfler 218f33c8020SAxel Dörfler sScreen.x--; 219f33c8020SAxel Dörfler sModule->put_glyph(sScreen.x, sScreen.y, ' ', sScreen.attr); 220f33c8020SAxel Dörfler } 221f33c8020SAxel Dörfler 222f33c8020SAxel Dörfler 223f33c8020SAxel Dörfler static void 224f33c8020SAxel Dörfler put_character(char c) 225f33c8020SAxel Dörfler { 226f33c8020SAxel Dörfler if (++sScreen.x >= sScreen.columns) { 227f33c8020SAxel Dörfler next_line(); 228f33c8020SAxel Dörfler sScreen.x++; 229f33c8020SAxel Dörfler } 230f33c8020SAxel Dörfler 231f33c8020SAxel Dörfler sModule->put_glyph(sScreen.x - 1, sScreen.y, c, sScreen.attr); 232f33c8020SAxel Dörfler } 233f33c8020SAxel Dörfler 234f33c8020SAxel Dörfler 235f33c8020SAxel Dörfler static void 23667f20716SAxel Dörfler set_vt100_attributes(int32 *args, int32 argCount) 23767f20716SAxel Dörfler { 23867f20716SAxel Dörfler if (argCount == 0) { 23967f20716SAxel Dörfler // that's the default (attributes off) 24067f20716SAxel Dörfler argCount++; 24167f20716SAxel Dörfler args[0] = 0; 24267f20716SAxel Dörfler } 24367f20716SAxel Dörfler 24467f20716SAxel Dörfler for (int32 i = 0; i < argCount; i++) { 24567f20716SAxel Dörfler switch (args[i]) { 24667f20716SAxel Dörfler case 0: // reset 24733965e02SAxel Dörfler sScreen.attr = sScreen.boot_debug_output ? 0xf0 : 0x0f; 24867f20716SAxel Dörfler sScreen.bright_attr = true; 24967f20716SAxel Dörfler sScreen.reverse_attr = false; 25067f20716SAxel Dörfler break; 25167f20716SAxel Dörfler case 1: // bright 25267f20716SAxel Dörfler sScreen.bright_attr = true; 25367f20716SAxel Dörfler sScreen.attr |= 0x08; // set the bright bit 25467f20716SAxel Dörfler break; 25567f20716SAxel Dörfler case 2: // dim 25667f20716SAxel Dörfler sScreen.bright_attr = false; 25767f20716SAxel Dörfler sScreen.attr &= ~0x08; // unset the bright bit 25867f20716SAxel Dörfler break; 25967f20716SAxel Dörfler case 4: // underscore we can't do 26067f20716SAxel Dörfler break; 26167f20716SAxel Dörfler case 5: // blink 26267f20716SAxel Dörfler sScreen.attr |= 0x80; // set the blink bit 26367f20716SAxel Dörfler break; 26467f20716SAxel Dörfler case 7: // reverse 26567f20716SAxel Dörfler sScreen.reverse_attr = true; 266855ab2b3SAxel Dörfler sScreen.attr = ((sScreen.attr & BMASK) >> 4) 267855ab2b3SAxel Dörfler | ((sScreen.attr & FMASK) << 4); 26867f20716SAxel Dörfler if (sScreen.bright_attr) 26967f20716SAxel Dörfler sScreen.attr |= 0x08; 27067f20716SAxel Dörfler break; 27167f20716SAxel Dörfler case 8: // hidden? 27267f20716SAxel Dörfler break; 27367f20716SAxel Dörfler 27467f20716SAxel Dörfler /* foreground colors */ 275855ab2b3SAxel Dörfler case 30: // black 276855ab2b3SAxel Dörfler case 31: // red 277855ab2b3SAxel Dörfler case 32: // green 278855ab2b3SAxel Dörfler case 33: // yellow 279855ab2b3SAxel Dörfler case 34: // blue 280855ab2b3SAxel Dörfler case 35: // magenta 281855ab2b3SAxel Dörfler case 36: // cyan 282855ab2b3SAxel Dörfler case 37: // white 283855ab2b3SAxel Dörfler { 284855ab2b3SAxel Dörfler const uint8 colors[] = {0, 4, 2, 6, 1, 5, 3, 7}; 285855ab2b3SAxel Dörfler sScreen.attr = (sScreen.attr & ~FMASK) | colors[args[i] - 30] 286855ab2b3SAxel Dörfler | (sScreen.bright_attr ? 0x08 : 0); 287855ab2b3SAxel Dörfler break; 288855ab2b3SAxel Dörfler } 28967f20716SAxel Dörfler 29067f20716SAxel Dörfler /* background colors */ 29167f20716SAxel Dörfler case 40: sScreen.attr = (sScreen.attr & ~BMASK) | (0 << 4); break; // black 29267f20716SAxel Dörfler case 41: sScreen.attr = (sScreen.attr & ~BMASK) | (4 << 4); break; // red 29367f20716SAxel Dörfler case 42: sScreen.attr = (sScreen.attr & ~BMASK) | (2 << 4); break; // green 29467f20716SAxel Dörfler case 43: sScreen.attr = (sScreen.attr & ~BMASK) | (6 << 4); break; // yellow 29567f20716SAxel Dörfler case 44: sScreen.attr = (sScreen.attr & ~BMASK) | (1 << 4); break; // blue 29667f20716SAxel Dörfler case 45: sScreen.attr = (sScreen.attr & ~BMASK) | (5 << 4); break; // magenta 29767f20716SAxel Dörfler case 46: sScreen.attr = (sScreen.attr & ~BMASK) | (3 << 4); break; // cyan 29867f20716SAxel Dörfler case 47: sScreen.attr = (sScreen.attr & ~BMASK) | (7 << 4); break; // white 29967f20716SAxel Dörfler } 30067f20716SAxel Dörfler } 30167f20716SAxel Dörfler } 30267f20716SAxel Dörfler 30367f20716SAxel Dörfler 30467f20716SAxel Dörfler static bool 30546af4e77SAxel Dörfler process_vt100_command(const char c, bool seenBracket, int32 *args, 30646af4e77SAxel Dörfler int32 argCount) 30767f20716SAxel Dörfler { 30867f20716SAxel Dörfler bool ret = true; 30967f20716SAxel Dörfler 31067f20716SAxel Dörfler // kprintf("process_vt100_command: c '%c', argCount %ld, arg[0] %ld, arg[1] %ld, seenBracket %d\n", 31167f20716SAxel Dörfler // c, argCount, args[0], args[1], seenBracket); 31267f20716SAxel Dörfler 31367f20716SAxel Dörfler if (seenBracket) { 31467f20716SAxel Dörfler switch (c) { 31546af4e77SAxel Dörfler case 'H': // set cursor position 31646af4e77SAxel Dörfler case 'f': 31746af4e77SAxel Dörfler { 31867f20716SAxel Dörfler int32 row = argCount > 0 ? args[0] : 1; 31967f20716SAxel Dörfler int32 col = argCount > 1 ? args[1] : 1; 32067f20716SAxel Dörfler if (row > 0) 32167f20716SAxel Dörfler row--; 32267f20716SAxel Dörfler if (col > 0) 32367f20716SAxel Dörfler col--; 32467f20716SAxel Dörfler move_cursor(col, row); 32567f20716SAxel Dörfler break; 32667f20716SAxel Dörfler } 32746af4e77SAxel Dörfler case 'A': // move up 32846af4e77SAxel Dörfler { 32946af4e77SAxel Dörfler int32 deltaY = argCount > 0 ? -args[0] : -1; 33046af4e77SAxel Dörfler if (deltaY == 0) 33146af4e77SAxel Dörfler deltaY = -1; 33246af4e77SAxel Dörfler move_cursor(sScreen.x, sScreen.y + deltaY); 33367f20716SAxel Dörfler break; 33467f20716SAxel Dörfler } 33567f20716SAxel Dörfler case 'e': 33646af4e77SAxel Dörfler case 'B': // move down 33746af4e77SAxel Dörfler { 33846af4e77SAxel Dörfler int32 deltaY = argCount > 0 ? args[0] : 1; 33946af4e77SAxel Dörfler if (deltaY == 0) 34046af4e77SAxel Dörfler deltaY = 1; 34146af4e77SAxel Dörfler move_cursor(sScreen.x, sScreen.y + deltaY); 34267f20716SAxel Dörfler break; 34367f20716SAxel Dörfler } 34446af4e77SAxel Dörfler case 'D': // move left 34546af4e77SAxel Dörfler { 34646af4e77SAxel Dörfler int32 deltaX = argCount > 0 ? -args[0] : -1; 34746af4e77SAxel Dörfler if (deltaX == 0) 34846af4e77SAxel Dörfler deltaX = -1; 34946af4e77SAxel Dörfler move_cursor(sScreen.x + deltaX, sScreen.y); 35067f20716SAxel Dörfler break; 35167f20716SAxel Dörfler } 35267f20716SAxel Dörfler case 'a': 35346af4e77SAxel Dörfler case 'C': // move right 35446af4e77SAxel Dörfler { 35546af4e77SAxel Dörfler int32 deltaX = argCount > 0 ? args[0] : 1; 35646af4e77SAxel Dörfler if (deltaX == 0) 35746af4e77SAxel Dörfler deltaX = 1; 35846af4e77SAxel Dörfler move_cursor(sScreen.x + deltaX, sScreen.y); 35967f20716SAxel Dörfler break; 36067f20716SAxel Dörfler } 36167f20716SAxel Dörfler case '`': 36246af4e77SAxel Dörfler case 'G': // set X position 36346af4e77SAxel Dörfler { 36446af4e77SAxel Dörfler int32 newX = argCount > 0 ? args[0] : 1; 36546af4e77SAxel Dörfler if (newX > 0) 36646af4e77SAxel Dörfler newX--; 36746af4e77SAxel Dörfler move_cursor(newX, sScreen.y); 36867f20716SAxel Dörfler break; 36967f20716SAxel Dörfler } 37046af4e77SAxel Dörfler case 'd': // set y position 37146af4e77SAxel Dörfler { 37246af4e77SAxel Dörfler int32 newY = argCount > 0 ? args[0] : 1; 37346af4e77SAxel Dörfler if (newY > 0) 37446af4e77SAxel Dörfler newY--; 37546af4e77SAxel Dörfler move_cursor(sScreen.x, newY); 37667f20716SAxel Dörfler break; 37767f20716SAxel Dörfler } 37867f20716SAxel Dörfler #if 0 37946af4e77SAxel Dörfler case 's': // save current cursor 38067f20716SAxel Dörfler save_cur(console, false); 38167f20716SAxel Dörfler break; 38246af4e77SAxel Dörfler case 'u': // restore cursor 38367f20716SAxel Dörfler restore_cur(console, false); 38467f20716SAxel Dörfler break; 38546af4e77SAxel Dörfler case 'r': // set scroll region 38646af4e77SAxel Dörfler { 38767f20716SAxel Dörfler int32 low = argCount > 0 ? args[0] : 1; 38867f20716SAxel Dörfler int32 high = argCount > 1 ? args[1] : sScreen.lines; 38967f20716SAxel Dörfler if (low <= high) 39067f20716SAxel Dörfler set_scroll_region(console, low - 1, high - 1); 39167f20716SAxel Dörfler break; 39267f20716SAxel Dörfler } 39346af4e77SAxel Dörfler case 'L': // scroll virtual down at cursor 39446af4e77SAxel Dörfler { 39567f20716SAxel Dörfler int32 lines = argCount > 0 ? args[0] : 1; 39667f20716SAxel Dörfler while (lines > 0) { 39767f20716SAxel Dörfler scrdown(console); 39867f20716SAxel Dörfler lines--; 39967f20716SAxel Dörfler } 40067f20716SAxel Dörfler break; 40167f20716SAxel Dörfler } 40246af4e77SAxel Dörfler case 'M': // scroll virtual up at cursor 40346af4e77SAxel Dörfler { 40467f20716SAxel Dörfler int32 lines = argCount > 0 ? args[0] : 1; 40567f20716SAxel Dörfler while (lines > 0) { 40667f20716SAxel Dörfler scrup(console); 40767f20716SAxel Dörfler lines--; 40867f20716SAxel Dörfler } 40967f20716SAxel Dörfler break; 41067f20716SAxel Dörfler } 41170c3e1a4SAxel Dörfler #endif 41267f20716SAxel Dörfler case 'K': 41367f20716SAxel Dörfler if (argCount == 0 || args[0] == 0) { 41467f20716SAxel Dörfler // erase to end of line 41570c3e1a4SAxel Dörfler erase_line(LINE_ERASE_RIGHT); 41667f20716SAxel Dörfler } else if (argCount > 0) { 41767f20716SAxel Dörfler if (args[0] == 1) 41870c3e1a4SAxel Dörfler erase_line(LINE_ERASE_LEFT); 41967f20716SAxel Dörfler else if (args[0] == 2) 42070c3e1a4SAxel Dörfler erase_line(LINE_ERASE_WHOLE); 42167f20716SAxel Dörfler } 42267f20716SAxel Dörfler break; 42370c3e1a4SAxel Dörfler #if 0 42467f20716SAxel Dörfler case 'J': 42567f20716SAxel Dörfler if (argCount == 0 || args[0] == 0) { 42667f20716SAxel Dörfler // erase to end of screen 42767f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_DOWN); 42867f20716SAxel Dörfler } else { 42967f20716SAxel Dörfler if (args[0] == 1) 43067f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_UP); 43167f20716SAxel Dörfler else if (args[0] == 2) 43267f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_WHOLE); 43367f20716SAxel Dörfler } 43467f20716SAxel Dörfler break; 43567f20716SAxel Dörfler #endif 43667f20716SAxel Dörfler case 'm': 43767f20716SAxel Dörfler if (argCount >= 0) 43867f20716SAxel Dörfler set_vt100_attributes(args, argCount); 43967f20716SAxel Dörfler break; 44067f20716SAxel Dörfler default: 44167f20716SAxel Dörfler ret = false; 44267f20716SAxel Dörfler } 44367f20716SAxel Dörfler } else { 44467f20716SAxel Dörfler switch (c) { 44567f20716SAxel Dörfler #if 0 44667f20716SAxel Dörfler case 'c': 44767f20716SAxel Dörfler reset_console(console); 44867f20716SAxel Dörfler break; 44967f20716SAxel Dörfler case 'D': 45067f20716SAxel Dörfler rlf(console); 45167f20716SAxel Dörfler break; 45267f20716SAxel Dörfler case 'M': 45367f20716SAxel Dörfler lf(console); 45467f20716SAxel Dörfler break; 45567f20716SAxel Dörfler case '7': 45667f20716SAxel Dörfler save_cur(console, true); 45767f20716SAxel Dörfler break; 45867f20716SAxel Dörfler case '8': 45967f20716SAxel Dörfler restore_cur(console, true); 46067f20716SAxel Dörfler break; 46167f20716SAxel Dörfler #endif 46267f20716SAxel Dörfler default: 46367f20716SAxel Dörfler ret = false; 46467f20716SAxel Dörfler } 46567f20716SAxel Dörfler } 46667f20716SAxel Dörfler 46767f20716SAxel Dörfler return ret; 46867f20716SAxel Dörfler } 46967f20716SAxel Dörfler 47067f20716SAxel Dörfler 47167f20716SAxel Dörfler static void 472f33c8020SAxel Dörfler parse_character(char c) 473f33c8020SAxel Dörfler { 47467f20716SAxel Dörfler switch (sScreen.state) { 47567f20716SAxel Dörfler case CONSOLE_STATE_NORMAL: 476f33c8020SAxel Dörfler // just output the stuff 477f33c8020SAxel Dörfler switch (c) { 478f33c8020SAxel Dörfler case '\n': 479f33c8020SAxel Dörfler next_line(); 480f33c8020SAxel Dörfler break; 481f33c8020SAxel Dörfler case 0x8: 482f33c8020SAxel Dörfler back_space(); 483f33c8020SAxel Dörfler break; 484f33c8020SAxel Dörfler case '\t': 48546af4e77SAxel Dörfler // TODO: real tab... 486f31dc4ddSAxel Dörfler sScreen.x = (sScreen.x + 8) & ~7; 487f31dc4ddSAxel Dörfler if (sScreen.x >= sScreen.columns) 488f31dc4ddSAxel Dörfler next_line(); 489f33c8020SAxel Dörfler break; 490f33c8020SAxel Dörfler 491f33c8020SAxel Dörfler case '\r': 492f33c8020SAxel Dörfler case '\0': 49367f20716SAxel Dörfler case '\a': // beep 494f33c8020SAxel Dörfler break; 495f33c8020SAxel Dörfler 49667f20716SAxel Dörfler case 0x1b: 49767f20716SAxel Dörfler // escape character 49846af4e77SAxel Dörfler sScreen.arg_count = 0; 49967f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_GOT_ESCAPE; 50067f20716SAxel Dörfler break; 501f33c8020SAxel Dörfler default: 502f33c8020SAxel Dörfler put_character(c); 503f33c8020SAxel Dörfler } 50467f20716SAxel Dörfler break; 50567f20716SAxel Dörfler case CONSOLE_STATE_GOT_ESCAPE: 50667f20716SAxel Dörfler // look for either commands with no argument, or the '[' character 50767f20716SAxel Dörfler switch (c) { 50867f20716SAxel Dörfler case '[': 50967f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_SEEN_BRACKET; 51067f20716SAxel Dörfler break; 51167f20716SAxel Dörfler default: 51246af4e77SAxel Dörfler sScreen.args[0] = 0; 51346af4e77SAxel Dörfler process_vt100_command(c, false, sScreen.args, 0); 51467f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 51567f20716SAxel Dörfler } 51667f20716SAxel Dörfler break; 51767f20716SAxel Dörfler case CONSOLE_STATE_SEEN_BRACKET: 51867f20716SAxel Dörfler switch (c) { 51967f20716SAxel Dörfler case '0'...'9': 52067f20716SAxel Dörfler sScreen.arg_count = 0; 52146af4e77SAxel Dörfler sScreen.args[0] = c - '0'; 52267f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_PARSING_ARG; 52367f20716SAxel Dörfler break; 52467f20716SAxel Dörfler case '?': 525855ab2b3SAxel Dörfler // private DEC mode parameter follows - we ignore those 526855ab2b3SAxel Dörfler // anyway 52767f20716SAxel Dörfler break; 52867f20716SAxel Dörfler default: 52938eb09a3SIngo Weinhold process_vt100_command(c, true, sScreen.args, 0); 53067f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 53146af4e77SAxel Dörfler break; 53267f20716SAxel Dörfler } 53367f20716SAxel Dörfler break; 53467f20716SAxel Dörfler case CONSOLE_STATE_NEW_ARG: 53567f20716SAxel Dörfler switch (c) { 53667f20716SAxel Dörfler case '0'...'9': 53746af4e77SAxel Dörfler if (++sScreen.arg_count == MAX_ARGS) { 53867f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 53967f20716SAxel Dörfler break; 54067f20716SAxel Dörfler } 54167f20716SAxel Dörfler sScreen.args[sScreen.arg_count] = c - '0'; 54267f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_PARSING_ARG; 54367f20716SAxel Dörfler break; 54467f20716SAxel Dörfler default: 545855ab2b3SAxel Dörfler process_vt100_command(c, true, sScreen.args, 546855ab2b3SAxel Dörfler sScreen.arg_count + 1); 54767f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 54846af4e77SAxel Dörfler break; 54967f20716SAxel Dörfler } 55067f20716SAxel Dörfler break; 55167f20716SAxel Dörfler case CONSOLE_STATE_PARSING_ARG: 55267f20716SAxel Dörfler // parse args 55367f20716SAxel Dörfler switch (c) { 55467f20716SAxel Dörfler case '0'...'9': 55567f20716SAxel Dörfler sScreen.args[sScreen.arg_count] *= 10; 55667f20716SAxel Dörfler sScreen.args[sScreen.arg_count] += c - '0'; 55767f20716SAxel Dörfler break; 55867f20716SAxel Dörfler case ';': 55967f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NEW_ARG; 56067f20716SAxel Dörfler break; 56167f20716SAxel Dörfler default: 562855ab2b3SAxel Dörfler process_vt100_command(c, true, sScreen.args, 563855ab2b3SAxel Dörfler sScreen.arg_count + 1); 56467f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 56546af4e77SAxel Dörfler break; 56667f20716SAxel Dörfler } 56767f20716SAxel Dörfler } 568f33c8020SAxel Dörfler } 569f33c8020SAxel Dörfler 570f33c8020SAxel Dörfler 571855ab2b3SAxel Dörfler static int 572855ab2b3SAxel Dörfler set_paging(int argc, char **argv) 573855ab2b3SAxel Dörfler { 574855ab2b3SAxel Dörfler if (argc > 1 && !strcmp(argv[1], "--help")) { 575855ab2b3SAxel Dörfler kprintf("usage: %s [on|off]\n", argv[0]); 576855ab2b3SAxel Dörfler return 0; 577855ab2b3SAxel Dörfler } 578855ab2b3SAxel Dörfler 579855ab2b3SAxel Dörfler if (argc == 1) 580855ab2b3SAxel Dörfler sScreen.paging = !sScreen.paging; 581855ab2b3SAxel Dörfler else if (!strcmp(argv[1], "on")) 582855ab2b3SAxel Dörfler sScreen.paging = true; 583855ab2b3SAxel Dörfler else if (!strcmp(argv[1], "off")) 584855ab2b3SAxel Dörfler sScreen.paging = false; 585855ab2b3SAxel Dörfler else 586855ab2b3SAxel Dörfler sScreen.paging = parse_expression(argv[1]) != 0; 587855ab2b3SAxel Dörfler 588855ab2b3SAxel Dörfler kprintf("paging is turned %s now.\n", sScreen.paging ? "on" : "off"); 589855ab2b3SAxel Dörfler return 0; 590855ab2b3SAxel Dörfler } 591855ab2b3SAxel Dörfler 592855ab2b3SAxel Dörfler 593f33c8020SAxel Dörfler // #pragma mark - 594f33c8020SAxel Dörfler 595f33c8020SAxel Dörfler 596f33c8020SAxel Dörfler status_t 597f33c8020SAxel Dörfler blue_screen_init(void) 598f33c8020SAxel Dörfler { 599f33c8020SAxel Dörfler extern console_module_info gFrameBufferConsoleModule; 600f33c8020SAxel Dörfler 601f33c8020SAxel Dörfler // we can't use get_module() here, since it's too early in the boot process 602f33c8020SAxel Dörfler 603f33c8020SAxel Dörfler if (!frame_buffer_console_available()) 604f33c8020SAxel Dörfler return B_ERROR; 605f33c8020SAxel Dörfler 606f33c8020SAxel Dörfler sModule = &gFrameBufferConsoleModule; 607*e7d7b1e2SRene Gollent sScreen.paging = !get_safemode_boolean( 608*e7d7b1e2SRene Gollent "disable_onscreen_paging", false); 609fec23a53SMichael Lotz sScreen.paging_timeout = false; 610855ab2b3SAxel Dörfler 611855ab2b3SAxel Dörfler add_debugger_command("paging", set_paging, "Enable or disable paging"); 612f33c8020SAxel Dörfler return B_OK; 613f33c8020SAxel Dörfler } 614f33c8020SAxel Dörfler 615f33c8020SAxel Dörfler 616173d0b2fSAxel Dörfler status_t 61792447917SAxel Dörfler blue_screen_enter(bool debugOutput) 618f33c8020SAxel Dörfler { 61992447917SAxel Dörfler sScreen.attr = debugOutput ? 0xf0 : 0x0f; 62092447917SAxel Dörfler // black on white for KDL, white on black for debug output 62133965e02SAxel Dörfler sScreen.boot_debug_output = debugOutput; 62233965e02SAxel Dörfler sScreen.ignore_output = false; 62333965e02SAxel Dörfler 624f33c8020SAxel Dörfler sScreen.x = sScreen.y = 0; 62567f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 626f33c8020SAxel Dörfler 627173d0b2fSAxel Dörfler if (sModule == NULL) 628173d0b2fSAxel Dörfler return B_NO_INIT; 629173d0b2fSAxel Dörfler 630f33c8020SAxel Dörfler sModule->get_size(&sScreen.columns, &sScreen.rows); 631f33c8020SAxel Dörfler #if !NO_CLEAR 632f33c8020SAxel Dörfler sModule->clear(sScreen.attr); 633f33c8020SAxel Dörfler #else 634f33c8020SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.columns, 3, ' ', sScreen.attr); 635f33c8020SAxel Dörfler #endif 636173d0b2fSAxel Dörfler return B_OK; 637f33c8020SAxel Dörfler } 638f33c8020SAxel Dörfler 639f33c8020SAxel Dörfler 640976e5259SIngo Weinhold bool 641976e5259SIngo Weinhold blue_screen_paging_enabled(void) 642976e5259SIngo Weinhold { 643976e5259SIngo Weinhold return sScreen.paging; 644976e5259SIngo Weinhold } 645976e5259SIngo Weinhold 646976e5259SIngo Weinhold 647976e5259SIngo Weinhold void 648976e5259SIngo Weinhold blue_screen_set_paging(bool enabled) 649976e5259SIngo Weinhold { 650976e5259SIngo Weinhold sScreen.paging = enabled; 651976e5259SIngo Weinhold } 652976e5259SIngo Weinhold 653976e5259SIngo Weinhold 654a1587d16SIngo Weinhold void 655a1587d16SIngo Weinhold blue_screen_clear_screen(void) 656a1587d16SIngo Weinhold { 657a1587d16SIngo Weinhold sModule->clear(sScreen.attr); 658a1587d16SIngo Weinhold move_cursor(0, 0); 659a1587d16SIngo Weinhold } 660a1587d16SIngo Weinhold 661a1587d16SIngo Weinhold 662f33c8020SAxel Dörfler char 663f33c8020SAxel Dörfler blue_screen_getchar(void) 664f33c8020SAxel Dörfler { 665f33c8020SAxel Dörfler return arch_debug_blue_screen_getchar(); 666f33c8020SAxel Dörfler } 667f33c8020SAxel Dörfler 668f33c8020SAxel Dörfler 669f33c8020SAxel Dörfler void 670f33c8020SAxel Dörfler blue_screen_putchar(char c) 671f33c8020SAxel Dörfler { 67233965e02SAxel Dörfler if (sScreen.ignore_output 67333965e02SAxel Dörfler && (in_command_invocation() || sScreen.boot_debug_output)) 674855ab2b3SAxel Dörfler return; 675855ab2b3SAxel Dörfler 676855ab2b3SAxel Dörfler sScreen.ignore_output = false; 677f33c8020SAxel Dörfler hide_cursor(); 678f33c8020SAxel Dörfler 679f33c8020SAxel Dörfler parse_character(c); 680f33c8020SAxel Dörfler 681f33c8020SAxel Dörfler update_cursor(sScreen.x, sScreen.y); 682f33c8020SAxel Dörfler } 683f33c8020SAxel Dörfler 684f33c8020SAxel Dörfler 685f33c8020SAxel Dörfler void 686f33c8020SAxel Dörfler blue_screen_puts(const char *text) 687f33c8020SAxel Dörfler { 68833965e02SAxel Dörfler if (sScreen.ignore_output 68933965e02SAxel Dörfler && (in_command_invocation() || sScreen.boot_debug_output)) 690855ab2b3SAxel Dörfler return; 691855ab2b3SAxel Dörfler 692855ab2b3SAxel Dörfler sScreen.ignore_output = false; 693f33c8020SAxel Dörfler hide_cursor(); 694f33c8020SAxel Dörfler 695f33c8020SAxel Dörfler while (text[0] != '\0') { 696f33c8020SAxel Dörfler parse_character(text[0]); 697f33c8020SAxel Dörfler text++; 698f33c8020SAxel Dörfler } 699f33c8020SAxel Dörfler 700f33c8020SAxel Dörfler update_cursor(sScreen.x, sScreen.y); 701f33c8020SAxel Dörfler } 702