Working on UDI support (UDI manager module now compiles)
[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 (UDI)
251                 else if(strncmp("udimod ", fData+i, 6) == 0) {
252                         //char  *tmp;
253                         i += 7;
254                         i += System_Int_GetString(fData+i, &sArg1);
255                         if(!sArg1)      goto read2eol;
256                         Module_LoadFile(sArg1, "");
257                 }
258                 // - Load Module (EDI)
259                 else if(strncmp("edimod ", fData+i, 6) == 0) {
260                         i += 7;
261                         i += System_Int_GetString(fData+i, &sArg1);
262                         if(!sArg1)      goto read2eol;
263                         Log("[CFG  ] Load EDI Module '%s'", sArg1);
264                         Module_LoadFile(sArg1, "");
265                 }
266                 // - Symlink
267                 else if(strncmp("symlink ", fData+i, 7) == 0) {
268                         i += 8;
269                         i += System_Int_GetString(fData+i, &sArg1);
270                         if(!sArg1)      goto read2eol;
271                         i += System_Int_GetString(fData+i, &sArg2);
272                         if(!sArg2)      goto read2eol;
273                         Log("[CFG  ] Symlink '%s' pointing to '%s'", sArg1, sArg2);
274                         VFS_Symlink(sArg1, sArg2);
275                 }
276                 // - New Directory
277                 else if(strncmp("mkdir ", fData+i, 5) == 0) {
278                         i += 6;
279                         i += System_Int_GetString(fData+i, &sArg1);
280                         if(!sArg1)      goto read2eol;
281                         Log("[CFG  ] New Directory '%s'", sArg1);
282                         VFS_MkDir(sArg1);
283                 }
284                 // - Spawn a task
285                 else if(strncmp("spawn ", fData+i, 5) == 0) {
286                         i += 6;
287                         i += System_Int_GetString(fData+i, &sArg1);
288                         if(!sArg1)      goto read2eol;
289                         Log("[CFG  ] Starting '%s' as a new task", sArg1);
290                         Proc_Spawn(sArg1);
291                 }
292                 else {
293                         Warning("Unknown configuration command, Line: '%s'", fData+i);
294                         goto read2eol;
295                 }
296         read2eol:
297                 if(sArg1)       free(sArg1);
298                 if(sArg2)       free(sArg2);
299                 if(sArg3)       free(sArg3);
300                 // Skip to EOL
301                 while(i < fLen && fData[i] != '\n')     i++;
302                 i ++;   // Skip \n
303         }
304         free(fData);
305 }
306
307 /**
308  * \fn int System_Int_GetString(char *Str, char **Dest)
309  * \brief Gets a string from another
310  * \note Destructive
311  * \param Str   Input String
312  * \param Dest  Pointer to output pointer
313  * \return Characters eaten from input
314  */
315 int System_Int_GetString(char *Str, char **Dest)
316 {
317          int    pos = 0;
318          int    start = 0;
319          int    len;
320          
321         //LogF("GetString: (Str='%s', Dest=0x%x)\n", Str, Dest);
322          
323         while(Str[pos] == ' ' || Str[pos] == '\t')      pos++;
324         if(Str[pos] == '\n' || Str[pos] == '\0') {
325                 *Dest = NULL;
326                 return pos;
327         }
328         
329         // Quoted String
330         if(Str[pos] == '"')
331         {
332                 pos ++;
333                 start = pos;
334                 while(Str[pos] != '"')  pos++;
335                 
336                 len = pos - start;
337                 *Dest = malloc( len + 1 );
338                 memcpy( *Dest, Str+start, len );
339                 (*Dest)[len] = '\0';
340                 
341                 //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
342                 
343                 pos++;
344                 return pos;
345         }
346         
347         // Non-Quoted String - Whitespace deliminated
348         start = pos;
349         while(Str[pos] != ' ' && Str[pos] != '\t' && Str[pos] != '\n')  pos++;
350         
351         len = pos - start;
352         //LogF(" GetString: len = %i\n", len);
353         *Dest = malloc( len + 1 );
354         memcpy( *Dest, Str+start, len );
355         (*Dest)[len] = '\0';
356         
357         //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
358         
359         return pos;
360 }

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