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

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