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

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