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