diff options
Diffstat (limited to 'sys/i386/netboot/start2.S')
| -rw-r--r-- | sys/i386/netboot/start2.S | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/sys/i386/netboot/start2.S b/sys/i386/netboot/start2.S new file mode 100644 index 000000000000..dd249c742d16 --- /dev/null +++ b/sys/i386/netboot/start2.S @@ -0,0 +1,332 @@ + +#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 */ +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 */ |
