#define UNPAGED 1 /* for proper kmain() prototype */ #include "kernel.h" #include #include #include #include #include #include #include #include #include #include #include "string.h" #include "arch_proto.h" #include "libexec.h" #include "direct_utils.h" #include "serial.h" #include "glo.h" #include #if USE_SYSDEBUG #define MULTIBOOT_VERBOSE 1 #endif /* to-be-built kinfo struct, diagnostics buffer */ kinfo_t kinfo; struct kmessages kmessages; /* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */ phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; } /* mb_utils.c uses this; we can reach it directly */ char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER; /* String length used for mb_itoa */ #define ITOA_BUFFER_SIZE 20 /* Kernel may use memory */ int kernel_may_alloc = 1; static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) { char *p = bigbuf; char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE; char *q; int namelen = strlen(name); int valuelen = strlen(value); /* Some variables we recognize */ if(!strcmp(name, SERVARNAME)) { cbi->do_serial_debug = 1; } if(!strcmp(name, SERBAUDVARNAME)) { cbi->serial_debug_baud = atoi(value); } /* Delete the item if already exists */ while (*p) { if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') { q = p; while (*q) q++; for (q++; q < bufend; q++, p++) *p = *q; break; } while (*p++) ; p++; } for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++) ; if (p > bigbuf) p++; /* Make sure there's enough space for the new parameter */ if (p + namelen + valuelen + 3 > bufend) return -1; strcpy(p, name); p[namelen] = '='; strcpy(p + namelen + 1, value); p[namelen + valuelen + 1] = 0; p[namelen + valuelen + 2] = 0; return 0; } int overlaps(multiboot_module_t *mod, int n, int cmp_mod) { multiboot_module_t *cmp = &mod[cmp_mod]; int m; #define INRANGE(mod, v) ((v) >= mod->mod_start && (v) <= thismod->mod_end) #define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \ INRANGE(mod1, mod2->mod_end)) for(m = 0; m < n; m++) { multiboot_module_t *thismod = &mod[m]; if(m == cmp_mod) continue; if(OVERLAP(thismod, cmp)) return 1; } return 0; } void get_parameters(u32_t ebx, kinfo_t *cbi) { multiboot_memory_map_t *mmap; multiboot_info_t *mbi = &cbi->mbi; int var_i,value_i, m, k; char *p; extern char _kern_phys_base, _kern_vir_base, _kern_size, _kern_unpaged_start, _kern_unpaged_end; phys_bytes kernbase = (phys_bytes) &_kern_phys_base, kernsize = (phys_bytes) &_kern_size; #define BUF 1024 static char cmdline[BUF]; /* get our own copy of the multiboot info struct and module list */ memcpy((void *) mbi, (void *) ebx, sizeof(*mbi)); /* Set various bits of info for the higher-level kernel. */ cbi->mem_high_phys = 0; cbi->user_sp = (vir_bytes) &_kern_vir_base; cbi->vir_kern_start = (vir_bytes) &_kern_vir_base; cbi->bootstrap_start = (vir_bytes) &_kern_unpaged_start; cbi->bootstrap_len = (vir_bytes) &_kern_unpaged_end - cbi->bootstrap_start; cbi->kmess = &kmess; /* set some configurable defaults */ cbi->do_serial_debug = 0; cbi->serial_debug_baud = 115200; /* parse boot command line */ if (mbi->flags&MULTIBOOT_INFO_CMDLINE) { static char var[BUF]; static char value[BUF]; /* Override values with cmdline argument */ memcpy(cmdline, (void *) mbi->cmdline, BUF); p = cmdline; while (*p) { var_i = 0; value_i = 0; while (*p == ' ') p++; if (!*p) break; while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1) var[var_i++] = *p++ ; var[var_i] = 0; if (*p++ != '=') continue; /* skip if not name=value */ while (*p && *p != ' ' && value_i < BUF - 1) value[value_i++] = *p++ ; value[value_i] = 0; mb_set_param(cbi->param_buf, var, value, cbi); } } /* round user stack down to leave a gap to catch kernel * stack overflow; and to distinguish kernel and user addresses * at a glance (0xf.. vs 0xe..) */ cbi->user_sp &= 0xF0000000; cbi->user_end = cbi->user_sp; assert(!(cbi->bootstrap_start % I386_PAGE_SIZE)); cbi->bootstrap_len = rounddown(cbi->bootstrap_len, I386_PAGE_SIZE); assert(mbi->flags & MULTIBOOT_INFO_MODS); assert(mbi->mods_count < MULTIBOOT_MAX_MODS); assert(mbi->mods_count > 0); memcpy(&cbi->module_list, (void *) mbi->mods_addr, mbi->mods_count * sizeof(multiboot_module_t)); memset(cbi->memmap, 0, sizeof(cbi->memmap)); /* mem_map has a variable layout */ if(mbi->flags & MULTIBOOT_INFO_MEM_MAP) { cbi->mmap_size = 0; for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr; (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size))) { if(mmap->type != MULTIBOOT_MEMORY_AVAILABLE) continue; add_memmap(cbi, mmap->addr, mmap->len); } } else { assert(mbi->flags & MULTIBOOT_INFO_MEMORY); add_memmap(cbi, 0, mbi->mem_lower_unused*1024); add_memmap(cbi, 0x100000, mbi->mem_upper_unused*1024); } /* Sanity check: the kernel nor any of the modules may overlap * with each other. Pretend the kernel is an extra module for a * second. */ k = mbi->mods_count; assert(k < MULTIBOOT_MAX_MODS); cbi->module_list[k].mod_start = kernbase; cbi->module_list[k].mod_end = kernbase + kernsize; cbi->mods_with_kernel = mbi->mods_count+1; cbi->kern_mod = k; for(m = 0; m < cbi->mods_with_kernel; m++) { #if 0 printf("checking overlap of module %08lx-%08lx\n", cbi->module_list[m].mod_start, cbi->module_list[m].mod_end); #endif if(overlaps(cbi->module_list, cbi->mods_with_kernel, m)) panic("overlapping boot modules/kernel"); /* We cut out the bits of memory that we know are * occupied by the kernel and boot modules. */ cut_memmap(cbi, cbi->module_list[m].mod_start, cbi->module_list[m].mod_end); } } kinfo_t *pre_init(u32_t magic, u32_t ebx) { /* Get our own copy boot params pointed to by ebx. * Here we find out whether we should do serial output. */ get_parameters(ebx, &kinfo); assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); /* Make and load a pagetable that will map the kernel * to where it should be; but first a 1:1 mapping so * this code stays where it should be. */ pg_clear(); pg_identity(&kinfo); kinfo.freepde_start = pg_mapkernel(); pg_load(); vm_enable_paging(); /* Done, return boot info so it can be passed to kmain(). */ return &kinfo; } int send_sig(endpoint_t proc_nr, int sig_nr) { return 0; } void minix_shutdown(timer_t *t) { arch_shutdown(RBT_PANIC); } void busy_delay_ms(int x) { }