2 #define UNPAGED 1 /* for proper kmain() prototype */
6 #include <minix/minlib.h>
7 #include <minix/board.h>
8 #include <sys/reboot.h>
9 #include <machine/partition.h>
11 #include "direct_utils.h"
16 #define MULTIBOOT_VERBOSE 1
19 /* to-be-built kinfo struct, diagnostics buffer */
21 struct kmessages kmessages
;
23 /* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */
24 phys_bytes
vir2phys(void *addr
) { return (phys_bytes
) addr
; }
26 /* mb_utils.c uses this; we can reach it directly */
27 char *video_mem
= (char *) MULTIBOOT_VIDEO_BUFFER
;
29 /* String length used for mb_itoa */
30 #define ITOA_BUFFER_SIZE 20
32 /* Kernel may use memory */
33 int kernel_may_alloc
= 1;
35 static int mb_set_param(char *bigbuf
, char *name
, char *value
, kinfo_t
*cbi
)
38 char *bufend
= bigbuf
+ MULTIBOOT_PARAM_BUF_SIZE
;
40 int namelen
= strlen(name
);
41 int valuelen
= strlen(value
);
43 /* Some variables we recognize */
44 if(!strcmp(name
, SERVARNAME
)) { cbi
->do_serial_debug
= 1; }
45 if(!strcmp(name
, SERBAUDVARNAME
)) { cbi
->serial_debug_baud
= atoi(value
); }
47 /* Delete the item if already exists */
49 if (strncmp(p
, name
, namelen
) == 0 && p
[namelen
] == '=') {
52 for (q
++; q
< bufend
; q
++, p
++)
61 for (p
= bigbuf
; p
< bufend
&& (*p
|| *(p
+ 1)); p
++)
65 /* Make sure there's enough space for the new parameter */
66 if (p
+ namelen
+ valuelen
+ 3 > bufend
)
71 strcpy(p
+ namelen
+ 1, value
);
72 p
[namelen
+ valuelen
+ 1] = 0;
73 p
[namelen
+ valuelen
+ 2] = 0;
77 int overlaps(multiboot_module_t
*mod
, int n
, int cmp_mod
)
79 multiboot_module_t
*cmp
= &mod
[cmp_mod
];
82 #define INRANGE(mod, v) ((v) >= mod->mod_start && (v) < mod->mod_end)
83 #define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \
84 INRANGE(mod1, mod2->mod_end-1))
85 for(m
= 0; m
< n
; m
++) {
86 multiboot_module_t
*thismod
= &mod
[m
];
87 if(m
== cmp_mod
) continue;
88 if(OVERLAP(thismod
, cmp
))
94 void get_parameters(u32_t ebx
, kinfo_t
*cbi
)
96 multiboot_memory_map_t
*mmap
;
97 multiboot_info_t
*mbi
= &cbi
->mbi
;
98 int var_i
,value_i
, m
, k
;
100 extern char _kern_phys_base
, _kern_vir_base
, _kern_size
,
101 _kern_unpaged_start
, _kern_unpaged_end
;
102 phys_bytes kernbase
= (phys_bytes
) &_kern_phys_base
,
103 kernsize
= (phys_bytes
) &_kern_size
;
105 static char cmdline
[BUF
];
107 /* get our own copy of the multiboot info struct and module list */
108 memcpy((void *) mbi
, (void *) ebx
, sizeof(*mbi
));
110 /* Set various bits of info for the higher-level kernel. */
111 cbi
->mem_high_phys
= 0;
112 cbi
->user_sp
= (vir_bytes
) &_kern_vir_base
;
113 cbi
->vir_kern_start
= (vir_bytes
) &_kern_vir_base
;
114 cbi
->bootstrap_start
= (vir_bytes
) &_kern_unpaged_start
;
115 cbi
->bootstrap_len
= (vir_bytes
) &_kern_unpaged_end
-
116 cbi
->bootstrap_start
;
119 /* set some configurable defaults */
120 cbi
->do_serial_debug
= 0;
121 cbi
->serial_debug_baud
= 115200;
123 /* parse boot command line */
124 if (mbi
->mi_flags
& MULTIBOOT_INFO_HAS_CMDLINE
) {
125 static char var
[BUF
];
126 static char value
[BUF
];
128 /* Override values with cmdline argument */
129 memcpy(cmdline
, (void *) mbi
->mi_cmdline
, BUF
);
134 while (*p
== ' ') p
++;
136 while (*p
&& *p
!= '=' && *p
!= ' ' && var_i
< BUF
- 1)
137 var
[var_i
++] = *p
++ ;
139 if (*p
++ != '=') continue; /* skip if not name=value */
140 while (*p
&& *p
!= ' ' && value_i
< BUF
- 1)
141 value
[value_i
++] = *p
++ ;
144 mb_set_param(cbi
->param_buf
, var
, value
, cbi
);
148 /* let higher levels know what we are booting on */
149 mb_set_param(cbi
->param_buf
, ARCHVARNAME
, (char *)get_board_arch_name(BOARD_ID_INTEL
), cbi
);
150 mb_set_param(cbi
->param_buf
, BOARDVARNAME
,(char *)get_board_name(BOARD_ID_INTEL
) , cbi
);
152 /* move user stack/data down to leave a gap to catch kernel
153 * stack overflow; and to distinguish kernel and user addresses
154 * at a glance (0xf.. vs 0xe..)
156 cbi
->user_sp
= USR_STACKTOP
;
157 cbi
->user_end
= USR_DATATOP
;
159 /* kernel bytes without bootstrap code/data that is currently
160 * still needed but will be freed after bootstrapping.
162 kinfo
.kernel_allocated_bytes
= (phys_bytes
) &_kern_size
;
163 kinfo
.kernel_allocated_bytes
-= cbi
->bootstrap_len
;
165 assert(!(cbi
->bootstrap_start
% I386_PAGE_SIZE
));
166 cbi
->bootstrap_len
= rounddown(cbi
->bootstrap_len
, I386_PAGE_SIZE
);
167 assert(mbi
->mi_flags
& MULTIBOOT_INFO_HAS_MODS
);
168 assert(mbi
->mi_mods_count
< MULTIBOOT_MAX_MODS
);
169 assert(mbi
->mi_mods_count
> 0);
170 memcpy(&cbi
->module_list
, (void *) mbi
->mi_mods_addr
,
171 mbi
->mi_mods_count
* sizeof(multiboot_module_t
));
173 memset(cbi
->memmap
, 0, sizeof(cbi
->memmap
));
174 /* mem_map has a variable layout */
175 if(mbi
->mi_flags
& MULTIBOOT_INFO_HAS_MMAP
) {
177 for (mmap
= (multiboot_memory_map_t
*) mbi
->mmap_addr
;
178 (unsigned long) mmap
< mbi
->mmap_addr
+ mbi
->mmap_length
;
179 mmap
= (multiboot_memory_map_t
*)
180 ((unsigned long) mmap
+ mmap
->mm_size
+ sizeof(mmap
->mm_size
))) {
181 if(mmap
->mm_type
!= MULTIBOOT_MEMORY_AVAILABLE
) continue;
182 add_memmap(cbi
, mmap
->mm_base_addr
, mmap
->mm_length
);
185 assert(mbi
->mi_flags
& MULTIBOOT_INFO_HAS_MEMORY
);
186 add_memmap(cbi
, 0, mbi
->mi_mem_lower
*1024);
187 add_memmap(cbi
, 0x100000, mbi
->mi_mem_upper
*1024);
190 /* Sanity check: the kernel nor any of the modules may overlap
191 * with each other. Pretend the kernel is an extra module for a
194 k
= mbi
->mi_mods_count
;
195 assert(k
< MULTIBOOT_MAX_MODS
);
196 cbi
->module_list
[k
].mod_start
= kernbase
;
197 cbi
->module_list
[k
].mod_end
= kernbase
+ kernsize
;
198 cbi
->mods_with_kernel
= mbi
->mi_mods_count
+1;
201 for(m
= 0; m
< cbi
->mods_with_kernel
; m
++) {
203 printf("checking overlap of module %08lx-%08lx\n",
204 cbi
->module_list
[m
].mod_start
, cbi
->module_list
[m
].mod_end
);
206 if(overlaps(cbi
->module_list
, cbi
->mods_with_kernel
, m
))
207 panic("overlapping boot modules/kernel");
208 /* We cut out the bits of memory that we know are
209 * occupied by the kernel and boot modules.
212 cbi
->module_list
[m
].mod_start
,
213 cbi
->module_list
[m
].mod_end
);
217 kinfo_t
*pre_init(u32_t magic
, u32_t ebx
)
219 assert(magic
== MULTIBOOT_INFO_MAGIC
);
221 /* Get our own copy boot params pointed to by ebx.
222 * Here we find out whether we should do serial output.
224 get_parameters(ebx
, &kinfo
);
226 /* Make and load a pagetable that will map the kernel
227 * to where it should be; but first a 1:1 mapping so
228 * this code stays where it should be.
232 kinfo
.freepde_start
= pg_mapkernel();
236 /* Done, return boot info so it can be passed to kmain(). */
240 void send_diag_sig(void) { }
241 void minix_shutdown(int how
) { arch_shutdown(how
); }
242 void busy_delay_ms(int x
) { }
243 int raise(int sig
) { panic("raise(%d)\n", sig
); }