Rev 4015 | Rev 4026 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4015 | Rev 4022 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2001-2004 Jakub Jermar |
2 | * Copyright (c) 2001-2004 Jakub Jermar |
3 | * Copyright (c) 2009 Jiri Svoboda |
3 | * Copyright (c) 2009 Jiri Svoboda |
4 | * Copyright (c) 2009 Martin Decky |
4 | * Copyright (c) 2009 Martin Decky |
5 | * All rights reserved. |
5 | * All rights reserved. |
6 | * |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
9 | * are met: |
10 | * |
10 | * |
11 | * - Redistributions of source code must retain the above copyright |
11 | * - Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * - Redistributions in binary form must reproduce the above copyright |
13 | * - Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
15 | * documentation and/or other materials provided with the distribution. |
16 | * - The name of the author may not be used to endorse or promote products |
16 | * - The name of the author may not be used to endorse or promote products |
17 | * derived from this software without specific prior written permission. |
17 | * derived from this software without specific prior written permission. |
18 | * |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
29 | */ |
30 | 30 | ||
31 | /** @addtogroup ia32 |
31 | /** @addtogroup ia32 |
32 | * @{ |
32 | * @{ |
33 | */ |
33 | */ |
34 | /** @file |
34 | /** @file |
35 | */ |
35 | */ |
36 | 36 | ||
37 | #include <arch.h> |
37 | #include <arch.h> |
38 | 38 | ||
39 | #include <arch/types.h> |
39 | #include <arch/types.h> |
40 | 40 | ||
41 | #include <arch/pm.h> |
41 | #include <arch/pm.h> |
42 | 42 | ||
- | 43 | #include <genarch/multiboot/multiboot.h> |
|
43 | #include <genarch/drivers/legacy/ia32/io.h> |
44 | #include <genarch/drivers/legacy/ia32/io.h> |
44 | #include <genarch/drivers/ega/ega.h> |
45 | #include <genarch/drivers/ega/ega.h> |
45 | #include <arch/drivers/vesa.h> |
46 | #include <arch/drivers/vesa.h> |
46 | #include <genarch/kbd/i8042.h> |
47 | #include <genarch/kbd/i8042.h> |
47 | #include <arch/drivers/i8254.h> |
48 | #include <arch/drivers/i8254.h> |
48 | #include <arch/drivers/i8259.h> |
49 | #include <arch/drivers/i8259.h> |
49 | 50 | ||
50 | #include <arch/context.h> |
51 | #include <arch/context.h> |
51 | 52 | ||
52 | #include <config.h> |
53 | #include <config.h> |
53 | 54 | ||
54 | #include <arch/interrupt.h> |
55 | #include <arch/interrupt.h> |
55 | #include <arch/asm.h> |
56 | #include <arch/asm.h> |
56 | #include <genarch/acpi/acpi.h> |
57 | #include <genarch/acpi/acpi.h> |
57 | 58 | ||
58 | #include <arch/bios/bios.h> |
59 | #include <arch/bios/bios.h> |
59 | 60 | ||
60 | #include <interrupt.h> |
61 | #include <interrupt.h> |
61 | #include <ddi/irq.h> |
62 | #include <ddi/irq.h> |
62 | #include <arch/debugger.h> |
63 | #include <arch/debugger.h> |
63 | #include <proc/thread.h> |
64 | #include <proc/thread.h> |
64 | #include <syscall/syscall.h> |
65 | #include <syscall/syscall.h> |
65 | #include <console/console.h> |
66 | #include <console/console.h> |
66 | #include <ddi/device.h> |
67 | #include <ddi/device.h> |
67 | #include <sysinfo/sysinfo.h> |
68 | #include <sysinfo/sysinfo.h> |
68 | #include <arch/boot/boot.h> |
69 | #include <arch/boot/boot.h> |
69 | #include <string.h> |
- | |
70 | #include <macros.h> |
- | |
71 | 70 | ||
72 | #ifdef CONFIG_SMP |
71 | #ifdef CONFIG_SMP |
73 | #include <arch/smp/apic.h> |
72 | #include <arch/smp/apic.h> |
74 | #endif |
73 | #endif |
75 | 74 | ||
76 | /** Extract command name from the multiboot module command line. |
- | |
77 | * |
- | |
78 | * @param buf Destination buffer (will always null-terminate). |
75 | /** Perform ia32-specific initialization before main_bsp() is called. |
79 | * @param n Size of destination buffer. |
- | |
80 | * @param cmd_line Input string (the command line). |
- | |
81 | * |
- | |
82 | */ |
- | |
83 | static void extract_command(char *buf, size_t n, const char *cmd_line) |
- | |
84 | { |
- | |
85 | const char *start, *end, *cp; |
- | |
86 | size_t max_len; |
- | |
87 | - | ||
88 | /* Find the first space. */ |
- | |
89 | end = strchr(cmd_line, ' '); |
- | |
90 | if (end == NULL) |
- | |
91 | end = cmd_line + strlen(cmd_line); |
- | |
92 | - | ||
93 | /* |
- | |
94 | * Find last occurence of '/' before 'end'. If found, place start at |
- | |
95 | * next character. Otherwise, place start at beginning of buffer. |
- | |
96 | */ |
- | |
97 | cp = end; |
- | |
98 | start = buf; |
- | |
99 | while (cp != start) { |
- | |
100 | if (*cp == '/') { |
- | |
101 | start = cp + 1; |
- | |
102 | break; |
- | |
103 | } |
- | |
104 | --cp; |
- | |
105 | } |
- | |
106 | - | ||
107 | /* Copy the command and null-terminate the string. */ |
- | |
108 | max_len = min(n - 1, (size_t) (end - start)); |
- | |
109 | strncpy(buf, start, max_len + 1); |
- | |
110 | buf[max_len] = '\0'; |
- | |
111 | } |
- | |
112 | - | ||
113 | /** C part of ia32 boot sequence. |
- | |
114 | * |
76 | * |
115 | * @param signature Should contain the multiboot signature. |
77 | * @param signature Should contain the multiboot signature. |
116 | * @param mi Pointer to the multiboot information structure. |
78 | * @param mi Pointer to the multiboot information structure. |
117 | */ |
79 | */ |
118 | void arch_pre_main(uint32_t signature, const mb_info_t *mi) |
80 | void arch_pre_main(uint32_t signature, const multiboot_info_t *mi) |
119 | { |
81 | { |
120 | uint32_t flags; |
- | |
121 | mb_mod_t *mods; |
- | |
122 | uint32_t i; |
- | |
123 | - | ||
124 | if (signature == MULTIBOOT_LOADER_MAGIC) |
- | |
125 | flags = mi->flags; |
- | |
126 | else { |
- | |
127 | /* No multiboot info available. */ |
82 | /* Parse multiboot information obtained from the bootloader. */ |
128 | flags = 0; |
- | |
129 | } |
- | |
130 | - | ||
131 | /* Copy module information. */ |
- | |
132 | - | ||
133 | if ((flags & MBINFO_FLAGS_MODS) != 0) { |
- | |
134 | init.cnt = mi->mods_count; |
- | |
135 | mods = mi->mods_addr; |
- | |
136 | - | ||
137 | for (i = 0; i < init.cnt; i++) { |
- | |
138 | init.tasks[i].addr = mods[i].start + 0x80000000; |
- | |
139 | init.tasks[i].size = mods[i].end - mods[i].start; |
- | |
140 | - | ||
141 | /* Copy command line, if available. */ |
- | |
142 | if (mods[i].string) { |
- | |
143 | extract_command(init.tasks[i].name, |
- | |
144 | CONFIG_TASK_NAME_BUFLEN, |
- | |
145 | mods[i].string); |
- | |
146 | } else |
- | |
147 | init.tasks[i].name[0] = '\0'; |
- | |
148 | } |
- | |
149 | } else |
- | |
150 | init.cnt = 0; |
- | |
151 | - | ||
152 | /* Copy memory map. */ |
- | |
153 | - | ||
154 | int32_t mmap_length; |
- | |
155 | mb_mmap_t *mme; |
- | |
156 | uint32_t size; |
- | |
157 | - | ||
158 | if ((flags & MBINFO_FLAGS_MMAP) != 0) { |
- | |
159 | mmap_length = mi->mmap_length; |
- | |
160 | mme = mi->mmap_addr; |
- | |
161 | e820counter = 0; |
- | |
162 | - | ||
163 | i = 0; |
- | |
164 | while (mmap_length > 0) { |
- | |
165 | e820table[i++] = mme->mm_info; |
- | |
166 | - | ||
167 | /* Compute address of next structure. */ |
- | |
168 | size = sizeof(mme->size) + mme->size; |
83 | multiboot_info_parse(signature, mi); |
169 | mme = ((void *) mme) + size; |
- | |
170 | mmap_length -= size; |
- | |
171 | } |
- | |
172 | - | ||
173 | e820counter = i; |
- | |
174 | } else |
- | |
175 | e820counter = 0; |
- | |
176 | 84 | ||
177 | #ifdef CONFIG_SMP |
85 | #ifdef CONFIG_SMP |
178 | /* Copy AP bootstrap routines below 1 MB. */ |
86 | /* Copy AP bootstrap routines below 1 MB. */ |
179 | memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, |
87 | memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, |
180 | (size_t) &_hardcoded_unmapped_size); |
88 | (size_t) &_hardcoded_unmapped_size); |
181 | #endif |
89 | #endif |
182 | } |
90 | } |
183 | 91 | ||
184 | void arch_pre_mm_init(void) |
92 | void arch_pre_mm_init(void) |
185 | { |
93 | { |
186 | pm_init(); |
94 | pm_init(); |
187 | 95 | ||
188 | if (config.cpu_active == 1) { |
96 | if (config.cpu_active == 1) { |
189 | interrupt_init(); |
97 | interrupt_init(); |
190 | bios_init(); |
98 | bios_init(); |
191 | 99 | ||
192 | /* PIC */ |
100 | /* PIC */ |
193 | i8259_init(); |
101 | i8259_init(); |
194 | } |
102 | } |
195 | } |
103 | } |
196 | 104 | ||
197 | void arch_post_mm_init(void) |
105 | void arch_post_mm_init(void) |
198 | { |
106 | { |
199 | if (config.cpu_active == 1) { |
107 | if (config.cpu_active == 1) { |
200 | /* Initialize IRQ routing */ |
108 | /* Initialize IRQ routing */ |
201 | irq_init(IRQ_COUNT, IRQ_COUNT); |
109 | irq_init(IRQ_COUNT, IRQ_COUNT); |
202 | 110 | ||
203 | /* hard clock */ |
111 | /* hard clock */ |
204 | i8254_init(); |
112 | i8254_init(); |
205 | 113 | ||
206 | #ifdef CONFIG_FB |
114 | #ifdef CONFIG_FB |
207 | if (vesa_present()) |
115 | if (vesa_present()) |
208 | vesa_init(); |
116 | vesa_init(); |
209 | else |
117 | else |
210 | #endif |
118 | #endif |
211 | ega_init(EGA_BASE, EGA_VIDEORAM); /* video */ |
119 | ega_init(EGA_BASE, EGA_VIDEORAM); /* video */ |
212 | 120 | ||
213 | /* Enable debugger */ |
121 | /* Enable debugger */ |
214 | debugger_init(); |
122 | debugger_init(); |
215 | /* Merge all memory zones to 1 big zone */ |
123 | /* Merge all memory zones to 1 big zone */ |
216 | zone_merge_all(); |
124 | zone_merge_all(); |
217 | } |
125 | } |
218 | } |
126 | } |
219 | 127 | ||
220 | void arch_post_cpu_init() |
128 | void arch_post_cpu_init() |
221 | { |
129 | { |
222 | #ifdef CONFIG_SMP |
130 | #ifdef CONFIG_SMP |
223 | if (config.cpu_active > 1) { |
131 | if (config.cpu_active > 1) { |
224 | l_apic_init(); |
132 | l_apic_init(); |
225 | l_apic_debug(); |
133 | l_apic_debug(); |
226 | } |
134 | } |
227 | #endif |
135 | #endif |
228 | } |
136 | } |
229 | 137 | ||
230 | void arch_pre_smp_init(void) |
138 | void arch_pre_smp_init(void) |
231 | { |
139 | { |
232 | if (config.cpu_active == 1) { |
140 | if (config.cpu_active == 1) { |
233 | #ifdef CONFIG_SMP |
141 | #ifdef CONFIG_SMP |
234 | acpi_init(); |
142 | acpi_init(); |
235 | #endif /* CONFIG_SMP */ |
143 | #endif /* CONFIG_SMP */ |
236 | } |
144 | } |
237 | } |
145 | } |
238 | 146 | ||
239 | void arch_post_smp_init(void) |
147 | void arch_post_smp_init(void) |
240 | { |
148 | { |
241 | devno_t devno = device_assign_devno(); |
149 | devno_t devno = device_assign_devno(); |
242 | /* keyboard controller */ |
150 | /* keyboard controller */ |
243 | (void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD); |
151 | (void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD); |
244 | 152 | ||
245 | /* |
153 | /* |
246 | * This is the necessary evil until the userspace driver is entirely |
154 | * This is the necessary evil until the userspace driver is entirely |
247 | * self-sufficient. |
155 | * self-sufficient. |
248 | */ |
156 | */ |
249 | sysinfo_set_item_val("kbd", NULL, true); |
157 | sysinfo_set_item_val("kbd", NULL, true); |
250 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
158 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
251 | sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
159 | sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
252 | } |
160 | } |
253 | 161 | ||
254 | void calibrate_delay_loop(void) |
162 | void calibrate_delay_loop(void) |
255 | { |
163 | { |
256 | i8254_calibrate_delay_loop(); |
164 | i8254_calibrate_delay_loop(); |
257 | if (config.cpu_active == 1) { |
165 | if (config.cpu_active == 1) { |
258 | /* |
166 | /* |
259 | * This has to be done only on UP. |
167 | * This has to be done only on UP. |
260 | * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked. |
168 | * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked. |
261 | */ |
169 | */ |
262 | i8254_normal_operation(); |
170 | i8254_normal_operation(); |
263 | } |
171 | } |
264 | } |
172 | } |
265 | 173 | ||
266 | /** Set thread-local-storage pointer |
174 | /** Set thread-local-storage pointer |
267 | * |
175 | * |
268 | * TLS pointer is set in GS register. That means, the GS contains |
176 | * TLS pointer is set in GS register. That means, the GS contains |
269 | * selector, and the descriptor->base is the correct address. |
177 | * selector, and the descriptor->base is the correct address. |
270 | */ |
178 | */ |
271 | unative_t sys_tls_set(unative_t addr) |
179 | unative_t sys_tls_set(unative_t addr) |
272 | { |
180 | { |
273 | THREAD->arch.tls = addr; |
181 | THREAD->arch.tls = addr; |
274 | set_tls_desc(addr); |
182 | set_tls_desc(addr); |
275 | 183 | ||
276 | return 0; |
184 | return 0; |
277 | } |
185 | } |
278 | 186 | ||
279 | /** Acquire console back for kernel |
187 | /** Acquire console back for kernel |
280 | * |
188 | * |
281 | */ |
189 | */ |
282 | void arch_grab_console(void) |
190 | void arch_grab_console(void) |
283 | { |
191 | { |
284 | #ifdef CONFIG_FB |
192 | #ifdef CONFIG_FB |
285 | vesa_redraw(); |
193 | vesa_redraw(); |
286 | #else |
194 | #else |
287 | ega_redraw(); |
195 | ega_redraw(); |
288 | #endif |
196 | #endif |
289 | } |
197 | } |
290 | 198 | ||
291 | /** Return console to userspace |
199 | /** Return console to userspace |
292 | * |
200 | * |
293 | */ |
201 | */ |
294 | void arch_release_console(void) |
202 | void arch_release_console(void) |
295 | { |
203 | { |
296 | } |
204 | } |
297 | 205 | ||
298 | /** Construct function pointer |
206 | /** Construct function pointer |
299 | * |
207 | * |
300 | * @param fptr function pointer structure |
208 | * @param fptr function pointer structure |
301 | * @param addr function address |
209 | * @param addr function address |
302 | * @param caller calling function address |
210 | * @param caller calling function address |
303 | * |
211 | * |
304 | * @return address of the function pointer |
212 | * @return address of the function pointer |
305 | * |
213 | * |
306 | */ |
214 | */ |
307 | void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
215 | void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
308 | { |
216 | { |
309 | return addr; |
217 | return addr; |
310 | } |
218 | } |
311 | 219 | ||
312 | /** @} |
220 | /** @} |
313 | */ |
221 | */ |
314 | 222 |