- Add support for attaching alternative DLTs to an interface.
[dragonfly.git] / sys / boot / pc98 / boot2 / start.S
1 /*
2  * Mach Operating System
3  * Copyright (c) 1992, 1991 Carnegie Mellon University
4  * All Rights Reserved.
5  * 
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  * 
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  * 
16  * Carnegie Mellon requests users of this software to return to
17  * 
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  * 
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  *
26  *      from: Mach, Revision 2.2  92/04/04  11:36:29  rpd
27  * $FreeBSD: src/sys/boot/pc98/boot2/start.S,v 1.5 2002/05/14 12:34:03 nyan Exp $
28  * $DragonFly: src/sys/boot/pc98/boot2/Attic/start.S,v 1.3 2003/11/10 06:08:38 dillon Exp $
29  */
30
31 /*
32   Copyright 1988, 1989, 1990, 1991, 1992 
33    by Intel Corporation, Santa Clara, California.
34
35                 All Rights Reserved
36
37 Permission to use, copy, modify, and distribute this software and
38 its documentation for any purpose and without fee is hereby
39 granted, provided that the above copyright notice appears in all
40 copies and that both the copyright notice and this permission notice
41 appear in supporting documentation, and that the name of Intel
42 not be used in advertising or publicity pertaining to distribution
43 of the software without specific, written prior permission.
44
45 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
46 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
47 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
48 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
49 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
50 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
51 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52 */
53 /*
54  * Ported to PC-9801 by Yoshio Kimura
55  */
56
57 #include        "asm.h"
58
59         .file   "start.S"
60
61 SIGNATURE=      0xaa55
62 LOADSZ=         8192    /* size of unix boot */
63
64 NAMEBLOCKMAGIC= 0xfadefeed /* value of magicnumebr for block2   */
65
66 /*
67  * This DEBUGMSG(msg) macro may be useful for debugging.  Its use is
68  * restricted to this file since it only works in real mode.
69  */
70 #define DEBUGMSG(msg)           \
71         data32                  ; \
72         mov     $msg, %esi      ; \
73         data32                  ; \
74         call    message
75
76         .code16
77         .text   
78         .globl  start
79
80 start:
81         jmp     main
82 boot_cyl:
83         .word   0
84         String  "IPL1   "
85
86 main:
87         /* set up %ds */
88         xor     %ax, %ax
89         mov     %ax, %ds
90
91         /* set up %ss and %esp */
92         mov     $BOOTSEG, %eax
93         mov     %ax, %ss
94         /*
95          * make a little room on the stack for
96          * us to save the default bootstring we might find..
97          * effectively, we push the bootstring.
98          */
99         mov     $BOOTSTACK-64, %esp
100
101         /* set up %es, (where we will load boot2 to) */
102         mov     %ax, %es
103
104         push    %es
105         push    %ecx
106         push    %dx
107
108         mov     $0xa000, %eax
109         mov     %ax, %es
110
111         /* set up graphic screen */
112         movb    $0x42, %ah
113         movb    $0xc0, %ch
114         int     $0x18
115         movb    $0x40, %ah
116         int     $0x18
117
118         mov     $0x0a00, %eax           /* 80 x 25 mode  */
119
120         int     $0x18
121         movb    $0x0c, %ah              /* text on */
122         int     $0x18
123
124         /* cursor home and on */
125         xor     %dx, %dx
126         movb    $0x13, %ah
127         int     $0x18
128         movb    $0x11, %ah
129         int     $0x18
130
131         /* keyboad reset */
132         movb    $0x03, %ah
133         int     $0x18
134
135         /* transfer PC-9801 system common area to 0xa1000 */
136         mov     $0x0000, %esi
137         mov     $0x1000, %edi
138         mov     $0x0630, %ecx
139         cld
140         rep
141         movsb
142
143         /* transfer EPSON machine type to 0xa1200 */
144         push    %ds
145         mov     $0xfd00, %eax
146         mov     %ax, %ds
147         mov     0x804, %eax
148         and     $0x00ffffff, %eax
149         mov     %eax, %es: (0x1624)
150
151         pop     %ds
152         pop     %dx
153         pop     %ecx
154         pop     %es
155
156         /* bootstrap passes */
157         mov     %cs, %bx
158         cmp     $0x1fe0, %bx
159         jz      fd
160         cmp     $0x1fc0, %bx
161         jnz     hd
162         xor     %cx, %cx
163         movb    0x584, %al
164         andb    $0xf0, %al
165         cmpb    $0x30, %al
166         jz      fd
167         cmpb    $0x90, %al
168         jnz     hd
169 fd:
170         mov     $0x0200, %cx
171         mov     $0x0001, %dx
172         movb    $0xd6, %ah
173         jmp     load
174 hd:
175         and     %cx, %cx
176         jnz     1f
177         .code32
178         addr32
179         mov     %cs: (boot_cyl), %ecx   /* actualy %cx in real mode */
180         .code16
181 1:
182         xor     %dx, %dx
183         movb    $0x06, %ah      
184
185 /*
186  * BIOS call "INT 0x1B Function 0xn6" to read sectors from disk into memory
187  *      Call with       %ah = 0xd6(for floppy disk) or 0x06(for hard disk)
188  *                      %al = DA/UA
189  *                      %bx = data length
190  *                      %ch = sector size(for floppy) or cylinder(for hard)
191  *                      %cl = cylinder
192  *                      %dh = head
193  *                      %dl = sector
194  *                      %es:%bp = segment:offset of buffer
195  *      Return:
196  *                      %ah = 0x0 on success; err code on failure
197  */
198
199 load:
200 #ifdef NAMEBLOCK
201 /*
202  * Load the second sector and see if it is a boot instruction block.
203  * If it is then scan the contents for the first valid string and copy it to 
204  * the location of the default boot string.. then zero it out.
205  * Finally write the block back to disk with the zero'd out entry..
206  * I hate writing at this stage but we need this to be persistant.
207  * If the boot fails, then the next boot will get the next string.
208  * /etc/rc will regenerate a complete block2 iff the boot succeeds.
209  *
210  * Format of block 2 is:
211  * [NAMEBLOCKMAGIC] <--0xdeafc0de
212  * [nulls]
213  * [bootstring]NULL  <---e.g. 0:wd(0,a)/kernel.experimental
214  * [bootstring]NULL  <---e.g. 0:wd(0,a)/kernel.old
215  * ....
216  * [bootstring]NULL  <---e.g. 0:wd(0,f)/kernel
217  * FF FF FF
218  */
219 where:
220         /*
221          * save things we might smash
222          * (that are not smashed immedatly after us anyway.)
223          */
224         data32
225         push    %ecx    /* preserve 'cyl,sector ' */
226         data32
227         push    %edx
228 /* 
229  * Load the second sector
230  * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
231  *      Call with       %ah = 0x2
232  *                      %al = number of sectors
233  *                      %ch = cylinder
234  *                      %cl = sector
235  *                      %dh = head
236  *                      %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
237  *                      %es:%bx = segment:offset of buffer
238  *      Return:
239  *                      %al = 0x0 on success; err code on failure
240  */
241         data32
242         movl    $0x0201, %eax   /function 2 (read) 1 sector */
243         xor     %ebx, %ebx      /* %bx = 0 */ /* buffer address (ES:0) */
244         data32
245         movl    $0x0002, %ecx   /* sector 2, cylinder 0 */
246         data32
247         andl    $0x00ff, %edx   /* head 0, drive N */
248         int     $0x13
249         data32
250         jb      read_error
251         /*
252          * confirm that it is one for us
253          */
254         data32
255         xorl    %ebx, %ebx      /* magic number at start of buffer */
256         data32
257         addr32
258         movl    %es:(%ebx), %eax
259         data32
260         cmpl    $NAMEBLOCKMAGIC, %eax
261         data32
262         jne     notours         /* not ours so return to caller */
263         /*
264          * scan for a bootstring
265          * Skip the magic number, and scan till we find a non-null,
266          * or a -1
267          */
268         incl    %ebx    /* quicker and smaller */
269         incl    %ebx
270         incl    %ebx
271 scan:
272         incl    %ebx
273         addr32
274         movb    %es:(%ebx), %al /* load the next byte */
275         testb   %al, %al        /* and if it is null */
276         data32                  /* keep scanning (past deleted entries) */
277         jz scan
278         incb    %al             /* now look for -1 */
279         data32
280         jz      notours         /* if we reach the 0xFF then we have finished */
281
282         /*
283          * save our settings.. we need them twice..
284          */
285         data32
286         push    %ebx
287         /*
288          * copy it to the default string location
289          * which is just above the stack for 64 bytes.
290          */
291         data32
292         movl    $BOOTSTACK-64, %ecx     /* 64 bytes at the top of the stack */
293 nxtbyte:
294         addr32
295         movb    %es:(%ebx), %al /* get the next byte in */
296         addr32
297         movb    %al, %es:(%ecx) /* and transfer it to the name buffer */
298         incl    %ebx            /* get on with the next byte */
299         incl    %ecx            /* get on with the next byte */
300         testb   %al, %al        /* if it was 0 then quit this */
301         data32
302         jnz nxtbyte             /* and looop if more to do */ 
303         
304         /*
305          * restore the saved settings and
306          * zero it out so next time we don't try it again
307          */
308         data32
309         pop     %ebx            /* get back our starting location */
310 #ifdef  NAMEBLOCK_WRITEBACK
311 nxtbyte2:
312         addr32
313         movb    %es:(%ebx), %al /* get the byte */
314         addr32
315         movb    $0,  %es:(%ebx) /* zero it out */
316         data32
317         incl    %ebx            /* point to the next byte */
318         testb   %al, %al        /* check if we have finished.. */
319         data32
320         jne nxtbyte2
321 /* 
322  * Write the second sector back
323  * Load the second sector
324  * BIOS call "INT 0x13 Function 0x3" to write sectors from memory to disk
325  *      Call with       %ah = 0x3
326  *                      %al = number of sectors
327  *                      %ch = cylinder
328  *                      %cl = sector
329  *                      %dh = head
330  *                      %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
331  *                      %es:%bx = segment:offset of buffer
332  *      Return:
333  *                      %al = 0x0 on success; err code on failure
334  */
335         data32
336         movl    $0x0301, %eax   /* write 1 sector */
337         xor     %ebx, %ebx      /* buffer is at offset 0 */ 
338         data32
339         movl    $0x0002, %ecx   /* block 2 */
340         data32
341         andl    $0xff, %edx     /* head 0 */
342         int     $0x13
343         data32
344         jnb     notours
345         data32
346         mov     $eread, %esi
347         jmp     err_stop
348 #endif  /* NAMEBLOCK_WRITEBACK */
349         /*
350          * return to the main-line
351          */
352 notours:
353         data32
354         pop     %edx
355         data32
356         pop     %ecx
357 #endif
358         mov     $LOADSZ, %ebx
359         movb    0x584, %al
360         xor     %bp, %bp        /* %bp = 0, put it at 0 in the BOOTSEG */
361         int     $0x1b
362         jc      read_error
363
364         /*
365          * ljmp to the second stage boot loader (boot2).
366          * After ljmp, %cs is BOOTSEG and boot1 (512 bytes) will be used
367          * as an internal buffer "intbuf".
368          */
369
370         .code32
371         data32
372         ljmp    $BOOTSEG, $ EXT(boot2)
373         .code16
374
375 /*
376  * read_error
377  */
378 read_error:
379         mov     $eread, %esi
380 err_stop:
381         call    message
382         jmp     stop
383
384 /*
385  * message: write the error message in %ds:%esi to console
386  */
387 message:
388
389         push    %eax
390         push    %ebx
391         push    %ds
392         push    %es
393         mov     $0xe000, %dx
394         mov     0x501, %al
395         testb   $0x08, %al
396         jnz     1f
397         mov     $0xa000, %dx
398 1:
399         mov     %dx, %es
400         mov     %cs, %ax
401         mov     %ax, %ds
402         mov     vram, %di
403         mov     $0x00e1, %bx
404         mov     $160, %cx
405         cld
406
407 nextb:
408         lodsb                   /* load a byte into %al */
409         cmpb    $0x0, %al
410         je      done
411         cmpb    $0x0d, %al
412         je      cr_code
413         cmpb    $0x0a, %al
414         je      lf_code
415         movb    %bl, %es:0x2000(%di)
416         stosb
417         inc     %di
418         jmp     move_cursor
419 lf_code:
420         add     %cx, %di
421         jmp     move_cursor
422 cr_code:
423         xor     %dx, %dx
424         mov     %di, %ax
425         div     %cx
426         sub     %dx, %di
427 move_cursor:
428         mov     %di, %dx
429         movb    $0x13, %ah
430         int     $0x18
431         jmp     nextb
432 done:
433         mov     %di, vram
434         pop     %es
435         pop     %ds
436         pop     %ebx
437         pop     %eax
438         ret
439
440 stop:   hlt
441         jmp     stop            /* halt doesnt actually halt forever */
442
443 vram:
444         .word   0
445
446 /* error messages */
447
448
449 #ifdef  DEBUG
450 one:    String          "1-\0"
451 two:    String          "2-\0"
452 three:  String          "3-\0"
453 four:   String          "4-\0"
454 #endif  /* DEBUG */
455 #ifdef  NAMEBLOCK_WRITEBACK
456 ewrite: String          "Write error\r\n\0"
457 #endif  /* NAMEBLOCK_WRITEBACK */
458 eread:  String          "Read error\r\n\0"
459 enoboot: String         "No bootable partition\r\n\0"
460 endofcode:
461
462         . = EXT(start) + 0x1be
463
464 /* Partition table */
465
466         .fill 0x30,0x1,0x0
467         .byte 0x80, 0x00, 0x01, 0x00
468         .byte 0xa5, 0xff, 0xff, 0xff
469         .byte 0x00, 0x00, 0x00, 0x00
470         .byte 0x50, 0xc3, 0x00, 0x00
471
472 /* the last 2 bytes in the sector 0 contain the signature */
473         .value  SIGNATURE
474
475 ENTRY(disklabel)
476         . = EXT(start) + 0x400