0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "boot.h"
0014 #include <asm/segment.h>
0015
0016
0017
0018
0019
0020 static void realmode_switch_hook(void)
0021 {
0022 if (boot_params.hdr.realmode_swtch) {
0023 asm volatile("lcallw *%0"
0024 : : "m" (boot_params.hdr.realmode_swtch)
0025 : "eax", "ebx", "ecx", "edx");
0026 } else {
0027 asm volatile("cli");
0028 outb(0x80, 0x70);
0029 io_delay();
0030 }
0031 }
0032
0033
0034
0035
0036 static void mask_all_interrupts(void)
0037 {
0038 outb(0xff, 0xa1);
0039 io_delay();
0040 outb(0xfb, 0x21);
0041 io_delay();
0042 }
0043
0044
0045
0046
0047 static void reset_coprocessor(void)
0048 {
0049 outb(0, 0xf0);
0050 io_delay();
0051 outb(0, 0xf1);
0052 io_delay();
0053 }
0054
0055
0056
0057
0058
0059 struct gdt_ptr {
0060 u16 len;
0061 u32 ptr;
0062 } __attribute__((packed));
0063
0064 static void setup_gdt(void)
0065 {
0066
0067
0068 static const u64 boot_gdt[] __attribute__((aligned(16))) = {
0069
0070 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
0071
0072 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
0073
0074
0075
0076 [GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
0077 };
0078
0079
0080
0081
0082 static struct gdt_ptr gdt;
0083
0084 gdt.len = sizeof(boot_gdt)-1;
0085 gdt.ptr = (u32)&boot_gdt + (ds() << 4);
0086
0087 asm volatile("lgdtl %0" : : "m" (gdt));
0088 }
0089
0090
0091
0092
0093 static void setup_idt(void)
0094 {
0095 static const struct gdt_ptr null_idt = {0, 0};
0096 asm volatile("lidtl %0" : : "m" (null_idt));
0097 }
0098
0099
0100
0101
0102 void go_to_protected_mode(void)
0103 {
0104
0105 realmode_switch_hook();
0106
0107
0108 if (enable_a20()) {
0109 puts("A20 gate not responding, unable to boot...\n");
0110 die();
0111 }
0112
0113
0114 reset_coprocessor();
0115
0116
0117 mask_all_interrupts();
0118
0119
0120 setup_idt();
0121 setup_gdt();
0122 protected_mode_jump(boot_params.hdr.code32_start,
0123 (u32)&boot_params + (ds() << 4));
0124 }