File: setup.S

package info (click to toggle)
memtest86+ 5.01-3
  • links: PTS
  • area: main
  • in suites: buster, sid, stretch
  • size: 1,336 kB
  • ctags: 2,585
  • sloc: ansic: 17,514; asm: 1,805; makefile: 239; sh: 127
file content (154 lines) | stat: -rw-r--r-- 3,497 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * 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)