Fixes to Libc, Doxygen Comments and VTerm layout
[tpg/acess2.git] / Kernel / system.c
1 /*
2  * Acess 2
3  * Architecture Independent System Init
4  * system.c
5  */
6 #include <common.h>
7
8 // === IMPORTS ===
9 extern int      Modules_LoadBuiltins();
10 extern int      PCI_Install();
11 extern void     DMA_Install();
12 extern void     Debug_SetKTerminal(char *File);
13
14 // === PROTOTYPES ===
15 void    System_Init(char *ArgString);
16 void    System_ParseCommandLine(char *ArgString);
17 void    System_ParseVFS(char *Arg);
18 void    System_ParseSetting(char *Arg);
19 void    System_ExecuteScript();
20  int    System_Int_GetString(char *Str, char **Dest);
21
22 // === GLOBALS ===
23 char    *gsConfigScript = "/Acess/Conf/BootConf.cfg";
24
25 // === CODE ===
26 void System_Init(char *ArgString)
27 {
28         // - Start Builtin Drivers & Filesystems
29         PCI_Install();
30         DMA_Install();
31         Modules_LoadBuiltins();
32         
33         // Set the debug to be echoed to the terminal
34         Debug_SetKTerminal("/Devices/vterm/0");
35         
36         // - Parse Kernel's Command Line
37         System_ParseCommandLine(ArgString);
38         
39         // - Execute the Config Script
40         Log("Executing config script...");
41         System_ExecuteScript();
42 }
43
44 /**
45  * \fn void System_ParseCommandLine(char *ArgString)
46  * \brief Parses the kernel's command line and sets the environment
47  */
48 void System_ParseCommandLine(char *ArgString)
49 {
50         char    *argv[32];
51          int    argc;
52          int    i;
53         char    *str;
54         
55         Log("Kernel Command Line: \"%s\"", ArgString);
56         
57         // --- Get Arguments ---
58         str = ArgString;
59         for( argc = 0; argc < 32; argc++ )
60         {
61                 while(*str == ' ')      str++;  // Eat Whitespace
62                 if(*str == '\0') {      argc--; break;} // End of string
63                 argv[argc] = str;
64                 while(*str && *str != ' ')
65                 {
66                         /*if(*str == '"') {
67                                 while(*str && !(*str == '"' && str[-1] != '\\'))
68                                         str ++;
69                         }*/
70                         str++;
71                 }
72                 if(*str == '\0')        break;  // End of string
73                 *str = '\0';    // Cap off argument string
74                 str ++; // and increment the string pointer
75         }
76         if(argc < 32)
77                 argc ++;        // Count last argument
78         
79         // --- Parse Arguments ---
80         for( i = 1; i < argc; i++ )
81         {
82                 if( argv[i][0] == '/' )
83                         System_ParseVFS( argv[i] );
84                 else
85                         System_ParseSetting( argv[i] );
86         }
87 }
88
89 /**
90  * \fn void System_ParseVFS(char *Arg)
91  */
92 void System_ParseVFS(char *Arg)
93 {
94         char    *value;
95          int    fd;
96         
97         value = Arg;
98         // Search for the '=' token
99         while( *value && *value != '=' )
100                 value++;
101         
102         // Check if the equals was found
103         if( *value == '\0' ) {
104                 Warning("Expected '=' in the string '%s'", Arg);
105                 return ;
106         }
107         
108         // Edit string
109         *value = '\0';  value ++;
110         
111         // Check assignment type
112         // - Symbolic Link <link>=<destination>
113         if(value[0] == '/')
114         {
115                 Log("Symbolic link '%s' pointing to '%s'", Arg, value);
116                 VFS_Symlink(Arg, value);
117         }
118         // - Mount <mountpoint>=<fs>:<device>
119         else
120         {
121                 char    *dev = value;
122                 // Find colon
123                 while(*dev && *dev != ':')      dev++;
124                 if(*dev) {
125                         *dev = '\0';
126                         dev++;  // Eat ':'
127                 }
128                 // Create Mountpoint
129                 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
130                         Log("Creating directory '%s'", Arg, value);
131                         VFS_MkDir( Arg );
132                 } else {
133                         VFS_Close(fd);
134                 }
135                 // Mount
136                 Log("Mounting '%s' to '%s' ('%s')", dev, Arg, value);
137                 VFS_Mount(dev, Arg, value, "");
138         }
139 }
140
141 /**
142  * \fn void System_ParseSetting(char *Arg)
143  */
144 void System_ParseSetting(char *Arg)
145 {
146         char    *value;
147         value = Arg;
148
149         // Search for the '=' token
150         while( *value && *value != '=' )
151                 value++;
152         
153         // Check for boolean/flag (no '=')
154         if(*value == '\0')
155         {
156                 if(strcmp(Arg, "") == 0) {
157                 } else {
158                         Warning("Kernel flag '%s' is not recognised", Arg);
159                 }
160         }
161         else
162         {
163                 *value = '\0';  // Remove '='
164                 value ++;       // and eat it's position
165                 
166                 if(strcmp(Arg, "SCRIPT") == 0) {
167                         Log("Config Script: '%s'", value);
168                         gsConfigScript = value;
169                 } else {
170                         Warning("Kernel config setting '%s' is not recognised", Arg);
171                 }
172                 
173         }
174 }
175
176 /**
177  * \fn void System_ExecuteScript()
178  */
179 void System_ExecuteScript()
180 {
181          int    fp;
182          int    fLen = 0;
183          int    i = 0, lineStart;
184         char    *sArg1, *sArg2, *sArg3;
185         char    *fData;
186         
187         // Open Script
188         fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
189         if(fp == -1) {
190                 Warning("[CFG] Passed script '%s' does not exist", gsConfigScript);
191                 return;
192         }
193         
194         // Read into memory buffer
195         VFS_Seek(fp, 0, SEEK_END);
196         fLen = VFS_Tell(fp);
197         VFS_Seek(fp, 0, SEEK_SET);
198         fData = malloc(fLen+1);
199         VFS_Read(fp, fLen, fData);
200         fData[fLen] = '\0';
201         VFS_Close(fp);
202         
203         // Read Script
204         while(i < fLen)
205         {
206                 sArg1 = sArg2 = sArg3 = NULL;
207                 
208                 lineStart = i;
209                 // Clear leading whitespace and find empty lines
210                 while(i < fLen && (fData[i] == ' ' || fData[i]=='\t'))  i ++;
211                 if(i == fLen)   break;
212                 if(fData[i] == '\n') {
213                         i++;
214                         continue;
215                 }
216                 
217                 // Comment
218                 if(fData[i] == ';' || fData[i] == '#') {
219                         while(i < fLen && fData[i] != '\n')     i ++;
220                         i ++;
221                         continue;
222                 }
223                 
224                 // Commands
225                 // - Mount
226                 if(strncmp("mount ", fData+i, 6) == 0) {
227                         i += 6;
228                         i += System_Int_GetString(fData+i, &sArg1);
229                         if(!sArg1)      goto read2eol;
230                         i += System_Int_GetString(fData+i, &sArg2);
231                         if(!sArg2)      goto read2eol;
232                         i += System_Int_GetString(fData+i, &sArg3);
233                         if(!sArg3)      goto read2eol;
234                         //Log("[CFG ] Mount '%s' to '%s' (%s)\n", sArg1, sArg2, sArg3);
235                         VFS_Mount(sArg1, sArg2, sArg3, "");
236                 }
237                 // - Load Module
238                 else if(strncmp("module ", fData+i, 6) == 0) {
239                         //char  *tmp;
240                         i += 7;
241                         i += System_Int_GetString(fData+i, &sArg1);
242                         if(!sArg1)      goto read2eol;
243                         Module_LoadFile(sArg1, "");     //!\todo Use the rest of the line as the argument string
244                 }
245                 // - Load Module
246                 else if(strncmp("edimod ", fData+i, 6) == 0) {
247                         i += 7;
248                         i += System_Int_GetString(fData+i, &sArg1);
249                         if(!sArg1)      goto read2eol;
250                         Log("[CFG ] Load EDI Module '%s'\n", sArg1);
251                         Module_LoadFile(sArg1, "");
252                 }
253                 // - Symlink
254                 else if(strncmp("symlink ", fData+i, 7) == 0) {
255                         i += 8;
256                         i += System_Int_GetString(fData+i, &sArg1);
257                         if(!sArg1)      goto read2eol;
258                         i += System_Int_GetString(fData+i, &sArg2);
259                         if(!sArg2)      goto read2eol;
260                         Log("[CFG ] Symlink '%s' pointing to '%s'\n", sArg1, sArg2);
261                         VFS_Symlink(sArg1, sArg2);
262                 }
263                 // - New Directory
264                 else if(strncmp("mkdir ", fData+i, 5) == 0) {
265                         i += 6;
266                         i += System_Int_GetString(fData+i, &sArg1);
267                         if(!sArg1)      goto read2eol;
268                         Log("[CFG ] New Directory '%s'\n", sArg1);
269                         VFS_MkDir(sArg1);
270                 }
271                 // - Spawn a task
272                 else if(strncmp("spawn ", fData+i, 5) == 0) {
273                         i += 6;
274                         i += System_Int_GetString(fData+i, &sArg1);
275                         if(!sArg1)      goto read2eol;
276                         Log("[CFG ] Starting '%s' as a new task\n", sArg1);
277                         Proc_Spawn(sArg1);
278                 }
279                 else {
280                         Warning("Unknown configuration command, Line: '%s'", fData+i);
281                         goto read2eol;
282                 }
283         read2eol:
284                 if(sArg1)       free(sArg1);
285                 if(sArg2)       free(sArg2);
286                 if(sArg3)       free(sArg3);
287                 // Skip to EOL
288                 while(i < fLen && fData[i] != '\n')     i++;
289                 i ++;   // Skip \n
290         }
291         free(fData);
292 }
293
294 /**
295  * \fn int System_Int_GetString(char *Str, char **Dest)
296  * \brief Gets a string from another
297  * \note Destructive
298  * \param Str   Input String
299  * \param Dest  Pointer to output pointer
300  * \return Characters eaten from input
301  */
302 int System_Int_GetString(char *Str, char **Dest)
303 {
304          int    pos = 0;
305          int    start = 0;
306          int    len;
307          
308         //LogF("GetString: (Str='%s', Dest=0x%x)\n", Str, Dest);
309          
310         while(Str[pos] == ' ' || Str[pos] == '\t')      pos++;
311         if(Str[pos] == '\n' || Str[pos] == '\0') {
312                 *Dest = NULL;
313                 return pos;
314         }
315         
316         // Quoted String
317         if(Str[pos] == '"')
318         {
319                 pos ++;
320                 start = pos;
321                 while(Str[pos] != '"')  pos++;
322                 
323                 len = pos - start;
324                 *Dest = malloc( len + 1 );
325                 memcpy( *Dest, Str+start, len );
326                 (*Dest)[len] = '\0';
327                 
328                 //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
329                 
330                 pos++;
331                 return pos;
332         }
333         
334         // Non-Quoted String - Whitespace deliminated
335         start = pos;
336         while(Str[pos] != ' ' && Str[pos] != '\t' && Str[pos] != '\n')  pos++;
337         
338         len = pos - start;
339         //LogF(" GetString: len = %i\n", len);
340         *Dest = malloc( len + 1 );
341         memcpy( *Dest, Str+start, len );
342         (*Dest)[len] = '\0';
343         
344         //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
345         
346         return pos;
347 }

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