Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[tpg/acess2.git] / KernelLand / Kernel / system.c
1 /*
2  * Acess 2 Kernel
3  * - By John Hodge (thePowersGang)
4  * system.c
5  * - Architecture Independent System Init
6  */
7 #define DEBUG   1
8 #include <acess.h>
9 #include <hal_proc.h>
10
11 // === IMPORTS ===
12 extern void     Arch_LoadBootModules(void);
13 extern int      Modules_LoadBuiltins(void);
14 extern void     Modules_SetBuiltinParams(char *Name, char *ArgString);
15 extern void     Debug_SetKTerminal(const char *File);
16 extern void     Timer_CallbackThread(void *);
17
18 // === PROTOTYPES ===
19 void    System_Init(char *Commandline);
20 void    System_ParseCommandLine(char *ArgString);
21 void    System_ExecuteCommandLine(void);
22 void    System_ParseVFS(char *Arg);
23 void    System_ParseModuleArgs(char *Arg);
24 void    System_ParseSetting(char *Arg);
25
26 // === GLOBALS ===
27 const char      *gsInitBinary = "/Acess/SBin/init";
28 char    *argv[32];
29  int    argc;
30
31 // === CODE ===
32 void System_Init(char *CommandLine)
33 {
34         Proc_SpawnWorker(Timer_CallbackThread, NULL);
35
36         // Parse Kernel's Command Line
37         System_ParseCommandLine(CommandLine);
38         
39         // Initialise modules
40         Log_Log("Config", "Initialising builtin modules...");
41         Modules_LoadBuiltins();
42         Arch_LoadBootModules();
43         
44         System_ExecuteCommandLine();
45         
46         // - Execute the Config Script
47         Log_Log("Config", "Spawning init '%s'", gsInitBinary);
48         if(Proc_Clone(CLONE_VM|CLONE_NOUSER) == 0)
49         {
50                 const char      *args[] = {gsInitBinary, 0};
51                 Proc_Execve(gsInitBinary, args, &args[1], 0);
52                 Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
53         }
54         
55         // Set the debug to be echoed to the terminal
56         Log_Log("Config", "Kernel now echoes to VT7 (Ctrl-Alt-F8)");
57         Debug_SetKTerminal("/Devices/VTerm/7");
58 }
59
60 /**
61  * \fn void System_ParseCommandLine(char *ArgString)
62  * \brief Parses the kernel's command line and sets the environment
63  */
64 void System_ParseCommandLine(char *ArgString)
65 {
66          int    i;
67         char    *str;
68         
69         Log_Log("Config", "Kernel Invocation (%p) \"%s\"", ArgString, ArgString);
70         
71         // --- Get Arguments ---
72         str = ArgString;
73         for( argc = 0; argc < 32; argc++ )
74         {
75                 // Eat Whitespace
76                 while(*str == ' ')      str++;
77                 // Check for the end of the string
78                 if(*str == '\0') {      argc--; break;} 
79                 argv[argc] = str;
80                 if(*str == '"') {
81                         while(*str && !(*str == '"' && str[-1] != '\\'))
82                                 str ++;
83                 }
84                 else {
85                         while(*str && *str != ' ')
86                                 str++;
87                 }
88                 if(*str == '\0')        break;  // Check for EOS
89                 *str = '\0';    // Cap off argument string
90                 str ++; // and increment the string pointer
91         }
92         if(argc < 32)
93                 argc ++;        // Count last argument
94         
95         // --- Parse Arguments (Pass 1) ---
96         for( i = 1; i < argc; i++ )
97         {
98                 switch(argv[i][0])
99                 {
100                 // --- VFS ---
101                 // Ignored on this pass
102                 case '/':
103                         break;
104                 
105                 // --- Module Paramaters ---
106                 // -VTerm:Width=640,Height=480,Scrollback=2
107                 case '-':
108                         System_ParseModuleArgs( argv[i] );
109                         break;
110                 // --- Config Options ---
111                 // SCRIPT=/Acess/Conf/BootConf.cfg
112                 default:
113                         System_ParseSetting( argv[i] );
114                         break;
115                 }
116         }
117 }
118
119 void System_ExecuteCommandLine(void)
120 {
121          int    i;
122         if(argc > 0)
123                 LOG("Invocation '%s'", argv[0]);
124         for( i = 1; i < argc; i++ )
125         {
126                 LOG("argv[%i] = '%s'", i, argv[i]);
127                 switch(argv[i][0])
128                 {
129                 // --- VFS ---
130                 // Mount    /System=ext2:/Devices/ATA/A1
131                 // Symlink  /Acess=/System/Acess2
132                 case '/':
133                         System_ParseVFS( argv[i] );
134                         break;
135                 }
136         }
137 }
138
139 /**
140  * \fn void System_ParseVFS(char *Arg)
141  */
142 void System_ParseVFS(char *Arg)
143 {
144         char    *value;
145          int    fd;
146         
147         value = Arg;
148         // Search for the '=' token
149         while( *value && *value != '=' )
150                 value++;
151         
152         // Check if the equals was found
153         if( *value == '\0' ) {
154                 Log_Warning("Config", "Expected '=' in the string '%s'", Arg);
155                 return ;
156         }
157         
158         // Edit string
159         *value = '\0';  value ++;
160         
161         // Check assignment type
162         // - Symbolic Link <link>=<destination>
163         if(value[0] == '/')
164         {
165 //              Log_Log("Config", "Symbolic link '%s' pointing to '%s'", Arg, value);
166                 VFS_Symlink(Arg, value);
167         }
168         // - Mount <mountpoint>=<fs>:<device>
169         else
170         {
171                 char    *dev = value;
172                 // Find colon
173                 while(*dev && *dev != ':')      dev++;
174                 if(*dev) {
175                         *dev = '\0';
176                         dev++;  // Eat ':'
177                 }
178                 // Create Mountpoint
179                 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
180 //                      Log_Log("Config", "Creating directory '%s'", Arg, value);
181                         VFS_MkDir( Arg );
182                 } else {
183                         VFS_Close(fd);
184                 }
185                 // Mount
186 //              Log_Log("Config", "Mounting '%s' to '%s' ('%s')", dev, Arg, value);
187                 VFS_Mount(dev, Arg, value, "");
188         }
189 }
190
191 /**
192  * \brief Parse a module argument string
193  * \param Arg   Argument string
194  */
195 void System_ParseModuleArgs(char *Arg)
196 {
197         char    *name, *args;
198          int    i;
199         
200         // Remove '-'   
201         name = Arg + 1;
202         
203         // Find the start of the args
204         i = strpos(name, ':');
205         if( i == -1 ) {
206                 Log_Warning("Config", "Module spec with no arguments");
207                 #if 1
208                 return ;
209                 #else
210                 i = strlen(name);
211                 args = name + i;
212                 #endif
213         }
214         else {
215                 name[i] = '\0';
216                 args = name + i + 1;
217         }
218         
219         Log_Log("Config", "Setting boot parameters for '%s' to '%s'", name, args);
220         Modules_SetBuiltinParams(name, args);
221 }
222
223 /**
224  * \fn void System_ParseSetting(char *Arg)
225  */
226 void System_ParseSetting(char *Arg)
227 {
228         char    *value;
229         value = Arg;
230
231         // Search for the '=' token
232         while( *value && *value != '=' )
233                 value++;
234         
235         // Check for boolean/flag (no '=')
236         if(*value == '\0')
237         {
238                 //if(strcmp(Arg, "") == 0) {
239                 //} else {
240                         Log_Warning("Config", "Kernel flag '%s' is not recognised", Arg);
241                 //}
242         }
243         else
244         {
245                 *value = '\0';  // Remove '='
246                 value ++;       // and eat it's position
247                 
248                 if(strcmp(Arg, "INIT") == 0) {
249                         Log_Log("Config", "Init binary: '%s'", value);
250                         if(strlen(value) == 0)
251                                 gsInitBinary = NULL;
252                         else
253                                 gsInitBinary = value;
254                 }
255                 else {
256                         Log_Warning("Config", "Kernel config setting '%s' is not recognised", Arg);
257                 }
258                 
259         }
260 }
261

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