xref: /netbsd-src/sys/arch/hppa/stand/xxboot/start.S (revision 6d3ceb1d619615401b17c9aa3e4bc674a1cb048b)
1;	$NetBSD: start.S,v 1.1 2014/02/24 07:23:43 skrll Exp $
2
3; Copyright (c) 2003 ITOH Yasufumi.
4; All rights reserved.
5;
6; Redistribution and use in source and binary forms, with or without
7; modification, are permitted provided that the following conditions
8; are met:
9; 1. Redistributions of source code must retain the above copyright
10;    notice, this list of conditions and the following disclaimer.
11; 2. Redistributions in binary forms are unlimited.
12;
13; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS''
14; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16; PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
17; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23; THE POSSIBILITY OF SUCH DAMAGE.
24
25	.level	1.0
26
27	.code
28	.origin	0
29	;
30	; LIF (Logical Interchange Format) header
31	;
32lifhdr:	.byte	0x80,0x00	; LIF magic
33	.string	"NetBSD"	; volume label (6 chars, fill with space)
34	.origin	0xf0
35	; 0xf0
36lif_ipl_addr:
37	.word	top-lifhdr	; start at 4KB (must be 2KB aligned)
38lif_ipl_size:
39	.word	0x00001000	; size 4KB (must be 2KB aligned)
40lif_ipl_entry:
41	.word	$START$-top	; entry offset
42
43	; ipl part 1 starts here
44	.origin	4096
45top:
46	;
47	; IPL startup
48	;
49	; arg0 = interact flag (1: interactive, 0: otherwise)
50	; arg1 = address of first doubleword past the end of ipl part 1
51	;
52	.export $START$,entry
53$START$:
54	b,n	start			; 0: entry address
55
56; version of interface of primary to secondary boot
57BOOT_IF_VERSION:	.equ	0
58; version 0: arg0 = interact flag, arg1 = version (0),
59;	     arg2 = end addr, arg3 = selected boot partition
60;	     r1, r3 - r22, r28, r29, r31 = cleared to zeros
61
62cksum:		.word	0		; 4: checksum will be stored here
63version:	.word	BOOT_IF_VERSION	; 8: version of interface
64rsvd1:		.word	0		; 12: future use
65rsvd2:		.word	0		; 16: future use
66rsvd3:		.word	0		; 20: future use
67
68start:
69	; set data pointer for relocatable data access
70	blr	%r0,%r27
71	; get PSW at entry
72	ssm	0,%r4
73	.export	$global$,data
74$global$:
75
76	; save parameters for main
77	copy	%arg0,%r3
78
79tmpdiskbufsz:		.equ	0x1000	; 4KB
80tmpdiskbuf_labelsec:	.equ	0x0200	; dbtob(LABELSECTOR)
81tmpdiskbuf_labelsecsz:	.equ	512
82tmpdiskbuf_part2:	.equ	0x0400
83tmpdiskbuf_part2sz:	.equ	0x0400
84tmpdiskbuf_part3:	.equ	0x0A00
85tmpdiskbuf_part3sz:	.equ	0x0600
86
87part1sz:		.equ	0x1000
88
89	; get next free address
90	.import	_end,data
91	addil	L%_end-$global$,%r27;%r1
92	ldo	R%_end-$global$(%r1),%r1
93
94	; 32bit environment (and this code) requires stack is 64byte aligned.
95	ldi	64-1,%r2
96	add	%r1,%r2,%r1
97	andcm	%r1,%r2,%r6			; r6 = tmp disk buffer
98	ldo	tmpdiskbufsz+64(%r6),%sp	; tmp stack
99
100	bl	print,%rp
101	ldo	str_startup-$global$(%r27),%arg0
102
103	;
104	; read part 2 and 3 of ipl (see README.ipl)
105	;
106
107	; read disk blocks which contains ipl part 2 and part 3
108	copy	%r6,%arg0
109	ldi	0,%arg2			; offset = 0
110	bl	boot_input,%rp
111	ldi	tmpdiskbufsz,%arg1	; read size
112
113	; part 2 address
114	ldo	top-$global$+part1sz(%r27),%r19
115
116	; copy part 2
117	ldo	tmpdiskbuf_part2(%r6),%r20
118	addi,tr	tmpdiskbuf_part2sz/4,%r0,%r2	; loop count, skip next
119cpipl2:	stws,ma		%r1,4(0,%r19)		; write to dst
120	addib,uv,n	-1,%r2,cpipl2		; check loop condition
121	ldws,ma		4(0,%r20),%r1		; read from src
122
123	; copy part 3
124	; (r19 already has destination address of part 3)
125	ldo	tmpdiskbuf_part3(%r6),%r20
126	addi,tr	tmpdiskbuf_part3sz/4,%r0,%r2	; loop count, skip next
127cpipl3:	stws,ma		%r1,4(0,%r19)		; write to dst
128	addib,uv,n	-1,%r2,cpipl3		; check loop condition
129	ldws,ma		4(0,%r20),%r1		; read from src
130
131	; flush data cache / invalidate instruction cache
132	ldo	top-$global$+part1sz(%r27),%r1	; part 2 address
133	ldi	16,%r20		; 16: cache line size
134flipl:	fdc	0(0,%r1)	; flush data cache line at r1
135	comb,<	%r1,%r19,flipl
136	fic,m	%r20(0,%r1)	; flush instruction cache line at r1, r1 += 16
137	sync			; I/O operation is guaranteed to finish
138				; in eight instructions after sync
139	;
140	; Now, whole the IPL is loaded
141	;
142
143	; clear BSS
144	.import	_edata,data
145	addil	L%_edata-$global$,%r27;%r1
146	ldo	R%_edata-$global$(%r1),%r1
147clrbss:	comb,<	%r1,%r6,clrbss
148	stws,ma	%r0,4(0,%r1)
149
150	; we have read disklabel -- save it for later use
151	.import	labelsector,data
152	addil	L%labelsector-$global$,%r27;%r1
153	ldo	R%labelsector-$global$(%r1),%r20
154	ldo	tmpdiskbuf_labelsec(%r6),%r21
155	addi,tr	tmpdiskbuf_labelsecsz/4,%r0,%r2	; loop count, skip next
156cplbl:	stws,ma		%r1,4(0,%r20)		; write to dst
157	addib,uv,n	-1,%r2,cplbl		; check loop condition
158	ldws,ma		4(0,%r21),%r1		; read from src
159
160	; set stack
161	; (r6 points at free space, 64byte aligned)
162	; 32bit environment (and this code) requires stack is 64byte aligned.
163	ldo	64(%r6),%sp	; 64 > 48: frame marker (32) + args(up to 4)
164
165	; stack usage
166	;	12bytes	arguments
167	;	32	frame marker
168
169	; parameters for main
170	copy	%r3,%arg0
171	copy	%r4,%arg2
172
173	.import	ipl_main,entry
174	bl	ipl_main,%rp
175	copy	%sp,%arg1
176
177	; main returned --- perform reset
178	bl	print,%rp
179	ldo	str_reset-$global$(%r27),%arg0
180	; FALLTHROUGH
181
182IOMOD_CMD:		.equ	0xFFFC0000 + (4*12)
183IOMOD_CMD_STOP:		.equ	0
184IOMOD_CMD_RESET:	.equ	5
185
186; void reboot(void)
187; void halt(void)
188	.export reboot,entry
189	.export halt,entry
190reboot:
191	addi,tr	IOMOD_CMD_RESET,%r0,%r1	; %r1 = IOMOD_CMD_RESET, skip next
192halt:	ldi	IOMOD_CMD_STOP,%r1
193iomcmd:	ldil	L%IOMOD_CMD,%r2
194	ldo	R%IOMOD_CMD(%r2),%r2
195	stwas	%r1,0(%r2)
196	b,n	.
197
198str_startup:
199	.string		"\r\n\n"
200	.stringz	"NetBSD/hppa FFS/LFS Primary Bootstrap\r\n\n"
201str_reset:
202	.stringz	"\r\nresetting..."
203	.align	4
204
205; void dispatch(unsigned interactive, unsigned top, unsigned end, int part,
206;		unsigned entry)
207	.export	dispatch,entry
208dispatch:
209	; flush data cache / invalidate instruction cache
210	ldi	16,%r20		; 16: cache line size
211flush:	fdc	0(0,%arg1)	; flush data cache line at arg1
212	comb,<	%arg1,%arg2,flush
213	fic,m	%r20(0,%arg1)	; flush instruction cache line at arg1, arg1+=16
214	sync
215	copy	%r0,%r1		; I/O operation is guaranteed to finish
216	copy	%r0,%r3		; in eight instructions after sync
217	copy	%r0,%r4
218	copy	%r0,%r5		; while waiting, clear unused registers
219	copy	%r0,%r6		; for future compatibility
220	copy	%r0,%r7
221	copy	%r0,%r8
222	copy	%r0,%r9
223	copy	%r0,%r10
224	copy	%r0,%r11
225	copy	%r0,%r12
226	copy	%r0,%r13
227	copy	%r0,%r14
228	copy	%r0,%r15
229	copy	%r0,%r16
230	copy	%r0,%r17
231	copy	%r0,%r18
232	copy	%r0,%r19
233	copy	%r0,%r20
234	copy	%r0,%r21
235	copy	%r0,%r22
236	copy	%r0,%r28	; r23-r26: arg3-arg0, r27: dp
237	copy	%r0,%r29	; r30: sp
238	copy	%r0,%r31
239	ldw	-52(%sp),%arg1			; arg4: exec address
240	ldo	reboot-$global$(%r27),%rp	; reboot if returns
241	bv	%r0(%arg1)			; execute
242	ldi	BOOT_IF_VERSION,%arg1
243
244;
245;	IODC subroutines
246;
247PZ_MEM_CONSOLE:		.equ	0x3a0
248PZ_MEM_BOOT:		.equ	0x3d0
249PZ_MEM_KEYBOARD:	.equ	0x400
250
251DEV_PATH:		.equ	0x00
252DEV_LAYERS:		.equ	0x08
253DEV_HPA:		.equ	0x20	; hard physical address space
254DEV_SPA:		.equ	0x24	; soft physical address space
255DEV_IODC_ENTRY:		.equ	0x28
256DEV_CLASS:		.equ	0x2c
257DEV_CL_DUPLEX:		.equ	0x7	; full-duplex console class
258
259IODC_ENTRY_IO_BOOTIN:		.equ	0
260IODC_ENTRY_IO_CONSOLEIN:	.equ	2
261IODC_ENTRY_IO_CONSOLEOUT:	.equ	3
262
263; call_iodc
264; inputs:
265;	%ret0	IODC base in page zero
266;	%rp	return address
267;	%r29	arg 8
268;	%r19	arg 7
269;	%r20	arg 6
270;	%r21	arg 5
271;	%r25	arg 1
272; outputs
273;	all scratch regs	undefined, unless defined by the IODC call
274call_iodc:
275	; set common arguments in registers
276	addil	L%retbuf-$global$,%r27;%r1
277	ldo	R%retbuf-$global$(%r1),%r22	; arg4: return buffer
278	ldo	DEV_LAYERS(%ret0),%arg3		; arg3: layer
279	ldw	DEV_SPA(%ret0),%arg2		; arg2: spa
280	ldw	DEV_HPA(%ret0),%arg0		; arg0: hpa
281	; check if narrow or wide mode
282	ssm	0,%r1				; get PSW
283	bb,<	%r1,4,call_iodc_64		; if W, call in 64bit mode
284	ldw	DEV_IODC_ENTRY(%ret0),%r1	; ENTRY_IO address
285
286	; narrow mode
287	stw	%r29,-68(%sp)			; arg8: maxsize / lang
288	stw	%r19,-64(%sp)			; arg7: size
289	stw	%r20,-60(%sp)			; arg6: buf
290	stw	%r21,-56(%sp)			; arg5: devaddr / unused
291	bv	%r0(%r1)			; call ENTRY_IO
292	stw	%r22,-52(%sp)			; arg4: return buffer
293
294call_iodc_64:
295	.allow	2.0
296	; On PA64 convention, arg0 - arg7 are passed in registers.
297	; Parameters are placed in INCREASING order.
298	; The argument pointer points at the first stack parameter.
299	; stack usage:
300	;	64bytes	allocated for register arguments arg0-arg7
301	;	 8	arg8 (argument pointer points here)
302	;	16	frame marker
303	std	%r29,-16-8(%sp)			; arg8: maxsize / lang
304;	std	%sp,-8(%sp)			; psp in frame marker
305	bv	%r0(%r1)			; call ENTRY_IO
306	ldo	-16-8(%sp),%r29			; argument pointer
307	.allow
308
309;
310; console output
311;
312; void putch(int)
313; void print(const char *string)
314	.align	4
315	.export putch,entry
316	.export print,entry
317putch:
318	stwm	%arg0,128(%sp)		; fake up a string on the stack
319	stb	%r0,-124(%sp)		; (see stack usage below)
320	addi,tr	-125,%sp,%arg0		; string address, skip next
321print:
322	.proc
323	.callinfo	frame=128,save_rp,no_unwind
324	.entry
325	ldo	128(%sp),%sp
326	stw	%rp,-128-20(%sp)
327
328	; stack usage:
329	;	36byte	IODC buffer (assume %sp was 64byte aligned)
330	;	 4	saved reg
331	;	88	arguments, frame marker
332	;		32bit: 36 (arguments) + 32 (frame marker)
333	;		64bit: 72 (arguments) + 16 (frame marker)
334prbufsiz:	.equ	36
335
336	; save callee-saves
337	stw	%r3,-92(%sp)
338
339	copy	%arg0,%r3
340
341prloop:
342	copy	%r0,%r19
343	ldi	prbufsiz,%r20
344	ldo	-128(%sp),%r1
345
346strloop:
347	ldb	0(%r3),%r2
348	comb,=	%r2,%r0,endstr
349	stbs,ma	%r2,1(0,%r1)
350	ldo	1(%r19),%r19
351	comb,<>	%r19,%r20,strloop
352	ldo	1(%r3),%r3
353
354endstr:
355	comb,=,n	%r19,%r0,endpr
356
357	; see IODC 3-51
358	; arg0 hpa
359	; arg1 option (ENTRY_IO_CONSOLEOUT (3))
360	; arg2 spa
361	; arg3 ID_addr (pointer to LAYER)
362	; arg4 R_addr (pointer to return buffer (64word?))
363	; arg5 unused (0)
364	; arg6 memaddr (64byte-aligned) string buffer
365	; arg7 reqsize
366	; arg8 lang (0)
367	ldi	PZ_MEM_CONSOLE,%ret0		; IODC base in page zero
368	copy	%r0,%r29			; arg8: lang
369;	copy	%r19,%r19			; arg7: size
370	ldo	-128(%sp),%r20			; arg6: buf
371;	copy	%r0,%r21			; arg5: unused
372	bl	call_iodc,%rp
373	ldi	IODC_ENTRY_IO_CONSOLEOUT,%arg1	; arg1: option
374	b,n	prloop
375
376endpr:
377	; restore callee-saves
378	ldw	-92(%sp),%r3
379
380	; return subroutine
381	ldw	-128-20(%sp),%rp
382	bv	%r0(%rp)
383	.exit
384	ldo	-128(%sp),%sp
385	.procend
386
387;
388; console input
389;
390; int getch(void)
391	.align	4
392	.export	getch,entry
393getch:
394	.proc
395	.callinfo	frame=192,save_rp,no_unwind
396	.entry
397	stw	%rp,-20(%sp)
398	ldo	192(%sp),%sp
399
400	; stack usage:
401	;	64byte	IODC buffer (assume %sp was 64byte aligned)
402	;	40	unused
403	;	88	arguments, frame marker
404	;		32bit: 36 (arguments) + 32 (frame marker)
405	;		64bit: 72 (arguments) + 16 (frame marker)
406
407	; check if console is full or half duplex
408	ldw	PZ_MEM_CONSOLE+DEV_CLASS(%r0),%r1	; device class
409	extru	%r1,31,4,%r1				; right 4bits are valid
410	ldi	PZ_MEM_CONSOLE,%ret0
411	comib,=,n	DEV_CL_DUPLEX,%r1,getch_console	; use CONSOLE if full
412	ldi	PZ_MEM_KEYBOARD,%ret0			; otherwise KEYBOARD
413getch_console:
414
415	; see IODC 3-50
416	; arg0 hpa
417	; arg1 option (ENTRY_IO_CONSOLEIN (2))
418	; arg2 spa
419	; arg3 ID_addr (pointer to LAYER)
420	; arg4 R_addr (pointer to return buffer (64word?))
421	; arg5 unused (0)
422	; arg6 memaddr (64byte-aligned, must have 64byte) data buffer
423	; arg7 reqsize
424	; arg8 lang (0)
425;	copy	%rp,%rp				; IODC base in page zero
426	copy	%r0,%r29			; arg8: lang
427	ldi	1,%r19				; arg7: size (1)
428	ldo	-192(%sp),%r20			; arg6: buf
429;	copy	%r0,%r21			; arg5: unused
430	bl	call_iodc,%rp
431	ldi	IODC_ENTRY_IO_CONSOLEIN,%arg1	; arg1: option
432
433	; make return value
434	comb,<>	%ret0,%r0,getch_ret		; return -1 on error
435	ldi	-1,%ret0
436	ldi	1,%r19
437
438	; check if narrow or wide mode
439	ssm	0,%r1				; get PSW
440	bb,<	%r1,4,getch_64
441	addil	L%retbuf-$global$,%r27;%r1
442	ldw	R%retbuf-$global$(%r1),%r2	; ret[0]
443	comclr,<>	%r19,%r2,%ret0		; return 0 if no char available
444getch_retc:
445	ldb	-192(%sp),%ret0			;  otherwise return the char
446
447getch_ret:
448	; return subroutine
449	ldw	-192-20(%sp),%rp
450	bv	%r0(%rp)
451	.exit
452	ldo	-192(%sp),%sp
453
454getch_64:
455	.allow	2.0
456	ldd	R%retbuf-$global$(%r1),%r2	; ret[0] (64bit)
457	b	getch_retc
458	cmpclr,*<>	%r19,%r2,%ret0		; return 0 if no char available
459	.allow
460	.procend
461
462;
463; read boot device
464;
465; void boot_input(void *buf, unsigned len, unsigned pos)
466	.align	4
467	.export boot_input,entry
468boot_input:
469	.proc
470	.callinfo	frame=128,save_rp,no_unwind
471	.entry
472	stw	%rp,-20(%sp)
473	ldo	128(%sp),%sp
474
475	; stack usage:
476	;	40byte	unused (alignment)
477	;	88	arguments, frame marker
478	;		32bit: 36 (arguments) + 32 (frame marker)
479	;		64bit: 72 (arguments) + 16 (frame marker)
480
481	; see IODC 3-46
482	; arg0 hpa
483	; arg1 option (ENTRY_IO_BOOTIN (0))
484	; arg2 spa
485	; arg3 ID_addr (pointer to LAYER)
486	; arg4 R_addr (pointer to return buffer (64word?))
487	; arg5 devaddr
488	; arg6 memaddr (64byte-aligned) string buffer
489	; arg7 reqsize
490	; arg8 maxsize
491	ldi	PZ_MEM_BOOT,%ret0		; IODC base in page zero
492	copy	%arg1,%r29			; arg8: maxsize
493	copy	%arg1,%r19			; arg7: size
494	copy	%arg0,%r20			; arg6: buf
495	copy	%arg2,%r21			; arg5: devaddr
496	bl	call_iodc,%rp
497	ldi	IODC_ENTRY_IO_BOOTIN,%arg1	; arg1: option
498
499	; return subroutine
500	ldw	-128-20(%sp),%rp
501	bv	%r0(%rp)
502	.exit
503	ldo	-128(%sp),%sp
504	.procend
505
506;
507;	utilities
508;	optimized for size
509;
510
511; int strcmp(const char *str1, const char *str2)
512	.align	4
513	.export		strcmp,entry
514strcmp:
515	.proc
516	.callinfo	frame=0,no_calls
517	.entry
518	ldbs,ma		1(0,%arg0),%r1
519strcmp_loop:
520	comb,=		%r1,%r0,strcmp_eos
521	ldbs,ma		1(0,%arg1),%r19
522	comb,=,n	%r1,%r19,strcmp_loop
523	ldbs,ma		1(0,%arg0),%r1
524strcmp_eos:
525	bv		%r0(%rp)
526	.exit
527	sub		%r1,%r19,%ret0
528	.procend
529
530; void memcpy(void *dst, const void *src, unsigned len)
531	.align	4
532	.export		memcpy,entry
533	.export		memmove,entry
534memcpy:
535memmove:
536	.proc
537	.callinfo	no_unwind		; multiple exit points
538	.entry
539;	copy		%arg0,%ret0		; uncomment this to conform ANSI
540	comb,<<,n	%arg0,%arg1,memcpy0	; copy forward or backward?
541	add		%arg0,%arg2,%arg0	; dst end address
542	add,tr		%arg1,%arg2,%arg1	; src end address, skip next
543memcpy_bwd:
544	stbs,mb		%r1,-1(0,%arg0)		; write to dst
545	addib,uv,n	-1,%arg2,memcpy_bwd	; check loop condition
546	ldbs,mb		-1(0,%arg1),%r1		; read from src
547	bv,n		%r0(%rp)		; return subroutine
548memcpy_fwd:
549	stbs,ma		%r1,1(0,%arg0)		; write to dst
550memcpy0:
551	addib,uv,n	-1,%arg2,memcpy_fwd	; check loop condition
552	ldbs,ma		1(0,%arg1),%r1		; read from src
553	.exit
554	bv,n		%r0(%rp)		; return subroutine
555	.procend
556
557;
558;	string table
559;	placed here to save space
560;
561	.export	str_seekseq, data
562	.export	str_startup, data
563	.export	str_bit_firmware, data
564	.export	str_crlf, data
565	.export	str_space, data
566	.export	str_rubout, data
567str_seekseq:
568	.stringz	"repositioning media...\r\n"
569str_bit_firmware:
570	.stringz	"bit firmware\r\n"
571str_rubout:
572	.byte		0x08, 0x20, 0x08, 0x00	; "\b \b"
573
574	.export	str_bootpart, data
575str_bootpart:
576	.string		"boot partition (a-p, ! to reboot) [a]:"
577str_space:
578	.stringz	" "
579	.export	str_booting_part, data
580str_booting_part:
581	.string		"\r\nbooting from partition _"
582str_crlf:
583	.stringz	"\r\n"
584	.export	str_warn_2GB, data
585str_warn_2GB:
586	.stringz	"boot partition exceeds 2GB boundary\r\n"
587	.export	str_warn_unused, data
588str_warn_unused:
589	.stringz	"unused partition\r\n"
590	.export	str_nolabel, data
591str_nolabel:
592	.stringz	"no disklabel\r\n"
593
594	.export	str_filesystem, data
595str_filesystem:
596	.stringz	"filesystem: _FS\r\n"
597	.export	str_nofs, data
598str_nofs:
599	.stringz	"no filesystem found\r\n"
600	.export	str_lookup, data
601	.export	str_loading, data
602	.export	str_at, data
603	.export	str_dddot, data
604	.export	str_done, data
605str_lookup:
606	.stringz	"looking up "
607str_loading:
608	.stringz	"loading "
609str_at:
610	.stringz	" at 0x"
611str_dddot:
612	.stringz	"..."
613str_done:
614	.stringz	"done\r\n"
615
616	.export	str_boot1, data
617	.export	str_boot2, data
618	.export	str_boot3, data
619str_boot1:
620	.stringz	"boot.hp700"
621str_boot2:
622	.stringz	"boot"
623str_boot3:
624	.stringz	"usr/mdec/boot"
625
626	.export	str_noboot, data
627str_noboot:
628	.stringz	"no secondary boot found\r\n"
629
630	.export	str_ukfmt, data
631str_ukfmt:
632	.stringz	": unknown format -- exec from top\r\n"
633
634	.bss
635	.align	64
636retbuf:	.block	32*8		; *4 for narrow mode / *8 for wide mode
637
638	.export diskbuf,data
639	.align	64
640diskbuf:
641	.block	2048
642