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

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