xref: /haiku/src/apps/bootmanager/bootman.S (revision b76ca311d17d58bd6c3ac6948d839076558adc88)
1*b76ca311SAxel Dörfler;
2*b76ca311SAxel Dörfler; Copyright 2007, Dengg David, david-d@gmx.at. All rights reserved.
3*b76ca311SAxel Dörfler; Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
4*b76ca311SAxel Dörfler; Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
5*b76ca311SAxel Dörfler; Distributed under the terms of the MIT License.
6*b76ca311SAxel Dörfler
7*b76ca311SAxel Dörfler; Steps to create BootLoader.h
8*b76ca311SAxel Dörfler; 1. nasm -f bin bootman.S -o bootman.bin
9*b76ca311SAxel Dörfler; 2. cc MakeArray.cpp -o make_array -lstdc++
10*b76ca311SAxel Dörfler; 3. ./make_array kBootLoader bootman.bin > BootLoader.h
11*b76ca311SAxel Dörfler; or
12*b76ca311SAxel Dörfler; nasm -f bin bootman.S -o bootman.bin && ./make_array kBootLoader bootman.bin > BootLoader.h
13*b76ca311SAxel Dörfler
14*b76ca311SAxel Dörfler%assign USE_TEST_MENU				0
15*b76ca311SAxel Dörfler
16*b76ca311SAxel Dörfler%assign BOOT_BLOCK_START_ADDRESS	0x7c00
17*b76ca311SAxel Dörfler
18*b76ca311SAxel Dörfler%assign MBR_SIGNATURE				0xAA55
19*b76ca311SAxel Dörfler
20*b76ca311SAxel Dörfler; BIOS calls
21*b76ca311SAxel Dörfler
22*b76ca311SAxel Dörfler%assign BIOS_VIDEO_SERVICES			0x10
23*b76ca311SAxel Dörfler%assign BIOS_DISK_SERVICES			0x13
24*b76ca311SAxel Dörfler%assign BIOS_KEYBOARD_SERVICES		0x16
25*b76ca311SAxel Dörfler%assign BIOS_REBOOT					0x19		; dl - boot drive number
26*b76ca311SAxel Dörfler%assign BIOS_TIME_SERVICES			0x1A
27*b76ca311SAxel Dörfler
28*b76ca311SAxel Dörfler; video services
29*b76ca311SAxel Dörfler%assign SET_VIDEO_MODE					0x00	; al - mode
30*b76ca311SAxel Dörfler
31*b76ca311SAxel Dörfler%assign	SET_CURSOR_SHAPE				0x01	; ch - starting scan line (5 bits)
32*b76ca311SAxel Dörfler												; cl - ending scan line (5 bits)
33*b76ca311SAxel Dörfler
34*b76ca311SAxel Dörfler%assign SET_CURSOR						0x02	; dl - column
35*b76ca311SAxel Dörfler												; dh - row
36*b76ca311SAxel Dörfler												; bh - page
37*b76ca311SAxel Dörfler
38*b76ca311SAxel Dörfler
39*b76ca311SAxel Dörfler%assign GET_CURSOR						0x03	; bh - page
40*b76ca311SAxel Dörfler												; -> dl - column
41*b76ca311SAxel Dörfler												;	dh - row
42*b76ca311SAxel Dörfler												;	Cursor shape:
43*b76ca311SAxel Dörfler												;	ch - starting scan line
44*b76ca311SAxel Dörfler												;	cl - ending scan line
45*b76ca311SAxel Dörfler
46*b76ca311SAxel Dörfler%assign	SCROLL_UP						0x06	; al - lines (0: clear screen)
47*b76ca311SAxel Dörfler												; bh - attribute
48*b76ca311SAxel Dörfler												; ch - upper line
49*b76ca311SAxel Dörfler												; cl - left column
50*b76ca311SAxel Dörfler												; dh - lower line
51*b76ca311SAxel Dörfler												; dl - right column
52*b76ca311SAxel Dörfler
53*b76ca311SAxel Dörfler%assign WRITE_CHAR						0x09	; al - char
54*b76ca311SAxel Dörfler												; bh - page
55*b76ca311SAxel Dörfler												; bl - attribute
56*b76ca311SAxel Dörfler												; cx - count
57*b76ca311SAxel Dörfler
58*b76ca311SAxel Dörfler;%assign WRITE_CHAR						0x0e	; al - char
59*b76ca311SAxel Dörfler												; bh - page
60*b76ca311SAxel Dörfler												; bl - foreground color (graphics mode only)
61*b76ca311SAxel Dörfler
62*b76ca311SAxel Dörfler; disk services
63*b76ca311SAxel Dörfler%assign READ_DISK_SECTORS				0x02	; dl	- drive
64*b76ca311SAxel Dörfler												; es:bx - buffer
65*b76ca311SAxel Dörfler												; dh	- head (0 - 15)
66*b76ca311SAxel Dörfler												; ch	- track 7:0 (0 - 1023)
67*b76ca311SAxel Dörfler												; cl	- track 9:8,
68*b76ca311SAxel Dörfler												;		 sector (1 - 17)
69*b76ca311SAxel Dörfler												; al	- sector count
70*b76ca311SAxel Dörfler												; -> al - sectors read
71*b76ca311SAxel Dörfler%assign READ_DRIVE_PARAMETERS			0x08	; dl - drive
72*b76ca311SAxel Dörfler												; -> cl - max cylinder 9:8
73*b76ca311SAxel Dörfler												;	   - sectors per track
74*b76ca311SAxel Dörfler												;	ch - max cylinder 7:0
75*b76ca311SAxel Dörfler												;	dh - max head
76*b76ca311SAxel Dörfler												;	dl - number of drives (?)
77*b76ca311SAxel Dörfler%assign CHECK_DISK_EXTENSIONS_PRESENT	0x41	; bx - 0x55aa
78*b76ca311SAxel Dörfler												; dl - drive
79*b76ca311SAxel Dörfler												; -> success: carry clear
80*b76ca311SAxel Dörfler												;	ah - extension version
81*b76ca311SAxel Dörfler												;	bx - 0xaa55
82*b76ca311SAxel Dörfler												;	cx - support bit mask
83*b76ca311SAxel Dörfler												; -> error: carry set
84*b76ca311SAxel Dörfler%assign EXTENDED_READ					0x42	; dl - drive
85*b76ca311SAxel Dörfler												; ds:si - address packet
86*b76ca311SAxel Dörfler												; -> success: carry clear
87*b76ca311SAxel Dörfler												; -> error: carry set
88*b76ca311SAxel Dörfler
89*b76ca311SAxel Dörfler%assign FIXED_DISK_SUPPORT				0x1	 	; flag indicating fixed disk
90*b76ca311SAxel Dörfler												; extension command subset
91*b76ca311SAxel Dörfler
92*b76ca311SAxel Dörfler; keyboard services
93*b76ca311SAxel Dörfler%assign READ_CHAR						0x00	; -> al - ASCII char
94*b76ca311SAxel Dörfler												;	ah - scan code
95*b76ca311SAxel Dörfler
96*b76ca311SAxel Dörfler%assign	PROBE_CHAR						0x01	; -> zf = 0
97*b76ca311SAxel Dörfler												;	al - ASCII char
98*b76ca311SAxel Dörfler												;	ah - scan code
99*b76ca311SAxel Dörfler
100*b76ca311SAxel Dörfler%assign	GET_MODIFIER_KEYS				0x02	;-> al - modifier key bitmask
101*b76ca311SAxel Dörfler
102*b76ca311SAxel Dörfler; timer services
103*b76ca311SAxel Dörfler%assign READ_CLOCK						0x00	; -> cx	- high word
104*b76ca311SAxel Dörfler												;	dx - low word
105*b76ca311SAxel Dörfler												;	one tick = 1/18.2s
106*b76ca311SAxel Dörfler
107*b76ca311SAxel Dörfler%assign	TICKS_PER_SECOND				19
108*b76ca311SAxel Dörfler
109*b76ca311SAxel Dörfler; video modes
110*b76ca311SAxel Dörfler%assign GRAPHIC_MODE_80x25				0x12	; 640 x 480 graphic mode
111*b76ca311SAxel Dörfler
112*b76ca311SAxel Dörfler%assign TEXT_COLUMNS					80		; Number of columns
113*b76ca311SAxel Dörfler%assign TEXT_ROWS						25		; Number of rows
114*b76ca311SAxel Dörfler
115*b76ca311SAxel Dörfler; Colors
116*b76ca311SAxel Dörfler%assign	BLACK							0
117*b76ca311SAxel Dörfler%assign	BLUE							1
118*b76ca311SAxel Dörfler%assign	GREEN							2
119*b76ca311SAxel Dörfler%assign CYAN							3
120*b76ca311SAxel Dörfler%assign RED								4
121*b76ca311SAxel Dörfler%assign MAGENTA							5
122*b76ca311SAxel Dörfler%assign BROWN							6
123*b76ca311SAxel Dörfler%assign LIGHT_GRAY						7
124*b76ca311SAxel Dörfler%assign	DARK_GRAY						8
125*b76ca311SAxel Dörfler%assign	LIGHT_BLUE						9
126*b76ca311SAxel Dörfler%assign	LIGHT_GREEN						10
127*b76ca311SAxel Dörfler%assign	LIGHT_CYAN						11
128*b76ca311SAxel Dörfler%assign	LIGHT_RED						12
129*b76ca311SAxel Dörfler%assign	LIGHT_MAGENTA					13
130*b76ca311SAxel Dörfler%assign	YELLOW							14
131*b76ca311SAxel Dörfler%assign	WHITE							15
132*b76ca311SAxel Dörfler
133*b76ca311SAxel Dörfler%assign BRIGHT_COLOR_MASK				8
134*b76ca311SAxel Dörfler
135*b76ca311SAxel Dörfler; Characters
136*b76ca311SAxel Dörfler%assign	TRIANGLE_TO_RIGHT				16
137*b76ca311SAxel Dörfler%assign	TRIANGLE_TO_LEFT				17
138*b76ca311SAxel Dörfler
139*b76ca311SAxel Dörfler; Key codes
140*b76ca311SAxel Dörfler%assign KEY_DOWN						0x50
141*b76ca311SAxel Dörfler%assign KEY_UP							0x48
142*b76ca311SAxel Dörfler%assign KEY_RETURN						0x1C
143*b76ca311SAxel Dörfler
144*b76ca311SAxel Dörfler; Modifier key bitmasks
145*b76ca311SAxel Dörfler%assign MODIFIER_RIGHT_SHIFT_KEY		0x01
146*b76ca311SAxel Dörfler%assign MODIFIER_LEFT_SHIFT_KEY			0x02
147*b76ca311SAxel Dörfler%assign MODIFIER_CONTROL_KEY			0x04
148*b76ca311SAxel Dörfler%assign MODIFIER_ALT_KEY				0x08
149*b76ca311SAxel Dörfler%assign MODIFIER_SCROLL_LOCK_KEY		0x10
150*b76ca311SAxel Dörfler%assign MODIFIER_NUM_LOCK_KEY			0x20
151*b76ca311SAxel Dörfler%assign MODIFIER_CAPS_LOCK_KEY			0x40
152*b76ca311SAxel Dörfler%assign MODIFIER_INSERT_KEY				0x80
153*b76ca311SAxel Dörfler
154*b76ca311SAxel Dörfler; String constants with their length
155*b76ca311SAxel Dörfler%define TITLE							'Haiku Boot Manager'
156*b76ca311SAxel Dörfler%strlen TITLE_LENGTH					TITLE
157*b76ca311SAxel Dörfler%define SELECT_OS_MESSAGE				'Select an OS from the menu'
158*b76ca311SAxel Dörfler%strlen SELECT_OS_MESSAGE_LENGTH		SELECT_OS_MESSAGE
159*b76ca311SAxel Dörfler
160*b76ca311SAxel Dörfler; 16 bit code
161*b76ca311SAxel DörflerSECTION
162*b76ca311SAxel DörflerBITS 16
163*b76ca311SAxel Dörfler
164*b76ca311SAxel Dörfler
165*b76ca311SAxel Dörfler; nicer way to get the size of a structure
166*b76ca311SAxel Dörfler%define sizeof(s)	s %+ _size
167*b76ca311SAxel Dörfler
168*b76ca311SAxel Dörfler; using a structure in a another structure definition
169*b76ca311SAxel Dörfler%macro  nstruc  1-2	 1
170*b76ca311SAxel Dörfler					resb	sizeof(%1) * %2
171*b76ca311SAxel Dörfler%endmacro
172*b76ca311SAxel Dörfler
173*b76ca311SAxel Dörfler; Variables on stack
174*b76ca311SAxel Dörflerstruc	Locals
175*b76ca311SAxel Dörfler	selection		resw	1
176*b76ca311SAxel Dörfler	firstLine		resb	2 ; low byte used only
177*b76ca311SAxel Dörfler	timeoutTicks	resd	1
178*b76ca311SAxel Dörfler	cursorX			resb	1
179*b76ca311SAxel Dörfler	cursorY			resb	1
180*b76ca311SAxel Dörfler	cursorShape		resw	1
181*b76ca311SAxel Dörflerendstruc
182*b76ca311SAxel Dörfler
183*b76ca311SAxel DörflercursorPosition		equ cursorX
184*b76ca311SAxel Dörfler
185*b76ca311SAxel Dörfler%macro DEBUG_PAUSE 0
186*b76ca311SAxel Dörfler	push	ax
187*b76ca311SAxel Dörfler	mov		ah, READ_CHAR
188*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES
189*b76ca311SAxel Dörfler	pop		ax
190*b76ca311SAxel Dörfler%endmacro
191*b76ca311SAxel Dörfler
192*b76ca311SAxel Dörfler%macro CLEAR_SCREEN 0
193*b76ca311SAxel Dörfler	mov		ah, SCROLL_UP
194*b76ca311SAxel Dörfler	xor		al, al
195*b76ca311SAxel Dörfler	mov		bh, WHITE
196*b76ca311SAxel Dörfler	xor		cx, cx
197*b76ca311SAxel Dörfler	mov		dx, (TEXT_ROWS-1) * 0x100 + (TEXT_COLUMNS-1)
198*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
199*b76ca311SAxel Dörfler%endmacro
200*b76ca311SAxel Dörfler
201*b76ca311SAxel Dörfler; Prints a null terminated string
202*b76ca311SAxel Dörfler; bl ... color
203*b76ca311SAxel Dörfler; si ... offset to string
204*b76ca311SAxel Dörfler%macro PRINT_STRING 0
205*b76ca311SAxel Dörfler	push	ax
206*b76ca311SAxel Dörfler	push	bx
207*b76ca311SAxel Dörfler	push	cx
208*b76ca311SAxel Dörfler	push	dx
209*b76ca311SAxel Dörfler	xor		bh, bh								; write on page 0
210*b76ca311SAxel Dörfler	jmp		.loop_condition
211*b76ca311SAxel Dörfler.loop
212*b76ca311SAxel Dörfler	mov		dx, [bp + cursorPosition]
213*b76ca311SAxel Dörfler	mov		ah, SET_CURSOR
214*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
215*b76ca311SAxel Dörfler
216*b76ca311SAxel Dörfler	inc		byte [bp + cursorX]
217*b76ca311SAxel Dörfler
218*b76ca311SAxel Dörfler	mov		cx, 1
219*b76ca311SAxel Dörfler	mov		ah, WRITE_CHAR
220*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
221*b76ca311SAxel Dörfler.loop_condition
222*b76ca311SAxel Dörfler	lodsb
223*b76ca311SAxel Dörfler	cmp		al, 0
224*b76ca311SAxel Dörfler	jnz		.loop
225*b76ca311SAxel Dörfler	pop		dx
226*b76ca311SAxel Dörfler	pop		cx
227*b76ca311SAxel Dörfler	pop		bx
228*b76ca311SAxel Dörfler	pop		ax
229*b76ca311SAxel Dörfler	ret
230*b76ca311SAxel Dörfler%endmacro
231*b76ca311SAxel Dörfler
232*b76ca311SAxel Dörfler; 64 bit value
233*b76ca311SAxel Dörflerstruc   quadword
234*b76ca311SAxel Dörfler	.lower			resd	1
235*b76ca311SAxel Dörfler	.upper			resd	1
236*b76ca311SAxel Dörflerendstruc
237*b76ca311SAxel Dörfler
238*b76ca311SAxel Dörfler; address packet as required by the EXTENDED_READ BIOS call
239*b76ca311SAxel Dörflerstruc   AddressPacket
240*b76ca311SAxel Dörfler	.packet_size	resb	1
241*b76ca311SAxel Dörfler	.reserved1		resb	1
242*b76ca311SAxel Dörfler	.block_count	resb	1
243*b76ca311SAxel Dörfler	.reserved2		resb	1
244*b76ca311SAxel Dörfler	.buffer			resd	1
245*b76ca311SAxel Dörfler	.offset			nstruc	quadword
246*b76ca311SAxel Dörflerendstruc
247*b76ca311SAxel Dörfler
248*b76ca311SAxel Dörflerstruc	BootLoaderAddress
249*b76ca311SAxel Dörfler	.device			resb	1			; hard drive number
250*b76ca311SAxel Dörfler	.offset			nstruc	quadword	; LBA of start start sector
251*b76ca311SAxel Dörflerendstruc
252*b76ca311SAxel Dörfler
253*b76ca311SAxel Dörfler; use code available in stage 1
254*b76ca311SAxel Dörfler%define printstr printStringStage1
255*b76ca311SAxel Dörfler
256*b76ca311SAxel Dörflerstage1:
257*b76ca311SAxel Dörfler	mov		ax, 0x07C0							; BOOT_BLOCK_START_ADDRESS / 16
258*b76ca311SAxel Dörfler	mov		ds, ax								; Setup segment registers
259*b76ca311SAxel Dörfler	mov		es, ax
260*b76ca311SAxel Dörfler	mov		ss, ax
261*b76ca311SAxel Dörfler
262*b76ca311SAxel Dörfler	mov		sp, 0xFFFF - sizeof(Locals)			; Make stack empty
263*b76ca311SAxel Dörfler	mov		bp, sp
264*b76ca311SAxel Dörfler
265*b76ca311SAxel Dörfler	cld											; String operations increment index registers
266*b76ca311SAxel Dörfler
267*b76ca311SAxel Dörfler	CLEAR_SCREEN
268*b76ca311SAxel Dörfler	call	hideCursor
269*b76ca311SAxel Dörfler
270*b76ca311SAxel Dörfler	mov		bh, 0								; Text output on page 0
271*b76ca311SAxel Dörfler
272*b76ca311SAxel Dörfler	; Print title centered at row 2
273*b76ca311SAxel Dörfler	mov		dx, 1 * 0x100 + (40 - TITLE_LENGTH / 2)
274*b76ca311SAxel Dörfler	mov		[bp + cursorPosition], dx
275*b76ca311SAxel Dörfler
276*b76ca311SAxel Dörfler	mov		si, kTitle
277*b76ca311SAxel Dörfler	mov		bl, WHITE
278*b76ca311SAxel Dörfler	call	printstr
279*b76ca311SAxel Dörfler
280*b76ca311SAxel Dörfler	; Print message centered at second last row
281*b76ca311SAxel Dörfler	mov		dx, (TEXT_ROWS-2) * 0x100 + (40 - SELECT_OS_MESSAGE_LENGTH / 2)
282*b76ca311SAxel Dörfler	mov		[bp + cursorPosition], dx
283*b76ca311SAxel Dörfler
284*b76ca311SAxel Dörfler	mov		bl, LIGHT_GRAY
285*b76ca311SAxel Dörfler	mov		si, kSelectOSMessage
286*b76ca311SAxel Dörfler	call	printstr
287*b76ca311SAxel Dörfler
288*b76ca311SAxel Dörfler	; Chain load rest of boot loader
289*b76ca311SAxel Dörfler	mov		ah, EXTENDED_READ					; Load 3 more sectors
290*b76ca311SAxel Dörfler	mov		dl, 0x80							; First HDD
291*b76ca311SAxel Dörfler	mov		si, nextStageDAP
292*b76ca311SAxel Dörfler	int		BIOS_DISK_SERVICES
293*b76ca311SAxel Dörfler	jc		.error								; I/O error
294*b76ca311SAxel Dörfler	jmp		stage2								; Continue in loaded stage 2
295*b76ca311SAxel Dörfler
296*b76ca311SAxel Dörfler.error:
297*b76ca311SAxel Dörfler	call	showCursor
298*b76ca311SAxel Dörfler	mov		si, kError
299*b76ca311SAxel Dörfler	mov		bl, RED
300*b76ca311SAxel Dörfler	call	printstr
301*b76ca311SAxel Dörfler
302*b76ca311SAxel Dörfler	mov		ah, READ_CHAR
303*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES
304*b76ca311SAxel Dörfler
305*b76ca311SAxel Dörfler	mov		dl, 0x80
306*b76ca311SAxel Dörfler	int		BIOS_REBOOT
307*b76ca311SAxel Dörfler
308*b76ca311SAxel DörflerprintStringStage1:
309*b76ca311SAxel Dörfler	PRINT_STRING
310*b76ca311SAxel Dörfler
311*b76ca311SAxel DörflerhideCursor:
312*b76ca311SAxel Dörfler	mov		ah, GET_CURSOR
313*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
314*b76ca311SAxel Dörfler	mov		[bp + cursorShape], cx
315*b76ca311SAxel Dörfler
316*b76ca311SAxel Dörfler	mov		ah, SET_CURSOR_SHAPE
317*b76ca311SAxel Dörfler	mov		cx, 0x2000
318*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
319*b76ca311SAxel Dörfler	ret
320*b76ca311SAxel Dörfler
321*b76ca311SAxel DörflershowCursor:
322*b76ca311SAxel Dörfler	mov		cx, [bp + cursorShape]
323*b76ca311SAxel Dörfler	mov		ah, SET_CURSOR_SHAPE
324*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
325*b76ca311SAxel Dörfler	ret
326*b76ca311SAxel Dörfler
327*b76ca311SAxel DörflernextStageDAP:
328*b76ca311SAxel Dörfler	istruc AddressPacket
329*b76ca311SAxel Dörfler		at AddressPacket.packet_size,	db		0x10
330*b76ca311SAxel Dörfler		at AddressPacket.block_count,	db		0x03
331*b76ca311SAxel Dörfler		at AddressPacket.buffer,		dw		0x0200, 0x07c0
332*b76ca311SAxel Dörfler		at AddressPacket.offset,		dw		1
333*b76ca311SAxel Dörfler	iend
334*b76ca311SAxel Dörfler
335*b76ca311SAxel DörflerkTitle:
336*b76ca311SAxel Dörfler	db		TITLE, 0x00
337*b76ca311SAxel DörflerkSelectOSMessage:
338*b76ca311SAxel Dörfler	db		SELECT_OS_MESSAGE, 0x00
339*b76ca311SAxel DörflerkError:
340*b76ca311SAxel Dörfler	db		'Error loading sectors!', 0x00
341*b76ca311SAxel Dörfler
342*b76ca311SAxel DörflerkStage1UnusedSpace	equ	440 - ($-$$)
343*b76ca311SAxel Dörfler	; Fill the missing space to reach byte 440
344*b76ca311SAxel Dörfler	times kStage1UnusedSpace db 'B'
345*b76ca311SAxel Dörfler
346*b76ca311SAxel DörflerkDiskSignatue:
347*b76ca311SAxel Dörfler	dw		0, 0
348*b76ca311SAxel DörflerkReserved
349*b76ca311SAxel Dörfler	dw		0
350*b76ca311SAxel DörflerkPartitionTable
351*b76ca311SAxel Dörfler	times	64 db 0
352*b76ca311SAxel Dörfler
353*b76ca311SAxel DörflerkMBRSignature:
354*b76ca311SAxel Dörfler	; Magic marker "AA55" (to identify a valid boot record)
355*b76ca311SAxel Dörfler	dw		MBR_SIGNATURE
356*b76ca311SAxel Dörfler
357*b76ca311SAxel Dörfler; ======================================================================
358*b76ca311SAxel Dörfler; ======================= SECOND SECTOR ================================
359*b76ca311SAxel Dörfler; ======================================================================
360*b76ca311SAxel Dörfler
361*b76ca311SAxel Dörfler; Use code available in stage 1
362*b76ca311SAxel Dörfler%define printstr printStringStage2
363*b76ca311SAxel Dörfler
364*b76ca311SAxel Dörfler%assign	TIMEOUT_OFF		0xffff
365*b76ca311SAxel Dörfler
366*b76ca311SAxel Dörfler
367*b76ca311SAxel Dörflerstage2:
368*b76ca311SAxel Dörfler	mov		ax, [defaultItem]					; Select default item
369*b76ca311SAxel Dörfler	mov		[bp + selection], ax
370*b76ca311SAxel Dörfler
371*b76ca311SAxel Dörfler	mov		ax, TICKS_PER_SECOND				; Calculate timeout ticks
372*b76ca311SAxel Dörfler	mul		word [timeout]
373*b76ca311SAxel Dörfler	mov		bx, dx
374*b76ca311SAxel Dörfler	push	ax
375*b76ca311SAxel Dörfler
376*b76ca311SAxel Dörfler	mov		ah, READ_CLOCK
377*b76ca311SAxel Dörfler	int		BIOS_TIME_SERVICES
378*b76ca311SAxel Dörfler
379*b76ca311SAxel Dörfler	pop		ax									; Add current ticks
380*b76ca311SAxel Dörfler	add		ax, dx
381*b76ca311SAxel Dörfler	adc		bx, cx
382*b76ca311SAxel Dörfler	mov		[bp + timeoutTicks], ax
383*b76ca311SAxel Dörfler	mov		[bp + timeoutTicks + 2], bx
384*b76ca311SAxel Dörfler
385*b76ca311SAxel Dörfler	mov		al, [listItemCount]					; Calculate start row for menu
386*b76ca311SAxel Dörfler	shr		al, 1
387*b76ca311SAxel Dörfler	mov		bl, TEXT_ROWS / 2
388*b76ca311SAxel Dörfler	sub		bl, al								; y = TEXT_ROWS / 2 - number of items / 2
389*b76ca311SAxel Dörfler	mov		[bp + firstLine], bl
390*b76ca311SAxel Dörfler
391*b76ca311SAxel Dörfler	mov		ah, GET_MODIFIER_KEYS				; Disable timeout if ALT key is pressed
392*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES
393*b76ca311SAxel Dörfler	and		al, MODIFIER_ALT_KEY
394*b76ca311SAxel Dörfler	jz		showMenu
395*b76ca311SAxel Dörfler	mov		word [timeout], TIMEOUT_OFF
396*b76ca311SAxel Dörfler
397*b76ca311SAxel DörflershowMenu:
398*b76ca311SAxel Dörfler	call	printMenu
399*b76ca311SAxel Dörfler
400*b76ca311SAxel Dörfler	cmp		word [timeout], TIMEOUT_OFF
401*b76ca311SAxel Dörfler	je		inputLoop
402*b76ca311SAxel Dörfler
403*b76ca311SAxel DörflertimeoutLoop:
404*b76ca311SAxel Dörfler	mov		ah, PROBE_CHAR
405*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES
406*b76ca311SAxel Dörfler	jnz		inputLoop							; cancel timeout if key is pressed
407*b76ca311SAxel Dörfler	call	isTimeoutReached
408*b76ca311SAxel Dörfler	jnc		timeoutLoop
409*b76ca311SAxel Dörfler	jmp		bootSelectedPartition
410*b76ca311SAxel Dörfler
411*b76ca311SAxel DörflerisTimeoutReached:
412*b76ca311SAxel Dörfler	mov		ah, READ_CLOCK
413*b76ca311SAxel Dörfler	int		BIOS_TIME_SERVICES
414*b76ca311SAxel Dörfler	cmp		cx, [bp + timeoutTicks + 2]
415*b76ca311SAxel Dörfler	jb		.returnFalse
416*b76ca311SAxel Dörfler	ja		.returnTrue
417*b76ca311SAxel Dörfler	cmp		dx, [bp + timeoutTicks]
418*b76ca311SAxel Dörfler	ja		.returnTrue
419*b76ca311SAxel Dörfler.returnFalse:
420*b76ca311SAxel Dörfler	clc
421*b76ca311SAxel Dörfler	ret
422*b76ca311SAxel Dörfler.returnTrue:
423*b76ca311SAxel Dörfler	stc
424*b76ca311SAxel Dörfler	ret
425*b76ca311SAxel Dörfler
426*b76ca311SAxel Dörfler; ================== Wait for a key and do something with it ==================
427*b76ca311SAxel DörflermainLoop:
428*b76ca311SAxel Dörfler	call	printMenu
429*b76ca311SAxel Dörfler
430*b76ca311SAxel DörflerinputLoop:
431*b76ca311SAxel Dörfler	mov		ah, READ_CHAR
432*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES				; AL = ASCII Code, AH = Scancode
433*b76ca311SAxel Dörfler
434*b76ca311SAxel Dörfler	cmp		ah, KEY_DOWN
435*b76ca311SAxel Dörfler	je		selectNextPartition
436*b76ca311SAxel Dörfler
437*b76ca311SAxel Dörfler	cmp		ah, KEY_UP
438*b76ca311SAxel Dörfler	je		selectPreviousPartition
439*b76ca311SAxel Dörfler
440*b76ca311SAxel Dörfler	cmp		ah, KEY_RETURN
441*b76ca311SAxel Dörfler	jne		inputLoop
442*b76ca311SAxel Dörfler	jmp		bootSelectedPartition
443*b76ca311SAxel Dörfler
444*b76ca311SAxel DörflerselectNextPartition:
445*b76ca311SAxel Dörfler	mov		ax, [bp + selection]
446*b76ca311SAxel Dörfler	inc		ax
447*b76ca311SAxel Dörfler	cmp		ax, [listItemCount]
448*b76ca311SAxel Dörfler	jne		.done								; At end of list?
449*b76ca311SAxel Dörfler	xor		ax, ax								; Then jump to first entry
450*b76ca311SAxel Dörfler.done:
451*b76ca311SAxel Dörfler	mov		[bp + selection], ax
452*b76ca311SAxel Dörfler	jmp		mainLoop
453*b76ca311SAxel Dörfler
454*b76ca311SAxel DörflerselectPreviousPartition:
455*b76ca311SAxel Dörfler	mov		ax, [bp + selection]
456*b76ca311SAxel Dörfler	or		ax, ax
457*b76ca311SAxel Dörfler	jnz		.done								; At top of list?
458*b76ca311SAxel Dörfler	mov		ax, [listItemCount]					; Then jump to last entry
459*b76ca311SAxel Dörfler.done:
460*b76ca311SAxel Dörfler	dec		ax
461*b76ca311SAxel Dörfler	mov		[bp + selection], ax
462*b76ca311SAxel Dörfler	jmp		mainLoop
463*b76ca311SAxel Dörfler
464*b76ca311SAxel Dörfler
465*b76ca311SAxel Dörfler; ======================= Print the OS list ============================
466*b76ca311SAxel DörflerprintMenu:
467*b76ca311SAxel Dörfler	mov		al, [bp + firstLine]
468*b76ca311SAxel Dörfler	mov		[bp + cursorY], al
469*b76ca311SAxel Dörfler
470*b76ca311SAxel Dörfler	mov		si, list							; Start at top of list
471*b76ca311SAxel Dörfler	xor		cx, cx								; The index of the current item
472*b76ca311SAxel Dörfler
473*b76ca311SAxel Dörfler.loop:
474*b76ca311SAxel Dörfler	lodsb										; String length incl. 0-terminator
475*b76ca311SAxel Dörfler	add		al, 3								; center menu item
476*b76ca311SAxel Dörfler	shr		al, 1								; x = TEXT_COLUMNS / 2 - length / 2
477*b76ca311SAxel Dörfler	mov		dl, TEXT_COLUMNS / 2
478*b76ca311SAxel Dörfler	sub		dl, al
479*b76ca311SAxel Dörfler	mov		[bp + cursorX], dl
480*b76ca311SAxel Dörfler
481*b76ca311SAxel Dörfler	mov		al, TRIANGLE_TO_RIGHT
482*b76ca311SAxel Dörfler	call	updateMarker
483*b76ca311SAxel Dörfler	inc		byte [bp + cursorX]
484*b76ca311SAxel Dörfler
485*b76ca311SAxel Dörfler	mov		di, cx
486*b76ca311SAxel Dörfler	and		di, 3
487*b76ca311SAxel Dörfler	mov		bl, [kColorTable + di]				; Text color
488*b76ca311SAxel Dörfler
489*b76ca311SAxel Dörfler	cmp		cx, [bp + selection]
490*b76ca311SAxel Dörfler	jne		.print								; Selected item reached?
491*b76ca311SAxel Dörfler	xor		bl, BRIGHT_COLOR_MASK				; Highlight it
492*b76ca311SAxel Dörfler
493*b76ca311SAxel Dörfler.print:
494*b76ca311SAxel Dörfler	call	printstr
495*b76ca311SAxel Dörfler	add		si, sizeof(BootLoaderAddress)
496*b76ca311SAxel Dörfler
497*b76ca311SAxel Dörfler	add		byte [bp + cursorX], 1
498*b76ca311SAxel Dörfler	mov		al, TRIANGLE_TO_LEFT
499*b76ca311SAxel Dörfler	call	updateMarker
500*b76ca311SAxel Dörfler
501*b76ca311SAxel Dörfler	inc		byte [bp + cursorY]
502*b76ca311SAxel Dörfler	inc		cx
503*b76ca311SAxel Dörfler
504*b76ca311SAxel Dörfler	cmp		cx, [listItemCount]
505*b76ca311SAxel Dörfler	jne		.loop
506*b76ca311SAxel Dörfler	ret
507*b76ca311SAxel Dörfler
508*b76ca311SAxel DörflerupdateMarker:
509*b76ca311SAxel Dörfler	cmp		cx, [bp + selection]
510*b76ca311SAxel Dörfler	je		.print
511*b76ca311SAxel Dörfler	mov		al, ' '								; Clear marker
512*b76ca311SAxel Dörfler.print
513*b76ca311SAxel Dörfler	mov		bl, WHITE
514*b76ca311SAxel Dörfler	jmp		printChar							; return from subroutine
515*b76ca311SAxel Dörfler
516*b76ca311SAxel Dörfler
517*b76ca311SAxel Dörfler; ========================== Chainload ==========================
518*b76ca311SAxel Dörfler
519*b76ca311SAxel DörflerbootSelectedPartition:
520*b76ca311SAxel Dörfler
521*b76ca311SAxel Dörfler	call	showCursor
522*b76ca311SAxel Dörfler
523*b76ca311SAxel Dörfler	call	getSelectedBootLoaderAddress
524*b76ca311SAxel Dörfler	lodsb										; Set boot drive
525*b76ca311SAxel Dörfler	mov		dl, al
526*b76ca311SAxel Dörfler
527*b76ca311SAxel Dörfler	mov		di, bootSectorDAP+AddressPacket.offset	; Copy start sector
528*b76ca311SAxel Dörfler	mov		cx, 4								; It is stored in a quad word
529*b76ca311SAxel Dörfler.copy_start_sector
530*b76ca311SAxel Dörfler	lodsw
531*b76ca311SAxel Dörfler	stosw
532*b76ca311SAxel Dörfler	loop .copy_start_sector
533*b76ca311SAxel Dörfler
534*b76ca311SAxel Dörfler	mov		ah, EXTENDED_READ					; Now read start sector from HD
535*b76ca311SAxel Dörfler	mov		si, bootSectorDAP
536*b76ca311SAxel Dörfler	int		BIOS_DISK_SERVICES
537*b76ca311SAxel Dörfler	mov		si, kReadError
538*b76ca311SAxel Dörfler	jc		printAndHalt						; Failed to read sector
539*b76ca311SAxel Dörfler
540*b76ca311SAxel Dörfler	mov		ax, [kMBRSignature]
541*b76ca311SAxel Dörfler	cmp		ax, MBR_SIGNATURE
542*b76ca311SAxel Dörfler	mov		si, kNoBootablePartitionError
543*b76ca311SAxel Dörfler	jne		printAndHalt						; Missing signature
544*b76ca311SAxel Dörfler
545*b76ca311SAxel Dörfler	CLEAR_SCREEN
546*b76ca311SAxel Dörfler
547*b76ca311SAxel Dörfler	; Print "Loading <name>" at top of screen
548*b76ca311SAxel Dörfler	mov		word [bp + cursorPosition], 0
549*b76ca311SAxel Dörfler	mov		si, kLoadingMessage
550*b76ca311SAxel Dörfler	mov		bl, LIGHT_GRAY
551*b76ca311SAxel Dörfler	call	printstr
552*b76ca311SAxel Dörfler
553*b76ca311SAxel Dörfler	inc		byte [bp + cursorX]
554*b76ca311SAxel Dörfler	call	getSelectedMenuItem
555*b76ca311SAxel Dörfler	inc		si									; Skip string length byte
556*b76ca311SAxel Dörfler	call	printstr
557*b76ca311SAxel Dörfler
558*b76ca311SAxel Dörfler	mov		dx, 0x100
559*b76ca311SAxel Dörfler	xor		bh, bh
560*b76ca311SAxel Dörfler	mov		ah, SET_CURSOR
561*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
562*b76ca311SAxel Dörfler
563*b76ca311SAxel Dörfler	call	getSelectedBootLoaderAddress
564*b76ca311SAxel Dörfler	mov		dl, [si]							; drive number in dl
565*b76ca311SAxel Dörfler
566*b76ca311SAxel Dörfler	jmp		$$									; Start loaded boot loader
567*b76ca311SAxel Dörfler
568*b76ca311SAxel Dörfler
569*b76ca311SAxel DörflerprintAndHalt:
570*b76ca311SAxel Dörfler	mov		dx, (TEXT_ROWS-4) * 0x100 + (TEXT_COLUMNS / 3)
571*b76ca311SAxel Dörfler	mov		[bp + cursorPosition], dx
572*b76ca311SAxel Dörfler
573*b76ca311SAxel Dörfler	mov		bx, 0x0F							; Page number and foreground color
574*b76ca311SAxel Dörfler	call	printstr
575*b76ca311SAxel Dörfler	mov		ah, READ_CHAR
576*b76ca311SAxel Dörfler	int		BIOS_KEYBOARD_SERVICES
577*b76ca311SAxel Dörfler	mov		dl, 0x80
578*b76ca311SAxel Dörfler	int		BIOS_REBOOT
579*b76ca311SAxel Dörfler
580*b76ca311SAxel Dörfler; Output:
581*b76ca311SAxel Dörfler;	si	address of selected menu item
582*b76ca311SAxel Dörfler; Trashes:
583*b76ca311SAxel Dörfler;	ax, cx
584*b76ca311SAxel DörflergetSelectedMenuItem:
585*b76ca311SAxel Dörfler	mov		si, list							; Search address of start sector
586*b76ca311SAxel Dörfler												; of the selected item.
587*b76ca311SAxel Dörfler	mov		cx, [bp + selection]
588*b76ca311SAxel Dörfler	inc		cx									; Number of required iterations
589*b76ca311SAxel Dörfler
590*b76ca311SAxel Dörfler	xor		ah, ah								; The high-byte of the string length
591*b76ca311SAxel Dörfler												; see loop body
592*b76ca311SAxel Dörfler	jmp		.entry
593*b76ca311SAxel Dörfler
594*b76ca311SAxel Dörfler.loop:
595*b76ca311SAxel Dörfler	lodsb										; Length of menu item name
596*b76ca311SAxel Dörfler	add		si, ax								; Skip name to BootLoaderAddess
597*b76ca311SAxel Dörfler	add		si, sizeof(BootLoaderAddress)
598*b76ca311SAxel Dörfler
599*b76ca311SAxel Dörfler.entry:
600*b76ca311SAxel Dörfler	loop	.loop
601*b76ca311SAxel Dörfler	ret
602*b76ca311SAxel Dörfler
603*b76ca311SAxel DörflergetSelectedBootLoaderAddress:
604*b76ca311SAxel Dörfler	call	getSelectedMenuItem
605*b76ca311SAxel Dörfler	lodsb
606*b76ca311SAxel Dörfler	xor		ah, ah
607*b76ca311SAxel Dörfler	add		si, ax								; Skip name
608*b76ca311SAxel Dörfler	ret
609*b76ca311SAxel Dörfler
610*b76ca311SAxel DörflerprintStringStage2:
611*b76ca311SAxel Dörfler	PRINT_STRING
612*b76ca311SAxel Dörfler
613*b76ca311SAxel Dörfler; al ... ASCII character
614*b76ca311SAxel Dörfler; bl ... color
615*b76ca311SAxel DörflerprintChar:
616*b76ca311SAxel Dörfler	push	ax
617*b76ca311SAxel Dörfler	push	bx
618*b76ca311SAxel Dörfler	push	cx
619*b76ca311SAxel Dörfler	push	dx
620*b76ca311SAxel Dörfler
621*b76ca311SAxel Dörfler	xor		bh, bh								; Write on page 0
622*b76ca311SAxel Dörfler
623*b76ca311SAxel Dörfler	mov		dx, [bp + cursorPosition]
624*b76ca311SAxel Dörfler	mov		ah, SET_CURSOR
625*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
626*b76ca311SAxel Dörfler
627*b76ca311SAxel Dörfler	inc		byte [bp + cursorX]
628*b76ca311SAxel Dörfler
629*b76ca311SAxel Dörfler	mov		cx, 1
630*b76ca311SAxel Dörfler	mov		ah, WRITE_CHAR
631*b76ca311SAxel Dörfler	int		BIOS_VIDEO_SERVICES
632*b76ca311SAxel Dörfler
633*b76ca311SAxel Dörfler	pop		dx
634*b76ca311SAxel Dörfler	pop		cx
635*b76ca311SAxel Dörfler	pop		bx
636*b76ca311SAxel Dörfler	pop		ax
637*b76ca311SAxel Dörfler	ret
638*b76ca311SAxel Dörfler
639*b76ca311SAxel Dörfler; ================================ DATA ===========================
640*b76ca311SAxel Dörfler
641*b76ca311SAxel DörflerbootSectorDAP:
642*b76ca311SAxel Dörfler	istruc AddressPacket
643*b76ca311SAxel Dörfler		at AddressPacket.packet_size,	db		0x10
644*b76ca311SAxel Dörfler		at AddressPacket.block_count,	db		0x01
645*b76ca311SAxel Dörfler		at AddressPacket.buffer,		dw		0x0000, 0x07c0
646*b76ca311SAxel Dörfler	iend
647*b76ca311SAxel Dörfler
648*b76ca311SAxel DörflerkColorTable:
649*b76ca311SAxel Dörfler	db BLUE, RED, GREEN, CYAN
650*b76ca311SAxel DörflerkReadError:
651*b76ca311SAxel Dörfler	db		'Error loading sectors', 0x00
652*b76ca311SAxel DörflerkNoBootablePartitionError:
653*b76ca311SAxel Dörfler	db		'Not a bootable partition', 0x00
654*b76ca311SAxel DörflerkLoadingMessage:
655*b76ca311SAxel Dörfler	db		'Loading', 0x00
656*b76ca311SAxel Dörfler
657*b76ca311SAxel Dörfler
658*b76ca311SAxel DörflerlistItemCount:
659*b76ca311SAxel DörflerdefaultItem			equ		listItemCount + 2
660*b76ca311SAxel Dörflertimeout				equ		defaultItem + 2
661*b76ca311SAxel Dörflerlist				equ		timeout + 2
662*b76ca311SAxel Dörfler
663*b76ca311SAxel Dörfler; dw number of entries
664*b76ca311SAxel Dörfler; dw the default entry
665*b76ca311SAxel Dörfler; dw the timeout (-1 for none)
666*b76ca311SAxel Dörfler; entry:
667*b76ca311SAxel Dörfler; db size of partition name 0-terminated string
668*b76ca311SAxel Dörfler; db 0-terminated string with partition name
669*b76ca311SAxel Dörfler; db hard drive number
670*b76ca311SAxel Dörfler; quadword start sector
671*b76ca311SAxel Dörfler
672*b76ca311SAxel Dörfler%if USE_TEST_MENU
673*b76ca311SAxel Dörfler	dw		0x06
674*b76ca311SAxel Dörfler
675*b76ca311SAxel Dörfler	dw		2
676*b76ca311SAxel Dörfler
677*b76ca311SAxel Dörfler	dw		5
678*b76ca311SAxel Dörfler
679*b76ca311SAxel Dörfler	db		0x06
680*b76ca311SAxel Dörfler	db		'HAIKU', 0
681*b76ca311SAxel Dörfler	db		0x80
682*b76ca311SAxel Dörfler	dw		1, 0, 0, 0
683*b76ca311SAxel Dörfler
684*b76ca311SAxel Dörfler	db		0x08
685*b76ca311SAxel Dörfler	db		'FreeBSD', 0
686*b76ca311SAxel Dörfler	db		0x80
687*b76ca311SAxel Dörfler	dw		0x003F, 0, 0, 0
688*b76ca311SAxel Dörfler
689*b76ca311SAxel Dörfler	db		0x04
690*b76ca311SAxel Dörfler	db		'DOS', 0
691*b76ca311SAxel Dörfler	db		0x80
692*b76ca311SAxel Dörfler	dw		0x003E, 0, 0, 0
693*b76ca311SAxel Dörfler
694*b76ca311SAxel Dörfler	db		0x06
695*b76ca311SAxel Dörfler	db		'LINUX', 0
696*b76ca311SAxel Dörfler	db		0x80
697*b76ca311SAxel Dörfler	dw		0x003F, 0, 0, 0
698*b76ca311SAxel Dörfler
699*b76ca311SAxel Dörfler	db		0x08
700*b76ca311SAxel Dörfler	db		'BeOS R5', 0
701*b76ca311SAxel Dörfler	db		0x80
702*b76ca311SAxel Dörfler	dw		0x003F, 0, 0, 0
703*b76ca311SAxel Dörfler
704*b76ca311SAxel Dörfler	db		0x07
705*b76ca311SAxel Dörfler	db		'OpenBSD', 0
706*b76ca311SAxel Dörfler	db		0x80
707*b76ca311SAxel Dörfler	dw		0xAAAA, 0, 0, 0
708*b76ca311SAxel Dörfler
709*b76ca311SAxel Dörfler	dw		kStage1UnusedSpace
710*b76ca311SAxel Dörfler%endif
711*b76ca311SAxel Dörfler
712