File indexing completed on 2025-05-11 08:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifdef HAVE_CONFIG_H
0033 #include "config.h"
0034 #endif
0035
0036 #include <rtems.h>
0037
0038 #include <rtems/monitor.h>
0039
0040 #include <stdio.h>
0041 #include <string.h>
0042 #include <stdlib.h>
0043 #include <inttypes.h>
0044 #include <termios.h>
0045 #include <unistd.h>
0046
0047 #ifndef MONITOR_PROMPT
0048 #define MONITOR_PROMPT "rtems"
0049 #endif
0050
0051
0052
0053
0054
0055 #define KEYS_EXTENDED (0x8000)
0056 #define KEYS_NORMAL_MASK (0x00ff)
0057 #define KEYS_INS (0)
0058 #define KEYS_DEL (1)
0059 #define KEYS_UARROW (2)
0060 #define KEYS_DARROW (3)
0061 #define KEYS_LARROW (4)
0062 #define KEYS_RARROW (5)
0063 #define KEYS_HOME (6)
0064 #define KEYS_END (7)
0065 #define KEYS_F1 (8)
0066 #define KEYS_F2 (9)
0067 #define KEYS_F3 (10)
0068 #define KEYS_F4 (11)
0069 #define KEYS_F5 (12)
0070 #define KEYS_F6 (13)
0071 #define KEYS_F7 (14)
0072 #define KEYS_F8 (15)
0073 #define KEYS_F9 (16)
0074 #define KEYS_F10 (17)
0075
0076 #define RTEMS_COMMAND_BUFFER_SIZE (75)
0077
0078 static char monitor_prompt[32];
0079 static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
0080 static int pos;
0081 static int logged_in;
0082
0083
0084
0085
0086
0087 #define RTEMS_COMMAND_HISTORIES (20)
0088
0089 static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
0090 static int history_pos[RTEMS_COMMAND_HISTORIES];
0091 static int history;
0092 static int history_next;
0093
0094
0095
0096
0097
0098
0099
0100
0101 struct translation_table
0102 {
0103 char expecting;
0104 const struct translation_table *branch;
0105 unsigned int key;
0106 };
0107
0108 static const struct translation_table trans_two[] =
0109 {
0110 { '~', 0, KEYS_INS },
0111 { 0, 0, 0 }
0112 };
0113
0114 static const struct translation_table trans_three[] =
0115 {
0116 { '~', 0, KEYS_DEL },
0117 { 0, 0, 0 }
0118 };
0119
0120 static const struct translation_table trans_tab_csi[] =
0121 {
0122 { '2', trans_two, 0 },
0123 { '3', trans_three, 0 },
0124 { 'A', 0, KEYS_UARROW },
0125 { 'B', 0, KEYS_DARROW },
0126 { 'D', 0, KEYS_LARROW },
0127 { 'C', 0, KEYS_RARROW },
0128 { 'F', 0, KEYS_END },
0129 { 'H', 0, KEYS_HOME },
0130 { 0, 0, 0 }
0131 };
0132
0133 static const struct translation_table trans_tab_O[] =
0134 {
0135 { '1', 0, KEYS_F1 },
0136 { '2', 0, KEYS_F2 },
0137 { '3', 0, KEYS_F3 },
0138 { '4', 0, KEYS_F4 },
0139 { '5', 0, KEYS_F5 },
0140 { '6', 0, KEYS_F6 },
0141 { '7', 0, KEYS_F7 },
0142 { '8', 0, KEYS_F8 },
0143 { '9', 0, KEYS_F9 },
0144 { ':', 0, KEYS_F10 },
0145 { 'P', 0, KEYS_F1 },
0146 { 'Q', 0, KEYS_F2 },
0147 { 'R', 0, KEYS_F3 },
0148 { 'S', 0, KEYS_F4 },
0149 { 'T', 0, KEYS_F5 },
0150 { 'U', 0, KEYS_F6 },
0151 { 'V', 0, KEYS_F7 },
0152 { 'W', 0, KEYS_F8 },
0153 { 'X', 0, KEYS_F9 },
0154 { 'Y', 0, KEYS_F10 },
0155 { 0, 0, 0 }
0156 };
0157
0158 static const struct translation_table trans_tab[] =
0159 {
0160 { '[', trans_tab_csi, 0 },
0161 { 'O', trans_tab_O, 0 },
0162 { 0, 0, 0 }
0163 };
0164
0165
0166
0167
0168
0169
0170
0171
0172 static unsigned int
0173 rtems_monitor_getchar (void)
0174 {
0175 const struct translation_table *translation = 0;
0176 for (;;)
0177 {
0178 char c = getchar ();
0179 if (c == 27)
0180 translation = trans_tab;
0181 else
0182 {
0183
0184
0185
0186
0187 if (translation)
0188 {
0189
0190
0191
0192
0193
0194 int index = 0;
0195 int branched = 0;
0196 while ((translation[index].expecting != '\0') ||
0197 (translation[index].key != '\0'))
0198 {
0199 if (translation[index].expecting == c)
0200 {
0201
0202
0203
0204 if (translation[index].branch == 0)
0205 return KEYS_EXTENDED | translation[index].key;
0206 else
0207 {
0208 translation = translation[index].branch;
0209 branched = 1;
0210 break;
0211 }
0212 }
0213 index++;
0214 }
0215
0216
0217
0218 if (!branched)
0219 translation = 0;
0220 }
0221 else
0222 return c;
0223 }
0224 }
0225 }
0226
0227
0228
0229
0230
0231 static int
0232 rtems_monitor_line_editor (
0233 char *command
0234 )
0235 {
0236 int repeating = 0;
0237
0238 memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
0239 history = history_next;
0240 pos = 0;
0241
0242 if (!logged_in)
0243 fprintf(stdout,"\nMonitor ready, press enter to login.\n\n");
0244 else
0245 fprintf(stdout,"%s $ ", monitor_prompt);
0246
0247 while (1)
0248 {
0249 unsigned int extended_key;
0250 char c;
0251
0252 fflush (stdout);
0253
0254 extended_key = rtems_monitor_getchar ();
0255 c = extended_key & KEYS_NORMAL_MASK;
0256
0257
0258
0259
0260 extended_key &= ~KEYS_NORMAL_MASK;
0261
0262 if (!extended_key && !logged_in)
0263 {
0264 if (c == '\n')
0265 {
0266 logged_in = 1;
0267
0268
0269
0270
0271 fprintf(stdout,"%s $ ", monitor_prompt);
0272 }
0273 }
0274 else
0275 {
0276 if (extended_key)
0277 {
0278 switch (c)
0279 {
0280 case KEYS_END:
0281 fprintf(stdout, "%s", buffer + pos);
0282 pos = (int) strlen (buffer);
0283 break;
0284
0285 case KEYS_HOME:
0286 fprintf(stdout,"\r%s $ ", monitor_prompt);
0287 pos = 0;
0288 break;
0289
0290 case KEYS_LARROW:
0291 if (pos > 0)
0292 {
0293 pos--;
0294 putchar ('\b');
0295 }
0296 break;
0297
0298 case KEYS_RARROW:
0299 if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
0300 {
0301 putchar (buffer[pos]);
0302 pos++;
0303 }
0304 break;
0305
0306 case KEYS_UARROW:
0307
0308
0309
0310
0311 if (history)
0312 {
0313 int end;
0314 int bs;
0315 if (history == history_next)
0316 {
0317 memcpy (history_buffer[history_next], buffer,
0318 RTEMS_COMMAND_BUFFER_SIZE);
0319 history_pos[history_next] = pos;
0320 }
0321 history--;
0322 memcpy (buffer, history_buffer[history],
0323 RTEMS_COMMAND_BUFFER_SIZE);
0324 pos = history_pos[history];
0325 fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
0326 fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
0327 end = (int) strlen (buffer);
0328 for (bs = 0; bs < (end - pos); bs++)
0329 putchar ('\b');
0330 }
0331 break;
0332
0333 case KEYS_DARROW:
0334 if (history < history_next)
0335 {
0336 int end;
0337 int bs;
0338 history++;
0339 memcpy (buffer, history_buffer[history],
0340 RTEMS_COMMAND_BUFFER_SIZE);
0341 pos = history_pos[history];
0342 fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
0343 fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
0344 end = (int) strlen (buffer);
0345 for (bs = 0; bs < (end - pos); bs++)
0346 putchar ('\b');
0347 }
0348 break;
0349
0350 case KEYS_DEL:
0351 if (buffer[pos] != '\0')
0352 {
0353 int end;
0354 int bs;
0355 memmove (&buffer[pos], &buffer[pos + 1],
0356 strlen (&buffer[pos + 1]) + 1);
0357 fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
0358 end = (int) strlen (buffer);
0359 for (bs = 0; bs < (end - pos); bs++)
0360 putchar ('\b');
0361 }
0362 break;
0363 }
0364 }
0365 else
0366 {
0367 switch (c)
0368 {
0369 case '\b':
0370 case '\x7e':
0371 case '\x7f':
0372 if (pos > 0)
0373 {
0374 int bs;
0375 pos--;
0376
0377
0378
0379
0380
0381 memmove(
0382 buffer + pos,
0383 buffer + pos + 1,
0384 RTEMS_COMMAND_BUFFER_SIZE - pos - 1
0385 );
0386 buffer[RTEMS_COMMAND_BUFFER_SIZE - 1] = '\0';
0387 fprintf(stdout,"\b%s \b", buffer + pos);
0388 for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
0389 putchar ('\b');
0390 }
0391 break;
0392
0393 case '\n':
0394
0395
0396
0397 fprintf(stdout,"\n");
0398 repeating = 1;
0399
0400
0401
0402
0403 if (strlen (buffer))
0404 {
0405 if (history_next && (history == history_next))
0406 {
0407
0408
0409
0410
0411 if (strcmp (history_buffer[history_next - 1], buffer))
0412 repeating = 0;
0413 }
0414 else
0415 repeating = 0;
0416 }
0417 if (!repeating)
0418 {
0419 memcpy (history_buffer[history_next], buffer,
0420 RTEMS_COMMAND_BUFFER_SIZE);
0421 history_pos[history_next] = pos;
0422 if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
0423 history_next++;
0424 else
0425 {
0426 memmove (history_buffer[0], history_buffer[1],
0427 RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
0428 memmove (&history_pos[0], &history_pos[1],
0429 sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
0430 }
0431 }
0432 else
0433 {
0434 #ifdef ENABLE_ENTER_REPEATS
0435 if (history_next)
0436 memcpy (buffer, history_buffer[history_next - 1],
0437 RTEMS_COMMAND_BUFFER_SIZE);
0438 #endif
0439 }
0440 memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
0441 return repeating;
0442 break;
0443
0444 default:
0445 if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
0446 (c >= ' ') && (c <= 'z'))
0447 {
0448 int end;
0449 end = strlen (buffer);
0450 if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
0451 {
0452 int ch, bs;
0453 for (ch = end; ch > pos; ch--)
0454 buffer[ch] = buffer[ch - 1];
0455 fprintf(stdout, "%s", buffer + pos);
0456 for (bs = 0; bs < (end - pos + 1); bs++)
0457 putchar ('\b');
0458 }
0459 buffer[pos++] = c;
0460 if (pos > end)
0461 buffer[pos] = '\0';
0462 putchar (c);
0463 }
0464 break;
0465 }
0466 }
0467 }
0468 }
0469 }
0470
0471
0472
0473
0474
0475
0476
0477 int
0478 rtems_monitor_make_argv(
0479 char *cp,
0480 int *argc_p,
0481 char **argv)
0482 {
0483 int argc = 0;
0484
0485 while ((cp = strtok(cp, " \t\n\r")))
0486 {
0487 argv[argc++] = cp;
0488 cp = (char *) NULL;
0489 }
0490 argv[argc] = (char *) NULL;
0491
0492 return *argc_p = argc;
0493 }
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 int
0504 rtems_monitor_command_read(char *command,
0505 int *argc,
0506 char **argv)
0507 {
0508 char *env_prompt;
0509
0510 env_prompt = getenv("RTEMS_MONITOR_PROMPT");
0511
0512
0513
0514
0515 #if defined(RTEMS_MULTIPROCESSING)
0516 if (!rtems_configuration_get_user_multiprocessing_table ())
0517 snprintf (monitor_prompt, sizeof(monitor_prompt), "%s",
0518 (env_prompt == NULL) ? MONITOR_PROMPT: env_prompt);
0519 else
0520 #endif
0521 if (rtems_monitor_default_node != rtems_monitor_node)
0522 snprintf (monitor_prompt, sizeof(monitor_prompt),
0523 "%" PRId32 "-%s-%" PRId32 "", rtems_monitor_node,
0524 (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt,
0525 rtems_monitor_default_node);
0526 else
0527 snprintf (monitor_prompt, sizeof(monitor_prompt),
0528 "%" PRId32 "-%s", rtems_monitor_node,
0529 (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt);
0530
0531 rtems_monitor_line_editor (command);
0532
0533 return rtems_monitor_make_argv (command, argc, argv);
0534 }
0535
0536
0537
0538
0539
0540 void
0541 rtems_monitor_task(
0542 rtems_task_argument monitor_flags
0543 )
0544 {
0545 char command_buffer[513];
0546 int argc;
0547 char *argv[64];
0548 bool verbose = false;
0549 struct termios term;
0550
0551
0552
0553
0554
0555 if (tcgetattr (STDIN_FILENO, &term) < 0)
0556 {
0557 fprintf(stdout,"rtems-monitor: cannot get terminal attributes.\n");
0558 }
0559 else
0560 {
0561
0562
0563
0564
0565 term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
0566
0567
0568
0569
0570
0571
0572 term.c_lflag &= ~(INPCK | ISTRIP | IXON);
0573 term.c_cc[VMIN] = 1;
0574 term.c_cc[VTIME] = 0;
0575
0576 if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
0577 {
0578 fprintf(stdout,"cannot set terminal attributes\n");
0579 }
0580 }
0581
0582 if (!(monitor_flags & RTEMS_MONITOR_NOSYMLOAD)) {
0583 rtems_monitor_symbols_loadup();
0584 }
0585
0586 if (monitor_flags & RTEMS_MONITOR_SUSPEND)
0587 (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
0588
0589 for (;;)
0590 {
0591 const rtems_monitor_command_entry_t *command;
0592
0593 if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
0594 continue;
0595 if (argc < 1
0596 || (command = rtems_monitor_command_lookup(argv [0])) == 0) {
0597
0598 fprintf(stdout,"Unrecognised command; try 'help'\n");
0599 continue;
0600 }
0601
0602 command->command_function(argc, argv, &command->command_arg, verbose);
0603
0604 fflush(stdout);
0605 }
0606 }
0607
0608
0609 void
0610 rtems_monitor_kill(void)
0611 {
0612 if (rtems_monitor_task_id)
0613 rtems_task_delete(rtems_monitor_task_id);
0614 rtems_monitor_task_id = 0;
0615
0616 rtems_monitor_server_kill();
0617 }
0618
0619 void
0620 rtems_monitor_init(
0621 uint32_t monitor_flags
0622 )
0623 {
0624 rtems_status_code status;
0625
0626 rtems_monitor_kill();
0627
0628 status = rtems_task_create(RTEMS_MONITOR_NAME,
0629 1,
0630 RTEMS_MINIMUM_STACK_SIZE * 2,
0631 RTEMS_INTERRUPT_LEVEL(0),
0632 RTEMS_DEFAULT_ATTRIBUTES,
0633 &rtems_monitor_task_id);
0634 if (status != RTEMS_SUCCESSFUL)
0635 {
0636 rtems_error(status, "could not create monitor task");
0637 return;
0638 }
0639
0640 rtems_monitor_node = rtems_object_id_get_node(rtems_monitor_task_id);
0641 rtems_monitor_default_node = rtems_monitor_node;
0642
0643 rtems_monitor_server_init(monitor_flags);
0644
0645 if (!(monitor_flags & RTEMS_MONITOR_NOTASK)) {
0646
0647
0648
0649 status = rtems_task_start(
0650 rtems_monitor_task_id, rtems_monitor_task, monitor_flags);
0651 if (status != RTEMS_SUCCESSFUL) {
0652 rtems_error(status, "could not start monitor");
0653 return;
0654 }
0655 }
0656 }