blob: f80875b01519ef0cc7a128f175d14c78dbc4c5ee [file] [log] [blame]
/*
* setup.s is responsible for getting the system data from the BIOS,
* and putting them into the appropriate places in system memory.
* both setup.s and system has been loaded by the bootblock.
*
* 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86.
*/
#define __ASSEMBLY__
#include "defs.h"
.code16
.section ".setup", "ax", @progbits
.globl start
start:
# ok, the read went well
# now we want to move to protected mode ...
cli # no interrupts allowed #
movb $0x80, %al # disable NMI for the bootup sequence
outb %al, $0x70
# The system will move itself to its rightful place.
# reload the segment registers and the stack since the
# APs also execute this code
#ljmp $INITSEG, $(reload - start + 0x200)
reload:
movw $INITSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %ss # reset the stack to INITSEG:0x4000-12.
movw %dx, %sp
push %cs
pop %ds
lidt idt_48 - start # load idt with 0,0
lgdt gdt_48 - start # load gdt with whatever appropriate
# that was painless, now we enable A20
# start from grub-a20.patch
/*
* try to switch gateA20 using PORT92, the "Fast A20 and Init"
* register
*/
mov $0x92, %dx
inb %dx, %al
/* skip the port92 code if it's unimplemented (read returns 0xff) */
cmpb $0xff, %al
jz alt_a20_done
/* set or clear bit1, the ALT_A20_GATE bit */
movb 4(%esp), %ah
testb %ah, %ah
jz alt_a20_cont1
orb $2, %al
jmp alt_a20_cont2
alt_a20_cont1:
and $0xfd, %al
/* clear the INIT_NOW bit; don't accidently reset the machine */
alt_a20_cont2:
and $0xfe, %al
outb %al, %dx
alt_a20_done:
# end from grub-a20.patch
call empty_8042
movb $0xD1, %al # command write
outb %al, $0x64
call empty_8042
movb $0xDF, %al # A20 on
outb %al, $0x60
call empty_8042
/*
* Note that the short jump isn't strictly needed, althought there are
* reasons why it might be a good idea. It won't hurt in any case.
*/
movw $0x0001, %ax # protected mode (PE) bit
lmsw %ax # This is it#
jmp flush_instr
flush_instr:
movw $KERNEL_DS, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs)
/*
* This routine checks that the keyboard command queue is empty
* (after emptying the output buffers)
*
* No timeout is used - if this hangs there is something wrong with
* the machine, and we probably couldn't proceed anyway.
*/
empty_8042:
call delay
inb $0x64, %al # 8042 status port
cmpb $0xff, %al # from grub-a20-patch, skip if not impl
jz empty_8042_ret
testb $1, %al # output buffer?
jz no_output
call delay
inb $0x60, %al # read it
jmp empty_8042
no_output:
testb $2, %al # is input buffer full?
jnz empty_8042 # yes - loop
empty_8042_ret:
ret
#
# Delay is needed after doing i/o
#
delay:
.word 0x00eb # jmp $+2
ret
gdt:
.word 0,0,0,0 # dummy
.word 0,0,0,0 # unused
.word 0x7FFF # limit 128mb
.word 0x0000 # base address=0
.word 0x9A00 # code read/exec
.word 0x00C0 # granularity=4096, 386
.word 0x7FFF # limit 128mb
.word 0x0000 # base address=0
.word 0x9200 # data read/write
.word 0x00C0 # granularity=4096, 386
idt_48:
.word 0 # idt limit=0
.long 0 # idt base=0L
gdt_48:
.word 0x800 # gdt limit=2048, 256 GDT entries
.word 512+gdt - start,0x9 # gdt base = 0X9xxxx
msg1:
.asciz "Setup.S\r\n"
/* Pad setup to the proper size */
.org (SETUPSECS*512)