1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <reent.h>
15 #include <sys/fcntl.h>
16 #include "sdkconfig.h"
17 #include "esp_rom_uart.h"
18 
syscall_not_implemented(struct _reent * r,...)19 static int syscall_not_implemented(struct _reent *r, ...)
20 {
21     __errno_r(r) = ENOSYS;
22     return -1;
23 }
24 
syscall_not_implemented_aborts(void)25 static int syscall_not_implemented_aborts(void)
26 {
27     abort();
28 }
29 
_write_r_console(struct _reent * r,int fd,const void * data,size_t size)30 ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t size)
31 {
32     const char* cdata = (const char*) data;
33     if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
34         for (size_t i = 0; i < size; ++i) {
35             esp_rom_uart_tx_one_char(cdata[i]);
36         }
37         return size;
38     }
39     __errno_r(r) = EBADF;
40     return -1;
41 }
42 
_read_r_console(struct _reent * r,int fd,void * data,size_t size)43 ssize_t _read_r_console(struct _reent *r, int fd, void * data, size_t size)
44 {
45     char* cdata = (char*) data;
46     if (fd == STDIN_FILENO) {
47         size_t received;
48         for (received = 0; received < size; ++received) {
49             int status = esp_rom_uart_rx_one_char((uint8_t*) &cdata[received]);
50             if (status != 0) {
51                 break;
52             }
53         }
54         if (received == 0) {
55             errno = EWOULDBLOCK;
56             return -1;
57         }
58         return received;
59     }
60     __errno_r(r) = EBADF;
61     return -1;
62 }
63 
_fstat_r_console(struct _reent * r,int fd,struct stat * st)64 static ssize_t _fstat_r_console(struct _reent *r, int fd, struct stat * st)
65 {
66     if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
67         memset(st, 0, sizeof(*st));
68         /* This needs to be set so that stdout and stderr are line buffered. */
69         st->st_mode = S_IFCHR;
70         return 0;
71     }
72     __errno_r(r) = EBADF;
73     return -1;
74 }
75 
76 
77 /* The following weak definitions of syscalls will be used unless
78  * another definition is provided. That definition may come from
79  * VFS, LWIP, or the application.
80  */
81 ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size)
82     __attribute__((weak,alias("_read_r_console")));
83 ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size)
84     __attribute__((weak,alias("_write_r_console")));
85 int _fstat_r (struct _reent *r, int fd, struct stat *st)
86     __attribute__((weak,alias("_fstat_r_console")));
87 
88 
89 /* The aliases below are to "syscall_not_implemented", which
90  * doesn't have the same signature as the original function.
91  * Disable type mismatch warnings for this reason.
92  */
93 #if defined(__GNUC__) && !defined(__clang__)
94 #pragma GCC diagnostic push
95 #pragma GCC diagnostic ignored "-Wattribute-alias"
96 #endif
97 
98 int _open_r(struct _reent *r, const char * path, int flags, int mode)
99     __attribute__((weak,alias("syscall_not_implemented")));
100 int _close_r(struct _reent *r, int fd)
101     __attribute__((weak,alias("syscall_not_implemented")));
102 off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode)
103     __attribute__((weak,alias("syscall_not_implemented")));
104 int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
105     __attribute__((weak,alias("syscall_not_implemented")));
106 int _stat_r(struct _reent *r, const char * path, struct stat * st)
107     __attribute__((weak,alias("syscall_not_implemented")));
108 int _link_r(struct _reent *r, const char* n1, const char* n2)
109     __attribute__((weak,alias("syscall_not_implemented")));
110 int _unlink_r(struct _reent *r, const char *path)
111     __attribute__((weak,alias("syscall_not_implemented")));
112 int _rename_r(struct _reent *r, const char *src, const char *dst)
113     __attribute__((weak,alias("syscall_not_implemented")));
114 int _isatty_r(struct _reent *r, int fd)
115     __attribute__((weak,alias("syscall_not_implemented")));
116 
117 
118 /* These functions are not expected to be overridden */
119 int _system_r(struct _reent *r, const char *str)
120     __attribute__((alias("syscall_not_implemented")));
121 int raise(int sig)
122     __attribute__((alias("syscall_not_implemented_aborts")));
123 int _raise_r(struct _reent *r, int sig)
124     __attribute__((alias("syscall_not_implemented_aborts")));
125 void* _sbrk_r(struct _reent *r, ptrdiff_t sz)
126     __attribute__((alias("syscall_not_implemented_aborts")));
127 int _getpid_r(struct _reent *r)
128     __attribute__((alias("syscall_not_implemented")));
129 int _kill_r(struct _reent *r, int pid, int sig)
130     __attribute__((alias("syscall_not_implemented")));
131 void _exit(int __status)
132     __attribute__((alias("syscall_not_implemented_aborts")));
133 
134 #if defined(__GNUC__) && !defined(__clang__)
135 #pragma GCC diagnostic pop
136 #endif
137 
138 /* Similar to syscall_not_implemented, but not taking struct _reent argument */
system(const char * str)139 int system(const char* str)
140 {
141     errno = ENOSYS;
142     return -1;
143 }
144 
145 /* Replaces newlib fcntl, which has been compiled without HAVE_FCNTL */
fcntl(int fd,int cmd,...)146 int fcntl(int fd, int cmd, ...)
147 {
148     va_list args;
149     va_start(args, cmd);
150     int arg = va_arg(args, int);
151     va_end(args);
152     struct _reent* r = __getreent();
153     return _fcntl_r(r, fd, cmd, arg);
154 }
155 
156 /* No-op function, used to force linking this file,
157    instead of the syscalls implementation from libgloss.
158  */
newlib_include_syscalls_impl(void)159 void newlib_include_syscalls_impl(void)
160 {
161 }
162