| #include <stdint.h> |
| |
| #include "semihosting.h" |
| |
| size_t strlen(const char *buf) |
| { |
| int len = 0; |
| while (buf[len]) |
| len++; |
| return len; |
| } |
| |
| #define O_RDONLY 0 |
| #define O_WRONLY 1 |
| #define O_RDWR 2 |
| #define O_RDWR 2 |
| #define O_TRUNC 0x0800 |
| |
| int errno; |
| |
| /* These semihosting functions came from the Freedom Metal source. */ |
| static int open(const char *name, int flags, int mode) { |
| int semiflags = 0; |
| |
| switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { |
| case O_RDONLY: |
| semiflags = 0; /* 'r' */ |
| break; |
| case O_WRONLY: |
| if (flags & O_TRUNC) |
| semiflags = 4; /* 'w' */ |
| else |
| semiflags = 8; /* 'a' */ |
| break; |
| default: |
| if (flags & O_TRUNC) |
| semiflags = 6; /* 'w+' */ |
| else |
| semiflags = 10; /* 'a+' */ |
| break; |
| } |
| |
| volatile semihostparam_t arg = {.param1 = (uintptr_t)name, |
| .param2 = (uintptr_t)semiflags, |
| .param3 = (uintptr_t)strlen(name)}; |
| |
| int ret = (int)semihost_call_host(SEMIHOST_SYS_OPEN, (uintptr_t)&arg); |
| if (ret == -1) |
| errno = semihost_call_host(SEMIHOST_SYS_ERRNO, 0); |
| return ret; |
| } |
| |
| static ssize_t write(int file, const void *ptr, size_t len) |
| { |
| volatile semihostparam_t arg = {.param1 = (uintptr_t)file, |
| .param2 = (uintptr_t)ptr, |
| .param3 = (uintptr_t)len}; |
| ssize_t ret = |
| (ssize_t)semihost_call_host(SEMIHOST_SYS_WRITE, (uintptr_t)&arg); |
| |
| return (len - ret); |
| } |
| |
| int main() |
| { |
| char *filename = NULL; |
| const char *message = "Hello, world!\n"; |
| int fd; |
| |
| begin: |
| fd = open(filename, O_WRONLY, 0644); |
| write(fd, message, strlen(message)); |
| } |