blob: 85592ad8b4528188f1cdc00020b2ed8e59dc9582 [file] [log] [blame]
Martin Roth9b1b3352016-02-24 12:27:06 -08001/*
2 * setup.s is responsible for getting the system data from the BIOS,
3 * and putting them into the appropriate places in system memory.
4 * both setup.s and system has been loaded by the bootblock.
5 *
6 * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86.
7 */
8
9#define __ASSEMBLY__
10#include "defs.h"
11
12.code16
13.section ".setup", "ax", @progbits
14.globl start
15start:
Martin Roth4dcd13d2016-02-24 13:53:07 -080016# ok, the read went well
Martin Roth9b1b3352016-02-24 12:27:06 -080017# now we want to move to protected mode ...
18
19
20 cli # no interrupts allowed #
21 movb $0x80, %al # disable NMI for the bootup sequence
22 outb %al, $0x70
23
24# The system will move itself to its rightful place.
Martin Roth4dcd13d2016-02-24 13:53:07 -080025# reload the segment registers and the stack since the
Martin Roth9b1b3352016-02-24 12:27:06 -080026# APs also execute this code
27#ljmp $INITSEG, $(reload - start + 0x200)
28reload:
29 movw $INITSEG, %ax
30 movw %ax, %ds
31 movw %ax, %es
32 movw %ax, %fs
33 movw %ax, %ss # reset the stack to INITSEG:0x4000-12.
34 movw %dx, %sp
35 push %cs
36 pop %ds
37 lidt idt_48 - start # load idt with 0,0
38 lgdt gdt_48 - start # load gdt with whatever appropriate
39
40# that was painless, now we enable A20
41# start from grub-a20.patch
42 /*
43 * try to switch gateA20 using PORT92, the "Fast A20 and Init"
44 * register
45 */
46 mov $0x92, %dx
47 inb %dx, %al
48 /* skip the port92 code if it's unimplemented (read returns 0xff) */
49 cmpb $0xff, %al
50 jz alt_a20_done
Martin Roth4dcd13d2016-02-24 13:53:07 -080051
Martin Roth9b1b3352016-02-24 12:27:06 -080052 /* set or clear bit1, the ALT_A20_GATE bit */
53 movb 4(%esp), %ah
54 testb %ah, %ah
55 jz alt_a20_cont1
56 orb $2, %al
57 jmp alt_a20_cont2
58alt_a20_cont1:
59 and $0xfd, %al
60
61 /* clear the INIT_NOW bit; don't accidently reset the machine */
62alt_a20_cont2:
63 and $0xfe, %al
64 outb %al, %dx
65
66alt_a20_done:
67# end from grub-a20.patch
68
69 call empty_8042
Martin Roth4dcd13d2016-02-24 13:53:07 -080070
Martin Roth9b1b3352016-02-24 12:27:06 -080071 movb $0xD1, %al # command write
72 outb %al, $0x64
Martin Roth4dcd13d2016-02-24 13:53:07 -080073 call empty_8042
Martin Roth9b1b3352016-02-24 12:27:06 -080074
75 movb $0xDF, %al # A20 on
76 outb %al, $0x60
77 call empty_8042
78
79/*
80 * Note that the short jump isn't strictly needed, althought there are
81 * reasons why it might be a good idea. It won't hurt in any case.
82 */
83 movw $0x0001, %ax # protected mode (PE) bit
84 lmsw %ax # This is it#
85 jmp flush_instr
86flush_instr:
87 movw $KERNEL_DS, %ax
88 movw %ax, %ds
89 movw %ax, %es
90 movw %ax, %ss
91 movw %ax, %fs
92 movw %ax, %gs
93
94data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs)
95
96/*
97 * This routine checks that the keyboard command queue is empty
98 * (after emptying the output buffers)
99 *
100 * No timeout is used - if this hangs there is something wrong with
101 * the machine, and we probably couldn't proceed anyway.
102 */
103empty_8042:
104 call delay
105 inb $0x64, %al # 8042 status port
106 cmpb $0xff, %al # from grub-a20-patch, skip if not impl
107 jz empty_8042_ret
108 testb $1, %al # output buffer?
109 jz no_output
110 call delay
111 inb $0x60, %al # read it
112 jmp empty_8042
Martin Roth4dcd13d2016-02-24 13:53:07 -0800113
Martin Roth9b1b3352016-02-24 12:27:06 -0800114no_output:
115 testb $2, %al # is input buffer full?
116 jnz empty_8042 # yes - loop
117empty_8042_ret:
118 ret
119#
120# Delay is needed after doing i/o
121#
122delay:
123 .word 0x00eb # jmp $+2
124 ret
125
126gdt:
127 .word 0,0,0,0 # dummy
128
129 .word 0,0,0,0 # unused
130
131 .word 0x7FFF # limit 128mb
132 .word 0x0000 # base address=0
133 .word 0x9A00 # code read/exec
134 .word 0x00C0 # granularity=4096, 386
135
136 .word 0x7FFF # limit 128mb
137 .word 0x0000 # base address=0
138 .word 0x9200 # data read/write
139 .word 0x00C0 # granularity=4096, 386
140
141idt_48:
142 .word 0 # idt limit=0
143 .long 0 # idt base=0L
144
145gdt_48:
146 .word 0x800 # gdt limit=2048, 256 GDT entries
147 .word 512+gdt - start,0x9 # gdt base = 0X9xxxx
148
149msg1:
150 .asciz "Setup.S\r\n"
151
152 /* Pad setup to the proper size */
153 .org (SETUPSECS*512)
154