freebsd-dev/sys/boot/pc98/boot2/boot1.S
Yoshihiro Takahashi 02694ba6bc Reimplement the boot2 for pc98 completely.
It's based on the newest i386's one and has the advantage of:

 - ELF binary support.
 - UFS2 filesystem support.
 - Many FreeBSD slices support on a disk.

Tested by:	SATOU Tomokazu ( tomo1770 _ maple _ ocn _ ne _ jp ),
		WATANABE Kazuhiro ( CQG00620 _ nifty _ ne _ jp ) and
		nyan

MFC after:	2 week

Happy New Year in Japan!!
2009-12-31 15:03:33 +00:00

396 lines
7.5 KiB
ArmAsm

/*-
* Copyright (c) 2008-2009 TAKAHASHI Yoshihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/* Memory Locations */
.set STACK_OFF,0x6000 # Stack offset
.set LOAD_SIZE,8192 # Load size
.set DAUA,0x0584 # DA/UA
.set MEM_REL,0x700 # Relocation address
.set MEM_ARG,0x900 # Arguments
.set MEM_BUF,0x8cec # Load area
.set MEM_BTX,0x9000 # BTX start
.set MEM_JMP,0x9010 # BTX entry point
.set MEM_USR,0xa000 # Client start
/* PC98 machine type from sys/pc98/pc98/pc98_machdep.h */
.set MEM_SYS, 0xa100 # System common area segment
.set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
.set EPSON_ID, 0x0624 # EPSON machine id
.set M_NEC_PC98, 0x0001
.set M_EPSON_PC98, 0x0002
.set M_NOT_H98, 0x0010
.set M_H98, 0x0020
.set M_NOTE, 0x0040
.set M_NORMAL, 0x1000
.set M_8M, 0x8000
/* Partition Constants */
.set PRT_OFF,0x1be # Partition offset
/* Misc. Constants */
.set SIZ_PAG,0x1000 # Page size
.set SIZ_SEC,0x200 # Sector size
.set NSECT,0x10
.globl start
.globl read
.globl putc
.code16
start: jmp main
boot_cyl: .org 4
.ascii "IPL1 "
main: cld
/* Setup the stack */
xor %si,%si
mov %si,%ss
mov $STACK_OFF,%sp
push %cx
/* Relocate ourself to MEM_REL */
push %cs
pop %ds
mov %si,%es
mov $MEM_REL,%di
mov $SIZ_SEC,%cx
rep
movsb
/* Transfer PC-9801 system common area */
xor %ax,%ax
mov %ax,%si
mov %ax,%ds
mov %ax,%di
mov $MEM_SYS,%ax
mov %ax,%es
mov $0x0600,%cx
rep
movsb
/* Transfer EPSON machine type */
mov $0xfd00,%ax
mov %ax,%ds
mov (0x804),%eax
and $0x00ffffff,%eax
mov %eax,%es:(EPSON_ID)
/* Set machine type to PC98_SYSTEM_PARAMETER */
#ifdef SET_MACHINE_TYPE
call set_machine_type
#else
mov $M_NEC_PC98+M_NOT_H98,%eax
mov %eax,%es:(PC98_MACHINE_TYPE)
#endif
/* Setup graphic screen */
mov $0x42,%ah /* 640x400 */
mov $0xc0,%ch
int $0x18
mov $0x40,%ah /* graph on */
int $0x18
/* Setup text screen */
mov $0x0a00,%ax /* 80x25 */
int $0x18
mov $0x0c,%ah /* text on */
int $0x18
mov $0x13,%ah /* cursor home */
xor %dx,%dx
int $0x18
mov $0x11,%ah /* cursor on */
int $0x18
/* Setup keyboard */
mov $0x03,%ah
int $0x18
pop %cx
/* bootstrap passes */
xor %edi,%edi
mov %di,%ds
mov %di,%es
mov %cs,%bx
cmp $0x1fe0,%bx
jz boot_fd
cmp $0x1fc0,%bx
jnz boot_hd
xor %cx,%cx
mov (DAUA),%al
and $0xf0,%al
cmp $0x30,%al
jz boot_fd
cmp $0x90,%al
jnz boot_hd
boot_fd: xor %cx,%cx
jmp boot_load
boot_hd: test %cx,%cx
jnz boot_load
mov %cs:(boot_cyl),%cx
boot_load: mov %cx,MEM_ARG /* Save cylinder number */
mov %cx,%di
xor %dx,%dx
mov $LOAD_SIZE,%bx
mov $MEM_BUF,%bp
push %cs
callw read
jc error
/* Transfer boot2.bin */
mov $MEM_BTX,%bx
mov 0xa(%bx),%si /* BTX size */
add %bx,%si /* start of boot2.bin */
mov $MEM_USR+SIZ_PAG*2,%di
mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx
sub %si,%cx
rep
movsb
/* Enable A20 */
xor %ax,%ax
outb %al,$0xf2
mov $0x02,%al
outb %al,$0xf6
/* Start BTX */
ljmp $0x0000,$MEM_JMP
/*
* Reads sectors from the disk.
* Call with:
*
* %bx - bytes to read
* %cx - cylinder
* %dh - head
* %dl - sector
* %edi - lba
* %es:(%bp) - buffer to read data into
*/
read: xor %ax,%ax
mov %ax,%ds
mov $0x06,%ah
mov (DAUA),%al
mov %ax,%si
and $0xf0,%al
cmp $0x30,%al /* 1.44MB FDD */
jz read_fd
cmp $0x90,%al /* 1MB FDD */
jz read_fd
cmp $0xa0,%al /* Is SCSI device? */
jnz read_load
push %cx
mov %si,%cx
and $0x0f,%cl
inc %cl
mov (0x482),%ah
shr %cl,%ah /* Is SCSI HDD? */
pop %cx
jc read_load
and $0xff7f,%si /* SCSI MO */
mov %di,%cx
shr $16,%di
mov %di,%dx
jmp read_load
read_fd: or $0xd000,%si
or $0x0200,%cx
inc %dx
read_load: mov %si,%ax
int $0x1b
lret
/*
* Print out the error message, wait for a keypress, and then reboot
* the machine.
*/
error: push %cs
pop %ds
mov $msg_eread,%si
call putstr
xor %ax,%ax /* Get keypress */
int $0x18
xor %ax,%ax /* CPU reset */
outb %al,$0xf0
halt: hlt
jmp halt /* Spin */
/*
* Display a null-terminated string.
*/
putstr.0: push %cs
callw putc
putstr: lodsb
test %al,%al
jne putstr.0
ret
/*
* Display a single char.
*/
putc: pusha
xor %dx,%dx
mov %dx,%ds
mov MEM_REL+cursor-start,%di
mov $0xa000,%bx
mov %bx,%es
mov $(80*2),%cx
cmp $0x08,%al
je putc.bs
cmp $0x0d,%al
je putc.cr
cmp $0x0a,%al
je putc.lf
cmp $0x5c,%al /* \ */
jne 1f
mov $0xfc,%al
1: movb $0xe1,%es:0x2000(%di)
stosw
jmp putc.scr
putc.bs: test %di,%di
jz putc.move
dec %di
dec %di
movb $0xe1,%es:0x2000(%di)
movw $0x20,%es:(%di)
jmp putc.move
putc.cr: mov %di,%ax
div %cx
sub %dx,%di
jmp putc.move
putc.lf: add %cx,%di
putc.scr: cmp $(80*2*25),%di /* Scroll screen */
jb putc.move
push %ds
mov %bx,%ds
mov $(80*2),%si
xor %di,%di
mov $(80*24/2),%cx
rep
movsl
xor %ax,%ax
mov $0x20,%al
mov $80,%cl
rep
stosw
pop %ds
mov $(80*24*2),%di
putc.move: mov %di,MEM_REL+cursor-start /* Move cursor */
mov $0x13,%ah
mov %di,%dx
int $0x18
popa
lret
cursor: .word 0
#ifdef SET_MACHINE_TYPE
/*
* Set machine type to PC98_SYSTEM_PARAMETER.
*/
set_machine_type:
xor %edx,%edx
mov %dx,%ds
// mov $MEM_SYS,%ax
// mov %ax,%es
/* Wait V-SYNC */
vsync.1: inb $0x60,%al
test $0x20,%al
jnz vsync.1
vsync.2: inb $0x60,%al
test $0x20,%al
jz vsync.2
/* ANK 'A' font */
xor %al,%al
outb %al,$0xa1
mov $0x41,%al
outb %al,$0xa3
/* Get 'A' font from CG window */
push %ds
mov $0xa400,%ax
mov %ax,%ds
xor %eax,%eax
xor %bx,%bx
mov $4,%cx
font.1: add (%bx),%eax
add $4,%bx
loop font.1
pop %ds
cmp $0x6efc58fc,%eax
jnz m_epson
m_pc98: or $M_NEC_PC98,%edx
mov $0x0458,%bx
mov (%bx),%al
test $0x80,%al
jz m_not_h98
or $M_H98,%edx
jmp 1f
m_epson: or $M_EPSON_PC98,%edx
m_not_h98: or $M_NOT_H98,%edx
1: inb $0x42,%al
test $0x20,%al
jz 1f
or $M_8M,%edx
1: mov $0x0400,%bx
mov (%bx),%al
test $0x80,%al
jz 1f
or $M_NOTE,%edx
1: mov $PC98_MACHINE_TYPE,%bx
mov %edx,%es:(%bx)
ret
#endif
/* Messages */
msg_eread: .asciz "Error\r\n"
.org PRT_OFF,0x90
/* Partition table */
.fill 0x30,0x1,0x0
.byte 0x80, 0x00, 0x01, 0x00
.byte 0xa5, 0xff, 0xff, 0xff
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x50, 0xc3, 0x00, 0x00
.word 0xaa55 # Magic number