source: rtems/c/src/lib/libbsp/i386/pc386/start/start.s @ d2632274

4.104.114.84.95
Last change on this file since d2632274 was 7150f00f, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 1, 1997 at 10:06:48 PM

Inclusion of PC386 BSP submitted by Pedro Miguel Da Cruz Neto Romano
<pmcnr@…> and Jose Rufino <ruf@…>
of NavIST (http://pandora.ist.utl.pt/).

  • Property mode set to 100644
File size: 11.9 KB
Line 
1/*-------------------------------------------------------------------------+
2| start.s v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file contains the entry point for the application.
5| The name of this entry point is compiler dependent.
6| It jumps to the BSP which is responsible for performing all initialization.
7+--------------------------------------------------------------------------+
8| (C) Copyright 1997 -
9| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
10|
11| http://pandora.ist.utl.pt
12|
13| Instituto Superior Tecnico * Lisboa * PORTUGAL
14+--------------------------------------------------------------------------+
15| Disclaimer:
16|
17| This file is provided "AS IS" without warranty of any kind, either
18| expressed or implied.
19+--------------------------------------------------------------------------+
20| This code is based on an earlier generation RTEMS i386 start.s and the
21| following copyright applies:
22|
23| **************************************************************************
24| *  COPYRIGHT (c) 1989-1997.
25| *  On-Line Applications Research Corporation (OAR). 
26| *  Copyright assigned to U.S. Government, 1994.
27| *
28| *  The license and distribution terms for this file may be
29| *  found in the file LICENSE in this distribution or at
30| *  http://www.OARcorp.com/rtems/license.html.
31| **************************************************************************
32|
33| Also based on (from the Linux source tree):
34|   video.S - Copyright (C) 1995, 1996 Martin Mares <mj@k332.feld.cvut.cz>
35+--------------------------------------------------------------------------*/
36
37
38#include "asm.h"
39
40/*----------------------------------------------------------------------------+
41| Constants
42+----------------------------------------------------------------------------*/
43
44#ifdef pc386
45
46.set PROT_CODE_SEG, 0x08        # offset of code segment descriptor into GDT
47.set CR0_PE,        1           # protected mode flag on CR0 register
48
49#endif /* pc386 */
50
51/*----------------------------------------------------------------------------+
52| A Descriptor table register has the following format: 
53+----------------------------------------------------------------------------*/
54
55.set DTR_LIMIT, 0               # offset of two byte limit
56.set DTR_BASE,  2               # offset of four byte base address
57.set DTR_SIZE,  6               # size of DTR register
58
59/*----------------------------------------------------------------------------+
60| CODE section
61+----------------------------------------------------------------------------*/
62
63BEGIN_CODE
64
65        PUBLIC (start)          # GNU default entry point
66
67        EXTERN (main)
68        EXTERN (load_segments)
69        EXTERN (exit)
70
71SYM (start):
72
73/*----------------------------------------------------------------------------+
74| Switch VGA video to 80 lines x 50 columns mode. Has to be done before turning
75| protected mode on since it uses BIOS int 10h (video) services.
76+----------------------------------------------------------------------------*/
77
78#if defined(pc386) && defined(RTEMS_VIDEO_80x50)
79       
80.code16
81
82        movw    $0x0003, ax     # forced set
83        int     $0x10
84        movw    $0x1112, ax     # use 8x8 font
85        xorb    %bl, %bl
86        int     $0x10
87        movw    $0x1201, ax     # turn off cursor emulation
88        movb    $0x34, %bl
89        int     $0x10
90        movb    $0x01, ah       # define cursor (scan lines 0 to 7)
91        movw    $0x0007, cx
92        int     $0x10
93
94.code32
95
96#endif /* pc386 && RTEMS_VIDEO_80x50 */
97
98        nop
99        cli                     # DISABLE INTERRUPTS!!!
100
101/*----------------------------------------------------------------------------+
102| Bare PC machines boot in real mode! We have to turn protected mode on.
103+----------------------------------------------------------------------------*/
104
105#ifdef pc386
106
107        data16
108        movl    $ SYM(gdtptr), eax
109        data16
110        andl    $0x0000ffff, eax        # get offset into segment
111        addr16
112        lgdt    cs:(eax)                # load Global Descriptor Table
113        data16
114        movl    $ SYM(idtptr), eax
115        data16
116        andl    $0x0000ffff, eax        # get offset into segment
117        addr16
118        lidt    cs:(eax)                # load Interrupt Descriptor Table
119       
120        movl    %cr0, eax
121        data16
122        orl     $CR0_PE, eax
123        movl    eax, %cr0               # turn on protected mode
124
125        data16
126        ljmp    $PROT_CODE_SEG, $ SYM(next)     # flush prefetch queue
127
128SYM(next):
129
130#endif /* pc386 */
131
132/*----------------------------------------------------------------------------+
133| Load the segment registers (this is done by the board's BSP) and perform any
134| other board specific initialization procedures.
135|
136| NOTE: Upon return, gs will contain the segment descriptor for a segment which
137|       maps directly to all of physical memory.
138+----------------------------------------------------------------------------*/
139
140        jmp     SYM (_load_segments)    # load board dependent segments
141
142/*----------------------------------------------------------------------------+
143| Set up the stack
144+----------------------------------------------------------------------------*/
145
146        PUBLIC (_establish_stack)
147SYM (_establish_stack):
148
149        movl    $_end, eax              # eax = end of bss/start of heap
150        addl    $heap_size, eax         # eax = end of heap
151        movl    eax, stack_start        # Save for brk() routine
152        addl    $stack_size, eax        # make room for stack
153        andl    $0xffffffc0, eax        # align it on 16 byte boundary
154        movl    eax, esp                # set stack pointer
155        movl    eax, ebp                # set base pointer
156
157/*----------------------------------------------------------------------------+
158| Zero out the BSS segment
159+----------------------------------------------------------------------------*/
160
161SYM (zero_bss):
162        cld                             # make direction flag count up
163        movl    $ SYM (_end), ecx       # find end of .bss
164        movl    $ SYM (_bss_start), edi # edi = beginning of .bss
165        subl    edi, ecx                # ecx = size of .bss in bytes
166        shll    ecx                     # size of .bss in longs
167        xorl    eax, eax                # value to clear out memory
168        repne                           # while ecx != 0
169        stosl                           #   clear a long in the bss
170
171        /*---------------------------------------------------------------------+
172        | Copy the Global Descriptor Table to our space
173        +---------------------------------------------------------------------*/
174
175        sgdt    SYM (_Original_GDTR)    # save original GDT
176        movzwl  SYM (_Original_GDTR)+DTR_LIMIT, ecx     # size of GDT in bytes;
177                                        # limit is 8192 entries * 8 bytes per
178
179        /*---------------------------------------------------------------------+
180        | make ds:esi point to the original GDT
181        +---------------------------------------------------------------------*/
182
183        movl    SYM (_Original_GDTR)+DTR_BASE, esi
184        push    ds                      # save ds
185        movw    gs, ax
186        movw    ax, ds
187
188        /*---------------------------------------------------------------------+
189        | make es:edi point to the new (our copy) GDT
190        +---------------------------------------------------------------------*/
191
192        movl    $ SYM (_Global_descriptor_table), edi
193
194        rep
195        movsb                           # copy the GDT (ds:esi -> es:edi)
196
197        pop     ds                      # restore ds
198
199        /*---------------------------------------------------------------------+
200        | Build and load new contents of GDTR
201        +---------------------------------------------------------------------*/
202
203        movw    SYM (_Original_GDTR)+DTR_LIMIT, ecx     # set new limit
204        movw    cx, SYM (_New_GDTR)+DTR_LIMIT
205
206        push    $ SYM (_Global_descriptor_table)
207        push    es
208        call    SYM (i386_Logical_to_physical)
209        addl    $6, esp
210        movl    eax, SYM (_New_GDTR)+DTR_BASE   # set new base
211
212        cmpb    $0, SYM (_Do_Load_GDT)  # Should the new GDT be loaded?
213        je      SYM (no_gdt_load)       # NO, then branch
214        lgdt    SYM (_New_GDTR)         # load the new GDT
215
216SYM (no_gdt_load):
217
218        /*---------------------------------------------------------------------+
219        | Copy the Interrupt Descriptor Table to our space
220        +---------------------------------------------------------------------*/
221
222        sidt    SYM (_Original_IDTR)    # save original IDT
223        movzwl  SYM (_Original_IDTR)+DTR_LIMIT, ecx     # size of IDT in bytes;
224                                        #limit is 256 entries * 8 bytes per
225
226        /*---------------------------------------------------------------------+
227        | make ds:esi point to the original IDT
228        +---------------------------------------------------------------------*/
229
230        movl    SYM (_Original_IDTR)+DTR_BASE, esi
231
232        push    ds                      # save ds
233        movw    gs, ax
234        movw    ax, ds
235
236        /*---------------------------------------------------------------------+
237        | make es:edi point to the new (our copy) IDT
238        +---------------------------------------------------------------------*/
239
240        movl    $ SYM (Interrupt_descriptor_table), edi
241
242        rep
243        movsb                           # copy the IDT (ds:esi -> es:edi)
244        pop     ds                      # restore ds
245
246        /*---------------------------------------------------------------------+
247        | Build and load new contents of IDTR
248        +---------------------------------------------------------------------*/
249
250        movw    SYM (_Original_IDTR+DTR_LIMIT), ecx     # set new limit
251        movw    cx, SYM (_New_IDTR)+DTR_LIMIT
252
253        push    $ SYM (Interrupt_descriptor_table)
254        push    es
255        call    SYM (i386_Logical_to_physical)
256        addl    $6, esp
257        movl    eax, SYM (_New_IDTR)+DTR_BASE           # set new base
258
259        cmpb    $0, SYM (_Do_Load_IDT)  # Should the new IDT be loaded?
260        je      SYM (no_idt_load)       # NO, then branch
261        lidt    SYM (_New_IDTR)         # load the new IDT
262SYM (no_idt_load):
263
264        /*---------------------------------------------------------------------+
265        | Initialize the i387.
266        |
267        | Using the NO WAIT form of the instruction insures that if it is not
268        | present the board will not lock up or get an exception.
269        +---------------------------------------------------------------------*/
270
271        fninit                          # MUST USE NO-WAIT FORM
272
273        /*---------------------------------------------------------------------+
274        | Transfer control to User's Board Support Package
275        +---------------------------------------------------------------------*/
276
277        pushl   $0                      # environp
278        pushl   $0                      # argv
279        pushl   $0                      # argc
280        call    SYM (main)
281        addl    $12, esp
282
283        /*---------------------------------------------------------------------+
284        | Clean up
285        +---------------------------------------------------------------------*/
286
287        EXTERN (return_to_monitor)
288
289        PUBLIC (Bsp_cleanup)
290
291SYM (Bsp_cleanup):
292
293        cmpb    $0, SYM (_Do_Load_IDT)  # Was the new IDT loaded?
294        je      SYM (no_idt_restore)    # NO, then branch
295        lidt    SYM (_Original_IDTR)    # restore the new IDT
296
297SYM (no_idt_restore):
298
299        cmpb    $0, SYM (_Do_Load_GDT)  # Was the new GDT loaded?
300        je      SYM (no_gdt_restore)    # NO, then branch
301        lgdt    SYM (_Original_GDTR)    # restore the new GDT
302
303SYM (no_gdt_restore):
304
305        jmp     SYM (_return_to_monitor)
306
307END_CODE
308
309/*----------------------------------------------------------------------------+
310| DATA section
311+----------------------------------------------------------------------------*/
312
313BEGIN_DATA
314
315#ifdef pc386
316
317/**************************
318* GLOBAL DESCRIPTOR TABLE *
319**************************/
320
321        .align  4
322SYM(gdtptr):
323        /* we use the NULL descriptor to store the GDT pointer - a trick quite
324           nifty due to: Robert Collins (rcollins@x86.org) */
325        .word   gdtlen - 1
326        .long   gdtptr
327        .word   0x0000
328
329        /* code segment */
330        .word   0xffff, 0
331        .byte   0, 0x9f, 0xcf, 0
332
333        /* data segment */
334        .word   0xffff, 0
335        .byte   0, 0x93, 0xcf, 0
336
337        .set    gdtlen, . - gdtptr      # length of GDT
338       
339/*************************************
340* INTERRUPT DESCRIPTOR TABLE POINTER *
341*************************************/
342
343        .align  4
344SYM(idtptr):
345        .word   0x07ff  # limit at maximum (allows all 256 interrupts)
346        .word   0, 0    # base at 0
347
348#endif /* pc386 */
349
350        EXTERN (Do_Load_IDT)    # defined in the BSP
351        EXTERN (Do_Load_GDT)    # defined in the BSP
352
353        .align  2
354        PUBLIC (start_frame)
355SYM (start_frame):
356        .long   0
357
358        PUBLIC (stack_start)
359SYM (stack_start):
360        .long   0
361
362END_DATA
363
364/*----------------------------------------------------------------------------+
365| BSS section
366+----------------------------------------------------------------------------*/
367
368BEGIN_BSS
369
370        PUBLIC (heap_size)
371        .set    heap_size, 0x2000
372
373        PUBLIC (stack_size)
374        .set    stack_size, 0x1000
375
376        PUBLIC (Interrupt_descriptor_table)
377SYM (Interrupt_descriptor_table):
378        .space (256 * 8)        # reserve space for all 256 interrupts
379
380        PUBLIC (_Original_IDTR)
381SYM (_Original_IDTR):
382        .space DTR_SIZE
383
384        PUBLIC (_New_IDTR)
385SYM (_New_IDTR):
386        .space DTR_SIZE
387
388        PUBLIC (_Global_descriptor_table)
389SYM (_Global_descriptor_table):
390#ifdef pc386
391       
392        .space (3 * 8)  # the PC386 bsp only needs 3 segment descriptors:
393#else                   #   NULL, CODE and DATA
394        .space (8192 * 8)
395       
396#endif /* pc386 */
397
398        PUBLIC (_Original_GDTR)
399SYM (_Original_GDTR):
400        .space DTR_SIZE
401
402        PUBLIC (_New_GDTR)
403SYM (_New_GDTR):
404        .space DTR_SIZE
405
406        PUBLIC (_Physical_base_of_ds)
407SYM (_Physical_base_of_ds):
408        .space 4
409
410        PUBLIC (_Physical_base_of_cs)
411SYM (_Physical_base_of_cs):
412        .space 4
413
414END_BSS
415
416END
Note: See TracBrowser for help on using the repository browser.