/* start.s
*
* This file contains the entry point for the application.
* The name of this entry point is compiler dependent.
* It jumps to the BSP which is responsible for performing
* all initialization.
*
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include "asm.h"
/*
* A Descriptor table register has the following format
*/
.set DTR_LIMIT, 0 # offset of two byte limit
.set DTR_BASE, 2 # offset of four byte base address
.set DTR_SIZE, 6 # size of DTR register
BEGIN_DATA
EXTERN (Do_Load_IDT)
EXTERN (Do_Load_GDT)
END_DATA
BEGIN_CODE
PUBLIC (start) # GNU default entry point
EXTERN (boot_card)
EXTERN (load_segments)
EXTERN (exit)
SYM (start):
nop
cli # DISABLE INTERRUPTS!!!
/*
* Load the segment registers
*
* NOTE: Upon return, gs will contain the segment descriptor for
* a segment which maps directly to all of physical memory.
*/
jmp SYM (_load_segments) # load board dependent segments
/*
* Set up the stack
*/
PUBLIC (_establish_stack)
SYM (_establish_stack):
movl $end,eax # eax = end of bss/start of heap
addl $heap_size,eax # eax = end of heap
movl eax,stack_start # Save for brk() routine
addl $stack_size,eax # make room for stack
andl $0xffffffc0,eax # align it on 16 byte boundary
movl eax,esp # set stack pointer
movl eax,ebp # set base pointer
/*
* Zero out the BSS segment
*/
SYM (zero_bss):
cld # make direction flag count up
movl $ SYM (end),ecx # find end of .bss
movl $ SYM (_bss_start),edi # edi = beginning of .bss
subl edi,ecx # ecx = size of .bss in bytes
shrl ecx # size of .bss in longs
shrl ecx
xorl eax,eax # value to clear out memory
repne # while ecx != 0
stosl # clear a long in the bss
/*
* Copy the Global Descriptor Table to our space
*/
sgdt SYM (_Original_GDTR) # save original GDT
movzwl SYM (_Original_GDTR)+DTR_LIMIT,ecx
/* size of GDT in bytes; limit is */
/* 8192 entries * 8 bytes per */
/*
* make ds:esi point to the original GDT
*/
movl SYM (_Original_GDTR)+DTR_BASE,esi
push ds # save ds
movw gs,ax
movw ax,ds
/*
* make es:edi point to the new (our copy) GDT
*/
movl $ SYM (_Global_descriptor_table),edi
rep
movsb # copy the GDT (ds:esi -> es:edi)
pop ds # restore ds
/*
* Build and load new contents of GDTR
*/
movw SYM (_Original_GDTR)+DTR_LIMIT,ecx # set new limit
movw cx, SYM (_New_GDTR)+DTR_LIMIT
push $ SYM (_Global_descriptor_table)
push es
call SYM (i386_Logical_to_physical)
addl $6,esp
movl eax, SYM (_New_GDTR)+DTR_BASE # set new base
cmpb $0, SYM (_Do_Load_GDT) # Should the new GDT be loaded?
je SYM (no_gdt_load) # NO, then branch
lgdt SYM (_New_GDTR) # load the new GDT
SYM (no_gdt_load):
/*
* Copy the Interrupt Descriptor Table to our space
*/
sidt SYM (_Original_IDTR) # save original IDT
movzwl SYM (_Original_IDTR)+DTR_LIMIT,ecx
/* size of IDT in bytes; limit is */
/* 256 entries * 8 bytes per */
/*
* make ds:esi point to the original IDT
*/
movl SYM (_Original_IDTR)+DTR_BASE,esi
push ds # save ds
movw gs,ax
movw ax,ds
/*
* make es:edi point to the new (our copy) IDT
*/
movl $ SYM (Interrupt_descriptor_table),edi
rep
movsb # copy the IDT (ds:esi -> es:edi)
pop ds # restore ds
/*
* Build and load new contents of IDTR
*/
movw SYM (_Original_IDTR+DTR_LIMIT),ecx # set new limit
movw cx,SYM (_New_IDTR)+DTR_LIMIT
push $ SYM (Interrupt_descriptor_table)
push es
call SYM (i386_Logical_to_physical)
addl $6,esp
movl eax, SYM (_New_IDTR)+DTR_BASE # set new base
cmpb $0, SYM (_Do_Load_IDT) # Should the new IDT be loaded?
je SYM (no_idt_load) # NO, then branch
lidt SYM (_New_IDTR) # load the new IDT
SYM (no_idt_load):
/*
* Initialize the i387.
*
* Using the NO WAIT form of the instruction insures that
* if it is not present the board will not lock up or get an
* exception.
*/
fninit # MUST USE NO-WAIT FORM
/*
* Transfer control to User's Board Support Package
*/
pushl $0 # environp
pushl $0 # argv
pushl $0 # argc
call SYM (boot_card)
addl $12,esp
/*
* Clean up
*/
EXTERN (return_to_monitor)
PUBLIC (Bsp_cleanup)
SYM (Bsp_cleanup):
cmpb $0, SYM (_Do_Load_IDT) # Was the new IDT loaded?
je SYM (no_idt_restore) # NO, then branch
lidt SYM (_Original_IDTR) # restore the new IDT
SYM (no_idt_restore):
cmpb $0, SYM (_Do_Load_GDT) # Was the new GDT loaded?
je SYM (no_gdt_restore) # NO, then branch
lgdt SYM (_Original_GDTR) # restore the new GDT
SYM (no_gdt_restore):
jmp SYM (_return_to_monitor)
END_CODE
BEGIN_DATA
.align 2
PUBLIC (start_frame)
SYM (start_frame):
.long 0
PUBLIC (stack_start)
SYM (stack_start):
.long 0
END_DATA
BEGIN_BSS
PUBLIC(heap_size)
.set heap_size,0x2000
PUBLIC(stack_size)
.set stack_size,0x1000
PUBLIC (Interrupt_descriptor_table)
SYM (Interrupt_descriptor_table):
.space 256*8
PUBLIC (_Original_IDTR)
SYM (_Original_IDTR):
.space DTR_SIZE
PUBLIC (_New_IDTR)
SYM (_New_IDTR):
.space DTR_SIZE
PUBLIC (_Global_descriptor_table)
SYM (_Global_descriptor_table):
.space 8192*8
PUBLIC (_Original_GDTR)
SYM (_Original_GDTR):
.space DTR_SIZE
PUBLIC (_New_GDTR)
SYM (_New_GDTR):
.space DTR_SIZE
PUBLIC (_Physical_base_of_ds)
SYM (_Physical_base_of_ds):
.space 4
PUBLIC (_Physical_base_of_cs)
SYM (_Physical_base_of_cs):
.space 4
END_BSS
END