2 #define UNPAGED 1 /* for proper kmain() prototype */
4 #include "kernel/kernel.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>
17 #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) < 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
))
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
->mi_flags
& MULTIBOOT_INFO_HAS_CMDLINE
) {
133 static char var
[BUF
];
134 static char value
[BUF
];
136 /* Override values with cmdline argument */
137 memcpy(cmdline
, (void *) mbi
->mi_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 /* 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
);
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..)
164 cbi
->user_sp
&= 0xF0000000;
165 cbi
->user_end
= cbi
->user_sp
;
167 /* kernel bytes without bootstrap code/data that is currently
168 * still needed but will be freed after bootstrapping.
170 kinfo
.kernel_allocated_bytes
= (phys_bytes
) &_kern_size
;
171 kinfo
.kernel_allocated_bytes
-= cbi
->bootstrap_len
;
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
));
181 memset(cbi
->memmap
, 0, sizeof(cbi
->memmap
));
182 /* mem_map has a variable layout */
183 if(mbi
->mi_flags
& MULTIBOOT_INFO_HAS_MMAP
) {
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
);
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);
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
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;
209 for(m
= 0; m
< cbi
->mods_with_kernel
; m
++) {
211 printf("checking overlap of module %08lx-%08lx\n",
212 cbi
->module_list
[m
].mod_start
, cbi
->module_list
[m
].mod_end
);
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.
220 cbi
->module_list
[m
].mod_start
,
221 cbi
->module_list
[m
].mod_end
);
225 kinfo_t
*pre_init(u32_t magic
, u32_t ebx
)
227 /* Get our own copy boot params pointed to by ebx.
228 * Here we find out whether we should do serial output.
230 get_parameters(ebx
, &kinfo
);
232 assert(magic
== MULTIBOOT_INFO_MAGIC
);
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.
240 kinfo
.freepde_start
= pg_mapkernel();
244 /* Done, return boot info so it can be passed to kmain(). */
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
); }