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