2 #define UNPAGED 1 /* for proper kmain() prototype */
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>
16 #include "arch_proto.h"
18 #include "direct_utils.h"
21 #include <machine/multiboot.h>
24 #define MULTIBOOT_VERBOSE 1
27 /* to-be-built kinfo struct, diagnostics buffer */
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
)
46 char *bufend
= bigbuf
+ MULTIBOOT_PARAM_BUF_SIZE
;
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 */
57 if (strncmp(p
, name
, namelen
) == 0 && p
[namelen
] == '=') {
60 for (q
++; q
< bufend
; q
++, p
++)
69 for (p
= bigbuf
; p
< bufend
&& (*p
|| *(p
+ 1)); p
++)
73 /* Make sure there's enough space for the new parameter */
74 if (p
+ namelen
+ valuelen
+ 3 > bufend
)
79 strcpy(p
+ namelen
+ 1, value
);
80 p
[namelen
+ valuelen
+ 1] = 0;
81 p
[namelen
+ valuelen
+ 2] = 0;
85 int overlaps(multiboot_module_t
*mod
, int n
, int cmp_mod
)
87 multiboot_module_t
*cmp
= &mod
[cmp_mod
];
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
))
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
;
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
;
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
;
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
);
142 while (*p
== ' ') p
++;
144 while (*p
&& *p
!= '=' && *p
!= ' ' && var_i
< BUF
- 1)
145 var
[var_i
++] = *p
++ ;
147 if (*p
++ != '=') continue; /* skip if not name=value */
148 while (*p
&& *p
!= ' ' && value_i
< BUF
- 1)
149 value
[value_i
++] = *p
++ ;
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
) {
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
);
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
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;
204 for(m
= 0; m
< cbi
->mods_with_kernel
; m
++) {
206 printf("checking overlap of module %08lx-%08lx\n",
207 cbi
->module_list
[m
].mod_start
, cbi
->module_list
[m
].mod_end
);
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.
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.
235 kinfo
.freepde_start
= pg_mapkernel();
239 /* Done, return boot info so it can be passed to kmain(). */
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
) { }