From 4050a7fb50ab19ac410e3535d6afe4a65d737fc5 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 27 May 1998 19:34:37 +0000 Subject: Numerous changes including the following: + DEBUG_EARLY_START re-added (Eric Valette) + segment register initialization (Aleksey/Quality Quorum) + heap size use correction + more debug printk's + increased heap size. Now works with grub boot on all systems I have access to including desktops and a laptop. This is with the i386-rtems tools. Neither i386-rtemself nor netboot produces a working executable. --- c/src/lib/libbsp/i386/pc386/start/start.s | 253 +++++-------------------- c/src/lib/libbsp/i386/pc386/startup/bspstart.c | 28 ++- c/src/lib/libbsp/i386/pc386/startup/ldsegs.s | 170 ++++++++++++----- 3 files changed, 194 insertions(+), 257 deletions(-) (limited to 'c/src/lib/libbsp') diff --git a/c/src/lib/libbsp/i386/pc386/start/start.s b/c/src/lib/libbsp/i386/pc386/start/start.s index 3ed542c255..8be3defef4 100644 --- a/c/src/lib/libbsp/i386/pc386/start/start.s +++ b/c/src/lib/libbsp/i386/pc386/start/start.s @@ -12,10 +12,8 @@ | | Instituto Superior Tecnico * Lisboa * PORTUGAL +--------------------------------------------------------------------------+ -| | Modified the 20/05/1998 by valette@crf.canon.fr in order to give a working | example of eraly stage debugging via the DEBUG_EARLY_START define. -| +--------------------------------------------------------------------------+ | Disclaimer: | @@ -38,22 +36,19 @@ | $Id$ +--------------------------------------------------------------------------*/ +/* + * The most trivial start.s possible. It does not know anything + * about system it is running on, so it will jump to appropriate + * place in BSP specific place to do things it knows nothing about + */ #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 - /*----------------------------------------------------------------------------+ | Size of heap and stack: +----------------------------------------------------------------------------*/ -.set HEAP_SIZE, 0x2000 +.set HEAP_SIZE, 256 .set STACK_SIZE, 0x1000 /*----------------------------------------------------------------------------+ @@ -65,20 +60,19 @@ BEGIN_CODE PUBLIC (start) # GNU default entry point EXTERN (boot_card) - EXTERN (load_segments) - EXTERN (exit) + EXTERN (_load_segments) + EXTERN (_return_to_monitor) EXTERN (_IBMPC_initVideo) - EXTERN (debugPoolingGetChar) + EXTERN (debugPollingGetChar) /* - * In case it crash on your machine and this is not due + * In case this crashes on your machine and this is not due * to video mode set by the loader, you may try to define - * the follwoing variable -#define DEBUG_EARLY_START + * the following variable: */ - -SYM (start): +#define DEBUG_EARLY_START +SYM (start): nop cli # DISABLE INTERRUPTS!!! #ifdef DEBUG_EARLY_START @@ -98,12 +92,13 @@ SYM (start): call printk addl $4, esp - call debugPoolingGetChar + /*call debugPollingGetChar */ #endif /*----------------------------------------------------------------------------+ | Load the segment registers (this is done by the board's BSP) and perform any -| other board specific initialization procedures. +| other board specific initialization procedures, this piece of code +| does not know anything about | | NOTE: Upon return, gs will contain the segment descriptor for a segment which | maps directly to all of physical memory. @@ -119,8 +114,7 @@ SYM (start): 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 _heap_size, eax # eax = end of heap addl $STACK_SIZE, eax # make room for stack andl $0xffffffc0, eax # align it on 16 byte boundary movl eax, esp # set stack pointer @@ -141,112 +135,18 @@ SYM (zero_bss): 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. - +---------------------------------------------------------------------*/ +/*---------------------------------------------------------------------+ +| 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 - +---------------------------------------------------------------------*/ +/*---------------------------------------------------------------------+ +| Transfer control to User's Board Support Package ++---------------------------------------------------------------------*/ pushl $0 # environp pushl $0 # argv @@ -254,106 +154,45 @@ SYM (no_idt_load): 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): +/*---------------------------------------------------------------------+ +| Clean up - we do not know anything about it, so we will +| jump to BSP specific code to do cleanup ++---------------------------------------------------------------------*/ jmp SYM (_return_to_monitor) END_CODE -/*----------------------------------------------------------------------------+ -| DATA section -+----------------------------------------------------------------------------*/ - BEGIN_DATA - EXTERN (Do_Load_IDT) # defined in the BSP - EXTERN (Do_Load_GDT) # defined in the BSP - - .align 2 - PUBLIC (start_frame) -SYM (start_frame): - .long 0 + PUBLIC(_heap_size) +SYM(_heap_size): + .long HEAP_SIZE << 10 - PUBLIC (stack_start) -SYM (stack_start): - .long 0 + PUBLIC(_stack_size) +SYM(_stack_size): + .long STACK_SIZE #ifdef DEBUG_EARLY_START - + PUBLIC (welcome_msg) SYM (welcome_msg) : .string "Ready to debug RTEMS ?\nEnter \n" -#endif - -END_DATA - -/*----------------------------------------------------------------------------+ -| BSS section -+----------------------------------------------------------------------------*/ - -BEGIN_BSS - - PUBLIC (_heap_size) -SYM (_heap_size): - .long HEAP_SIZE - - PUBLIC (_stack_size) -SYM (_stack_size): - .long STACK_SIZE - - PUBLIC (Interrupt_descriptor_table) -SYM (Interrupt_descriptor_table): - .space (256 * 8) # reserve space for all 256 interrupts + PUBLIC (hex_msg) +SYM (hex_msg) : + .string "0x%x\n" - PUBLIC (_Original_IDTR) -SYM (_Original_IDTR): - .space DTR_SIZE + PUBLIC (made_it_msg) +SYM (made_it_msg) : + .string "made it to %d\n" - PUBLIC (_New_IDTR) -SYM (_New_IDTR): - .space DTR_SIZE +#endif - PUBLIC (_Global_descriptor_table) -SYM (_Global_descriptor_table): - .space (3 * 8) # the PC386 bsp only needs 3 segment descriptors: - # NULL, CODE and DATA - PUBLIC (_Original_GDTR) -SYM (_Original_GDTR): - .space DTR_SIZE +END_DATA - PUBLIC (_New_GDTR) -SYM (_New_GDTR): - .space DTR_SIZE +END - 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 diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c index 370b7487d7..d952457485 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c @@ -81,8 +81,8 @@ void bsp_pretasking_hook(void) if (rtemsFreeMemStart & (CPU_ALIGNMENT - 1)) /* not aligned => align it */ rtemsFreeMemStart = (rtemsFreeMemStart+CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); - bsp_libc_init((void *)rtemsFreeMemStart, HEAP_SIZE << 10, 0); - rtemsFreeMemStart += HEAP_SIZE << 10; /* HEAP_SIZE is in KBytes */ + bsp_libc_init((void *)rtemsFreeMemStart, _heap_size, 0); + rtemsFreeMemStart += _heap_size; /* HEAP_SIZE in KBytes */ #ifdef RTEMS_DEBUG @@ -125,4 +125,28 @@ void bsp_start( void ) BSP_Configuration.work_space_start = (void *)rtemsFreeMemStart; rtemsFreeMemStart += BSP_Configuration.work_space_size; + + /* + * The following information is very useful when debugging. + */ + +#if 0 + printk( "work_space_size = 0x%x\n", BSP_Configuration.work_space_size ); + printk( "maximum_extensions = 0x%x\n", BSP_Configuration.maximum_extensions ); + printk( "microseconds_per_tick = 0x%x\n", + BSP_Configuration.microseconds_per_tick ); + printk( "ticks_per_timeslice = 0x%x\n", + BSP_Configuration.ticks_per_timeslice ); + printk( "maximum_devices = 0x%x\n", BSP_Configuration.maximum_devices ); + printk( "number_of_device_drivers = 0x%x\n", + BSP_Configuration.number_of_device_drivers ); + printk( "Device_driver_table = 0x%x\n", + BSP_Configuration.Device_driver_table ); + + printk( "_heap_size = 0x%x\n", _heap_size ); + printk( "_stack_size = 0x%x\n", _stack_size ); + printk( "rtemsFreeMemStart = 0x%x\n", rtemsFreeMemStart ); + printk( "work_space_start = 0x%x\n", BSP_Configuration.work_space_start ); + printk( "work_space_size = 0x%x\n", BSP_Configuration.work_space_size ); +#endif } /* bsp_start */ diff --git a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s index 16f791830a..0f120974c6 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s +++ b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s @@ -42,32 +42,17 @@ #include "asm.h" -/*----------------------------------------------------------------------------+ -| Constants -+----------------------------------------------------------------------------*/ -.set PROT_DATA_SEG, 0x10 # offset in gdt -.set RESET_SS, PROT_DATA_SEG # initial value of stack segment register -.set RESET_DS, PROT_DATA_SEG # initial value of data segment register -.set RESET_ES, PROT_DATA_SEG # initial value of extra segment register -.set RESET_FS, PROT_DATA_SEG # initial value of "f" segment register -.set RESET_GS, PROT_DATA_SEG # initial value of "g" segment register - - -/*----------------------------------------------------------------------------+ -| Macros -+----------------------------------------------------------------------------*/ -#define LOAD_SEGMENTS(_value, _segment) \ - movw $ ## _value, ax; \ - movw ax, _segment - /*----------------------------------------------------------------------------+ | CODE section +----------------------------------------------------------------------------*/ BEGIN_CODE - EXTERN (establish_stack) + EXTERN (_establish_stack) + EXTERN (Timer_exit) + EXTERN (Clock_exit) + .p2align 4 /*----------------------------------------------------------------------------+ | delay +------------------------------------------------------------------------------ @@ -79,30 +64,65 @@ SYM(delay): /*-------------------------------------------------------------------------+ | Function: _load_segments -| Description: Load board segment registers with apropriate values + -| reprogram PIC. +| Description: Current environment is standard PC booted by grub. +| So, there is no value in saving current GDT and IDT +| Settings we have to set it up ourseves. (Naturally +| it will be not so in case we are booted by some +| boot monitor, however, then it will be different +| BSP), After that we have to load board segment registers +| with apropriate values + reprogram PIC. | Global Variables: None. | Arguments: None. | Returns: Nothing. +--------------------------------------------------------------------------*/ + .p2align 4 + PUBLIC (_load_segments) SYM (_load_segments): + + lgdt SYM(gdtdesc) + lidt SYM(idtdesc) + + /* Load CS, flush prefetched queue */ + ljmp $0x8, $next_step + +next_step: + /* Load segment registers */ + movw $0x10, ax + movw ax, ss + movw ax, ds + movw ax, es + movw ax, fs + movw ax, gs + + /* Set default interrupt handler */ + movl $0, ecx + movl $Interrupt_descriptor_table, eax + movl $_default_int_handler, ebx + movl ebx, edx + sarl $16, edx +loop: + movw bx, (eax) + movw $0x8, 2(eax) + movw $0x8e00, 4(eax) + movw dx, 8(eax) + addl $8, eax + addl $1, ecx + cmpl $255, ecx + jle loop + - LOAD_SEGMENTS(RESET_SS, ss) - LOAD_SEGMENTS(RESET_DS, ds) - LOAD_SEGMENTS(RESET_ES, es) - LOAD_SEGMENTS(RESET_FS, fs) - LOAD_SEGMENTS(RESET_GS, gs) - - /*---------------------------------------------------------------------+ - | Now we have to reprogram the interrupts :-(. We put them right after - | the intel-reserved hardware interrupts, at int 0x20-0x2F. There they - | won't mess up anything. Sadly IBM really messed this up with the - | original PC, and they haven't been able to rectify it afterwards. Thus - | the bios puts interrupts at 0x08-0x0f, which is used for the internal - | hardware interrupts as well. We just have to reprogram the 8259's, and - | it isn't fun. - +---------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------+ +| Now we have to reprogram the interrupts :-(. We put them right after +| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they +| won't mess up anything. Sadly IBM really messed this up with the +| original PC, and they haven't been able to rectify it afterwards. Thus +| the bios puts interrupts at 0x08-0x0f, which is used for the internal +| hardware interrupts as well. We just have to reprogram the 8259's, and +| it isn't fun. ++---------------------------------------------------------------------*/ movb $0x11, al /* initialization sequence */ outb al, $0x20 /* send it to 8259A-1 */ @@ -146,6 +166,9 @@ SYM (_load_segments): | Arguments: None. | Returns: Nothing. +--------------------------------------------------------------------------*/ + + .p2align 4 + PUBLIC (_return_to_monitor) SYM (_return_to_monitor): @@ -153,22 +176,73 @@ SYM (_return_to_monitor): call SYM (Clock_exit) jmp SYM (start) -END_CODE +/*-------------------------------------------------------------------------+ +| Function: _default_int_handler +| Description: default interrupt handler +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ + .p2align 4 + + PUBLIC (_default_int_handler) +SYM (_default_int_handler): + iret -/*----------------------------------------------------------------------------+ -| DATA section -+----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------+ +| GDT itself ++--------------------------------------------------------------------------*/ + + .p2align 4 + + PUBLIC (_Global_descriptor_table) +SYM (_Global_descriptor_table): -BEGIN_DATA + /* NULL segment */ + .word 0, 0 + .byte 0, 0, 0, 0 - PUBLIC (_Do_Load_IDT) -SYM (_Do_Load_IDT): - .byte 1 # load RTEMS own Interrupt Descriptor Table + /* code segment */ + .word 0xffff, 0 + .byte 0, 0x9e, 0xcf, 0 - PUBLIC (_Do_Load_GDT) -SYM (_Do_Load_GDT): - .byte 0 # use the Global Descriptor Table that is already defined + /* data segment */ + .word 0xffff, 0 + .byte 0, 0x92, 0xcf, 0 + + +/*---------------------------------------------------------------------------+ +| Descriptor of GDT ++--------------------------------------------------------------------------*/ +SYM (gdtdesc): + .word (3*8 - 1) + .long SYM (_Global_descriptor_table) -END_DATA + +/*---------------------------------------------------------------------------+ +| IDT itself ++---------------------------------------------------------------------------*/ + .p2align 4 + + PUBLIC(Interrupt_descriptor_table) +SYM(Interrupt_descriptor_table): + .rept 256 + .word 0,0,0,0 + .endr + +/*---------------------------------------------------------------------------+ +| Descriptor of IDT ++--------------------------------------------------------------------------*/ +SYM(idtdesc): + .word (256*8 - 1) + .long SYM (Interrupt_descriptor_table) + +END_CODE END + + + + + + -- cgit v1.2.3