1433d6423SLionel Sambuc #define UNPAGED 1 /* for proper kmain() prototype */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc #include "kernel/kernel.h"
4433d6423SLionel Sambuc #include <assert.h>
5433d6423SLionel Sambuc #include <stdlib.h>
6433d6423SLionel Sambuc #include <minix/minlib.h>
7433d6423SLionel Sambuc #include <minix/const.h>
8433d6423SLionel Sambuc #include <minix/type.h>
9433d6423SLionel Sambuc #include <minix/board.h>
10433d6423SLionel Sambuc #include <minix/com.h>
11433d6423SLionel Sambuc #include <sys/types.h>
12433d6423SLionel Sambuc #include <sys/param.h>
13433d6423SLionel Sambuc #include <sys/reboot.h>
14433d6423SLionel Sambuc #include "string.h"
15433d6423SLionel Sambuc #include "arch_proto.h"
16433d6423SLionel Sambuc #include "direct_utils.h"
17433d6423SLionel Sambuc #include "bsp_serial.h"
18433d6423SLionel Sambuc #include "glo.h"
19433d6423SLionel Sambuc #include <machine/multiboot.h>
20433d6423SLionel Sambuc
21433d6423SLionel Sambuc #if USE_SYSDEBUG
22433d6423SLionel Sambuc #define MULTIBOOT_VERBOSE 1
23433d6423SLionel Sambuc #endif
24433d6423SLionel Sambuc
25433d6423SLionel Sambuc /* to-be-built kinfo struct, diagnostics buffer */
26433d6423SLionel Sambuc kinfo_t kinfo;
27433d6423SLionel Sambuc struct kmessages kmessages;
28433d6423SLionel Sambuc
29433d6423SLionel Sambuc /* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */
vir2phys(void * addr)30433d6423SLionel Sambuc phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; }
31433d6423SLionel Sambuc
32433d6423SLionel Sambuc static void setup_mbi(multiboot_info_t *mbi, char *bootargs);
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc /* String length used for mb_itoa */
35433d6423SLionel Sambuc #define ITOA_BUFFER_SIZE 20
36433d6423SLionel Sambuc
37433d6423SLionel Sambuc /* Kernel may use memory */
38433d6423SLionel Sambuc int kernel_may_alloc = 1;
39433d6423SLionel Sambuc
40433d6423SLionel Sambuc /* kernel bss */
41433d6423SLionel Sambuc extern u32_t _edata;
42433d6423SLionel Sambuc extern u32_t _end;
43433d6423SLionel Sambuc
44433d6423SLionel Sambuc /* kernel unpaged bss */
45433d6423SLionel Sambuc extern char _kern_unpaged_edata;
46433d6423SLionel Sambuc extern char _kern_unpaged_end;
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc /**
49433d6423SLionel Sambuc *
50433d6423SLionel Sambuc * The following function combines a few things together
51433d6423SLionel Sambuc * that can well be done using standard libc like strlen/strstr
52433d6423SLionel Sambuc * and such but these are not available in pre_init stage.
53433d6423SLionel Sambuc *
54433d6423SLionel Sambuc * The function expects content to be in the form of space separated
55433d6423SLionel Sambuc * key value pairs.
56433d6423SLionel Sambuc * param content the contents to search in
57433d6423SLionel Sambuc * param key the key to find (this *should* include the key/value delimiter)
58433d6423SLionel Sambuc * param value a pointer to an initialized char * of at least value_max_len length
59433d6423SLionel Sambuc * param value_max_len the maximum length of the value to store in value including
60433d6423SLionel Sambuc * the end char
61433d6423SLionel Sambuc *
62433d6423SLionel Sambuc **/
find_value(char * content,char * key,char * value,int value_max_len)63433d6423SLionel Sambuc int find_value(char * content,char * key,char *value,int value_max_len){
64433d6423SLionel Sambuc
65433d6423SLionel Sambuc char *iter,*keyp;
66433d6423SLionel Sambuc int key_len,content_len,match_len,value_len;
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc /* return if the input is invalid */
69433d6423SLionel Sambuc if (key == NULL || content == NULL || value == NULL) {
70433d6423SLionel Sambuc return 1;
71433d6423SLionel Sambuc }
72433d6423SLionel Sambuc
73433d6423SLionel Sambuc /* find the key and content length */
74433d6423SLionel Sambuc key_len = content_len =0;
75433d6423SLionel Sambuc for(iter = key ; *iter != '\0'; iter++, key_len++);
76433d6423SLionel Sambuc for(iter = content ; *iter != '\0'; iter++, content_len++);
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc /* return if key or content length invalid */
79433d6423SLionel Sambuc if (key_len == 0 || content_len == 0) {
80433d6423SLionel Sambuc return 1;
81433d6423SLionel Sambuc }
82433d6423SLionel Sambuc
83433d6423SLionel Sambuc /* now find the key in the contents */
84433d6423SLionel Sambuc match_len =0;
85433d6423SLionel Sambuc for (iter = content ,keyp=key; match_len < key_len && *iter != '\0' ; iter++) {
86433d6423SLionel Sambuc if (*iter == *keyp) {
87433d6423SLionel Sambuc match_len++;
88433d6423SLionel Sambuc keyp++;
89433d6423SLionel Sambuc continue;
90433d6423SLionel Sambuc }
91433d6423SLionel Sambuc /* The current key does not match the value , reset */
92433d6423SLionel Sambuc match_len =0;
93433d6423SLionel Sambuc keyp=key;
94433d6423SLionel Sambuc }
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc if (match_len == key_len) {
97433d6423SLionel Sambuc printf("key found at %d %s\n", match_len, &content[match_len]);
98433d6423SLionel Sambuc value_len = 0;
99433d6423SLionel Sambuc /* copy the content to the value char iter already points to the first
100433d6423SLionel Sambuc char value */
101433d6423SLionel Sambuc while(*iter != '\0' && *iter != ' ' && value_len + 1< value_max_len) {
102433d6423SLionel Sambuc *value++ = *iter++;
103433d6423SLionel Sambuc value_len++;
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc *value='\0';
106433d6423SLionel Sambuc return 0;
107433d6423SLionel Sambuc }
108433d6423SLionel Sambuc return 1; /* not found */
109433d6423SLionel Sambuc }
110433d6423SLionel Sambuc
mb_set_param(char * bigbuf,char * name,char * value,kinfo_t * cbi)111433d6423SLionel Sambuc static int mb_set_param(char *bigbuf,char *name,char *value, kinfo_t *cbi)
112433d6423SLionel Sambuc {
113433d6423SLionel Sambuc /* bigbuf contains a list of key=value pairs separated by \0 char.
114433d6423SLionel Sambuc * The list itself is ended by a second \0 terminator*/
115433d6423SLionel Sambuc char *p = bigbuf;
116433d6423SLionel Sambuc char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE;
117433d6423SLionel Sambuc char *q;
118433d6423SLionel Sambuc int namelen = strlen(name);
119433d6423SLionel Sambuc int valuelen = strlen(value);
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc /* Some variables we recognize */
122433d6423SLionel Sambuc if(!strcmp(name, SERVARNAME)) { cbi->do_serial_debug = 1; }
123433d6423SLionel Sambuc if(!strcmp(name, SERBAUDVARNAME)) { cbi->serial_debug_baud = atoi(value); }
124433d6423SLionel Sambuc
125433d6423SLionel Sambuc /* Delete the item if already exists */
126433d6423SLionel Sambuc while (*p) {
127433d6423SLionel Sambuc if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') {
128433d6423SLionel Sambuc q = p;
129433d6423SLionel Sambuc /* let q point to the end of the entry */
130433d6423SLionel Sambuc while (*q) q++;
131433d6423SLionel Sambuc /* now copy the remained of the buffer */
132433d6423SLionel Sambuc for (q++; q < bufend; q++, p++)
133433d6423SLionel Sambuc *p = *q;
134433d6423SLionel Sambuc break;
135433d6423SLionel Sambuc }
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc /* find the end of the buffer */
138433d6423SLionel Sambuc while (*p++);
139433d6423SLionel Sambuc p++;
140433d6423SLionel Sambuc }
141433d6423SLionel Sambuc
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc /* find the first empty spot */
144433d6423SLionel Sambuc for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++);
145433d6423SLionel Sambuc
146433d6423SLionel Sambuc /* unless we are the first entry step over the delimiter */
147433d6423SLionel Sambuc if (p > bigbuf) p++;
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc /* Make sure there's enough space for the new parameter */
150433d6423SLionel Sambuc if (p + namelen + valuelen + 3 > bufend) {
151433d6423SLionel Sambuc return -1;
152433d6423SLionel Sambuc }
153433d6423SLionel Sambuc
154433d6423SLionel Sambuc strcpy(p, name);
155433d6423SLionel Sambuc p[namelen] = '=';
156433d6423SLionel Sambuc strcpy(p + namelen + 1, value);
157433d6423SLionel Sambuc p[namelen + valuelen + 1] = 0;
158433d6423SLionel Sambuc p[namelen + valuelen + 2] = 0; /* end with a second delimiter */
159433d6423SLionel Sambuc return 0;
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
overlaps(multiboot_module_t * mod,int n,int cmp_mod)162433d6423SLionel Sambuc int overlaps(multiboot_module_t *mod, int n, int cmp_mod)
163433d6423SLionel Sambuc {
164433d6423SLionel Sambuc multiboot_module_t *cmp = &mod[cmp_mod];
165433d6423SLionel Sambuc int m;
166433d6423SLionel Sambuc
167433d6423SLionel Sambuc #define INRANGE(mod, v) ((v) >= mod->mod_start && (v) <= thismod->mod_end)
168433d6423SLionel Sambuc #define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \
169433d6423SLionel Sambuc INRANGE(mod1, mod2->mod_end))
170433d6423SLionel Sambuc for(m = 0; m < n; m++) {
171433d6423SLionel Sambuc multiboot_module_t *thismod = &mod[m];
172433d6423SLionel Sambuc if(m == cmp_mod) continue;
173433d6423SLionel Sambuc if(OVERLAP(thismod, cmp)) {
174433d6423SLionel Sambuc return 1;
175433d6423SLionel Sambuc }
176433d6423SLionel Sambuc }
177433d6423SLionel Sambuc return 0;
178433d6423SLionel Sambuc }
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc /* XXX: hard-coded stuff for modules */
181433d6423SLionel Sambuc #define MB_MODS_NR NR_BOOT_MODULES
182433d6423SLionel Sambuc #define MB_MODS_BASE 0x82000000
183433d6423SLionel Sambuc #define MB_MODS_ALIGN 0x00800000 /* 8 MB */
184433d6423SLionel Sambuc #define MB_MMAP_START 0x80000000
185433d6423SLionel Sambuc #define MB_MMAP_SIZE 0x10000000 /* 256 MB */
186433d6423SLionel Sambuc
187433d6423SLionel Sambuc multiboot_module_t mb_modlist[MB_MODS_NR];
188433d6423SLionel Sambuc multiboot_memory_map_t mb_memmap;
189433d6423SLionel Sambuc
setup_mbi(multiboot_info_t * mbi,char * bootargs)190433d6423SLionel Sambuc void setup_mbi(multiboot_info_t *mbi, char *bootargs)
191433d6423SLionel Sambuc {
192433d6423SLionel Sambuc memset(mbi, 0, sizeof(*mbi));
193433d6423SLionel Sambuc mbi->flags = MULTIBOOT_INFO_MODS | MULTIBOOT_INFO_MEM_MAP |
194433d6423SLionel Sambuc MULTIBOOT_INFO_CMDLINE;
195433d6423SLionel Sambuc mbi->mi_mods_count = MB_MODS_NR;
196433d6423SLionel Sambuc mbi->mods_addr = (u32_t)&mb_modlist;
197433d6423SLionel Sambuc
198433d6423SLionel Sambuc int i;
199433d6423SLionel Sambuc for (i = 0; i < MB_MODS_NR; ++i) {
200433d6423SLionel Sambuc mb_modlist[i].mod_start = MB_MODS_BASE + i * MB_MODS_ALIGN;
201433d6423SLionel Sambuc mb_modlist[i].mod_end = mb_modlist[i].mod_start + MB_MODS_ALIGN
202433d6423SLionel Sambuc - ARM_PAGE_SIZE;
203433d6423SLionel Sambuc mb_modlist[i].cmdline = 0;
204433d6423SLionel Sambuc }
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc /* morph the bootargs into multiboot */
207433d6423SLionel Sambuc mbi->cmdline = (u32_t) bootargs;
208433d6423SLionel Sambuc
209433d6423SLionel Sambuc mbi->mmap_addr =(u32_t)&mb_memmap;
210433d6423SLionel Sambuc mbi->mmap_length = sizeof(mb_memmap);
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc mb_memmap.size = sizeof(multiboot_memory_map_t);
213433d6423SLionel Sambuc mb_memmap.mm_base_addr = MB_MMAP_START;
214433d6423SLionel Sambuc mb_memmap.mm_length = MB_MMAP_SIZE;
215433d6423SLionel Sambuc mb_memmap.type = MULTIBOOT_MEMORY_AVAILABLE;
216433d6423SLionel Sambuc }
217433d6423SLionel Sambuc
get_parameters(kinfo_t * cbi,char * bootargs)218433d6423SLionel Sambuc void get_parameters(kinfo_t *cbi, char *bootargs)
219433d6423SLionel Sambuc {
220433d6423SLionel Sambuc multiboot_memory_map_t *mmap;
221433d6423SLionel Sambuc multiboot_info_t *mbi = &cbi->mbi;
222433d6423SLionel Sambuc int var_i,value_i, m, k;
223433d6423SLionel Sambuc char *p;
224433d6423SLionel Sambuc extern char _kern_phys_base, _kern_vir_base, _kern_size,
225433d6423SLionel Sambuc _kern_unpaged_start, _kern_unpaged_end;
226433d6423SLionel Sambuc phys_bytes kernbase = (phys_bytes) &_kern_phys_base,
227433d6423SLionel Sambuc kernsize = (phys_bytes) &_kern_size;
228433d6423SLionel Sambuc #define BUF 1024
229433d6423SLionel Sambuc static char cmdline[BUF];
230433d6423SLionel Sambuc
231433d6423SLionel Sambuc /* get our own copy of the multiboot info struct and module list */
232433d6423SLionel Sambuc setup_mbi(mbi, bootargs);
233433d6423SLionel Sambuc
234433d6423SLionel Sambuc /* Set various bits of info for the higher-level kernel. */
235433d6423SLionel Sambuc cbi->mem_high_phys = 0;
236433d6423SLionel Sambuc cbi->user_sp = (vir_bytes) &_kern_vir_base;
237433d6423SLionel Sambuc cbi->vir_kern_start = (vir_bytes) &_kern_vir_base;
238433d6423SLionel Sambuc cbi->bootstrap_start = (vir_bytes) &_kern_unpaged_start;
239433d6423SLionel Sambuc cbi->bootstrap_len = (vir_bytes) &_kern_unpaged_end -
240433d6423SLionel Sambuc cbi->bootstrap_start;
241433d6423SLionel Sambuc cbi->kmess = &kmess;
242433d6423SLionel Sambuc
243433d6423SLionel Sambuc /* set some configurable defaults */
244433d6423SLionel Sambuc cbi->do_serial_debug = 1;
245433d6423SLionel Sambuc cbi->serial_debug_baud = 115200;
246433d6423SLionel Sambuc
247433d6423SLionel Sambuc /* parse boot command line */
248433d6423SLionel Sambuc if (mbi->flags&MULTIBOOT_INFO_CMDLINE) {
249433d6423SLionel Sambuc static char var[BUF];
250433d6423SLionel Sambuc static char value[BUF];
251433d6423SLionel Sambuc
252433d6423SLionel Sambuc /* Override values with cmdline argument */
253433d6423SLionel Sambuc memcpy(cmdline, (void *) mbi->cmdline, BUF);
254433d6423SLionel Sambuc p = cmdline;
255433d6423SLionel Sambuc while (*p) {
256433d6423SLionel Sambuc var_i = 0;
257433d6423SLionel Sambuc value_i = 0;
258433d6423SLionel Sambuc while (*p == ' ') p++; /* skip spaces */
259433d6423SLionel Sambuc if (!*p) break; /* is this the end? */
260433d6423SLionel Sambuc while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1)
261433d6423SLionel Sambuc var[var_i++] = *p++ ;
262433d6423SLionel Sambuc var[var_i] = 0;
263433d6423SLionel Sambuc if (*p++ != '=') continue; /* skip if not name=value */
264433d6423SLionel Sambuc while (*p && *p != ' ' && value_i < BUF - 1) {
265433d6423SLionel Sambuc value[value_i++] = *p++ ;
266433d6423SLionel Sambuc }
267433d6423SLionel Sambuc value[value_i] = 0;
268433d6423SLionel Sambuc
269433d6423SLionel Sambuc mb_set_param(cbi->param_buf, var, value, cbi);
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc }
272433d6423SLionel Sambuc
273433d6423SLionel Sambuc /* let higher levels know what we are booting on */
274433d6423SLionel Sambuc mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(machine.board_id), cbi);
275433d6423SLionel Sambuc mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(machine.board_id) , cbi);
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc
27853398d73SCristiano Giuffrida /* move user stack/data down to leave a gap to catch kernel
279433d6423SLionel Sambuc * stack overflow; and to distinguish kernel and user addresses
280433d6423SLionel Sambuc * at a glance (0xf.. vs 0xe..)
281433d6423SLionel Sambuc */
28253398d73SCristiano Giuffrida cbi->user_sp = USR_STACKTOP;
28353398d73SCristiano Giuffrida cbi->user_end = USR_DATATOP;
284433d6423SLionel Sambuc
285433d6423SLionel Sambuc /* kernel bytes without bootstrap code/data that is currently
286433d6423SLionel Sambuc * still needed but will be freed after bootstrapping.
287433d6423SLionel Sambuc */
288433d6423SLionel Sambuc kinfo.kernel_allocated_bytes = (phys_bytes) &_kern_size;
289433d6423SLionel Sambuc kinfo.kernel_allocated_bytes -= cbi->bootstrap_len;
290433d6423SLionel Sambuc
291433d6423SLionel Sambuc assert(!(cbi->bootstrap_start % ARM_PAGE_SIZE));
292433d6423SLionel Sambuc cbi->bootstrap_len = rounddown(cbi->bootstrap_len, ARM_PAGE_SIZE);
293433d6423SLionel Sambuc assert(mbi->flags & MULTIBOOT_INFO_MODS);
294433d6423SLionel Sambuc assert(mbi->mi_mods_count < MULTIBOOT_MAX_MODS);
295433d6423SLionel Sambuc assert(mbi->mi_mods_count > 0);
296433d6423SLionel Sambuc memcpy(&cbi->module_list, (void *) mbi->mods_addr,
297433d6423SLionel Sambuc mbi->mi_mods_count * sizeof(multiboot_module_t));
298433d6423SLionel Sambuc
299433d6423SLionel Sambuc memset(cbi->memmap, 0, sizeof(cbi->memmap));
300433d6423SLionel Sambuc /* mem_map has a variable layout */
301433d6423SLionel Sambuc if(mbi->flags & MULTIBOOT_INFO_MEM_MAP) {
302433d6423SLionel Sambuc cbi->mmap_size = 0;
303433d6423SLionel Sambuc for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
304433d6423SLionel Sambuc (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
305433d6423SLionel Sambuc mmap = (multiboot_memory_map_t *)
306433d6423SLionel Sambuc ((unsigned long) mmap + mmap->size + sizeof(mmap->size))) {
307433d6423SLionel Sambuc if(mmap->type != MULTIBOOT_MEMORY_AVAILABLE) continue;
308433d6423SLionel Sambuc add_memmap(cbi, mmap->mm_base_addr, mmap->mm_length);
309433d6423SLionel Sambuc }
310433d6423SLionel Sambuc } else {
311433d6423SLionel Sambuc assert(mbi->flags & MULTIBOOT_INFO_MEMORY);
312433d6423SLionel Sambuc add_memmap(cbi, 0, mbi->mem_lower_unused*1024);
313433d6423SLionel Sambuc add_memmap(cbi, 0x100000, mbi->mem_upper_unused*1024);
314433d6423SLionel Sambuc }
315433d6423SLionel Sambuc
316433d6423SLionel Sambuc /* Sanity check: the kernel nor any of the modules may overlap
317433d6423SLionel Sambuc * with each other. Pretend the kernel is an extra module for a
318433d6423SLionel Sambuc * second.
319433d6423SLionel Sambuc */
320433d6423SLionel Sambuc k = mbi->mi_mods_count;
321433d6423SLionel Sambuc assert(k < MULTIBOOT_MAX_MODS);
322433d6423SLionel Sambuc cbi->module_list[k].mod_start = kernbase;
323433d6423SLionel Sambuc cbi->module_list[k].mod_end = kernbase + kernsize;
324433d6423SLionel Sambuc cbi->mods_with_kernel = mbi->mi_mods_count+1;
325433d6423SLionel Sambuc cbi->kern_mod = k;
326433d6423SLionel Sambuc
327433d6423SLionel Sambuc for(m = 0; m < cbi->mods_with_kernel; m++) {
328433d6423SLionel Sambuc #if 0
329433d6423SLionel Sambuc printf("checking overlap of module %08lx-%08lx\n",
330433d6423SLionel Sambuc cbi->module_list[m].mod_start, cbi->module_list[m].mod_end);
331433d6423SLionel Sambuc #endif
332433d6423SLionel Sambuc if(overlaps(cbi->module_list, cbi->mods_with_kernel, m))
333433d6423SLionel Sambuc panic("overlapping boot modules/kernel");
334433d6423SLionel Sambuc /* We cut out the bits of memory that we know are
335433d6423SLionel Sambuc * occupied by the kernel and boot modules.
336433d6423SLionel Sambuc */
337433d6423SLionel Sambuc cut_memmap(cbi,
338433d6423SLionel Sambuc cbi->module_list[m].mod_start,
339433d6423SLionel Sambuc cbi->module_list[m].mod_end);
340433d6423SLionel Sambuc }
341433d6423SLionel Sambuc }
342433d6423SLionel Sambuc
343433d6423SLionel Sambuc /*
344433d6423SLionel Sambuc * During low level init many things are not supposed to work
345433d6423SLionel Sambuc * serial being one of them. We therefore can't rely on the
346433d6423SLionel Sambuc * serial to debug. POORMANS_FAILURE_NOTIFICATION can be used
347433d6423SLionel Sambuc * before we setup our own vector table and will result in calling
348433d6423SLionel Sambuc * the bootloader's debugging methods that will hopefully show some
349433d6423SLionel Sambuc * information like the currnet PC at on the serial.
350433d6423SLionel Sambuc */
351433d6423SLionel Sambuc #define POORMANS_FAILURE_NOTIFICATION asm volatile("svc #00\n")
352433d6423SLionel Sambuc
353433d6423SLionel Sambuc /* use the passed cmdline argument to determine the machine id */
set_machine_id(char * cmdline)354433d6423SLionel Sambuc void set_machine_id(char *cmdline)
355433d6423SLionel Sambuc {
356433d6423SLionel Sambuc
357433d6423SLionel Sambuc char boardname[20];
358433d6423SLionel Sambuc memset(boardname,'\0',20);
359433d6423SLionel Sambuc if (find_value(cmdline,"board_name=",boardname,20)){
360433d6423SLionel Sambuc /* we expect the bootloader to pass a board_name as argument
361433d6423SLionel Sambuc * this however did not happen and given we still are in early
362433d6423SLionel Sambuc * boot we can't use the serial. We therefore generate an interrupt
363433d6423SLionel Sambuc * and hope the bootloader will do something nice with it */
364433d6423SLionel Sambuc POORMANS_FAILURE_NOTIFICATION;
365433d6423SLionel Sambuc }
366433d6423SLionel Sambuc machine.board_id = get_board_id_by_short_name(boardname);
367433d6423SLionel Sambuc
368433d6423SLionel Sambuc if (machine.board_id ==0){
369433d6423SLionel Sambuc /* same thing as above there is no safe escape */
370433d6423SLionel Sambuc POORMANS_FAILURE_NOTIFICATION;
371433d6423SLionel Sambuc }
372433d6423SLionel Sambuc }
373433d6423SLionel Sambuc
pre_init(int argc,char ** argv)374433d6423SLionel Sambuc kinfo_t *pre_init(int argc, char **argv)
375433d6423SLionel Sambuc {
376433d6423SLionel Sambuc char *bootargs;
377433d6423SLionel Sambuc /* This is the main "c" entry point into the kernel. It gets called
378433d6423SLionel Sambuc from head.S */
379433d6423SLionel Sambuc
380433d6423SLionel Sambuc /* Clear BSS */
381433d6423SLionel Sambuc memset(&_edata, 0, (u32_t)&_end - (u32_t)&_edata);
382433d6423SLionel Sambuc memset(&_kern_unpaged_edata, 0, (u32_t)&_kern_unpaged_end - (u32_t)&_kern_unpaged_edata);
383433d6423SLionel Sambuc
384433d6423SLionel Sambuc /* we get called in a c like fashion where the first arg
385433d6423SLionel Sambuc * is the program name (load address) and the rest are
386433d6423SLionel Sambuc * arguments. by convention the second argument is the
387433d6423SLionel Sambuc * command line */
388433d6423SLionel Sambuc if (argc != 2) {
389433d6423SLionel Sambuc POORMANS_FAILURE_NOTIFICATION;
390433d6423SLionel Sambuc }
391433d6423SLionel Sambuc
392433d6423SLionel Sambuc bootargs = argv[1];
393433d6423SLionel Sambuc set_machine_id(bootargs);
394433d6423SLionel Sambuc bsp_ser_init();
395433d6423SLionel Sambuc /* Get our own copy boot params pointed to by ebx.
396433d6423SLionel Sambuc * Here we find out whether we should do serial output.
397433d6423SLionel Sambuc */
398433d6423SLionel Sambuc get_parameters(&kinfo, bootargs);
399433d6423SLionel Sambuc
400433d6423SLionel Sambuc /* Make and load a pagetable that will map the kernel
401433d6423SLionel Sambuc * to where it should be; but first a 1:1 mapping so
402433d6423SLionel Sambuc * this code stays where it should be.
403433d6423SLionel Sambuc */
404433d6423SLionel Sambuc dcache_clean(); /* clean the caches */
405433d6423SLionel Sambuc pg_clear();
406433d6423SLionel Sambuc pg_identity(&kinfo);
407433d6423SLionel Sambuc kinfo.freepde_start = pg_mapkernel();
408433d6423SLionel Sambuc pg_load();
409433d6423SLionel Sambuc vm_enable_paging();
410433d6423SLionel Sambuc
411433d6423SLionel Sambuc /* Done, return boot info so it can be passed to kmain(). */
412433d6423SLionel Sambuc return &kinfo;
413433d6423SLionel Sambuc }
414433d6423SLionel Sambuc
415433d6423SLionel Sambuc /* pre_init gets executed at the memory location where the kernel was loaded by the boot loader.
416433d6423SLionel Sambuc * at that stage we only have a minimum set of functionality present (all symbols gets renamed to
417433d6423SLionel Sambuc * ensure this). The following methods are used in that context. Once we jump to kmain they are no
418433d6423SLionel Sambuc * longer used and the "real" implementations are visible
419433d6423SLionel Sambuc */
send_diag_sig(void)420433d6423SLionel Sambuc void send_diag_sig(void) { }
minix_shutdown(int how)421*cfd712b4SDavid van Moolenbroek void minix_shutdown(int how) { arch_shutdown(how); }
busy_delay_ms(int x)422433d6423SLionel Sambuc void busy_delay_ms(int x) { }
raise(int n)423433d6423SLionel Sambuc int raise(int n) { panic("raise(%d)\n", n); }
kern_phys_map_ptr(phys_bytes base_address,vir_bytes io_size,int vm_flags,struct kern_phys_map * priv,vir_bytes ptr)424433d6423SLionel Sambuc int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size, int vm_flags,
4253c8950ccSBen Gras struct kern_phys_map * priv, vir_bytes ptr) { return -1; };
426433d6423SLionel Sambuc struct machine machine; /* pre init stage machine */
427