1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include "boot.h"
18#include <asm/segment.h>
19
20
21
22
23
24static void realmode_switch_hook(void)
25{
26 if (boot_params.hdr.realmode_swtch) {
27 asm volatile("lcallw *%0"
28 : : "m" (boot_params.hdr.realmode_swtch)
29 : "eax", "ebx", "ecx", "edx");
30 } else {
31 asm volatile("cli");
32 outb(0x80, 0x70);
33 io_delay();
34 }
35}
36
37
38
39
40
41static void move_kernel_around(void)
42{
43
44
45
46#ifndef __BIG_KERNEL__
47 u16 dst_seg, src_seg;
48 u32 syssize;
49
50 dst_seg = 0x1000 >> 4;
51 src_seg = 0x10000 >> 4;
52 syssize = boot_params.hdr.syssize;
53
54 while (syssize) {
55 int paras = (syssize >= 0x1000) ? 0x1000 : syssize;
56 int dwords = paras << 2;
57
58 asm volatile("pushw %%es ; "
59 "pushw %%ds ; "
60 "movw %1,%%es ; "
61 "movw %2,%%ds ; "
62 "xorw %%di,%%di ; "
63 "xorw %%si,%%si ; "
64 "rep;movsl ; "
65 "popw %%ds ; "
66 "popw %%es"
67 : "+c" (dwords)
68 : "r" (dst_seg), "r" (src_seg)
69 : "esi", "edi");
70
71 syssize -= paras;
72 dst_seg += paras;
73 src_seg += paras;
74 }
75#endif
76}
77
78
79
80
81static void mask_all_interrupts(void)
82{
83 outb(0xff, 0xa1);
84 io_delay();
85 outb(0xfb, 0x21);
86 io_delay();
87}
88
89
90
91
92static void reset_coprocessor(void)
93{
94 outb(0, 0xf0);
95 io_delay();
96 outb(0, 0xf1);
97 io_delay();
98}
99
100
101
102
103#define GDT_ENTRY(flags,base,limit) \
104 (((u64)(base & 0xff000000) << 32) | \
105 ((u64)flags << 40) | \
106 ((u64)(limit & 0x00ff0000) << 32) | \
107 ((u64)(base & 0x00ffffff) << 16) | \
108 ((u64)(limit & 0x0000ffff)))
109
110struct gdt_ptr {
111 u16 len;
112 u32 ptr;
113} __attribute__((packed));
114
115static void setup_gdt(void)
116{
117
118
119 static const u64 boot_gdt[] __attribute__((aligned(16))) = {
120
121 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
122
123 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
124
125
126
127 [GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
128 };
129
130
131
132
133 static struct gdt_ptr gdt;
134
135 gdt.len = sizeof(boot_gdt)-1;
136 gdt.ptr = (u32)&boot_gdt + (ds() << 4);
137
138 asm volatile("lgdtl %0" : : "m" (gdt));
139}
140
141
142
143
144static void setup_idt(void)
145{
146 static const struct gdt_ptr null_idt = {0, 0};
147 asm volatile("lidtl %0" : : "m" (null_idt));
148}
149
150
151
152
153void go_to_protected_mode(void)
154{
155
156 realmode_switch_hook();
157
158
159 move_kernel_around();
160
161
162 if (enable_a20()) {
163 puts("A20 gate not responding, unable to boot...\n");
164 die();
165 }
166
167
168 reset_coprocessor();
169
170
171 mask_all_interrupts();
172
173
174 setup_idt();
175 setup_gdt();
176 protected_mode_jump(boot_params.hdr.code32_start,
177 (u32)&boot_params + (ds() << 4));
178}
179