• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* -----------------------------------------------------------------------
2 *
3 *   Copyright 2010-2011 Gene Cumm
4 *
5 *   Portions from mbr.S:
6 *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
7 *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
8 *
9 *   Permission is hereby granted, free of charge, to any person
10 *   obtaining a copy of this software and associated documentation
11 *   files (the "Software"), to deal in the Software without
12 *   restriction, including without limitation the rights to use,
13 *   copy, modify, merge, publish, distribute, sublicense, and/or
14 *   sell copies of the Software, and to permit persons to whom
15 *   the Software is furnished to do so, subject to the following
16 *   conditions:
17 *
18 *   The above copyright notice and this permission notice shall
19 *   be included in all copies or substantial portions of the Software.
20 *
21 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 *   OTHER DEALINGS IN THE SOFTWARE.
29 *
30 * ----------------------------------------------------------------------- */
31
32/*
33 * handoff.S: MBR/VBR-like codeblock to display handoff data
34 *
35 * Displays the values of DL, DS, SI, the contents of [DS:SI] (16 bytes),
36 * the values of ES, DI, the contents of [ES:DI] (4 bytes), scans memory for
37 * $PnP then reports a boot failure.
38 *
39 * This should (hopefully) be only 8086 code
40 */
41
42/*
43 * Install instructions (assuming your target is /dev/dev; file or block device):
44 *
45 * MBR:
46 * dd conv=notrunc bs=440 count=1 if=handoff.bin of=/dev/dev
47 *
48 * VBR/PBR (should work for FAT12/16/32, ext[234]fs, btrfs):
49 * echo -en "\0353\0130\0220" |dd conv=notrunc bs=1 count=3 of=/dev/dev
50 * dd conv=notrunc bs=2 count=210 seek=45 if=handoff.bin of=/dev/dev
51 */
52
53// #define DEBUG_MARKER1	/* Insert markers in binary */
54// #define DEBUG_START	/* Print entry addresses at start */
55// #define DEBUG_LOADE	/* movw versus pop */
56#define DEBUG_PNP	/* Scan for $PnP and show address */
57#define DEBUG_PAK	/* Press Any Key before boot fail */
58// #define DEBUG_ENTRY_REG	/* Store (manually as pusha is 80186) registers */
59// #define DEBUG_FDT	/* Print the floppy descriptor table; INT 1Eh*/
60
61#ifdef DEBUG_MARKER1
62	.macro ASCII_MARKER1 s:vararg
63	.ascii	\s
64	.endm
65#else	/* DEBUG_MARKER1 */
66	.macro ASCII_MARKER1 s:vararg
67	.endm
68#endif	/* DEBUG_MARKER1 */
69
70#ifdef DEBUG_LOADE
71	.macro LOADE r:req, t:req
72	movw	(es_\r), %\t
73	.endm
74#else	/* DEBUG_LOADE */
75	.macro LOADE r:req, t:req
76	popw %\t
77	.endm
78#endif	/* DEBUG_LOADE */
79
80	.code16
81	.text
82
83entry		= 0x7c00
84stack		= (entry)
85e_start		= (stack)
86e_ax		= (e_start-2)
87e_ss		= (e_ax-2)
88e_sp		= (e_ss-2)
89e_bot		= (e_ss)
90/* Doubtful this will be used */
91e0_beg		= (e_bot)
92e0_ax		= (e0_beg-2)
93e0_cx		= (e0_ax-2)
94e0_dx		= (e0_cx-2)
95e0_bx		= (e0_dx-2)
96e0_sp		= (e0_bx-2)
97e0_bp		= (e0_sp-2)
98e0_si		= (e0_bp-2)
99e0_di		= (e0_si-2)
100e0_ds		= (e0_di-2)
101e0_es		= (e0_ds-2)
102e0_bot		= (e0_es)
103es_beg		= (e0_bot)	/* Original register values from entry point */
104es_di		= (es_beg-2)
105es_es		= (es_di-2)
106es_si		= (es_es-2)
107es_ds		= (es_si-2)
108es_bot		= (es_ds)
109
110BIOS_page	= 0x462
111
112int_1e		= (4*0x1e)
113int_1e_seg	= (int_1e)
114int_1e_off	= (int_1e+2)
115
116	.globl	_start
117_start:
118	cli
119#ifdef DEBUG_ENTRY_REG
120	movw	%ax, e_ax
121	movw	%ss, e_ss
122	movw	%sp, e_sp
123#endif /* DEBUG_ENTRY_REG */
124	xorw	%ax, %ax
125	movw	%ax, %ss
126#ifdef DEBUG_ENTRY_REG
127	movw	$e0_beg, %sp
128	/* pushaw */		/* 80186 */
129	pushw	%ax
130	pushw	%cx
131	pushw	%dx
132	pushw	%bx
133	pushw	%sp
134	pushw	%bp
135	pushw	%si
136	pushw	%di
137	pushw	%ds
138	pushw	%es
139#else /* DEBUG_ENTRY_REG */
140	movw	$es_beg, %sp
141#endif /* DEBUG_ENTRY_REG */
142	pushw	%di		/* es:di -> $PnP header */
143	pushw	%es
144	pushw	%si
145	pushw	%ds
146	sti
147	cld
148	pushw	%cs
149	popw	%ds
150
151#ifdef DEBUG_START
152	pushw	%dx
153	call	crlf
154	movw	$(_start),%dx	/* 0x0600 mbr.ld .text address */
155	call	wrhexw
156	call	crlf
157	call	caddr
158caddr:
159	popw	%dx
160	subw	$(caddr - _start), %dx
161	call	wrhexw
162	call	crlf
163	popw	%dx
164#endif	/* DEBUG_START */
165
166	/* write DL */
167pr_dl:	call	wrstr
168	.ascii	"DL: \0"
169	call	wrhexb
170	/* DS */
171pr_ds:	call	wrstr
172	.ascii	"  DS: \0"
173	LOADE	ds, dx
174	pushw	%dx
175	popw	%es
176	call	wrhexw
177	/* SI */
178pr_si:	call	wrstr
179	.ascii	"  SI: \0"
180	LOADE	si, dx
181	pushw	%dx
182	popw	%di
183	call	wrhexw
184	call	crlf
185	/* DS:SI */
186	movw	$16, %cx
187	call	wrhexbses
188	call	crlf
189
190	/* ES */
191pr_es:	call	wrstr
192	.ascii	"ES: \0"
193	LOADE	es, dx
194	pushw	%dx
195	popw	%es
196	call	wrhexw
197pr_di:	call	wrstr
198	.ascii	"  DI: \0"
199	LOADE	di, dx
200	pushw	%dx
201	popw	%di
202	call	wrhexw
203	call	crlf
204	/* ES:DI */	/* %es:0(%di) */
205	movw	$4, %cx
206	call	wrhexbses
207
208#ifdef DEBUG_PNP
209	subw	$4, %si
210	es lodsw
211	cmpw	$0x5024, %ax
212	jne	scn_pnp
213	es lodsw
214	cmpw	$0x506E, %ax
215	jne	scn_pnp
216	call	wrstr
217	.ascii	" =$PnP\0"
218scn_pnp:
219	call	crlf
220	/* $PnP Scan */
221	movw	$0xf000, %dx
222	pushw	%dx
223	popw	%es
224	movw	$0, %si
225	movw	$0x1000, %cx
226	/* 0x506E5024 */
227	movw	$0x5024, %dx
228	movw	$0x506E, %bx
229ch_pnp:	es lodsw	/* Check for $PnP */
230	cmpw	%dx, %ax
231	jne	ch_pnp_l
232	es lodsw
233	cmpw	%bx, %ax
234	je	pr_pnp
235ch_pnp_l:		/* Check $PnP failed; loop to next address */
236	addw	$14, %si
237	andw	$0xFFF0, %si
238	loopw	ch_pnp
239	jmp	pnp_end
240pr_pnp:
241	pushw	%si
242	call	wrstr
243	.ascii	"$PnP-\0"
244	movw	%es, %dx
245	call	wrhexw
246	movb	$':, %al
247	call	wrchr
248	popw	%dx
249	andw	$0xFFF0, %dx
250	call	wrhexw
251#endif	/* DEBUG_PNP */
252	call	crlf
253pnp_end:
254
255#ifdef DEBUG_FDT
256	/* INT 1Eh: Floppy Parameter Table Pointer */
257pr_1e:	call	wrstr
258	.ascii	"INT 1Eh: \0"
259	mov	$int_1e,%bx
260	les	(%bx),%di
261	pushw	%es
262	popw	%dx
263	call	wrhexw
264	movb	$':, %al
265	call	wrchr
266	pushw	%di
267	popw	%dx
268	call	wrhexw
269	call	crlf
270	/* [INT 1Eh] */
271	movw	$14, %cx
272	call	wrhexbses
273	call	crlf
274#endif	/* DEBUG_FDT */
275
276end:
277	jmp	bootfail
278
279	ASCII_MARKER1	"wc"
280wrchr:
281	movb	$0x0e, %ah
282	movb	(BIOS_page), %bh
283	movb	$0x07, %bl
284	int	$0x10		/* May destroy %bp */
285	ret
286
287	ASCII_MARKER1	"ws"
288wrstr:
289	pop	%si
290wrstr_l:
291	lodsb
292	cmpb	$0, %al
293	je	wrstr_d
294	call	wrchr
295	jmp	wrstr_l
296wrstr_d:
297	push	%si
298	ret
299
300crlf:
301	call	wrstr
302	.ascii	"\r\n\0"
303	ret
304
305	ASCII_MARKER1	"hx"
306wrhexn:
307	and	$0x0F, %al
308	cmpb	$10, %al
309	jae	.alph
310	addb	$'0, %al
311	jmp	.wc
312.alph:
313	addb	$('A - 10), %al
314.wc:
315	call wrchr
316	ret
317
318wrhexb:
319	pushw	%cx
320	movb	%dl, %al
321	pushw	%ax
322	movb	$4, %cl
323	rorw	%cl, %ax
324	call	wrhexn
325	popw	%ax
326	call	wrhexn
327	popw	%cx
328	ret
329
330wrhexw:
331	pushw	%cx
332	movb	$8, %cl
333	rorw	%cl, %dx
334	call wrhexb
335	rorw	%cl, %dx
336	call wrhexb
337	popw	%cx
338	ret
339
340	ASCII_MARKER1	"HE"
341wrhexbses:
342	pushw	%di
343	popw	%si
344wrhexbses_l:
345	movb	$' , %al
346	call	wrchr
347	es lodsb
348	movw	%ax, %dx
349	call	wrhexb
350	loop	wrhexbses_l
351	ret
352
353data:
354	ASCII_MARKER1	"bf"
355bootfail:
356#ifdef DEBUG_PAK
357	call wrstr
358	.ascii	"\r\n\r\nPress any key\r\n\0"
359	xor	%ax, %ax
360	int	$0x16
361#endif
362	int	$0x18		/* Boot failure */
363die:
364	hlt
365	jmp	die
366