748c744f0c0abf0a2e3330fb1d823b7df4b664fe
[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                 VFS_Open("/Devices/pts/vt0", VFS_OPENFLAG_READ|VFS_OPENFLAG_USER);      // 0: stdin
52                 VFS_Open("/Devices/pts/vt0", VFS_OPENFLAG_WRITE|VFS_OPENFLAG_USER);     // 1: stdout
53                 VFS_DuplicateFD(1, 2);  // 2: stderr
54                 Proc_Execve(gsInitBinary, args, &args[1], 0);
55                 Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
56         }
57         
58         // Set the debug to be echoed to the terminal
59         Log_Log("Config", "Kernel now echoes to VT7 (Ctrl-Alt-F8)");
60         Debug_SetKTerminal("/Devices/pts/vt7");
61         
62         // Run a thread to reap unowned threads
63         for( ;; )
64         {
65                  int    status;
66                 // TODO: Inform init when a thread dies
67                 int tid = Threads_WaitTID(-1, &status);
68                 Log_Debug("Thread0", "Thread %i exited with status %i", tid, status);
69         }
70 }
71
72 /**
73  * \fn void System_ParseCommandLine(char *ArgString)
74  * \brief Parses the kernel's command line and sets the environment
75  */
76 void System_ParseCommandLine(char *ArgString)
77 {
78          int    i;
79         char    *str;
80         
81         Log_Log("Config", "Kernel Invocation (%p) \"%s\"", ArgString, ArgString);
82         
83         // --- Get Arguments ---
84         str = ArgString;
85         for( argc = 0; argc < 32; argc++ )
86         {
87                 // Eat Whitespace
88                 while(*str == ' ')      str++;
89                 // Check for the end of the string
90                 if(*str == '\0') {
91                         argc--;
92                         break;
93                 }
94                 argv[argc] = str;
95                 if(*str == '"') {
96                         while(*str && !(*str == '"' && str[-1] != '\\'))
97                                 str ++;
98                 }
99                 else {
100                         while(*str && *str != ' ')
101                                 str++;
102                 }
103                 if(*str == '\0')        break;  // Check for EOS
104                 *str = '\0';    // Cap off argument string
105                 str ++; // and increment the string pointer
106         }
107         if(argc < 32)
108                 argc ++;        // Count last argument
109         
110         // --- Parse Arguments (Pass 1) ---
111         for( i = 1; i < argc; i++ )
112         {
113                 switch(argv[i][0])
114                 {
115                 // --- VFS ---
116                 // Ignored on this pass
117                 case '/':
118                         break;
119                 
120                 // --- Module Paramaters ---
121                 // -VTerm:Width=640,Height=480,Scrollback=2
122                 case '-':
123                         System_ParseModuleArgs( argv[i] );
124                         break;
125                 // --- Config Options ---
126                 // SCRIPT=/Acess/Conf/BootConf.cfg
127                 default:
128                         System_ParseSetting( argv[i] );
129                         break;
130                 }
131         }
132 }
133
134 void System_ExecuteCommandLine(void)
135 {
136          int    i;
137         if(argc > 0)
138                 LOG("Invocation '%s'", argv[0]);
139         for( i = 1; i < argc; i++ )
140         {
141                 LOG("argv[%i] = '%s'", i, argv[i]);
142                 switch(argv[i][0])
143                 {
144                 // --- VFS ---
145                 // Mount    /System=ext2:/Devices/ATA/A1
146                 // Symlink  /Acess=/System/Acess2
147                 case '/':
148                         System_ParseVFS( argv[i] );
149                         break;
150                 }
151         }
152 }
153
154 /**
155  * \fn void System_ParseVFS(char *Arg)
156  */
157 void System_ParseVFS(char *Arg)
158 {
159         char    *value;
160          int    fd;
161         
162         value = Arg;
163         // Search for the '=' token
164         while( *value && *value != '=' )
165                 value++;
166         
167         // Check if the equals was found
168         if( *value == '\0' ) {
169                 Log_Warning("Config", "Expected '=' in the string '%s'", Arg);
170                 return ;
171         }
172         
173         // Edit string
174         *value = '\0';  value ++;
175         
176         // Check assignment type
177         // - Symbolic Link <link>=<destination>
178         if(value[0] == '/')
179         {
180 //              Log_Log("Config", "Symbolic link '%s' pointing to '%s'", Arg, value);
181                 VFS_Symlink(Arg, value);
182         }
183         // - Mount <mountpoint>=<fs>:<device>
184         else
185         {
186                 char    *dev = value;
187                 // Find colon
188                 while(*dev && *dev != ':')      dev++;
189                 if(*dev) {
190                         *dev = '\0';
191                         dev++;  // Eat ':'
192                 }
193                 // Create Mountpoint
194                 if( (fd = VFS_Open(Arg, 0)) == -1 ) {
195 //                      Log_Log("Config", "Creating directory '%s'", Arg, value);
196                         VFS_MkDir( Arg );
197                 } else {
198                         VFS_Close(fd);
199                 }
200                 // Mount
201 //              Log_Log("Config", "Mounting '%s' to '%s' ('%s')", dev, Arg, value);
202                 VFS_Mount(dev, Arg, value, "");
203         }
204 }
205
206 /**
207  * \brief Parse a module argument string
208  * \param Arg   Argument string
209  */
210 void System_ParseModuleArgs(char *Arg)
211 {
212         char    *name, *args;
213          int    i;
214         
215         // Remove '-'   
216         name = Arg + 1;
217         
218         // Find the start of the args
219         i = strpos(name, ':');
220         if( i == -1 ) {
221                 Log_Warning("Config", "Module spec with no arguments");
222                 #if 1
223                 return ;
224                 #else
225                 i = strlen(name);
226                 args = name + i;
227                 #endif
228         }
229         else {
230                 name[i] = '\0';
231                 args = name + i + 1;
232         }
233         
234         Log_Log("Config", "Setting boot parameters for '%s' to '%s'", name, args);
235         Modules_SetBuiltinParams(name, args);
236 }
237
238 /**
239  * \fn void System_ParseSetting(char *Arg)
240  */
241 void System_ParseSetting(char *Arg)
242 {
243         char    *value;
244         value = Arg;
245
246         // Search for the '=' token
247         while( *value && *value != '=' )
248                 value++;
249         
250         // Check for boolean/flag (no '=')
251         if(*value == '\0')
252         {
253                 //if(strcmp(Arg, "") == 0) {
254                 //} else {
255                         Log_Warning("Config", "Kernel flag '%s' is not recognised", Arg);
256                 //}
257         }
258         else
259         {
260                 *value = '\0';  // Remove '='
261                 value ++;       // and eat it's position
262                 
263                 if(strcmp(Arg, "INIT") == 0) {
264                         Log_Log("Config", "Init binary: '%s'", value);
265                         if(strlen(value) == 0)
266                                 gsInitBinary = NULL;
267                         else
268                                 gsInitBinary = value;
269                 }
270                 else {
271                         Log_Warning("Config", "Kernel config setting '%s' is not recognised", Arg);
272                 }
273                 
274         }
275 }
276

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