1/*
2 * Copyright 2004-2005, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Copyright 2006, Marcus Overhagen, marcus@overhagen.de. All rights reserved.
4 * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved.
5 * Distributed under the terms of the MIT License.
6 */
7
8
9// system state according to PXE specification:
10//   CS:IP	0000:7C00
11//   ES:BX 	address of the PXENV+ structure
12//   SS:[SP+4] 	address of the !PXE structure.
13//   SS:SP	at least 1.5KB of free stack
14
15// memory map:
16// 0x00000 - 0x07bff		real mode IDT, stack
17// 0x07C00 - 0x08FFF		original boot loader location
18// 0x10000 - 0x8AFFF		relocated boot loader
19// 0x8B000 - 0x8CFFF		used by stage2 trampoline code
20// 0x8D000 - 0x9F7FF		PXE and UNDI code and data segments
21// 0x9F800 - 0xA0000		extended BIOS data area
22
23#define GLOBAL(x) .globl x ; x
24
25.equ LOAD_ADDRESS,							0x10000
26.equ INITIAL_LOAD_ADDRESS,					0x07C00
27.equ INITIAL_LOAD_OFFSET,					INITIAL_LOAD_ADDRESS - LOAD_ADDRESS
28
29.text
30.code16
31
32pxe_start:
33			// setup segments
34			xorw	%ax, %ax
35			movw	%ax, %ds
36			movw	%ax, %es
37			movw	%ax, %ss
38			movw	$0x7c00, %sp
39
40			cld
41
42			// print start banner
43			mov		$kStartMessage + INITIAL_LOAD_OFFSET, %esi
44			call	puts
45
46			// switch to unreal mode
47			cli
48			call	enable_a20
49			call	go_unreal
50			sti
51			movl	$kUnrealMessage + INITIAL_LOAD_OFFSET, %esi
52			call	puts
53
54			// relocate boot loader code to expected start address
55			movl	$_end, %ecx			// desired end address
56			addl	$3, %ecx			// long word align
57			andb	$0xfc, %cl			// (should be page aligned anyway, though)
58			movl	%ecx, %edi
59			subl	$LOAD_ADDRESS, %ecx	// number of bytes to copy
60			movl	$INITIAL_LOAD_ADDRESS, %esi
61			addl	%ecx, %esi			// current end address
62			shrl	$2, %ecx			// number of long words
63_copy:		subl	$4, %esi
64			subl	$4, %edi
65			movl	(%esi), %eax
66			movl	%eax, (%edi)
67			decl	%ecx
68			jnz		_copy
69
70			// jump into the relocated boot loader
71.code32
72			.byte	0x66
73			ljmp	$0x1000, $relocated_start - LOAD_ADDRESS
74.code16
75
76relocated_start:
77			cli
78
79			// switch to PM
80			.code32
81			.byte	0x66
82			.byte	0x67
83			lgdt	pm_gdt_descriptor
84			.code16
85
86			movl	%cr0, %eax
87			orb		$0x1, %al
88			movl	%eax, %cr0
89
90.code32
91			.byte	0x66
92			ljmp	$0x8, $pm_start
93pm_start:
94			mov		$0x10, %ax
95			mov		%ax, %ds
96			mov		%ax, %es
97			mov		%ax, %fs
98			mov		%ax, %gs
99			mov		%ax, %ss
100
101			call	_start
102
103
104.code16
105stop:		hlt
106			jmp		stop
107
108
109
110puts:		pushal
111_puts2:		lodsb
112			testb	%al, %al
113			jnz		putc
114			popal
115			ret
116putc:		movw	$0x7, %bx
117			movb	$0xe, %ah
118			int		$0x10
119			jmp		_puts2
120
121
122enable_a20:	inb		$0x92, %al
123			testb	$0x02, %al
124			jnz		_a20_out
125			orb		$0x02, %al
126			andb	$0xfe, %al
127			outb	%al, $0x92
128_a20_out:	ret
129
130
131go_unreal:	pushw	%ds
132			pushw	%es
133			pushw	%bx
134			.code32
135			.byte	0x66
136			.byte	0x67
137			lgdt	unreal_gdt_descriptor + INITIAL_LOAD_OFFSET
138			.code16
139			movl	%cr0, %eax
140			orb		$1, %al
141			movl	%eax, %cr0
142			movw	$8, %bx
143			movw	%bx, %ds
144			movw	%bx, %es
145			decb	%al
146			movl	%eax, %cr0
147			popw	%bx
148			popw	%es
149			popw	%ds
150			ret
151
152
153kStartMessage:			.asciz	"\r\nHaiku PXE bootloader version 1.0\r\n\r\n"
154kUnrealMessage:			.asciz	"Switch to unreal mode done\r\n"
155
156
157.balign 8
158unreal_gdt:
159			.long	0
160			.long	0
161			.long	0x0000ffff
162			.long	0x00cf9200
163
164unreal_gdt_descriptor:
165			.word	0x10
166			.long	unreal_gdt + INITIAL_LOAD_OFFSET
167
168.balign 8
169pm_gdt:
170	// null descriptor
171			.long	0
172			.long	0
173
174	// kernel code segment
175			.long	0x0000ffff
176			.long	0x00cf9e00
177	// kernel data and stack segment
178			.long	0x0000ffff
179			.long	0x00cf9200
180
181	// real mode 16 bit code segment
182			.long	0x0000ffff
183			.long	0x00009e01
184	// real mode 16 bit data and stack segment
185			.long	0x0000ffff
186			.long	0x00009201
187	// real mode 16 bit stack segment
188			.long	0x0000ffff
189			.long	0x00009200
190
191pm_gdt_descriptor:
192			.word	0x2f
193			.long	pm_gdt
194
195
196
197//--------------------------------------------------------------
198
199
200/* global data table */
201.balign 8
202
203GLOBAL(gMultiBootInfo):
204	.long	0
205
206GLOBAL(gBootPartitionOffset):
207	.long	0xffffffff
208
209GLOBAL(gBootedFromImage):
210	.byte	1
211
212GLOBAL(gBootDriveID):
213	.byte	0xff
214
215.balign 8
216