/* Copyright (C) 1994 Free Software Foundation, Inc. Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil), On-Line Applications Research Corporation. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* entry.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. * */ .data .global _Do_Load_IDT .global _Do_Load_GDT .text .global start # GNU default entry point .global _establish_stack .global _bsp_start .global _load_segments .global __exit 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 _load_segments # load board dependent segments # # Set up the stack # _establish_stack: movl $stack_end,%esp # set stack pointer movl $stack_end,%ebp # set base pointer # # Zero out the BSS segment # zero_bss: cld # make direction flag count up movl $_end,%ecx # find end of .bss movl $_bss_start,%edi # edi = beginning of .bss subl %edi,%ecx # ecx = size of .bss in bytes shrl $2,%ecx # size of .bss in longs xorl %eax,%eax # value to clear out memory repne # while ecx != 0 stosl # clear a long in the bss # # Set the C heap information for malloc # movl $heap_size,___C_heap_size # set ___C_heap_size movl $heap_memory,___C_heap_start # set ___C_heap_start # # Copy the Global Descriptor Table to our space # sgdt _Original_GDTR # save original GDT movzwl _Original_GDTR_limit,%ecx # size of GDT in bytes; limit # is 8192 entries * 8 bytes per # make ds:esi point to the original GDT movl _Original_GDTR_base,%esi push %ds # save ds movw %gs,%ax movw %ax,%ds # make es:edi point to the new (our copy) GDT movl $_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 _Original_GDTR_limit,%ecx # set new limit movw %cx,_New_GDTR_limit push $_Global_descriptor_table push %es call _Logical_to_physical addl $6,%esp movl %eax,_New_GDTR_base # set new base cmpb $0,_Do_Load_GDT # Should the new GDT be loaded? je no_gdt_load # NO, then branch lgdt _New_GDTR # load the new GDT no_gdt_load: # # Copy the Interrupt Descriptor Table to our space # sidt _Original_IDTR # save original IDT movzwl _Original_IDTR_limit,%ecx # size of IDT in bytes; limit # is 256 entries * 8 bytes per # make ds:esi point to the original IDT movl _Original_IDTR_base,%esi push %ds # save ds movw %gs,%ax movw %ax,%ds # make es:edi point to the new (our copy) IDT movl $_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 _Original_IDTR_limit,%ecx # set new limit movw %cx,_New_IDTR_limit push $_Interrupt_descriptor_table push %es call _Logical_to_physical addl $6,%esp movl %eax,_New_IDTR_base # set new base cmpb $0,_Do_Load_IDT # Should the new IDT be loaded? je no_idt_load # NO, then branch lidt _New_IDTR # load the new IDT 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 call __Board_Initialize # initialize the board pushl $0 # envp = NULL pushl $0 # argv = NULL pushl $0 # argc = NULL call ___libc_init # initialize the library and # call main addl $12,%esp pushl $0 # argc = NULL call __exit # call the Board specific exit addl $4,%esp # # Clean up # .global _Bsp_cleanup .global _return_to_monitor _Bsp_cleanup: cmpb $0,_Do_Load_IDT # Was the new IDT loaded? je no_idt_restore # NO, then branch lidt _Original_IDTR # restore the new IDT no_idt_restore: cmpb $0,_Do_Load_GDT # Was the new GDT loaded? je no_gdt_restore # NO, then branch lgdt _Original_GDTR # restore the new GDT no_gdt_restore: jmp _return_to_monitor # # void *Logical_to_physical( # rtems_unsigned16 segment, # void *address # ); # # Returns thirty-two bit physical address for segment:address. # .global _Logical_to_physical .set SEGMENT_ARG, 4 .set ADDRESS_ARG, 8 _Logical_to_physical: xorl %eax,%eax # clear eax movzwl SEGMENT_ARG(%esp),%ecx # ecx = segment value movl $_Global_descriptor_table,%edx # edx = address of our GDT addl %ecx,%edx # edx = address of desired entry movb 7(%edx),%ah # ah = base 31:24 movb 4(%edx),%al # al = base 23:16 shll $16,%eax # move ax into correct bits movw 2(%edx),%ax # ax = base 0:15 movl ADDRESS_ARG(%esp),%ecx # ecx = address to convert addl %eax,%ecx # ecx = physical address equivalent movl %ecx,%eax # eax = ecx ret # # void *Physical_to_logical( # rtems_unsigned16 segment, # void *address # ); # # Returns thirty-two bit physical address for segment:address. # .global _Physical_to_logical #.set SEGMENT_ARG, 4 #.set ADDRESS_ARG, 8 -- use sets from above _Physical_to_logical: xorl %eax,%eax # clear eax movzwl SEGMENT_ARG(%esp),%ecx # ecx = segment value movl $_Global_descriptor_table,%edx # edx = address of our GDT addl %ecx,%edx # edx = address of desired entry movb 7(%edx),%ah # ah = base 31:24 movb 4(%edx),%al # al = base 23:16 shll $16,%eax # move ax into correct bits movw 2(%edx),%ax # ax = base 0:15 movl ADDRESS_ARG(%esp),%ecx # ecx = address to convert subl %eax,%ecx # ecx = logical address equivalent movl %ecx,%eax # eax = ecx ret /* * Data Declarations. Start with a macro which helps declare space. */ .bss #define DECLARE_SPACE(_name,_space,_align) \ .globl _name ; \ .align _align ; \ _name##: .space _space #define DECLARE_LABEL(_name) \ .globl _name ; \ _name##: #define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2) #define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2) #define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1) /* * Require environment stuff */ DECLARE_LABEL(_environ) DECLARE_PTR(environ) DECLARE_LABEL(_errno) DECLARE_U32(errno) /* * Miscellaneous Variables used to restore the CPU state. * * Start with a macro to declare the space for the contents of * a Descriptor Table register. */ #define DECLARE_DTR_SPACE(_name) \ .global _name ; \ .align 4 ; \ _name##: ; \ _name##_limit: .space 2 ; \ _name##_base: .space 4 DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4) DECLARE_SPACE(_Global_descriptor_table,8192*8,4) DECLARE_DTR_SPACE(_Original_IDTR) DECLARE_DTR_SPACE(_New_IDTR) DECLARE_DTR_SPACE(_Original_GDTR) DECLARE_DTR_SPACE(_New_GDTR) DECLARE_SPACE(_Physical_base_of_ds,4,4) DECLARE_SPACE(_Physical_base_of_cs,4,4) /* * Stack Size and Space */ .set stack_size, 0x20000 DECLARE_SPACE(stack_memory,stack_size,4) DECLARE_LABEL(stack_end)