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