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 // - Start Builtin Drivers & Filesystems
44 StartupPrint("Scanning PCI Bus...");
46 StartupPrint("Loading DMA...");
48 StartupPrint("Loading staticly compiled modules...");
49 Modules_LoadBuiltins();
51 // Set the debug to be echoed to the terminal
52 StartupPrint("Kernel now echoes to VT6 (Ctrl-Alt-F7)");
53 Debug_SetKTerminal("/Devices/VTerm/6");
55 // - Parse Kernel's Command Line
56 System_ParseCommandLine(ArgString);
58 // - Execute the Config Script
59 Log("Executing config script...");
60 System_ExecuteScript();
64 * \fn void System_ParseCommandLine(char *ArgString)
65 * \brief Parses the kernel's command line and sets the environment
67 void System_ParseCommandLine(char *ArgString)
74 Log("Kernel Command Line: \"%s\"", ArgString);
76 // --- Get Arguments ---
78 for( argc = 0; argc < 32; argc++ )
80 while(*str == ' ') str++; // Eat Whitespace
81 if(*str == '\0') { argc--; break;} // End of string
83 while(*str && *str != ' ')
86 while(*str && !(*str == '"' && str[-1] != '\\'))
91 if(*str == '\0') break; // End of string
92 *str = '\0'; // Cap off argument string
93 str ++; // and increment the string pointer
96 argc ++; // Count last argument
98 // --- Parse Arguments ---
99 for( i = 1; i < argc; i++ )
101 if( argv[i][0] == '/' )
102 System_ParseVFS( argv[i] );
104 System_ParseSetting( argv[i] );
109 * \fn void System_ParseVFS(char *Arg)
111 void System_ParseVFS(char *Arg)
117 // Search for the '=' token
118 while( *value && *value != '=' )
121 // Check if the equals was found
122 if( *value == '\0' ) {
123 Warning("Expected '=' in the string '%s'", Arg);
128 *value = '\0'; value ++;
130 // Check assignment type
131 // - Symbolic Link <link>=<destination>
134 Log("Symbolic link '%s' pointing to '%s'", Arg, value);
135 VFS_Symlink(Arg, value);
137 // - Mount <mountpoint>=<fs>:<device>
142 while(*dev && *dev != ':') dev++;
148 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
149 Log("Creating directory '%s'", Arg, value);
155 Log("Mounting '%s' to '%s' ('%s')", dev, Arg, value);
156 VFS_Mount(dev, Arg, value, "");
161 * \fn void System_ParseSetting(char *Arg)
163 void System_ParseSetting(char *Arg)
168 // Search for the '=' token
169 while( *value && *value != '=' )
172 // Check for boolean/flag (no '=')
175 if(strcmp(Arg, "") == 0) {
177 Warning("Kernel flag '%s' is not recognised", Arg);
182 *value = '\0'; // Remove '='
183 value ++; // and eat it's position
185 if(strcmp(Arg, "SCRIPT") == 0) {
186 Log("Config Script: '%s'", value);
187 gsConfigScript = value;
189 Warning("Kernel config setting '%s' is not recognised", Arg);
196 * \fn void System_ExecuteScript()
198 void System_ExecuteScript()
208 fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
210 Warning("[CFG] Passed script '%s' does not exist", gsConfigScript);
214 // Read into memory buffer
215 VFS_Seek(fp, 0, SEEK_END);
217 VFS_Seek(fp, 0, SEEK_SET);
218 fData = malloc(fLen+1);
219 VFS_Read(fp, fLen, fData);
226 file = System_Int_ParseFile(fData);
229 for( i = 0; i < file->nLines; i++ )
231 line = &file->Lines[i];
232 if( line->nParts == 0 ) continue; // Skip blank
235 if( strcmp(line->Parts[0], "mount") == 0 ) {
236 if( line->nParts != 4 ) {
237 Warning("Configuration command 'mount' requires 3 arguments, %i given",
241 //Log("[CFG ] Mount '%s' to '%s' (%s)",
242 // line->Parts[1], line->Parts[2], line->Parts[3]);
243 //! \todo Use an optional 4th argument for the options string
244 VFS_Mount(line->Parts[1], line->Parts[2], line->Parts[3], "");
247 else if(strcmp(line->Parts[0], "module") == 0) {
248 if( line->nParts < 2 || line->nParts > 3 ) {
249 Warning("Configuration command 'module' requires 1 or 2 arguments, %i given",
253 if( line->nParts == 3 )
254 Module_LoadFile(line->Parts[1], line->Parts[2]);
256 Module_LoadFile(line->Parts[1], "");
259 else if(strcmp(line->Parts[0], "udimod") == 0) {
260 if( line->nParts != 2 ) {
261 Warning("Configuration command 'udimod' requires 1 argument, %i given",
265 Log("[CFG ] Load UDI Module '%s'", line->Parts[1]);
266 Module_LoadFile(line->Parts[1], "");
269 else if(strcmp(line->Parts[0], "edimod") == 0) {
270 if( line->nParts != 2 ) {
271 Warning("Configuration command 'edimod' requires 1 argument, %i given",
275 Log("[CFG ] Load EDI Module '%s'", line->Parts[1]);
276 Module_LoadFile(line->Parts[1], "");
279 else if(strcmp(line->Parts[0], "symlink") == 0) {
280 if( line->nParts != 3 ) {
281 Warning("Configuration command 'symlink' requires 2 arguments, %i given",
285 Log("[CFG ] Symlink '%s' pointing to '%s'",
286 line->Parts[1], line->Parts[2]);
287 VFS_Symlink(line->Parts[1], line->Parts[2]);
290 else if(strcmp(line->Parts[0], "mkdir") == 0) {
291 if( line->nParts != 2 ) {
292 Warning("Configuration command 'mkdir' requires 1 argument, %i given",
296 Log("[CFG ] New Directory '%s'", line->Parts[1]);
297 VFS_MkDir(line->Parts[1]);
300 else if(strcmp(line->Parts[0], "spawn") == 0) {
301 if( line->nParts != 2 ) {
302 Warning("Configuration command 'spawn' requires 1 argument, %i given",
306 Log("[CFG ] Starting '%s' as a new task", line->Parts[1]);
307 Proc_Spawn(line->Parts[1]);
310 Warning("Unknown configuration command '%s' on line %i",
317 // Clean up after ourselves
318 for( i = 0; i < file->nLines; i++ ) {
319 if( file->Lines[i].nParts == 0 ) continue; // Skip blank
320 free( file->Lines[i].Parts );
327 * \brief Parses a config file
328 * \param FileData Read/Write buffer containing the config file data
330 * \return ::tConfigFile structure that represents the original contents
333 tConfigFile *System_Int_ParseFile(char *FileData)
341 ENTER("pFileData", FileData);
343 // Prescan and count the number of lines
344 for(ptr = FileData; *ptr; ptr++)
346 if(*ptr != '\n') continue;
348 if(ptr == FileData) {
354 if(ptr[-1] == '\\') continue;
359 LOG("nLines = %i", nLines);
361 // Ok so we have `nLines` lines, now to allocate our return
362 ret = malloc( sizeof(tConfigFile) + sizeof(tConfigLine)*nLines );
363 ret->nLines = nLines;
365 // Read the file for real
367 ptr = FileData, i = 0;
374 ret->Lines[i].nParts = 0;
379 // Read leading whitespace
380 while( *ptr == '\t' || *ptr == ' ' ) ptr++;
383 if( *ptr == '\0' || *ptr == '\n' ) {
384 if(*ptr == '\n') ptr ++;
388 if( *ptr == '#' || *ptr == ';' ) {
389 while( *ptr && *ptr != '\n' ) ptr ++;
390 if(*ptr == '\n') ptr ++;
394 ret->Lines[i].nParts ++;
398 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
403 while( *ptr && !(*ptr == '\t' || *ptr == ' ') && *ptr != '\n' )
407 LOG("ret->Lines[%i].nParts = %i", i, ret->Lines[i].nParts);
409 if( ret->Lines[i].nParts == 0 ) {
410 ret->Lines[i].Parts = NULL;
414 // Allocate part list
415 ret->Lines[i].Parts = malloc( sizeof(char*) * ret->Lines[i].nParts );
418 for( ptr = start, j = 0; ; j++ )
420 // Read leading whitespace
421 while( *ptr == '\t' || *ptr == ' ' ) ptr++;
424 if( *ptr == '\0' || *ptr == '\n' ) {
425 if(*ptr == '\n') ptr ++;
429 if( *ptr == '#' || *ptr == ';' ) {
430 while( *ptr && *ptr != '\n' ) ptr ++;
431 if(*ptr == '\n') ptr ++;
435 ret->Lines[i].Parts[j] = ptr;
440 while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
445 while( *ptr != '\t' && *ptr != ' ' && *ptr != '\n' )
449 // Break if we have reached NULL
451 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
456 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
460 *ptr = '\0'; // Cap off string
461 LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
462 ptr ++; // And increment for the next round