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

4.104.114.84.95
Last change on this file since 60b791ad was 60b791ad, checked in by Joel Sherrill <joel.sherrill@…>, on 02/17/98 at 23:46:28

updated copyright to 1998

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