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