|
15 | 15 | #include "sysjump.h" |
16 | 16 | #include "system.h" |
17 | 17 | #include "task.h" |
| 18 | +#include "test_util.h" |
18 | 19 | #include "timer.h" |
19 | 20 | #include "uart.h" |
20 | 21 | #include "usb_console.h" |
@@ -366,13 +367,56 @@ ENABLE_CLANG_WARNING("-Winfinite-recursion") |
366 | 367 | ENABLE_GCC_WARNING("-Winfinite-recursion") |
367 | 368 | #endif |
368 | 369 |
|
| 370 | +#ifdef CONFIG_CMD_CRASH_NESTED |
| 371 | +static bool command_crash_nested_enabled; |
| 372 | +static int command_crash_nested_argc; |
| 373 | +static const char **command_crash_nested_argv; |
| 374 | +test_mockable_static void command_crash_nested_enable(int argc, |
| 375 | + const char **argv) |
| 376 | +{ |
| 377 | + command_crash_nested_argc = argc; |
| 378 | + command_crash_nested_argv = argv; |
| 379 | + command_crash_nested_enabled = true; |
| 380 | +} |
| 381 | +test_mockable_static void command_crash_nested_disable(void) |
| 382 | +{ |
| 383 | + command_crash_nested_enabled = false; |
| 384 | +} |
| 385 | +/* Forward declare command_crash so it can be referenced in |
| 386 | + * command_crash_nested_handler. |
| 387 | + */ |
| 388 | +static int command_crash(int argc, const char **argv); |
| 389 | +/* |
| 390 | + * Called from the panic handler. |
| 391 | + * Triggers a nested crash when enabled. |
| 392 | + */ |
| 393 | +int command_crash_nested_handler(void) |
| 394 | +{ |
| 395 | + if (!command_crash_nested_enabled) |
| 396 | + return EC_SUCCESS; |
| 397 | + /* Must be re-enabled after each run */ |
| 398 | + command_crash_nested_enabled = false; |
| 399 | + /* Decrement argc and shift argv */ |
| 400 | + return command_crash(command_crash_nested_argc - 1, |
| 401 | + command_crash_nested_argv + 1); |
| 402 | +} |
| 403 | +#endif /* CONFIG_CMD_CRASH_NESTED */ |
| 404 | + |
369 | 405 | /*****************************************************************************/ |
370 | 406 | /* Console commands */ |
371 | 407 | static int command_crash(int argc, const char **argv) |
372 | 408 | { |
373 | 409 | if (argc < 2) |
374 | 410 | return EC_ERROR_PARAM1; |
375 | 411 |
|
| 412 | + if (argc > 2) { |
| 413 | + if (IS_ENABLED(CONFIG_CMD_CRASH_NESTED)) { |
| 414 | + command_crash_nested_enable(argc, argv); |
| 415 | + } else { |
| 416 | + return EC_ERROR_PARAM_COUNT; |
| 417 | + } |
| 418 | + } |
| 419 | + |
376 | 420 | if (!strcasecmp(argv[1], "assert")) { |
377 | 421 | ASSERT(0); |
378 | 422 | } else if (!strcasecmp(argv[1], "divzero")) { |
@@ -417,17 +461,28 @@ static int command_crash(int argc, const char **argv) |
417 | 461 | cflush(); |
418 | 462 | ccprintf("%08x\n", *(volatile unsigned int *)null_ptr); |
419 | 463 | } else { |
| 464 | + /* Disable nested crash on error */ |
| 465 | + if (IS_ENABLED(CONFIG_CMD_CRASH_NESTED)) |
| 466 | + command_crash_nested_disable(); |
420 | 467 | return EC_ERROR_PARAM1; |
421 | 468 | } |
422 | 469 |
|
| 470 | + /* Disable nested crash on error */ |
| 471 | + if (IS_ENABLED(CONFIG_CMD_CRASH_NESTED)) |
| 472 | + command_crash_nested_disable(); |
| 473 | + |
423 | 474 | /* Everything crashes, so shouldn't get back here */ |
424 | 475 | return EC_ERROR_UNKNOWN; |
425 | 476 | } |
426 | 477 |
|
427 | 478 | DECLARE_CONSOLE_COMMAND(crash, command_crash, |
428 | 479 | "[assert | divzero | udivzero | stack" |
429 | 480 | " | unaligned | watchdog | hang | null]", |
430 | | - "Crash the system (for testing)"); |
| 481 | + "Crash the system (for testing)." |
| 482 | +#ifndef CONFIG_CMD_CRASH_NESTED |
| 483 | + " Repeat argument for nested crashes." |
| 484 | +#endif /* CONFIG_CMD_CRASH_NESTED */ |
| 485 | +); |
431 | 486 |
|
432 | 487 | #ifdef TEST_BUILD |
433 | 488 | int test_command_crash(int argc, const char **argv) |
|
0 commit comments