newlib_init.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "sdkconfig.h"
  7. #include <string.h>
  8. #include <stdbool.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <stdlib.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/signal.h>
  15. #include <sys/unistd.h>
  16. #include <sys/reent.h>
  17. #include <assert.h>
  18. #include "esp_newlib.h"
  19. #include "esp_attr.h"
  20. #include "soc/soc_caps.h"
  21. #include "esp_rom_caps.h"
  22. #if CONFIG_IDF_TARGET_ESP32
  23. #include "esp32/rom/libc_stubs.h"
  24. #elif CONFIG_IDF_TARGET_ESP32S2
  25. #include "esp32s2/rom/libc_stubs.h"
  26. #elif CONFIG_IDF_TARGET_ESP32S3
  27. #include "esp32s3/rom/libc_stubs.h"
  28. #elif CONFIG_IDF_TARGET_ESP32C3
  29. #include "esp32c3/rom/libc_stubs.h"
  30. #elif CONFIG_IDF_TARGET_ESP32C2
  31. #include "esp32c2/rom/libc_stubs.h"
  32. #elif CONFIG_IDF_TARGET_ESP32C6
  33. #include "esp32c6/rom/libc_stubs.h"
  34. #elif CONFIG_IDF_TARGET_ESP32H2
  35. #include "esp32h2/rom/libc_stubs.h"
  36. #elif CONFIG_IDF_TARGET_ESP32P4
  37. #include "esp32p4/rom/libc_stubs.h"
  38. #endif
  39. extern int _printf_float(struct _reent *rptr,
  40. void *pdata,
  41. FILE * fp,
  42. int (*pfunc) (struct _reent *, FILE *, const char *, size_t len),
  43. va_list * ap);
  44. extern int _scanf_float(struct _reent *rptr,
  45. void *pdata,
  46. FILE *fp,
  47. va_list *ap);
  48. static void raise_r_stub(struct _reent *rptr)
  49. {
  50. _raise_r(rptr, 0);
  51. }
  52. static void esp_cleanup_r (struct _reent *rptr)
  53. {
  54. if (_REENT_STDIN(rptr) != _REENT_STDIN(_GLOBAL_REENT)) {
  55. _fclose_r(rptr, _REENT_STDIN(rptr));
  56. }
  57. if (_REENT_STDOUT(rptr) != _REENT_STDOUT(_GLOBAL_REENT)) {
  58. _fclose_r(rptr, _REENT_STDOUT(rptr));
  59. }
  60. if (_REENT_STDERR(rptr) !=_REENT_STDERR(_GLOBAL_REENT)) {
  61. _fclose_r(rptr, _REENT_STDERR(rptr));
  62. }
  63. }
  64. static struct syscall_stub_table s_stub_table = {
  65. .__getreent = &__getreent,
  66. ._malloc_r = &_malloc_r,
  67. ._free_r = &_free_r,
  68. ._realloc_r = &_realloc_r,
  69. ._calloc_r = &_calloc_r,
  70. ._abort = &abort,
  71. ._system_r = &_system_r,
  72. ._rename_r = &_rename_r,
  73. ._times_r = &_times_r,
  74. ._gettimeofday_r = &_gettimeofday_r,
  75. ._raise_r = &raise_r_stub,
  76. ._unlink_r = &_unlink_r,
  77. ._link_r = &_link_r,
  78. ._stat_r = &_stat_r,
  79. ._fstat_r = &_fstat_r,
  80. ._sbrk_r = &_sbrk_r,
  81. ._getpid_r = &_getpid_r,
  82. ._kill_r = &_kill_r,
  83. ._exit_r = NULL, // never called in ROM
  84. ._close_r = &_close_r,
  85. ._open_r = &_open_r,
  86. ._write_r = (int (*)(struct _reent *r, int, const void *, int)) &_write_r,
  87. ._lseek_r = (int (*)(struct _reent *r, int, int, int)) &_lseek_r,
  88. ._read_r = (int (*)(struct _reent *r, int, void *, int)) &_read_r,
  89. #if ESP_ROM_HAS_RETARGETABLE_LOCKING
  90. ._retarget_lock_init = &__retarget_lock_init,
  91. ._retarget_lock_init_recursive = &__retarget_lock_init_recursive,
  92. ._retarget_lock_close = &__retarget_lock_close,
  93. ._retarget_lock_close_recursive = &__retarget_lock_close_recursive,
  94. ._retarget_lock_acquire = &__retarget_lock_acquire,
  95. ._retarget_lock_acquire_recursive = &__retarget_lock_acquire_recursive,
  96. ._retarget_lock_try_acquire = &__retarget_lock_try_acquire,
  97. ._retarget_lock_try_acquire_recursive = &__retarget_lock_try_acquire_recursive,
  98. ._retarget_lock_release = &__retarget_lock_release,
  99. ._retarget_lock_release_recursive = &__retarget_lock_release_recursive,
  100. #else
  101. ._lock_init = &_lock_init,
  102. ._lock_init_recursive = &_lock_init_recursive,
  103. ._lock_close = &_lock_close,
  104. ._lock_close_recursive = &_lock_close_recursive,
  105. ._lock_acquire = &_lock_acquire,
  106. ._lock_acquire_recursive = &_lock_acquire_recursive,
  107. ._lock_try_acquire = &_lock_try_acquire,
  108. ._lock_try_acquire_recursive = &_lock_try_acquire_recursive,
  109. ._lock_release = &_lock_release,
  110. ._lock_release_recursive = &_lock_release_recursive,
  111. #endif
  112. #ifdef CONFIG_NEWLIB_NANO_FORMAT
  113. ._printf_float = &_printf_float,
  114. ._scanf_float = &_scanf_float,
  115. #else
  116. ._printf_float = NULL,
  117. ._scanf_float = NULL,
  118. #endif
  119. #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 \
  120. || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
  121. /* TODO IDF-2570 : mark that this assert failed in ROM, to avoid confusion between IDF & ROM
  122. assertion failures (as function names & source file names will be similar)
  123. */
  124. .__assert_func = __assert_func,
  125. /* We don't expect either ROM code to ever call __sinit, so it's implemented as abort() for now.
  126. __sinit may be called in IDF side only if /dev/console used as input/output. It called only
  127. once for _GLOBAL_REENT. Then reuse std file pointers from _GLOBAL_REENT in another reents.
  128. See esp_newlib_init() and esp_reent_init() for details.
  129. */
  130. .__sinit = (void *)abort,
  131. ._cleanup_r = &esp_cleanup_r,
  132. #endif
  133. };
  134. void esp_newlib_init(void)
  135. {
  136. #if CONFIG_IDF_TARGET_ESP32
  137. syscall_table_ptr_pro = syscall_table_ptr_app = &s_stub_table;
  138. #elif CONFIG_IDF_TARGET_ESP32S2
  139. syscall_table_ptr_pro = &s_stub_table;
  140. #else
  141. syscall_table_ptr = &s_stub_table;
  142. #endif
  143. #if __NEWLIB__ > 4 || ( __NEWLIB__ == 4 && __NEWLIB_MINOR__ > 1 ) /* TODO: IDF-8134 */
  144. memset(&__sglue, 0, sizeof(__sglue));
  145. _global_impure_ptr = _GLOBAL_REENT;
  146. #else
  147. static struct _reent s_reent;
  148. _GLOBAL_REENT = &s_reent;
  149. #endif
  150. /* Ensure that the initialization of sfp is prevented until esp_newlib_init_global_stdio() is explicitly invoked. */
  151. _GLOBAL_REENT->__cleanup = esp_cleanup_r;
  152. _REENT_SDIDINIT(_GLOBAL_REENT) = 1;
  153. environ = malloc(sizeof(char*));
  154. if (environ == 0) {
  155. // if allocation fails this early in startup process, there's nothing else other than to panic.
  156. abort();
  157. }
  158. environ[0] = NULL;
  159. esp_newlib_locks_init();
  160. }
  161. void esp_setup_newlib_syscalls(void) __attribute__((alias("esp_newlib_init")));
  162. void esp_newlib_init_global_stdio(const char *stdio_dev)
  163. {
  164. if (stdio_dev == NULL)
  165. {
  166. _GLOBAL_REENT->__cleanup = NULL;
  167. _REENT_SDIDINIT(_GLOBAL_REENT) = 0;
  168. __sinit(_GLOBAL_REENT);
  169. _GLOBAL_REENT->__cleanup = esp_cleanup_r;
  170. _REENT_SDIDINIT(_GLOBAL_REENT) = 1;
  171. } else {
  172. _REENT_STDIN(_GLOBAL_REENT) = fopen(stdio_dev, "r");
  173. _REENT_STDOUT(_GLOBAL_REENT) = fopen(stdio_dev, "w");
  174. _REENT_STDERR(_GLOBAL_REENT) = fopen(stdio_dev, "w");
  175. #if ESP_ROM_NEEDS_SWSETUP_WORKAROUND
  176. /*
  177. - This workaround for printf functions using 32-bit time_t after the 64-bit time_t upgrade
  178. - The 32-bit time_t usage is triggered through ROM Newlib functions printf related functions calling __swsetup_r() on
  179. the first call to a particular file pointer (i.e., stdin, stdout, stderr)
  180. - Thus, we call the toolchain version of __swsetup_r() now (before any printf calls are made) to setup all of the
  181. file pointers. Thus, the ROM newlib code will never call the ROM version of __swsetup_r().
  182. - See IDFGH-7728 for more details
  183. */
  184. extern int __swsetup_r (struct _reent *, FILE *);
  185. __swsetup_r(_GLOBAL_REENT, _REENT_STDIN(_GLOBAL_REENT));
  186. __swsetup_r(_GLOBAL_REENT, _REENT_STDOUT(_GLOBAL_REENT));
  187. __swsetup_r(_GLOBAL_REENT, _REENT_STDERR(_GLOBAL_REENT));
  188. #endif /* ESP_ROM_NEEDS_SWSETUP_WORKAROUND */
  189. }
  190. }