diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-09-10 13:43:54 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-09-10 13:43:54 +0100 |
commit | 7a7379aae55b17e0c9525b60d5cdee83769e7d3a (patch) | |
tree | acb3f71c7779e94cad11b1900f2066a5fc7d0cee | |
parent | 05f7921b1d89aa8178d9d33e6ff8c7f592ebedc5 (diff) |
semihosting tests: Add test of EXIT_EXTENDED
Add a minimal test of EXIT_EXTENDED if the implementation
provides it. Since using it at all exits the test, this is
not really possible to test properly in this single-binary
test setup, so we just use it for the final exit-success
if we can.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | semihosting.c | 15 | ||||
-rw-r--r-- | semihosting.h | 4 | ||||
-rw-r--r-- | usertest.c | 22 |
3 files changed, 41 insertions, 0 deletions
diff --git a/semihosting.c b/semihosting.c index 9c284af..7a0ee0c 100644 --- a/semihosting.c +++ b/semihosting.c @@ -176,6 +176,21 @@ void semi_exit(int subcode) while(1); /* should not be reached */ } +void semi_exit_extended(int subcode) +{ + /* If present, this always allows a subcode to be reported. */ + struct { + intptr_t reason; + intptr_t subcode; + } args; + + args.reason = REPORTEXC_REASON_APP_EXIT; + args.subcode = subcode; + __semi_call(SYS_EXIT_EXTENDED, &args); + + while(1); /* should not be reached */ +} + void semi_fatal(char const *message) { semi_write0(message); diff --git a/semihosting.h b/semihosting.h index f8c4e7b..06cda8d 100644 --- a/semihosting.h +++ b/semihosting.h @@ -36,6 +36,7 @@ #define SYS_GET_CMDLINE 0x15 #define SYS_REPORTEXC 0x18 #define REPORTEXC_REASON_APP_EXIT 0x20026 +#define SYS_EXIT_EXTENDED 0x20 #define SEMIHOSTING_SVC 0x123456 /* SVC comment field for semihosting */ #define FEATURE_DETECT_FILE ":semihosting-features" @@ -43,6 +44,8 @@ #define SHFB_MAGIC_1 0x48 #define SHFB_MAGIC_2 0x46 #define SHFB_MAGIC_3 0x42 +#define SH_EXT_EXIT_EXTENDED (1 << 0) +#define SH_EXT_STDOUT_STDERR (1 << 1) #ifndef __ASSEMBLER__ @@ -61,6 +64,7 @@ int semi_get_cmdline(char *buffer, int size, int *length); int semi_reportexc(int reason, int subcode); void semi_fatal(char const *message); void semi_exit(int subcode); +void semi_exit_extended(int subcode); /* * semi_load_file: * On entry *dest should be the buffer to write the data to, and @@ -43,6 +43,9 @@ const char file[] = "Small file of text data for test.\n"; #define TESTWRITE_FILE "tempdata.txt" const char writedata[] = "Data to write to temporary file.\n"; +int has_exit_extended; +int has_stdout_stderr; + static int test_istty(void) { int fd; @@ -245,6 +248,20 @@ static int test_feature_detect(void) semi_write0("PASS semihosting features file read successfully\n"); + /* Capture the feature flags we care about here for later tests */ + if (filebuf[4] & SH_EXT_EXIT_EXTENDED) { + semi_write0("INFO implementation supports EXIT_EXTENDED\n"); + has_exit_extended++; + } + if (filebuf[4] & SH_EXT_STDOUT_STDERR) { + semi_write0("INFO implementation supports STDOUT_STDERR\n"); + has_stdout_stderr++; + } + if (filebuf[4] & ~(SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR)) { + semi_write0("INFO implementation supports extensions " + "this test doesn't know about\n"); + } + if (semi_istty(fd)) { semi_write0("FAIL semihosting features file is a TTY?\n"); } else { @@ -350,6 +367,11 @@ int main(void) } semi_write0("ALL TESTS PASSED\n"); + + /* If we have EXIT_EXTENDED then use it */ + if (has_exit_extended) { + semi_exit_extended(0); + } semi_exit(0); /* not reached */ } |