3 * Architecture Independent System Init
23 extern int Modules_LoadBuiltins();
24 //extern int PCI_Install();
25 extern void DMA_Install();
26 extern void Debug_SetKTerminal(char *File);
27 extern void StartupPrint(char *Str);
30 void System_Init(char *ArgString);
31 void System_ParseCommandLine(char *ArgString);
32 void System_ParseVFS(char *Arg);
33 void System_ParseSetting(char *Arg);
34 void System_ExecuteScript();
35 tConfigFile *System_Int_ParseFile(char *File);
38 char *gsConfigScript = "/Acess/Conf/BootConf.cfg";
41 void System_Init(char *ArgString)
43 // Set the debug to be echoed to the terminal
44 StartupPrint("Kernel now echoes to VT7 (Ctrl-Alt-F8)");
45 Debug_SetKTerminal("/Devices/VTerm/7");
47 // - Parse Kernel's Command Line
48 System_ParseCommandLine(ArgString);
50 // - Execute the Config Script
51 Log_Log("CFG", "Executing config script...");
52 System_ExecuteScript();
56 * \fn void System_ParseCommandLine(char *ArgString)
57 * \brief Parses the kernel's command line and sets the environment
59 void System_ParseCommandLine(char *ArgString)
66 Log_Log("CFG", "Kernel Invocation \"%s\"", ArgString);
68 // --- Get Arguments ---
70 for( argc = 0; argc < 32; argc++ )
73 while(*str == ' ') str++;
74 // Check for the end of the string
75 if(*str == '\0') { argc--; break;}
77 while(*str && *str != ' ')
80 while(*str && !(*str == '"' && str[-1] != '\\'))
85 if(*str == '\0') break; // Check for EOS
86 *str = '\0'; // Cap off argument string
87 str ++; // and increment the string pointer
90 argc ++; // Count last argument
92 // --- Parse Arguments ---
93 for( i = 1; i < argc; i++ )
95 if( argv[i][0] == '/' )
96 System_ParseVFS( argv[i] );
98 System_ParseSetting( argv[i] );
103 * \fn void System_ParseVFS(char *Arg)
105 void System_ParseVFS(char *Arg)
111 // Search for the '=' token
112 while( *value && *value != '=' )
115 // Check if the equals was found
116 if( *value == '\0' ) {
117 Log_Warning("CFG", "Expected '=' in the string '%s'", Arg);
122 *value = '\0'; value ++;
124 // Check assignment type
125 // - Symbolic Link <link>=<destination>
128 Log_Log("CFG", "Symbolic link '%s' pointing to '%s'", Arg, value);
129 VFS_Symlink(Arg, value);
131 // - Mount <mountpoint>=<fs>:<device>
136 while(*dev && *dev != ':') dev++;
142 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
143 Log_Log("CFG", "Creating directory '%s'", Arg, value);
149 Log_Log("CFG", "Mounting '%s' to '%s' ('%s')", dev, Arg, value);
150 VFS_Mount(dev, Arg, value, "");
155 * \fn void System_ParseSetting(char *Arg)
157 void System_ParseSetting(char *Arg)
162 // Search for the '=' token
163 while( *value && *value != '=' )
166 // Check for boolean/flag (no '=')
169 //if(strcmp(Arg, "") == 0) {
171 Log_Warning("CFG", "Kernel flag '%s' is not recognised", Arg);
176 *value = '\0'; // Remove '='
177 value ++; // and eat it's position
179 if(strcmp(Arg, "SCRIPT") == 0) {
180 Log_Log("CFG", "Config Script: '%s'", value);
181 gsConfigScript = value;
183 Log_Warning("CFG", "Kernel config setting '%s' is not recognised", Arg);
190 * \fn void System_ExecuteScript()
192 void System_ExecuteScript()
202 fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
204 Log_Warning("CFG", "Passed script '%s' does not exist", gsConfigScript);
208 // Read into memory buffer
209 VFS_Seek(fp, 0, SEEK_END);
211 VFS_Seek(fp, 0, SEEK_SET);
212 fData = malloc(fLen+1);
213 VFS_Read(fp, fLen, fData);
220 file = System_Int_ParseFile(fData);
223 for( i = 0; i < file->nLines; i++ )
225 line = &file->Lines[i];
226 if( line->nParts == 0 ) continue; // Skip blank
229 if( strcmp(line->Parts[0], "mount") == 0 )
231 if( line->nParts != 4 ) {
232 Log_Warning("CFG", "Configuration command 'mount' requires 3 arguments, %i given",
236 //Log_Log("CFG", "Mount '%s' to '%s' (%s)",
237 // line->Parts[1], line->Parts[2], line->Parts[3]);
238 //! \todo Use an optional 4th argument for the options string
239 VFS_Mount(line->Parts[1], line->Parts[2], line->Parts[3], "");
242 else if(strcmp(line->Parts[0], "module") == 0)
244 if( line->nParts < 2 || line->nParts > 3 ) {
246 "Configuration command 'module' requires 1 or 2 arguments, %i given",
250 if( line->nParts == 3 )
251 Module_LoadFile(line->Parts[1], line->Parts[2]);
253 Module_LoadFile(line->Parts[1], "");
256 else if(strcmp(line->Parts[0], "udimod") == 0)
258 if( line->nParts != 2 ) {
259 Log_Warning("CFG", "Configuration command 'udimod' requires 1 argument, %i given",
263 Log_Log("CFG", "Load UDI Module '%s'", line->Parts[1]);
264 Module_LoadFile(line->Parts[1], "");
267 else if(strcmp(line->Parts[0], "edimod") == 0)
269 if( line->nParts != 2 ) {
270 Log_Warning("CFG", "Configuration command 'edimod' requires 1 argument, %i given",
274 Log_Log("CFG", "Load EDI Module '%s'", line->Parts[1]);
275 Module_LoadFile(line->Parts[1], "");
277 // Create a Symbolic Link
278 else if(strcmp(line->Parts[0], "symlink") == 0)
280 if( line->nParts != 3 ) {
281 Log_Warning("CFG", "Configuration command 'symlink' requires 2 arguments, %i given",
285 Log_Log("CFG", "Symlink '%s' pointing to '%s'",
286 line->Parts[1], line->Parts[2]);
287 VFS_Symlink(line->Parts[1], line->Parts[2]);
289 // Create a Directory
290 else if(strcmp(line->Parts[0], "mkdir") == 0)
292 if( line->nParts != 2 ) {
293 Log_Warning("CFG", "Configuration command 'mkdir' requires 1 argument, %i given",
297 Log_Log("CFG", "New Directory '%s'", line->Parts[1]);
298 VFS_MkDir(line->Parts[1]);
301 else if(strcmp(line->Parts[0], "spawn") == 0)
303 if( line->nParts != 2 ) {
304 Log_Warning("CFG", "Configuration command 'spawn' requires 1 argument, %i given",
308 Log_Log("CFG", "Starting '%s' as a new task", line->Parts[1]);
309 Proc_Spawn(line->Parts[1]);
312 Log_Warning("CFG", "Unknown configuration command '%s' on line %i",
319 // Clean up after ourselves
320 for( i = 0; i < file->nLines; i++ ) {
321 if( file->Lines[i].nParts == 0 ) continue; // Skip blank
322 free( file->Lines[i].Parts );
329 * \brief Parses a config file
330 * \param FileData Read/Write buffer containing the config file data
332 * \return ::tConfigFile structure that represents the original contents
335 tConfigFile *System_Int_ParseFile(char *FileData)
343 ENTER("pFileData", FileData);
345 // Prescan and count the number of lines
346 for(ptr = FileData; *ptr; ptr++)
348 if(*ptr != '\n') continue;
350 if(ptr == FileData) {
356 if(ptr[-1] == '\\') continue;
361 LOG("nLines = %i", nLines);
363 // Ok so we have `nLines` lines, now to allocate our return
364 ret = malloc( sizeof(tConfigFile) + sizeof(tConfigLine)*nLines );
365 ret->nLines = nLines;
367 // Read the file for real
369 ptr = FileData, i = 0;
376 ret->Lines[i].nParts = 0;
381 // Read leading whitespace
382 while( *ptr == '\t' || *ptr == ' ' ) ptr++;
385 if( *ptr == '\0' || *ptr == '\n' ) {
386 if(*ptr == '\n') ptr ++;
390 if( *ptr == '#' || *ptr == ';' ) {
391 while( *ptr && *ptr != '\n' ) ptr ++;
392 if(*ptr == '\n') ptr ++;
396 ret->Lines[i].nParts ++;
400 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
405 while( *ptr && !(*ptr == '\t' || *ptr == ' ') && *ptr != '\n' )
409 LOG("ret->Lines[%i].nParts = %i", i, ret->Lines[i].nParts);
411 if( ret->Lines[i].nParts == 0 ) {
412 ret->Lines[i].Parts = NULL;
416 // Allocate part list
417 ret->Lines[i].Parts = malloc( sizeof(char*) * ret->Lines[i].nParts );
420 for( ptr = start, j = 0; ; j++ )
422 // Read leading whitespace
423 while( *ptr == '\t' || *ptr == ' ' ) ptr++;
426 if( *ptr == '\0' || *ptr == '\n' ) {
427 if(*ptr == '\n') ptr ++;
431 if( *ptr == '#' || *ptr == ';' ) {
432 while( *ptr && *ptr != '\n' ) ptr ++;
433 if(*ptr == '\n') ptr ++;
437 ret->Lines[i].Parts[j] = ptr;
442 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
447 while( *ptr != '\t' && *ptr != ' ' && *ptr != '\n' )
451 // Break if we have reached NULL
453 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
458 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
462 *ptr = '\0'; // Cap off string
463 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
464 ptr ++; // And increment for the next round