xref: /minix3/minix/kernel/arch/i386/pre_init.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc 
2*433d6423SLionel Sambuc #define UNPAGED 1	/* for proper kmain() prototype */
3*433d6423SLionel Sambuc 
4*433d6423SLionel Sambuc #include "kernel/kernel.h"
5*433d6423SLionel Sambuc #include <assert.h>
6*433d6423SLionel Sambuc #include <stdlib.h>
7*433d6423SLionel Sambuc #include <minix/minlib.h>
8*433d6423SLionel Sambuc #include <minix/const.h>
9*433d6423SLionel Sambuc #include <minix/type.h>
10*433d6423SLionel Sambuc #include <minix/board.h>
11*433d6423SLionel Sambuc #include <minix/com.h>
12*433d6423SLionel Sambuc #include <sys/types.h>
13*433d6423SLionel Sambuc #include <sys/param.h>
14*433d6423SLionel Sambuc #include <sys/reboot.h>
15*433d6423SLionel Sambuc #include <machine/partition.h>
16*433d6423SLionel Sambuc #include "string.h"
17*433d6423SLionel Sambuc #include "arch_proto.h"
18*433d6423SLionel Sambuc #include "direct_utils.h"
19*433d6423SLionel Sambuc #include "serial.h"
20*433d6423SLionel Sambuc #include "glo.h"
21*433d6423SLionel Sambuc #include <machine/multiboot.h>
22*433d6423SLionel Sambuc 
23*433d6423SLionel Sambuc #if USE_SYSDEBUG
24*433d6423SLionel Sambuc #define MULTIBOOT_VERBOSE 1
25*433d6423SLionel Sambuc #endif
26*433d6423SLionel Sambuc 
27*433d6423SLionel Sambuc /* to-be-built kinfo struct, diagnostics buffer */
28*433d6423SLionel Sambuc kinfo_t kinfo;
29*433d6423SLionel Sambuc struct kmessages kmessages;
30*433d6423SLionel Sambuc 
31*433d6423SLionel Sambuc /* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */
32*433d6423SLionel Sambuc phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; }
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc /* mb_utils.c uses this; we can reach it directly */
35*433d6423SLionel Sambuc char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER;
36*433d6423SLionel Sambuc 
37*433d6423SLionel Sambuc /* String length used for mb_itoa */
38*433d6423SLionel Sambuc #define ITOA_BUFFER_SIZE 20
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc /* Kernel may use memory */
41*433d6423SLionel Sambuc int kernel_may_alloc = 1;
42*433d6423SLionel Sambuc 
43*433d6423SLionel Sambuc static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi)
44*433d6423SLionel Sambuc {
45*433d6423SLionel Sambuc 	char *p = bigbuf;
46*433d6423SLionel Sambuc 	char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE;
47*433d6423SLionel Sambuc 	char *q;
48*433d6423SLionel Sambuc 	int namelen = strlen(name);
49*433d6423SLionel Sambuc 	int valuelen = strlen(value);
50*433d6423SLionel Sambuc 
51*433d6423SLionel Sambuc 	/* Some variables we recognize */
52*433d6423SLionel Sambuc 	if(!strcmp(name, SERVARNAME)) { cbi->do_serial_debug = 1; }
53*433d6423SLionel Sambuc 	if(!strcmp(name, SERBAUDVARNAME)) { cbi->serial_debug_baud = atoi(value); }
54*433d6423SLionel Sambuc 
55*433d6423SLionel Sambuc 	/* Delete the item if already exists */
56*433d6423SLionel Sambuc 	while (*p) {
57*433d6423SLionel Sambuc 		if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') {
58*433d6423SLionel Sambuc 			q = p;
59*433d6423SLionel Sambuc 			while (*q) q++;
60*433d6423SLionel Sambuc 			for (q++; q < bufend; q++, p++)
61*433d6423SLionel Sambuc 				*p = *q;
62*433d6423SLionel Sambuc 			break;
63*433d6423SLionel Sambuc 		}
64*433d6423SLionel Sambuc 		while (*p++)
65*433d6423SLionel Sambuc 			;
66*433d6423SLionel Sambuc 		p++;
67*433d6423SLionel Sambuc 	}
68*433d6423SLionel Sambuc 
69*433d6423SLionel Sambuc 	for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++)
70*433d6423SLionel Sambuc 		;
71*433d6423SLionel Sambuc 	if (p > bigbuf) p++;
72*433d6423SLionel Sambuc 
73*433d6423SLionel Sambuc 	/* Make sure there's enough space for the new parameter */
74*433d6423SLionel Sambuc 	if (p + namelen + valuelen + 3 > bufend)
75*433d6423SLionel Sambuc 		return -1;
76*433d6423SLionel Sambuc 
77*433d6423SLionel Sambuc 	strcpy(p, name);
78*433d6423SLionel Sambuc 	p[namelen] = '=';
79*433d6423SLionel Sambuc 	strcpy(p + namelen + 1, value);
80*433d6423SLionel Sambuc 	p[namelen + valuelen + 1] = 0;
81*433d6423SLionel Sambuc 	p[namelen + valuelen + 2] = 0;
82*433d6423SLionel Sambuc 	return 0;
83*433d6423SLionel Sambuc }
84*433d6423SLionel Sambuc 
85*433d6423SLionel Sambuc int overlaps(multiboot_module_t *mod, int n, int cmp_mod)
86*433d6423SLionel Sambuc {
87*433d6423SLionel Sambuc 	multiboot_module_t *cmp = &mod[cmp_mod];
88*433d6423SLionel Sambuc 	int m;
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc #define INRANGE(mod, v) ((v) >= mod->mod_start && (v) < mod->mod_end)
91*433d6423SLionel Sambuc #define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \
92*433d6423SLionel Sambuc 			INRANGE(mod1, mod2->mod_end-1))
93*433d6423SLionel Sambuc 	for(m = 0; m < n; m++) {
94*433d6423SLionel Sambuc 		multiboot_module_t *thismod = &mod[m];
95*433d6423SLionel Sambuc 		if(m == cmp_mod) continue;
96*433d6423SLionel Sambuc 		if(OVERLAP(thismod, cmp))
97*433d6423SLionel Sambuc 			return 1;
98*433d6423SLionel Sambuc 	}
99*433d6423SLionel Sambuc 	return 0;
100*433d6423SLionel Sambuc }
101*433d6423SLionel Sambuc 
102*433d6423SLionel Sambuc void get_parameters(u32_t ebx, kinfo_t *cbi)
103*433d6423SLionel Sambuc {
104*433d6423SLionel Sambuc 	multiboot_memory_map_t *mmap;
105*433d6423SLionel Sambuc 	multiboot_info_t *mbi = &cbi->mbi;
106*433d6423SLionel Sambuc 	int var_i,value_i, m, k;
107*433d6423SLionel Sambuc 	char *p;
108*433d6423SLionel Sambuc 	extern char _kern_phys_base, _kern_vir_base, _kern_size,
109*433d6423SLionel Sambuc 		_kern_unpaged_start, _kern_unpaged_end;
110*433d6423SLionel Sambuc 	phys_bytes kernbase = (phys_bytes) &_kern_phys_base,
111*433d6423SLionel Sambuc 		kernsize = (phys_bytes) &_kern_size;
112*433d6423SLionel Sambuc #define BUF 1024
113*433d6423SLionel Sambuc 	static char cmdline[BUF];
114*433d6423SLionel Sambuc 
115*433d6423SLionel Sambuc 	/* get our own copy of the multiboot info struct and module list */
116*433d6423SLionel Sambuc 	memcpy((void *) mbi, (void *) ebx, sizeof(*mbi));
117*433d6423SLionel Sambuc 
118*433d6423SLionel Sambuc 	/* Set various bits of info for the higher-level kernel. */
119*433d6423SLionel Sambuc 	cbi->mem_high_phys = 0;
120*433d6423SLionel Sambuc 	cbi->user_sp = (vir_bytes) &_kern_vir_base;
121*433d6423SLionel Sambuc 	cbi->vir_kern_start = (vir_bytes) &_kern_vir_base;
122*433d6423SLionel Sambuc 	cbi->bootstrap_start = (vir_bytes) &_kern_unpaged_start;
123*433d6423SLionel Sambuc 	cbi->bootstrap_len = (vir_bytes) &_kern_unpaged_end -
124*433d6423SLionel Sambuc 		cbi->bootstrap_start;
125*433d6423SLionel Sambuc 	cbi->kmess = &kmess;
126*433d6423SLionel Sambuc 
127*433d6423SLionel Sambuc 	/* set some configurable defaults */
128*433d6423SLionel Sambuc 	cbi->do_serial_debug = 0;
129*433d6423SLionel Sambuc 	cbi->serial_debug_baud = 115200;
130*433d6423SLionel Sambuc 
131*433d6423SLionel Sambuc 	/* parse boot command line */
132*433d6423SLionel Sambuc 	if (mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) {
133*433d6423SLionel Sambuc 		static char var[BUF];
134*433d6423SLionel Sambuc 		static char value[BUF];
135*433d6423SLionel Sambuc 
136*433d6423SLionel Sambuc 		/* Override values with cmdline argument */
137*433d6423SLionel Sambuc 		memcpy(cmdline, (void *) mbi->mi_cmdline, BUF);
138*433d6423SLionel Sambuc 		p = cmdline;
139*433d6423SLionel Sambuc 		while (*p) {
140*433d6423SLionel Sambuc 			var_i = 0;
141*433d6423SLionel Sambuc 			value_i = 0;
142*433d6423SLionel Sambuc 			while (*p == ' ') p++;
143*433d6423SLionel Sambuc 			if (!*p) break;
144*433d6423SLionel Sambuc 			while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1)
145*433d6423SLionel Sambuc 				var[var_i++] = *p++ ;
146*433d6423SLionel Sambuc 			var[var_i] = 0;
147*433d6423SLionel Sambuc 			if (*p++ != '=') continue; /* skip if not name=value */
148*433d6423SLionel Sambuc 			while (*p && *p != ' ' && value_i < BUF - 1)
149*433d6423SLionel Sambuc 				value[value_i++] = *p++ ;
150*433d6423SLionel Sambuc 			value[value_i] = 0;
151*433d6423SLionel Sambuc 
152*433d6423SLionel Sambuc 			mb_set_param(cbi->param_buf, var, value, cbi);
153*433d6423SLionel Sambuc 		}
154*433d6423SLionel Sambuc 	}
155*433d6423SLionel Sambuc 
156*433d6423SLionel Sambuc         /* let higher levels know what we are booting on */
157*433d6423SLionel Sambuc         mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(BOARD_ID_INTEL), cbi);
158*433d6423SLionel Sambuc 	mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(BOARD_ID_INTEL) , cbi);
159*433d6423SLionel Sambuc 
160*433d6423SLionel Sambuc 	/* round user stack down to leave a gap to catch kernel
161*433d6423SLionel Sambuc 	 * stack overflow; and to distinguish kernel and user addresses
162*433d6423SLionel Sambuc 	 * at a glance (0xf.. vs 0xe..)
163*433d6423SLionel Sambuc 	 */
164*433d6423SLionel Sambuc 	cbi->user_sp &= 0xF0000000;
165*433d6423SLionel Sambuc 	cbi->user_end = cbi->user_sp;
166*433d6423SLionel Sambuc 
167*433d6423SLionel Sambuc 	/* kernel bytes without bootstrap code/data that is currently
168*433d6423SLionel Sambuc 	 * still needed but will be freed after bootstrapping.
169*433d6423SLionel Sambuc 	 */
170*433d6423SLionel Sambuc 	kinfo.kernel_allocated_bytes = (phys_bytes) &_kern_size;
171*433d6423SLionel Sambuc 	kinfo.kernel_allocated_bytes -= cbi->bootstrap_len;
172*433d6423SLionel Sambuc 
173*433d6423SLionel Sambuc 	assert(!(cbi->bootstrap_start % I386_PAGE_SIZE));
174*433d6423SLionel Sambuc 	cbi->bootstrap_len = rounddown(cbi->bootstrap_len, I386_PAGE_SIZE);
175*433d6423SLionel Sambuc 	assert(mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS);
176*433d6423SLionel Sambuc 	assert(mbi->mi_mods_count < MULTIBOOT_MAX_MODS);
177*433d6423SLionel Sambuc 	assert(mbi->mi_mods_count > 0);
178*433d6423SLionel Sambuc 	memcpy(&cbi->module_list, (void *) mbi->mi_mods_addr,
179*433d6423SLionel Sambuc 		mbi->mi_mods_count * sizeof(multiboot_module_t));
180*433d6423SLionel Sambuc 
181*433d6423SLionel Sambuc 	memset(cbi->memmap, 0, sizeof(cbi->memmap));
182*433d6423SLionel Sambuc 	/* mem_map has a variable layout */
183*433d6423SLionel Sambuc 	if(mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) {
184*433d6423SLionel Sambuc 		cbi->mmap_size = 0;
185*433d6423SLionel Sambuc 	        for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
186*433d6423SLionel Sambuc        	     (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
187*433d6423SLionel Sambuc        	       mmap = (multiboot_memory_map_t *)
188*433d6423SLionel Sambuc 		      	((unsigned long) mmap + mmap->mm_size + sizeof(mmap->mm_size))) {
189*433d6423SLionel Sambuc 			if(mmap->mm_type != MULTIBOOT_MEMORY_AVAILABLE) continue;
190*433d6423SLionel Sambuc 			add_memmap(cbi, mmap->mm_base_addr, mmap->mm_length);
191*433d6423SLionel Sambuc 		}
192*433d6423SLionel Sambuc 	} else {
193*433d6423SLionel Sambuc 		assert(mbi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY);
194*433d6423SLionel Sambuc 		add_memmap(cbi, 0, mbi->mi_mem_lower*1024);
195*433d6423SLionel Sambuc 		add_memmap(cbi, 0x100000, mbi->mi_mem_upper*1024);
196*433d6423SLionel Sambuc 	}
197*433d6423SLionel Sambuc 
198*433d6423SLionel Sambuc 	/* Sanity check: the kernel nor any of the modules may overlap
199*433d6423SLionel Sambuc 	 * with each other. Pretend the kernel is an extra module for a
200*433d6423SLionel Sambuc 	 * second.
201*433d6423SLionel Sambuc 	 */
202*433d6423SLionel Sambuc 	k = mbi->mi_mods_count;
203*433d6423SLionel Sambuc 	assert(k < MULTIBOOT_MAX_MODS);
204*433d6423SLionel Sambuc 	cbi->module_list[k].mod_start = kernbase;
205*433d6423SLionel Sambuc 	cbi->module_list[k].mod_end = kernbase + kernsize;
206*433d6423SLionel Sambuc 	cbi->mods_with_kernel = mbi->mi_mods_count+1;
207*433d6423SLionel Sambuc 	cbi->kern_mod = k;
208*433d6423SLionel Sambuc 
209*433d6423SLionel Sambuc 	for(m = 0; m < cbi->mods_with_kernel; m++) {
210*433d6423SLionel Sambuc #if 0
211*433d6423SLionel Sambuc 		printf("checking overlap of module %08lx-%08lx\n",
212*433d6423SLionel Sambuc 		  cbi->module_list[m].mod_start, cbi->module_list[m].mod_end);
213*433d6423SLionel Sambuc #endif
214*433d6423SLionel Sambuc 		if(overlaps(cbi->module_list, cbi->mods_with_kernel, m))
215*433d6423SLionel Sambuc 			panic("overlapping boot modules/kernel");
216*433d6423SLionel Sambuc 		/* We cut out the bits of memory that we know are
217*433d6423SLionel Sambuc 		 * occupied by the kernel and boot modules.
218*433d6423SLionel Sambuc 		 */
219*433d6423SLionel Sambuc 		cut_memmap(cbi,
220*433d6423SLionel Sambuc 			cbi->module_list[m].mod_start,
221*433d6423SLionel Sambuc 			cbi->module_list[m].mod_end);
222*433d6423SLionel Sambuc 	}
223*433d6423SLionel Sambuc }
224*433d6423SLionel Sambuc 
225*433d6423SLionel Sambuc kinfo_t *pre_init(u32_t magic, u32_t ebx)
226*433d6423SLionel Sambuc {
227*433d6423SLionel Sambuc 	assert(magic == MULTIBOOT_INFO_MAGIC);
228*433d6423SLionel Sambuc 
229*433d6423SLionel Sambuc 	/* Get our own copy boot params pointed to by ebx.
230*433d6423SLionel Sambuc 	 * Here we find out whether we should do serial output.
231*433d6423SLionel Sambuc 	 */
232*433d6423SLionel Sambuc 	get_parameters(ebx, &kinfo);
233*433d6423SLionel Sambuc 
234*433d6423SLionel Sambuc 	/* Make and load a pagetable that will map the kernel
235*433d6423SLionel Sambuc 	 * to where it should be; but first a 1:1 mapping so
236*433d6423SLionel Sambuc 	 * this code stays where it should be.
237*433d6423SLionel Sambuc 	 */
238*433d6423SLionel Sambuc 	pg_clear();
239*433d6423SLionel Sambuc 	pg_identity(&kinfo);
240*433d6423SLionel Sambuc 	kinfo.freepde_start = pg_mapkernel();
241*433d6423SLionel Sambuc 	pg_load();
242*433d6423SLionel Sambuc 	vm_enable_paging();
243*433d6423SLionel Sambuc 
244*433d6423SLionel Sambuc 	/* Done, return boot info so it can be passed to kmain(). */
245*433d6423SLionel Sambuc 	return &kinfo;
246*433d6423SLionel Sambuc }
247*433d6423SLionel Sambuc 
248*433d6423SLionel Sambuc void send_diag_sig(void) { }
249*433d6423SLionel Sambuc void minix_shutdown(minix_timer_t *t) { arch_shutdown(0); }
250*433d6423SLionel Sambuc void busy_delay_ms(int x) { }
251*433d6423SLionel Sambuc int raise(int sig) { panic("raise(%d)\n", sig); }
252