mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-27 11:55:06 +00:00
5904e1f57a
1.12 Makefile 1.14 bootmenu.c 1.20 main.c 1.3 makerom.c 1.3 misc.c 1.12 netboot.h 1.11 ns8390.c 1.1 ns8390.h 1.3 rpc.c 1.6 start2.S Submitted by: H. Nokubi <h-nokubi@nmit.mt.nec.co.jp>
723 lines
13 KiB
ArmAsm
723 lines
13 KiB
ArmAsm
|
|
#define STACKADDR 0xe000 /* Needs to be end of bss + stacksize */
|
|
#define KERN_CODE_SEG 0x08
|
|
#define KERN_DATA_SEG 0x10
|
|
#define REAL_MODE_CSEG 0x18
|
|
#define REAL_MODE_DSEG 0x20
|
|
#define CR0_PE 1
|
|
|
|
#define opsize .byte 0x66
|
|
#define addrsize .byte 0x67
|
|
|
|
/* At entry, the processor is in 16 bit real mode and the code is being
|
|
* executed from an address it was not linked to. Code must be pic and
|
|
* 32 bit sensitive until things are fixed up.
|
|
*/
|
|
#ifdef BOOTROM
|
|
#ifndef PC98
|
|
.word 0xaa55 /* bios extension signature */
|
|
.byte (ROMSIZE>>9) /* no. of 512B blocks */
|
|
jmp 1f /* enter from bios here */
|
|
.byte 0 /* checksum */
|
|
#ifdef PCI
|
|
.ascii "FreeBSD boot ROM.." /* 18 bytes total */
|
|
.word 0x1a
|
|
/* PCI rom data structure format */
|
|
.ascii "PCIR" /* signature */
|
|
.word PCI_VENDOR /* vendor ID */
|
|
.word PCI_DEVICE /* device ID */
|
|
.word 0 /* vital product data */
|
|
.word 0x0018 /* PCI data structure */
|
|
.byte 0 /* PCI data struct. rev -- 0 */
|
|
.byte PCI_CLASS /* Class code */
|
|
.word (ROMSIZE>>9) /* no. of 512B blocks */
|
|
.byte 0,0 /* rev. level */
|
|
.byte 0 /* code type - 0 =x86 */
|
|
.byte 0x80 /* indicator of last block */
|
|
.word 0 /* reserved */
|
|
#endif
|
|
1: push %eax
|
|
push %ds
|
|
xor %eax,%eax
|
|
mov %ax,%ds
|
|
.byte 0xa1 /* MOV 0x304,%ax */
|
|
.word 0x304
|
|
.byte 0x3d /* CMP $0x4d52, %ax == 'MR' */
|
|
.word 0x4d52
|
|
jz 2f
|
|
.byte 0xa1 /* MOV 0x64, %ax */
|
|
.word 0x64
|
|
.byte 0xa3 /* MOV %ax, 0x300 */
|
|
.word 0x300
|
|
.byte 0xa1 /* MOV 0x66, %ax */
|
|
.word 0x66
|
|
.byte 0xa3 /* MOV %ax, 0x302 */
|
|
.word 0x302
|
|
.byte 0xb8 /* MOV $_start-RELOCADDR, %ax */
|
|
.word (_start-RELOC)
|
|
.byte 0xa3 /* MOV %ax, 0x64 */
|
|
.word 0x64
|
|
mov %cs,%ax
|
|
.byte 0xa3 /* MOV %ax, 0x66 */
|
|
.word 0x66
|
|
.byte 0xb8 /* MOV 'MR',%ax */
|
|
.word 0x4d52
|
|
.byte 0xa3 /* MOV %ax, 0x304 */
|
|
.word 0x304
|
|
2: pop %ds
|
|
pop %eax
|
|
lret
|
|
#else /* defined PC98 */
|
|
.byte 0xcb /* 00 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 03 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 06 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0x55 /* 09 MAGIC */
|
|
.byte 0xaa
|
|
.byte 0x00
|
|
.byte 0xeb /* 0c jmp 1f */
|
|
.byte 0x22
|
|
.byte 0x00
|
|
.byte 0xcb /* 0f retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 12 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 15 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 18 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 1b retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 1e retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 21 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 24 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 27 retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 2a retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.byte 0xcb /* 2d retf */
|
|
.byte 0x00
|
|
.byte 0x00
|
|
1:
|
|
cli
|
|
pusha
|
|
opsize
|
|
mov $0x1fc0, %eax
|
|
mov %ax, %es
|
|
mov %esp, %eax
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
mov %eax, (0x0000)
|
|
mov %ss, %ax
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
mov %eax, (0x0004)
|
|
#endif
|
|
#endif
|
|
|
|
/**************************************************************************
|
|
START - Where all the fun begins....
|
|
**************************************************************************/
|
|
.globl _start
|
|
_start:
|
|
cli
|
|
cld
|
|
#ifdef BOOTROM /* relocate ourselves */
|
|
xor %esi, %esi /* zero for ROMs */
|
|
#else
|
|
.byte 0xbe /* MOV $0x100,%si -- 100h for .COM */
|
|
.word 0x100
|
|
#endif
|
|
xor %edi,%edi
|
|
.byte 0xb8 /* MOV $RELOCADDR>>4, %ax */
|
|
.word (RELOC>>4)
|
|
mov %ax, %es
|
|
.byte 0xb9 /* MOV $ROMSIZE, %cx */
|
|
.word ROMSIZE
|
|
cs
|
|
rep
|
|
movsb
|
|
opsize
|
|
ljmp $(RELOC>>4),$1f-RELOC /* Jmp to RELOC:1f */
|
|
1:
|
|
nop
|
|
#ifdef PC98
|
|
opsize
|
|
mov $0x0a00, %eax /* 80 x 25 mode */
|
|
int $0x18
|
|
movb $0x0c, %ah /* text on */
|
|
int $0x18
|
|
movb $0x16, %ah /* t-vram clear */
|
|
opsize
|
|
mov $0xe100, %edx
|
|
int $0x18
|
|
|
|
/* cursor home and on */
|
|
xor %edx, %edx
|
|
movb $0x13, %ah
|
|
int $0x18
|
|
movb $0x11, %ah
|
|
int $0x18
|
|
|
|
/* set up %ds */
|
|
xor %ax, %ax
|
|
mov %ax, %ds
|
|
|
|
opsize
|
|
mov $0xa000, %eax
|
|
mov %ax, %es
|
|
|
|
/* transfer PC-9801 system common area to 0xa1000 */
|
|
opsize
|
|
mov $0x0000, %esi
|
|
opsize
|
|
mov $0x1000, %edi
|
|
opsize
|
|
mov $0x0630, %ecx
|
|
cld
|
|
rep
|
|
movsb
|
|
|
|
/* transfer EPSON machine type to 0xa1200 */
|
|
push %ds
|
|
opsize
|
|
mov $0xfd00, %eax
|
|
mov %ax, %ds
|
|
addrsize
|
|
opsize
|
|
mov 0x804, %eax
|
|
opsize
|
|
and $0x00ffffff, %eax
|
|
addrsize
|
|
opsize
|
|
.byte 0x26
|
|
mov %eax, %es: (0x1624)
|
|
pop %ds
|
|
#endif
|
|
mov %cs,%ax
|
|
mov %ax,%ds
|
|
mov %ax,%es
|
|
mov %ax,%ss
|
|
.byte 0xb8 /* MOV $STACKADDR, %ax */
|
|
.word STACKADDR
|
|
mov %eax,%esp
|
|
opsize
|
|
call _real_to_prot
|
|
call _main
|
|
.globl _exit
|
|
_exit:
|
|
call _prot_to_real
|
|
#ifndef PC98
|
|
#ifdef BOOTROM
|
|
xor %eax,%eax
|
|
mov %ax,%ds
|
|
.byte 0xa1 /* MOV 0x302, %ax */
|
|
.word 0x302
|
|
push %eax
|
|
.byte 0xa1 /* MOV 0x300, %ax */
|
|
.word 0x300
|
|
push %eax
|
|
lret
|
|
#else
|
|
int $0x19
|
|
#endif
|
|
#else /* defined PC98 */
|
|
#ifdef BOOTROM
|
|
cli
|
|
movb $0x0e, %al /* CPU RESET */
|
|
outb %al, $0x37
|
|
xor %eax, %eax
|
|
mov %ax, %es
|
|
push %cs
|
|
push $2f
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
mov %esp, (0x0404)
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
movw %ss, (0x0406)
|
|
movb $0x00, %al
|
|
outb %al, $0xf0
|
|
1:
|
|
jmp 1b
|
|
2:
|
|
movb $0x0f, %al
|
|
outb %al, $0x37
|
|
|
|
opsize /* restore ss:sp */
|
|
mov $0x1fc0, %eax
|
|
mov %ax, %es
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
mov (0x0000), %ebx
|
|
addrsize
|
|
.byte 0x26 /* es: */
|
|
mov (0x0004), %eax
|
|
mov %ax, %ss
|
|
mov %ebx, %esp
|
|
sti
|
|
popa
|
|
lret
|
|
#else
|
|
mov $0x8000, %ecx
|
|
movb $0x00, %al
|
|
1:
|
|
jmp 1b
|
|
outb %al, $0x5f
|
|
loop 1b
|
|
outb %al, $0xf0
|
|
1:
|
|
jmp 1b
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef PC98
|
|
/**************************************************************************
|
|
CURRTICKS - Get Time
|
|
**************************************************************************/
|
|
.globl _currticks
|
|
_currticks:
|
|
push %ebp
|
|
mov %esp,%ebp
|
|
push %ebx
|
|
push %esi
|
|
push %edi
|
|
xor %edx,%edx
|
|
call _prot_to_real
|
|
xor %eax,%eax
|
|
int $0x1a
|
|
opsize
|
|
call _real_to_prot
|
|
xor %eax,%eax
|
|
shl $16,%ecx
|
|
mov %edx,%eax
|
|
or %ecx,%eax
|
|
pop %edi
|
|
pop %esi
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
|
|
/**************************************************************************
|
|
PUTCHAR - Print a character
|
|
**************************************************************************/
|
|
.globl _putchar
|
|
_putchar:
|
|
push %ebp
|
|
mov %esp,%ebp
|
|
push %ebx
|
|
push %esi
|
|
push %edi
|
|
movb 8(%ebp),%cl
|
|
call _prot_to_real
|
|
opsize
|
|
mov $1,%ebx
|
|
movb $0x0e,%ah
|
|
movb %cl,%al
|
|
int $0x10
|
|
opsize
|
|
call _real_to_prot
|
|
pop %edi
|
|
pop %esi
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
|
|
/**************************************************************************
|
|
GETCHAR - Get a character
|
|
**************************************************************************/
|
|
.globl _getchar
|
|
_getchar:
|
|
push %ebp
|
|
mov %esp,%ebp
|
|
push %ebx
|
|
push %esi
|
|
push %edi
|
|
call _prot_to_real
|
|
movb $0x0,%ah
|
|
int $0x16
|
|
movb %al,%bl
|
|
opsize
|
|
call _real_to_prot
|
|
xor %eax,%eax
|
|
movb %bl,%al
|
|
pop %edi
|
|
pop %esi
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
|
|
/**************************************************************************
|
|
ISKEY - Check for keyboard interrupt
|
|
**************************************************************************/
|
|
.globl _iskey
|
|
_iskey:
|
|
push %ebp
|
|
mov %esp,%ebp
|
|
push %ebx
|
|
push %esi
|
|
push %edi
|
|
call _prot_to_real
|
|
xor %ebx,%ebx
|
|
movb $0x1,%ah
|
|
int $0x16
|
|
opsize
|
|
jz 1f
|
|
movb %al,%bl
|
|
1:
|
|
opsize
|
|
call _real_to_prot
|
|
xor %eax,%eax
|
|
movb %bl,%al
|
|
pop %edi
|
|
pop %esi
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
#else /* defined PC98 */
|
|
/**************************************************************************
|
|
Get Date & Time
|
|
**************************************************************************/
|
|
.globl _bios98getdate
|
|
_bios98getdate:
|
|
push %ebp
|
|
mov %esp,%ebp
|
|
push %ebx
|
|
push %es
|
|
|
|
call _prot_to_real
|
|
|
|
opsize
|
|
mov $0x1ff0, %eax
|
|
mov %ax, %es
|
|
movb $0x00, %ah
|
|
opsize
|
|
mov $0x80, %ebx /* bios uses 1ff0:0080 */
|
|
int $0x1c
|
|
|
|
opsize
|
|
mov $0x82, %ebx
|
|
opsize
|
|
.byte 0x26 /* es: */
|
|
.byte 0x8b /* mov (%ebx), %ebx */
|
|
.byte 0x1f
|
|
|
|
opsize
|
|
call _real_to_prot
|
|
|
|
mov %ebx, %eax
|
|
pop %es
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
|
|
/*
|
|
* getc()
|
|
* BIOS call "INT 18H Function 00H" to read character from keyboard
|
|
* Call with %ah = 0x0
|
|
* Return: %ah = keyboard scan code
|
|
* %al = ASCII character
|
|
*/
|
|
|
|
.globl _getchar
|
|
_getchar:
|
|
push %ebp
|
|
mov %esp, %ebp
|
|
push %ebx /* save %ebx */
|
|
|
|
call _prot_to_real
|
|
|
|
movb $0x0, %ah
|
|
int $0x18
|
|
|
|
movb %al, %bl /* real_to_prot uses %eax */
|
|
|
|
opsize
|
|
call _real_to_prot
|
|
|
|
xor %eax, %eax
|
|
movb %bl, %al
|
|
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
/*
|
|
* ischar()
|
|
* if there is a character pending, return it; otherwise return 0
|
|
* BIOS call "INT 18H Function 01H" to check whether a character is pending
|
|
* Call with %ah = 0x1
|
|
* Return:
|
|
* If key waiting to be input:
|
|
* %ah = keyboard scan code
|
|
* %al = ASCII character
|
|
* %bh = 1
|
|
* else
|
|
* %bh = 0
|
|
*/
|
|
.globl _iskey
|
|
_iskey:
|
|
push %ebp
|
|
mov %esp, %ebp
|
|
push %ebx
|
|
|
|
call _prot_to_real /* enter real mode */
|
|
|
|
xor %ebx, %ebx
|
|
movb $0x1, %ah
|
|
int $0x18
|
|
andb %bh, %bh
|
|
opsize
|
|
jz nochar
|
|
movb %al, %bl
|
|
|
|
nochar:
|
|
opsize
|
|
call _real_to_prot
|
|
|
|
xor %eax, %eax
|
|
movb %bl, %al
|
|
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
* C library -- _setjmp, _longjmp
|
|
*
|
|
* longjmp(a,v)
|
|
* will generate a "return(v)" from the last call to
|
|
* setjmp(a)
|
|
* by restoring registers from the stack.
|
|
* The previous signal state is restored.
|
|
*/
|
|
|
|
.globl _setjmp
|
|
_setjmp:
|
|
movl 4(%esp),%ecx
|
|
movl 0(%esp),%edx
|
|
movl %edx, 0(%ecx)
|
|
movl %ebx, 4(%ecx)
|
|
movl %esp, 8(%ecx)
|
|
movl %ebp,12(%ecx)
|
|
movl %esi,16(%ecx)
|
|
movl %edi,20(%ecx)
|
|
movl %eax,24(%ecx)
|
|
movl $0,%eax
|
|
ret
|
|
|
|
.globl _longjmp
|
|
_longjmp:
|
|
movl 4(%esp),%edx
|
|
movl 8(%esp),%eax
|
|
movl 0(%edx),%ecx
|
|
movl 4(%edx),%ebx
|
|
movl 8(%edx),%esp
|
|
movl 12(%edx),%ebp
|
|
movl 16(%edx),%esi
|
|
movl 20(%edx),%edi
|
|
cmpl $0,%eax
|
|
jne 1f
|
|
movl $1,%eax
|
|
1: movl %ecx,0(%esp)
|
|
ret
|
|
|
|
/**************************************************************************
|
|
___MAIN - Dummy to keep GCC happy
|
|
**************************************************************************/
|
|
.globl ___main
|
|
___main:
|
|
ret
|
|
|
|
/**************************************************************************
|
|
REAL_TO_PROT - Go from REAL mode to Protected Mode
|
|
**************************************************************************/
|
|
.globl _real_to_prot
|
|
_real_to_prot:
|
|
cli
|
|
cs
|
|
addrsize
|
|
lgdt gdtarg-RELOC
|
|
mov %cr0, %eax
|
|
opsize
|
|
or $CR0_PE, %eax
|
|
mov %eax, %cr0 /* turn on protected mode */
|
|
|
|
/* jump to relocation, flush prefetch queue, and reload %cs */
|
|
opsize
|
|
ljmp $KERN_CODE_SEG, $1f
|
|
1:
|
|
/* reload other segment registers */
|
|
movl $KERN_DATA_SEG, %eax
|
|
movl %ax, %ds
|
|
movl %ax, %es
|
|
movl %ax, %ss
|
|
add $RELOC,%esp /* Fix up stack pointer */
|
|
pop %eax /* Fix up return Address */
|
|
add $RELOC,%eax
|
|
push %eax
|
|
ret
|
|
|
|
|
|
/**************************************************************************
|
|
PROT_TO_REAL - Go from Protected Mode to REAL Mode
|
|
**************************************************************************/
|
|
.globl _prot_to_real
|
|
_prot_to_real:
|
|
pop %eax
|
|
sub $RELOC,%eax /* Adjust return address */
|
|
push %eax
|
|
sub $RELOC,%esp /* Adjust stack pointer */
|
|
|
|
/* Prepare %ax while we're still in a mode that gas understands. */
|
|
movw $REAL_MODE_DSEG, %ax
|
|
|
|
ljmp $REAL_MODE_CSEG, $1f-RELOC /* jump to a 16 bit segment */
|
|
1:
|
|
mov %ax, %ds
|
|
mov %ax, %ss
|
|
mov %ax, %es
|
|
mov %ax, %fs
|
|
|
|
/* clear the PE bit of CR0 */
|
|
mov %cr0, %eax
|
|
opsize
|
|
andl $0!CR0_PE, %eax
|
|
mov %eax, %cr0
|
|
|
|
/* make intersegment jmp to flush the processor pipeline
|
|
* and reload CS register
|
|
*/
|
|
opsize
|
|
ljmp $(RELOC)>>4, $2f-RELOC
|
|
2:
|
|
/* we are in real mode now
|
|
* set up the real mode segment registers : DS, SS, ES
|
|
*/
|
|
mov %cs, %ax
|
|
mov %ax, %ds
|
|
mov %ax, %es
|
|
mov %ax, %ss
|
|
sti
|
|
opsize
|
|
ret
|
|
|
|
/**************************************************************************
|
|
GET DISK GEOMETRY INFO
|
|
**************************************************************************/
|
|
#ifdef PC98
|
|
/*
|
|
*
|
|
* get_diskinfo(): return a word that represents the
|
|
* max number of sectors and heads and drives for this device
|
|
*
|
|
*/
|
|
.globl _get_diskinfo
|
|
_get_diskinfo:
|
|
push %ebp
|
|
mov %esp, %ebp
|
|
push %ebx
|
|
push %esi
|
|
push %edi
|
|
|
|
movb 0x8(%ebp), %dl /* diskinfo(drive #) */
|
|
call _prot_to_real /* enter real mode */
|
|
|
|
movb %dl, %al /* ask for disk info */
|
|
andb $0xf0, %al
|
|
cmpb $0x90, %al
|
|
jz fdd
|
|
|
|
movb %dl, %al
|
|
movb $0x84, %ah
|
|
|
|
int $0x1b
|
|
|
|
jnc ok
|
|
/*
|
|
* Urk. Call failed. It is not supported for floppies by old BIOS's.
|
|
* Guess it's a 15-sector floppy.
|
|
*/
|
|
fdd:
|
|
subb %ah, %ah /* %ax = 0 */
|
|
movb %al, %al
|
|
movb %ah, %bh /* %bh = 0 */
|
|
movb $2, %bl /* %bl bits 0-3 = drive type,
|
|
bit 2 = 1.2M */
|
|
movb $79, %ch /* max track */
|
|
movb $1, %cl /* # floppy drives installed */
|
|
movb $2, %dh /* max head */
|
|
movb $15, %dl /* max sector */
|
|
/* es:di = parameter table */
|
|
/* carry = 0 */
|
|
ok:
|
|
|
|
opsize
|
|
call _real_to_prot /* back to protected mode */
|
|
|
|
/*
|
|
* form a longword representing all this gunk:
|
|
* 16 bit cylinder
|
|
* 8 bit head
|
|
* 8 bit sector
|
|
*/
|
|
mov %ecx, %eax
|
|
sall $16,%eax /* << 16 */
|
|
movb %dh, %ah /* max head */
|
|
movb %dl, %al /* max sector (and # sectors) */
|
|
|
|
pop %edi
|
|
pop %esi
|
|
pop %ebx
|
|
pop %ebp
|
|
ret
|
|
#endif
|
|
/**************************************************************************
|
|
GLOBAL DESCRIPTOR TABLE
|
|
**************************************************************************/
|
|
.align 4
|
|
gdt:
|
|
.word 0, 0
|
|
.byte 0, 0x00, 0x00, 0
|
|
|
|
/* code segment */
|
|
.word 0xffff, 0
|
|
.byte 0, 0x9f, 0xcf, 0
|
|
|
|
/* data segment */
|
|
.word 0xffff, 0
|
|
.byte 0, 0x93, 0xcf, 0
|
|
|
|
/* 16 bit real mode code segment */
|
|
.word 0xffff, RELOC & 0xffff
|
|
.byte (RELOC>>16), 0x9b, 0x00, (RELOC>>24)
|
|
|
|
/* 16 bit real mode data segment */
|
|
.word 0xffff, RELOC & 0xffff
|
|
.byte (RELOC>>16), 0x93, 0x00, (RELOC>>24)
|
|
|
|
.align 4
|
|
gdtarg:
|
|
.word 0x27 /* limit */
|
|
.long gdt /* addr */
|