hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/kernel/debug/kdb/kdb_io.c
....@@ -49,14 +49,88 @@
4949 return 0;
5050 }
5151
52
-static int kdb_read_get_key(char *buffer, size_t bufsize)
52
+/**
53
+ * kdb_handle_escape() - validity check on an accumulated escape sequence.
54
+ * @buf: Accumulated escape characters to be examined. Note that buf
55
+ * is not a string, it is an array of characters and need not be
56
+ * nil terminated.
57
+ * @sz: Number of accumulated escape characters.
58
+ *
59
+ * Return: -1 if the escape sequence is unwanted, 0 if it is incomplete,
60
+ * otherwise it returns a mapped key value to pass to the upper layers.
61
+ */
62
+static int kdb_handle_escape(char *buf, size_t sz)
63
+{
64
+ char *lastkey = buf + sz - 1;
65
+
66
+ switch (sz) {
67
+ case 1:
68
+ if (*lastkey == '\e')
69
+ return 0;
70
+ break;
71
+
72
+ case 2: /* \e<something> */
73
+ if (*lastkey == '[')
74
+ return 0;
75
+ break;
76
+
77
+ case 3:
78
+ switch (*lastkey) {
79
+ case 'A': /* \e[A, up arrow */
80
+ return 16;
81
+ case 'B': /* \e[B, down arrow */
82
+ return 14;
83
+ case 'C': /* \e[C, right arrow */
84
+ return 6;
85
+ case 'D': /* \e[D, left arrow */
86
+ return 2;
87
+ case '1': /* \e[<1,3,4>], may be home, del, end */
88
+ case '3':
89
+ case '4':
90
+ return 0;
91
+ }
92
+ break;
93
+
94
+ case 4:
95
+ if (*lastkey == '~') {
96
+ switch (buf[2]) {
97
+ case '1': /* \e[1~, home */
98
+ return 1;
99
+ case '3': /* \e[3~, del */
100
+ return 4;
101
+ case '4': /* \e[4~, end */
102
+ return 5;
103
+ }
104
+ }
105
+ break;
106
+ }
107
+
108
+ return -1;
109
+}
110
+
111
+/**
112
+ * kdb_getchar() - Read a single character from a kdb console (or consoles).
113
+ *
114
+ * Other than polling the various consoles that are currently enabled,
115
+ * most of the work done in this function is dealing with escape sequences.
116
+ *
117
+ * An escape key could be the start of a vt100 control sequence such as \e[D
118
+ * (left arrow) or it could be a character in its own right. The standard
119
+ * method for detecting the difference is to wait for 2 seconds to see if there
120
+ * are any other characters. kdb is complicated by the lack of a timer service
121
+ * (interrupts are off), by multiple input sources. Escape sequence processing
122
+ * has to be done as states in the polling loop.
123
+ *
124
+ * Return: The key pressed or a control code derived from an escape sequence.
125
+ */
126
+char kdb_getchar(void)
53127 {
54128 #define ESCAPE_UDELAY 1000
55129 #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */
56
- char escape_data[5]; /* longest vt100 escape sequence is 4 bytes */
57
- char *ped = escape_data;
130
+ char buf[4]; /* longest vt100 escape sequence is 4 bytes */
131
+ char *pbuf = buf;
58132 int escape_delay = 0;
59
- get_char_func *f, *f_escape = NULL;
133
+ get_char_func *f, *f_prev = NULL;
60134 int key;
61135
62136 for (f = &kdb_poll_funcs[0]; ; ++f) {
....@@ -65,109 +139,37 @@
65139 touch_nmi_watchdog();
66140 f = &kdb_poll_funcs[0];
67141 }
68
- if (escape_delay == 2) {
69
- *ped = '\0';
70
- ped = escape_data;
71
- --escape_delay;
72
- }
73
- if (escape_delay == 1) {
74
- key = *ped++;
75
- if (!*ped)
76
- --escape_delay;
77
- break;
78
- }
142
+
79143 key = (*f)();
80144 if (key == -1) {
81145 if (escape_delay) {
82146 udelay(ESCAPE_UDELAY);
83
- --escape_delay;
147
+ if (--escape_delay == 0)
148
+ return '\e';
84149 }
85150 continue;
86151 }
87
- if (bufsize <= 2) {
88
- if (key == '\r')
89
- key = '\n';
90
- *buffer++ = key;
91
- *buffer = '\0';
92
- return -1;
93
- }
94
- if (escape_delay == 0 && key == '\e') {
152
+
153
+ /*
154
+ * When the first character is received (or we get a change
155
+ * input source) we set ourselves up to handle an escape
156
+ * sequences (just in case).
157
+ */
158
+ if (f_prev != f) {
159
+ f_prev = f;
160
+ pbuf = buf;
95161 escape_delay = ESCAPE_DELAY;
96
- ped = escape_data;
97
- f_escape = f;
98162 }
99
- if (escape_delay) {
100
- *ped++ = key;
101
- if (f_escape != f) {
102
- escape_delay = 2;
103
- continue;
104
- }
105
- if (ped - escape_data == 1) {
106
- /* \e */
107
- continue;
108
- } else if (ped - escape_data == 2) {
109
- /* \e<something> */
110
- if (key != '[')
111
- escape_delay = 2;
112
- continue;
113
- } else if (ped - escape_data == 3) {
114
- /* \e[<something> */
115
- int mapkey = 0;
116
- switch (key) {
117
- case 'A': /* \e[A, up arrow */
118
- mapkey = 16;
119
- break;
120
- case 'B': /* \e[B, down arrow */
121
- mapkey = 14;
122
- break;
123
- case 'C': /* \e[C, right arrow */
124
- mapkey = 6;
125
- break;
126
- case 'D': /* \e[D, left arrow */
127
- mapkey = 2;
128
- break;
129
- case '1': /* dropthrough */
130
- case '3': /* dropthrough */
131
- /* \e[<1,3,4>], may be home, del, end */
132
- case '4':
133
- mapkey = -1;
134
- break;
135
- }
136
- if (mapkey != -1) {
137
- if (mapkey > 0) {
138
- escape_data[0] = mapkey;
139
- escape_data[1] = '\0';
140
- }
141
- escape_delay = 2;
142
- }
143
- continue;
144
- } else if (ped - escape_data == 4) {
145
- /* \e[<1,3,4><something> */
146
- int mapkey = 0;
147
- if (key == '~') {
148
- switch (escape_data[2]) {
149
- case '1': /* \e[1~, home */
150
- mapkey = 1;
151
- break;
152
- case '3': /* \e[3~, del */
153
- mapkey = 4;
154
- break;
155
- case '4': /* \e[4~, end */
156
- mapkey = 5;
157
- break;
158
- }
159
- }
160
- if (mapkey > 0) {
161
- escape_data[0] = mapkey;
162
- escape_data[1] = '\0';
163
- }
164
- escape_delay = 2;
165
- continue;
166
- }
167
- }
168
- break; /* A key to process */
163
+
164
+ *pbuf++ = key;
165
+ key = kdb_handle_escape(buf, pbuf - buf);
166
+ if (key < 0) /* no escape sequence; return best character */
167
+ return buf[pbuf - buf == 2 ? 1 : 0];
168
+ if (key > 0)
169
+ return key;
169170 }
170
- return key;
171
+
172
+ unreachable();
171173 }
172174
173175 /*
....@@ -188,17 +190,7 @@
188190 * function. It is not reentrant - it relies on the fact
189191 * that while kdb is running on only one "master debug" cpu.
190192 * Remarks:
191
- *
192
- * The buffer size must be >= 2. A buffer size of 2 means that the caller only
193
- * wants a single key.
194
- *
195
- * An escape key could be the start of a vt100 control sequence such as \e[D
196
- * (left arrow) or it could be a character in its own right. The standard
197
- * method for detecting the difference is to wait for 2 seconds to see if there
198
- * are any other characters. kdb is complicated by the lack of a timer service
199
- * (interrupts are off), by multiple input sources and by the need to sometimes
200
- * return after just one key. Escape sequence processing has to be done as
201
- * states in the polling loop.
193
+ * The buffer size must be >= 2.
202194 */
203195
204196 static char *kdb_read(char *buffer, size_t bufsize)
....@@ -233,9 +225,7 @@
233225 *cp = '\0';
234226 kdb_printf("%s", buffer);
235227 poll_again:
236
- key = kdb_read_get_key(buffer, bufsize);
237
- if (key == -1)
238
- return buffer;
228
+ key = kdb_getchar();
239229 if (key != 9)
240230 tab = 0;
241231 switch (key) {
....@@ -446,7 +436,7 @@
446436 char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt)
447437 {
448438 if (prompt && kdb_prompt_str != prompt)
449
- strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
439
+ strscpy(kdb_prompt_str, prompt, CMD_BUFLEN);
450440 kdb_printf(kdb_prompt_str);
451441 kdb_nextline = 1; /* Prompt and input resets line number */
452442 return kdb_read(buffer, bufsize);
....@@ -552,6 +542,44 @@
552542 return 0;
553543 }
554544
545
+static void kdb_msg_write(const char *msg, int msg_len)
546
+{
547
+ struct console *c;
548
+ const char *cp;
549
+ int len;
550
+
551
+ if (msg_len == 0)
552
+ return;
553
+
554
+ cp = msg;
555
+ len = msg_len;
556
+
557
+ while (len--) {
558
+ dbg_io_ops->write_char(*cp);
559
+ cp++;
560
+ }
561
+
562
+ for_each_console(c) {
563
+ if (!(c->flags & CON_ENABLED))
564
+ continue;
565
+ if (c == dbg_io_ops->cons)
566
+ continue;
567
+ /*
568
+ * Set oops_in_progress to encourage the console drivers to
569
+ * disregard their internal spin locks: in the current calling
570
+ * context the risk of deadlock is a bigger problem than risks
571
+ * due to re-entering the console driver. We operate directly on
572
+ * oops_in_progress rather than using bust_spinlocks() because
573
+ * the calls bust_spinlocks() makes on exit are not appropriate
574
+ * for this calling context.
575
+ */
576
+ ++oops_in_progress;
577
+ c->write(c, msg, msg_len);
578
+ --oops_in_progress;
579
+ touch_nmi_watchdog();
580
+ }
581
+}
582
+
555583 int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
556584 {
557585 int diag;
....@@ -563,8 +591,7 @@
563591 int this_cpu, old_cpu;
564592 char *cp, *cp2, *cphold = NULL, replaced_byte = ' ';
565593 char *moreprompt = "more> ";
566
- struct console *c = console_drivers;
567
- unsigned long uninitialized_var(flags);
594
+ unsigned long flags;
568595
569596 /* Serialize kdb_printf if multiple cpus try to write at once.
570597 * But if any cpu goes recursive in kdb, just print the output,
....@@ -701,23 +728,11 @@
701728 */
702729 retlen = strlen(kdb_buffer);
703730 cp = (char *) printk_skip_headers(kdb_buffer);
704
- if (!dbg_kdb_mode && kgdb_connected) {
731
+ if (!dbg_kdb_mode && kgdb_connected)
705732 gdbstub_msg_write(cp, retlen - (cp - kdb_buffer));
706
- } else {
707
- if (dbg_io_ops && !dbg_io_ops->is_console) {
708
- len = retlen - (cp - kdb_buffer);
709
- cp2 = cp;
710
- while (len--) {
711
- dbg_io_ops->write_char(*cp2);
712
- cp2++;
713
- }
714
- }
715
- while (c) {
716
- c->write(c, cp, retlen - (cp - kdb_buffer));
717
- touch_nmi_watchdog();
718
- c = c->next;
719
- }
720
- }
733
+ else
734
+ kdb_msg_write(cp, retlen - (cp - kdb_buffer));
735
+
721736 if (logging) {
722737 saved_loglevel = console_loglevel;
723738 console_loglevel = CONSOLE_LOGLEVEL_SILENT;
....@@ -750,7 +765,7 @@
750765
751766 /* check for having reached the LINES number of printed lines */
752767 if (kdb_nextline >= linecount) {
753
- char buf1[16] = "";
768
+ char ch;
754769
755770 /* Watch out for recursion here. Any routine that calls
756771 * kdb_printf will come back through here. And kdb_read
....@@ -766,58 +781,43 @@
766781 moreprompt = "more> ";
767782
768783 kdb_input_flush();
769
- c = console_drivers;
770
-
771
- if (dbg_io_ops && !dbg_io_ops->is_console) {
772
- len = strlen(moreprompt);
773
- cp = moreprompt;
774
- while (len--) {
775
- dbg_io_ops->write_char(*cp);
776
- cp++;
777
- }
778
- }
779
- while (c) {
780
- c->write(c, moreprompt, strlen(moreprompt));
781
- touch_nmi_watchdog();
782
- c = c->next;
783
- }
784
+ kdb_msg_write(moreprompt, strlen(moreprompt));
784785
785786 if (logging)
786787 printk("%s", moreprompt);
787788
788
- kdb_read(buf1, 2); /* '2' indicates to return
789
- * immediately after getting one key. */
789
+ ch = kdb_getchar();
790790 kdb_nextline = 1; /* Really set output line 1 */
791791
792792 /* empty and reset the buffer: */
793793 kdb_buffer[0] = '\0';
794794 next_avail = kdb_buffer;
795795 size_avail = sizeof(kdb_buffer);
796
- if ((buf1[0] == 'q') || (buf1[0] == 'Q')) {
796
+ if ((ch == 'q') || (ch == 'Q')) {
797797 /* user hit q or Q */
798798 KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */
799799 KDB_STATE_CLEAR(PAGER);
800800 /* end of command output; back to normal mode */
801801 kdb_grepping_flag = 0;
802802 kdb_printf("\n");
803
- } else if (buf1[0] == ' ') {
803
+ } else if (ch == ' ') {
804804 kdb_printf("\r");
805805 suspend_grep = 1; /* for this recursion */
806
- } else if (buf1[0] == '\n') {
806
+ } else if (ch == '\n' || ch == '\r') {
807807 kdb_nextline = linecount - 1;
808808 kdb_printf("\r");
809809 suspend_grep = 1; /* for this recursion */
810
- } else if (buf1[0] == '/' && !kdb_grepping_flag) {
810
+ } else if (ch == '/' && !kdb_grepping_flag) {
811811 kdb_printf("\r");
812812 kdb_getstr(kdb_grep_string, KDB_GREP_STRLEN,
813813 kdbgetenv("SEARCHPROMPT") ?: "search> ");
814814 *strchrnul(kdb_grep_string, '\n') = '\0';
815815 kdb_grepping_flag += KDB_GREPPING_FLAG_SEARCH;
816816 suspend_grep = 1; /* for this recursion */
817
- } else if (buf1[0] && buf1[0] != '\n') {
818
- /* user hit something other than enter */
817
+ } else if (ch) {
818
+ /* user hit something unexpected */
819819 suspend_grep = 1; /* for this recursion */
820
- if (buf1[0] != '/')
820
+ if (ch != '/')
821821 kdb_printf(
822822 "\nOnly 'q', 'Q' or '/' are processed at "
823823 "more prompt, input ignored\n");