4853df5bb0
I have put it here, because I belive we could share some code among the various kinds of boot-code, whenever we get the time to look at it. Submitted by: Martin Renters
333 lines
6.7 KiB
ArmAsm
333 lines
6.7 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 */
|
|
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 */
|