3 * Architecture Independent System Init
22 extern int Modules_LoadBuiltins();
23 extern int PCI_Install();
24 extern void DMA_Install();
25 extern void Debug_SetKTerminal(char *File);
26 extern void StartupPrint(char *Str);
29 void System_Init(char *ArgString);
30 void System_ParseCommandLine(char *ArgString);
31 void System_ParseVFS(char *Arg);
32 void System_ParseSetting(char *Arg);
33 void System_ExecuteScript();
34 tConfigFile *System_Int_ParseFile(char *File);
37 char *gsConfigScript = "/Acess/Conf/BootConf.cfg";
40 void System_Init(char *ArgString)
42 // - Start Builtin Drivers & Filesystems
43 StartupPrint("Scanning PCI Bus...");
45 StartupPrint("Loading DMA...");
47 StartupPrint("Loading staticly compiled modules...");
48 Modules_LoadBuiltins();
50 // Set the debug to be echoed to the terminal
51 StartupPrint("Kernel now echoes to VT6 (Ctrl-Alt-F7)");
52 Debug_SetKTerminal("/Devices/VTerm/6");
54 // - Parse Kernel's Command Line
55 System_ParseCommandLine(ArgString);
57 // - Execute the Config Script
58 Log("Executing config script...");
59 System_ExecuteScript();
63 * \fn void System_ParseCommandLine(char *ArgString)
64 * \brief Parses the kernel's command line and sets the environment
66 void System_ParseCommandLine(char *ArgString)
73 Log("Kernel Command Line: \"%s\"", ArgString);
75 // --- Get Arguments ---
77 for( argc = 0; argc < 32; argc++ )
79 while(*str == ' ') str++; // Eat Whitespace
80 if(*str == '\0') { argc--; break;} // End of string
82 while(*str && *str != ' ')
85 while(*str && !(*str == '"' && str[-1] != '\\'))
90 if(*str == '\0') break; // End of string
91 *str = '\0'; // Cap off argument string
92 str ++; // and increment the string pointer
95 argc ++; // Count last argument
97 // --- Parse Arguments ---
98 for( i = 1; i < argc; i++ )
100 if( argv[i][0] == '/' )
101 System_ParseVFS( argv[i] );
103 System_ParseSetting( argv[i] );
108 * \fn void System_ParseVFS(char *Arg)
110 void System_ParseVFS(char *Arg)
116 // Search for the '=' token
117 while( *value && *value != '=' )
120 // Check if the equals was found
121 if( *value == '\0' ) {
122 Warning("Expected '=' in the string '%s'", Arg);
127 *value = '\0'; value ++;
129 // Check assignment type
130 // - Symbolic Link <link>=<destination>
133 Log("Symbolic link '%s' pointing to '%s'", Arg, value);
134 VFS_Symlink(Arg, value);
136 // - Mount <mountpoint>=<fs>:<device>
141 while(*dev && *dev != ':') dev++;
147 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
148 Log("Creating directory '%s'", Arg, value);
154 Log("Mounting '%s' to '%s' ('%s')", dev, Arg, value);
155 VFS_Mount(dev, Arg, value, "");
160 * \fn void System_ParseSetting(char *Arg)
162 void System_ParseSetting(char *Arg)
167 // Search for the '=' token
168 while( *value && *value != '=' )
171 // Check for boolean/flag (no '=')
174 if(strcmp(Arg, "") == 0) {
176 Warning("Kernel flag '%s' is not recognised", Arg);
181 *value = '\0'; // Remove '='
182 value ++; // and eat it's position
184 if(strcmp(Arg, "SCRIPT") == 0) {
185 Log("Config Script: '%s'", value);
186 gsConfigScript = value;
188 Warning("Kernel config setting '%s' is not recognised", Arg);
195 * \fn void System_ExecuteScript()
197 void System_ExecuteScript()
207 fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
209 Warning("[CFG] Passed script '%s' does not exist", gsConfigScript);
213 // Read into memory buffer
214 VFS_Seek(fp, 0, SEEK_END);
216 VFS_Seek(fp, 0, SEEK_SET);
217 fData = malloc(fLen+1);
218 VFS_Read(fp, fLen, fData);
225 file = System_Int_ParseFile(fData);
228 for( i = 0; i < file->nLines; i++ )
230 line = &file->Lines[i];
231 if( line->nParts == 0 ) continue; // Skip blank
234 if( strcmp(line->Parts[0], "mount") == 0 ) {
235 if( line->nParts != 4 ) {
236 Warning("Configuration command 'mount' requires 3 arguments, %i given",
240 //Log("[CFG ] Mount '%s' to '%s' (%s)",
241 // line->Parts[1], line->Parts[2], line->Parts[3]);
242 //! \todo Use an optional 4th argument for the options string
243 VFS_Mount(line->Parts[1], line->Parts[2], line->Parts[3], "");
246 else if(strcmp(line->Parts[0], "module") == 0) {
247 if( line->nParts < 2 || line->nParts > 3 ) {
248 Warning("Configuration command 'module' requires 1 or 2 arguments, %i given",
252 if( line->nParts == 3 )
253 Module_LoadFile(line->Parts[1], line->Parts[2]);
255 Module_LoadFile(line->Parts[1], "");
258 else if(strcmp(line->Parts[0], "udimod") == 0) {
259 if( line->nParts != 2 ) {
260 Warning("Configuration command 'udimod' requires 1 argument, %i given",
264 Log("[CFG ] Load UDI Module '%s'", line->Parts[1]);
265 Module_LoadFile(line->Parts[1], "");
268 else if(strcmp(line->Parts[0], "edimod") == 0) {
269 if( line->nParts != 2 ) {
270 Warning("Configuration command 'edimod' requires 1 argument, %i given",
274 Log("[CFG ] Load EDI Module '%s'", line->Parts[1]);
275 Module_LoadFile(line->Parts[1], "");
278 else if(strcmp(line->Parts[0], "symlink") == 0) {
279 if( line->nParts != 3 ) {
280 Warning("Configuration command 'symlink' requires 2 arguments, %i given",
284 Log("[CFG ] Symlink '%s' pointing to '%s'",
285 line->Parts[1], line->Parts[2]);
286 VFS_Symlink(line->Parts[1], line->Parts[2]);
289 else if(strcmp(line->Parts[0], "mkdir") == 0) {
290 if( line->nParts != 3 ) {
291 Warning("Configuration command 'mkdir' requires 1 argument, %i given",
295 Log("[CFG ] New Directory '%s'", line->Parts[1]);
296 VFS_MkDir(line->Parts[1]);
299 else if(strcmp(line->Parts[0], "spawn") == 0) {
300 if( line->nParts != 3 ) {
301 Warning("Configuration command 'spawn' requires 1 argument, %i given",
305 Log("[CFG ] Starting '%s' as a new task", line->Parts[1]);
306 Proc_Spawn(line->Parts[1]);
309 Warning("Unknown configuration command '%s' on line %i",
316 // Clean up after ourselves
317 for( i = 0; i < file->nLines; i++ ) {
318 free( file->Lines[i].Parts );
325 * \brief Parses a config file
326 * \param FileData Read/Write buffer containing the config file data
328 * \return ::tConfigFile structure that represents the original contents
331 tConfigFile *System_Int_ParseFile(char *FileData)
339 // Prescan and count the number of lines
340 for(ptr = FileData; *ptr; ptr++)
342 if(*ptr != '\n') continue;
344 if(ptr == FileData) {
349 #if 0 // Don't handle windows style EOLs
352 if( &ptr[-1] == FileData ) {
356 if(ptr[-2] == '\\') continue;
361 if(ptr[-1] == '\\') continue;
366 // Ok so we have `nLines` lines, now to allocate our return
367 ret = malloc( sizeof(tConfigFile) + sizeof(tConfigLine)*nLines );
368 ret->nLines = nLines;
370 // Read the file for real
372 ptr = FileData, i = 0;
379 ret->Lines[i].nParts = 0;
384 // Read leading whitespace
385 while( *ptr && (*ptr == '\t' || *ptr == ' ') ) ptr++;
388 if( *ptr == '\0' || *ptr == '\n' ) break;
390 if( *ptr == '#' || *ptr == ';' ) break;
392 ret->Lines[i].nParts ++;
396 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
401 while( *ptr && !(*ptr == '\t' || *ptr == ' ') )
405 // Allocate part list
406 ret->Lines[i].Parts = malloc( sizeof(char*) * ret->Lines[i].nParts );
409 for( ptr = start, j = 0; ; j++ )
411 // Read leading whitespace
412 while( *ptr && (*ptr == '\t' || *ptr == ' ') ) ptr++;
415 if( *ptr == '\0' || *ptr == '\n' ) break;
417 if( *ptr == '#' || *ptr == ';' ) break;
420 ret->Lines[i].Parts[j] = ptr;
425 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
430 while( *ptr && !(*ptr == '\t' || *ptr == ' ') )
434 // Break if we have reached NULL
435 if( *ptr == '\0' ) break;
436 *ptr = '\0'; // Cap off string
437 ptr ++; // And increment for the next round