freebsd-dev/sys/i386/boot/netboot/start2.S
Poul-Henning Kamp 506c540bbb Improvementss to netboot
Initial but not yet functional PCI support.

Reviewed by:	phk
Submitted by:	Luigi Rizzo <luigi@labinfo.iet.unipi.it>
1996-04-03 19:01:37 +00:00

350 lines
7.2 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_SEG 0x18
#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
.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
#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
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
#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
/**************************************************************************
CURRTICKS - Get Time
**************************************************************************/
.globl _currticks
_currticks:
push %ebp
mov %esp,%ebp
push %ecx
push %edx
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 %edx
pop %ecx
pop %ebp
ret
/**************************************************************************
PUTCHAR - Print a character
**************************************************************************/
.globl _putchar
_putchar:
push %ebp
mov %esp,%ebp
push %ecx
push %ebx
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 %ebx
pop %ecx
pop %ebp
ret
/**************************************************************************
GETCHAR - Get a character
**************************************************************************/
.globl _getchar
_getchar:
push %ebp
mov %esp,%ebp
push %ebx
call _prot_to_real
movb $0x0,%ah
int $0x16
movb %al,%bl
opsize
call _real_to_prot
xor %eax,%eax
movb %bl,%al
pop %ebx
pop %ebp
ret
/**************************************************************************
ISKEY - Check for keyboard interrupt
**************************************************************************/
.globl _iskey
_iskey:
push %ebp
mov %esp,%ebp
push %ebx
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 %ebx
pop %ebp
ret
/*
* 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 */
ljmp $REAL_MODE_SEG, $1f /* jump to a 16 bit segment */
1:
/* 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
/**************************************************************************
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 */
.word 0xffff, 0
.byte 0, 0x9b, 0x0f, 0
.align 4
gdtarg:
.word 0x1f /* limit */
.long gdt /* addr */