- Misc changes
[tpg/acess2.git] / AcessNative / ld-acess.so_src / syscalls.c
1 /*
2  */
3 #include "../../Usermode/include/acess/sys.h"
4 #include "common.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include "request.h"
11
12 // === Types ===
13
14 // === IMPORTS ===
15
16 // === CODE ===
17 const char *ReadEntry(tOutValue **OutDest, tInValue **InDest,
18         int *Direction, const char *ArgTypes, va_list Args)
19 {
20         uint64_t        val64, *ptr64;
21         uint32_t        val32, *ptr32;
22          int    direction = 0;  // 0: Invalid, 1: Out, 2: In, 3: Out
23         char    *str;
24          int    len;
25         
26         // Eat whitespace
27         while(*ArgTypes && *ArgTypes == ' ')    ArgTypes ++;
28         if( *ArgTypes == '\0' ) return ArgTypes;
29         
30         // Get direction
31         switch(*ArgTypes)
32         {
33         case '>':       direction = 1;  break;
34         case '<':       direction = 2;  break;
35         case '?':       direction = 3;  break;
36         default:
37                 return NULL;
38         }
39         ArgTypes ++;
40         
41         // Eat whitespace
42         while(*ArgTypes && *ArgTypes == ' ')    ArgTypes ++;
43         if( *ArgTypes == '\0' ) return ArgTypes;
44         
45         // Internal helper macro
46         #define MAKE_OUT(_dest,_typeChar,_typeName,_value) do{if((_dest)){\
47                 *(_dest) = (tOutValue*)malloc(sizeof(tOutValue)+sizeof(_typeName));\
48                 (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\
49                 *(_typeName*)((*(_dest))->Data) = (_value);\
50                 }}while(0)
51         #define MAKE_IN(_dest,_typeChar,_typeName,_value) do{if((_dest)){\
52                 *(_dest) = (tInValue*)malloc(sizeof(tInValue));\
53                 (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\
54                 (*(_dest))->Data = (_value);\
55                 }}while(0)
56         
57         // Get type
58         switch(*ArgTypes)
59         {
60         case 'i':       // 32-bit integer
61                 // Input?
62                 if( direction & 2 )
63                 {
64                         ptr32 = va_arg(Args, uint32_t*);
65                         MAKE_IN(InDest, 'i', uint32_t*, ptr32);
66                         if( direction & 1 )
67                                 MAKE_OUT(OutDest, 'i', uint32_t, *ptr32);
68                 }
69                 else
70                 {
71                         val32 = va_arg(Args, uint32_t);
72                         MAKE_OUT(OutDest, 'i', uint32_t, val32);
73                 }
74                 break;
75         case 'I':       // 64-bit integer
76                 // Input?
77                 if( direction & 2 )
78                 {
79                         ptr64 = va_arg(Args, uint64_t*);
80                         MAKE_IN(InDest, 'I', uint64_t*, ptr64);
81                         if( direction & 1 )
82                                 MAKE_OUT(OutDest, 'I', uint64_t, *ptr64);
83                 }
84                 else
85                 {
86                         val64 = va_arg(Args, uint64_t);
87                         MAKE_OUT(OutDest, 'I', uint64_t, val64);
88                 }
89                 break;
90         case 's':
91                 // Input string makes no sense!
92                 if( direction & 2 ) {
93                         fprintf(stderr, "ReadEntry: Incoming string is not defined\n");
94                         return NULL;
95                 }
96                 
97                 str = va_arg(Args, char*);
98                 if( OutDest )
99                 {
100                          int    len = strlen(str) + 1;
101                         *OutDest = malloc( sizeof(tOutValue) + len );
102                         (*OutDest)->Type = 's';
103                         (*OutDest)->Length = len;
104                         memcpy((*OutDest)->Data, str, len);
105                 }
106                 break;
107         
108         case 'd':
109                 len = va_arg(Args, int);
110                 str = va_arg(Args, char*);
111                 
112                 // Input ?
113                 if( (direction & 2) && InDest )
114                 {
115                         *InDest = (tInValue*)malloc( sizeof(tInValue) );
116                         (*InDest)->Type = 'd';
117                         (*InDest)->Length = len;
118                         (*InDest)->Data = str;
119                 }
120                 
121                 // Output ?
122                 if( (direction & 1) && InDest )
123                 {
124                         *OutDest = (tOutValue*)malloc( sizeof(tOutValue) + len );
125                         (*OutDest)->Type = 'd';
126                         (*OutDest)->Length = len;
127                         memcpy((*OutDest)->Data, str, len);
128                 }
129                 break;
130         
131         default:
132                 return NULL;
133         }
134         ArgTypes ++;
135         #undef MAKE_ASSIGN
136         
137         *Direction = direction;
138         
139         return ArgTypes;
140 }
141
142 /**
143  * \param ArgTypes
144  *
145  * Whitespace is ignored
146  * >i:  Input Integer (32-bits)
147  * >I:  Input Long Integer (64-bits)
148  * >s:  Input String
149  * >d:  Input Buffer (Preceded by valid size)
150  * <I:  Output long integer
151  * <d:  Output Buffer (Preceded by valid size)
152  * ?d:  Bi-directional buffer (Preceded by valid size), buffer contents
153  *      are returned
154  */
155 int _Syscall(const char *ArgTypes, ...)
156 {
157         va_list args;
158          int    outCount = 0;
159          int    inCount = 0;
160         const char      *str;
161         
162         tOutValue       **output;
163         tInValue        **input;
164         
165         // Get data size
166         va_start(args, ArgTypes);
167         str = ArgTypes;
168         while(*str)
169         {
170                  int    dir;
171                 
172                 str = ReadEntry(NULL, NULL, &dir, str, args);
173                 if( !str )      break;
174                 
175                 // Out!
176                 if( dir & 1 )   outCount ++;
177                 
178                 // and.. In!
179                 if( dir & 2 )   inCount ++;
180         }
181         va_end(args);
182         
183         // Allocate buffers
184         output = malloc( outCount*sizeof(tOutValue*) );
185         input = malloc( inCount*sizeof(tInValue*) );
186         
187         // - re-zero so they can be used as indicies
188         outCount = 0;
189         inCount = 0;
190         
191         // Fill `output` and `input`
192         va_start(args, ArgTypes);
193         str = ArgTypes;
194         while(*str)
195         {
196                 tOutValue       *outParam;
197                 tInValue        *inParam;
198                  int    dir;
199                 
200                 str = ReadEntry(&outParam, &inParam, &dir, str, args);
201                 if( !str )      break;
202                 
203                 if( dir & 1 )
204                         output[outCount++] = outParam;
205                 if( dir & 2 )
206                         input[inCount++] = inParam;
207         }
208         va_end(args);
209         
210         // Send syscall request
211         
212         
213         // Clean up
214         while(outCount--)       free(output[outCount]);
215         free(output);
216         while(inCount--)        free(input[inCount]);
217         free(input);
218         
219         return 0;
220 }
221
222 // --- VFS Calls
223 int open(const char *Path, int Flags) {
224         return _Syscall(">s >i", Path, Flags);
225 }
226
227 void close(int FD) {
228         _Syscall(">i", FD);
229 }
230
231 size_t read(int FD, size_t Bytes, void *Dest) {
232         return _Syscall(">i >i <d", FD, Bytes, Bytes, Dest);
233 }
234
235 size_t write(int FD, size_t Bytes, void *Src) {
236         return _Syscall(">i >i >d", FD, Bytes, Bytes, Src);
237 }
238
239 int seek(int FD, int64_t Ofs, int Dir) {
240         return _Syscall(">i >I >i", FD, Ofs, Dir);
241 }
242
243 uint64_t tell(int FD) {
244         uint64_t        ret;
245         _Syscall("<I >i", &ret, FD);
246         return ret;
247 }
248
249 int ioctl(int fd, int id, void *data) {
250         // NOTE: 1024 byte size is a hack
251         return _Syscall(">i >i ?d", fd, id, 1024, data);
252 }
253 int finfo(int fd, t_sysFInfo *info, int maxacls) {
254         return _Syscall(">i <d >i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls);
255 }
256
257 int readdir(int fd, char *dest) {
258         return _Syscall(">i <s", fd, dest);
259 }
260
261 int _SysOpenChild(int fd, char *name, int flags) {
262         return _Syscall(">i >s >i", fd, name, flags);
263 }
264
265 int _SysGetACL(int fd, t_sysACL *dest) {
266         return _Syscall(">i <d", fd, sizeof(t_sysACL), dest);
267 }
268
269 int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) {
270         return _Syscall(">s >s >s >s", Device, Directory, Type, Options);
271 }
272
273
274 // --- Error Handler
275 int     _SysSetFaultHandler(int (*Handler)(int)) {
276         return 0;
277 }
278
279
280 // === Symbol List ===
281 #define DEFSYM(name)    {#name, name}
282 const tSym      caBuiltinSymbols[] = {
283         {"_exit", exit},
284         
285         DEFSYM(open),
286         DEFSYM(close),
287         DEFSYM(read),
288         DEFSYM(write),
289         DEFSYM(seek),
290         DEFSYM(tell),
291         DEFSYM(ioctl),
292         DEFSYM(finfo),
293         DEFSYM(readdir),
294         DEFSYM(_SysOpenChild),
295         DEFSYM(_SysGetACL),
296         DEFSYM(_SysMount),
297         
298         {"_SysSetFaultHandler", _SysSetFaultHandler}
299 };
300
301 const int       ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]);
302

UCC git Repository :: git.ucc.asn.au