-
Notifications
You must be signed in to change notification settings - Fork 3
/
armc-cstubs.c
229 lines (175 loc) · 6.07 KB
/
armc-cstubs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
Part of the Raspberry-Pi Bare Metal Tutorials
Copyright (c) 2013-2015, Brian Sidebotham
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/* For more information about this file, please visit:
https://sourceware.org/newlib/libc.html#Stubs
These are the newlib C-Library stubs for the valvers Raspberry-Pi bare-metal
tutorial */
/*
Graceful failure is permitted by returning an error code. A minor
complication arises here: the C library must be compatible with development
environments that supply fully functional versions of these subroutines.
Such environments usually return error codes in a global errno. However,
the Red Hat newlib C library provides a macro definition for errno in the
header file errno.h, as part of its support for reentrant routines (see
Reentrancy).
The bridge between these two interpretations of errno is straightforward:
the C library routines with OS interface calls capture the errno values
returned globally, and record them in the appropriate field of the
reentrancy structure (so that you can query them using the errno macro from
errno.h).
This mechanism becomes visible when you write stub routines for OS
interfaces. You must include errno.h, then disable the macro, like this:
*/
#include <errno.h>
#undef errno
extern int errno;
/* Required include for fstat() */
#include <sys/stat.h>
/* Required include for times() */
#include <sys/times.h>
/* A pointer to a list of environment variables and their values. For a minimal
environment, this empty list is adequate: */
char *__env[1] = {0};
char **environ = __env;
/* A helper function written in assembler to aid us in allocating memory */
extern caddr_t _get_stack_pointer(void);
/* Never return from _exit as there's no OS to exit to, so instead we trap
here */
void _exit( int status )
{
/* Stop the compiler complaining about unused variables by "using" it */
(void)status;
while(1)
{
/* TRAP HERE */
}
}
/* There's currently no implementation of a file system because there's no
file system! */
int _close( int file )
{
return -1;
}
/* Transfer control to a new process. Minimal implementation (for a system
without processes): */
int execve( char *name, char **argv, char **env )
{
errno = ENOMEM;
return -1;
}
/* Create a new process. Minimal implementation (for a system without
processes): */
int fork( void )
{
errno = EAGAIN;
return -1;
}
/* Status of an open file. For consistency with other minimal implementations
in these examples, all files are regarded as character special devices. The
sys/stat.h header file required is distributed in the include subdirectory
for this C library. */
int _fstat( int file, struct stat *st )
{
st->st_mode = S_IFCHR;
return 0;
}
/* Process-ID; this is sometimes used to generate strings unlikely to conflict
with other processes. Minimal implementation, for a system without
processes: */
int getpid( void )
{
return 1;
}
/* Query whether output stream is a terminal. For consistency with the other
minimal implementations, which only support output to stdout, this minimal
implementation is suggested: */
int _isatty(int file)
{
return 1;
}
/* Send a signal. Minimal implementation: */
int kill( int pid, int sig )
{
errno = EINVAL;
return -1;
}
/* Establish a new name for an existing file. Minimal implementation: */
int link( char *old, char *new )
{
errno = EMLINK;
return -1;
}
/* Set position in a file. Minimal implementation: */
int _lseek(int file, int ptr, int dir)
{
return 0;
}
/* Open a file. Minimal implementation: */
int open( const char *name, int flags, int mode )
{
return -1;
}
/* Read from a file. Minimal implementation: */
int _read( int file, char *ptr, int len )
{
return 0;
}
/* Increase program data space. As malloc and related functions depend on this,
it is useful to have a working implementation. The following suffices for a
standalone system; it exploits the symbol _end automatically defined by the
GNU linker. */
caddr_t _sbrk( int incr )
{
extern char _end;
static char* heap_end = 0;
char* prev_heap_end;
if( heap_end == 0 )
heap_end = &_end;
prev_heap_end = heap_end;
heap_end += incr;
return (caddr_t)prev_heap_end;
}
/* Status of a file (by name). Minimal implementation: */
int stat( const char *file, struct stat *st )
{
st->st_mode = S_IFCHR;
return 0;
}
/* Timing information for current process. Minimal implementation: */
clock_t times( struct tms *buf )
{
return -1;
}
/* Remove a file's directory entry. Minimal implementation: */
int unlink( char *name )
{
errno = ENOENT;
return -1;
}
/* Wait for a child process. Minimal implementation: */
int wait( int *status )
{
errno = ECHILD;
return -1;
}