aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/netboot/start2.S
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/netboot/start2.S')
-rw-r--r--sys/i386/netboot/start2.S332
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 */