/[pupa]/pupa/kern/i386/pc/startup.S
ViewVC logotype

Diff of /pupa/kern/i386/pc/startup.S

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.7 by okuji, Mon Jan 20 04:13:46 2003 UTC revision 1.8 by okuji, Fri Jan 31 03:26:56 2003 UTC
# Line 1  Line 1 
1  /*  /*
2   *  PUPA  --  Preliminary Universal Programming Architecture for GRUB   *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
3   *  Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.   *  Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
4   *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>   *  Copyright (C) 2002,2003  Yoshinori K. Okuji <okuji@enbug.org>
5   *   *
6   *  This program is free software; you can redistribute it and/or modify   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 50  Line 50 
50  #include <pupa/machine/memory.h>  #include <pupa/machine/memory.h>
51  #include <pupa/machine/console.h>  #include <pupa/machine/console.h>
52  #include <pupa/machine/linux.h>  #include <pupa/machine/linux.h>
53            #include <pupa/machine/kernel.h>
54                    
55  #define ABS(x)  ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)  #define ABS(x)  ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
56                    
57          .file   "startup.S"          .file   "startup.S"
# Line 88  VARIABLE(pupa_total_module_size) Line 89  VARIABLE(pupa_total_module_size)
89          .long   0          .long   0
90  VARIABLE(pupa_kernel_image_size)  VARIABLE(pupa_kernel_image_size)
91          .long   0          .long   0
92    VARIABLE(pupa_compressed_size)
93            .long   0
94  VARIABLE(pupa_install_dos_part)  VARIABLE(pupa_install_dos_part)
95          .long   0xFFFFFFFF          .long   0xFFFFFFFF
96  VARIABLE(pupa_install_bsd_part)  VARIABLE(pupa_install_bsd_part)
# Line 129  codestart: Line 132  codestart:
132          /* The ".code32" directive takes GAS out of 16-bit mode. */          /* The ".code32" directive takes GAS out of 16-bit mode. */
133          .code32          .code32
134    
135            incl    %eax
136            call    EXT_C(pupa_gate_a20)
137    
138            /* decompress the compressed part and put the result at 1MB */
139            movl    $0x100000, %esi
140            movl    $(START_SYMBOL + PUPA_KERNEL_MACHINE_RAW_SIZE), %edi
141    
142            pushl   %esi
143            pushl   EXT_C(pupa_compressed_size)
144            pushl   %edi
145            call    lzo1x_decompress
146            addl    $12, %esp
147    
148            /* copy back the decompressed part */
149            movl    %eax, %ecx
150            cld
151            rep
152            movsb
153    
154          /* copy modules before cleaning out the bss */          /* copy modules before cleaning out the bss */
155          movl    EXT_C(pupa_total_module_size), %ecx          movl    EXT_C(pupa_total_module_size), %ecx
156          movl    EXT_C(pupa_kernel_image_size), %esi          movl    EXT_C(pupa_kernel_image_size), %esi
# Line 148  codestart: Line 170  codestart:
170          /* compute the bss length */          /* compute the bss length */
171          movl    $END_SYMBOL, %ecx          movl    $END_SYMBOL, %ecx
172          subl    %edi, %ecx          subl    %edi, %ecx
173                                            
174          /* clean out */          /* clean out */
175            xorl    %eax, %eax
176          cld          cld
177          rep          rep
178          stosb          stosb
# Line 161  codestart: Line 184  codestart:
184    
185    
186  /*  /*
187     *  This is the area for all of the special variables.
188     */
189    
190            .p2align        2       /* force 4-byte alignment */
191    
192    protstack:
193            .long   PUPA_MEMORY_MACHINE_PROT_STACK
194    
195    VARIABLE(pupa_boot_drive)
196            .long   0
197    
198    VARIABLE(pupa_start_addr)
199            .long   START_SYMBOL
200    
201    VARIABLE(pupa_end_addr)
202            .long   END_SYMBOL
203            
204    VARIABLE(pupa_apm_bios_info)
205            .word   0       /* version */
206            .word   0       /* cseg */
207            .long   0       /* offset */
208            .word   0       /* cseg_16 */
209            .word   0       /* dseg_16 */
210            .word   0       /* cseg_len */
211            .word   0       /* cseg_16_len */
212            .word   0       /* dseg_16_len */
213            
214    /*
215     * This is the Global Descriptor Table
216     *
217     *  An entry, a "Segment Descriptor", looks like this:
218     *
219     * 31          24         19   16                 7           0
220     * ------------------------------------------------------------
221     * |             | |B| |A|       | |   |1|0|E|W|A|            |
222     * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL|  TYPE   | BASE 23:16 |
223     * |             | |D| |L| 19..16| |   |1|1|C|R|A|            |
224     * ------------------------------------------------------------
225     * |                             |                            |
226     * |        BASE 15..0           |       LIMIT 15..0          |
227     * |                             |                            |
228     * ------------------------------------------------------------
229     *
230     *  Note the ordering of the data items is reversed from the above
231     *  description.
232     */
233    
234            .p2align        2       /* force 4-byte alignment */
235    gdt:
236            .word   0, 0
237            .byte   0, 0, 0, 0
238    
239            /* code segment */
240            .word   0xFFFF, 0
241            .byte   0, 0x9A, 0xCF, 0
242    
243            /* data segment */
244            .word   0xFFFF, 0
245            .byte   0, 0x92, 0xCF, 0
246    
247            /* 16 bit real mode CS */
248            .word   0xFFFF, 0
249            .byte   0, 0x9E, 0, 0
250    
251            /* 16 bit real mode DS */
252            .word   0xFFFF, 0
253            .byte   0, 0x92, 0, 0
254    
255    
256    /* this is the GDT descriptor */
257    gdtdesc:
258            .word   0x27                    /* limit */
259            .long   gdt                     /* addr */
260    
261            
262    /*
263     *  These next two routines, "real_to_prot" and "prot_to_real" are structured
264     *  in a very specific way.  Be very careful when changing them.
265     *
266     *  NOTE:  Use of either one messes up %eax and %ebp.
267     */
268    
269    real_to_prot:
270            .code16
271            cli
272    
273            /* load the GDT register */
274            DATA32  ADDR32  lgdt    gdtdesc
275    
276            /* turn on protected mode */
277            movl    %cr0, %eax
278            orl     $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax
279            movl    %eax, %cr0
280    
281            /* jump to relocation, flush prefetch queue, and reload %cs */
282            DATA32  ljmp    $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
283    
284            .code32
285    protcseg:
286            /* reload other segment registers */
287            movw    $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
288            movw    %ax, %ds
289            movw    %ax, %es
290            movw    %ax, %fs
291            movw    %ax, %gs
292            movw    %ax, %ss
293    
294            /* put the return address in a known safe location */
295            movl    (%esp), %eax
296            movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK
297    
298            /* get protected mode stack */
299            movl    protstack, %eax
300            movl    %eax, %esp
301            movl    %eax, %ebp
302    
303            /* get return address onto the right stack */
304            movl    PUPA_MEMORY_MACHINE_REAL_STACK, %eax
305            movl    %eax, (%esp)
306    
307            /* zero %eax */
308            xorl    %eax, %eax
309    
310            /* return on the old (or initialized) stack! */
311            ret
312    
313    
314    prot_to_real:
315            /* just in case, set GDT */
316            lgdt    gdtdesc
317    
318            /* save the protected mode stack */
319            movl    %esp, %eax
320            movl    %eax, protstack
321    
322            /* get the return address */
323            movl    (%esp), %eax
324            movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK
325    
326            /* set up new stack */
327            movl    $PUPA_MEMORY_MACHINE_REAL_STACK, %eax
328            movl    %eax, %esp
329            movl    %eax, %ebp
330    
331            /* set up segment limits */
332            movw    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
333            movw    %ax, %ds
334            movw    %ax, %es
335            movw    %ax, %fs
336            movw    %ax, %gs
337            movw    %ax, %ss
338    
339            /* this might be an extra step */
340            /* jump to a 16 bit segment */
341            ljmp    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
342    
343    tmpcseg:
344            .code16
345    
346            /* clear the PE bit of CR0 */
347            movl    %cr0, %eax
348            andl    $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax
349            movl    %eax, %cr0
350    
351            /* flush prefetch queue, reload %cs */
352            DATA32  ljmp    $0, $realcseg
353    
354    realcseg:
355            /* we are in real mode now
356             * set up the real mode segment registers : DS, SS, ES
357             */
358            /* zero %eax */
359            xorl    %eax, %eax
360    
361            movw    %ax, %ds
362            movw    %ax, %es
363            movw    %ax, %fs
364            movw    %ax, %gs
365            movw    %ax, %ss
366    
367            /* restore interrupts */
368            sti
369    
370            /* return on new stack! */
371            DATA32  ret
372    
373            .code32
374    
375    
376    /*
377     * pupa_gate_a20(int on)
378     *
379     * Gate address-line 20 for high memory.
380     *
381     * This routine is probably overconservative in what it does, but so what?
382     *
383     * It also eats any keystrokes in the keyboard buffer.  :-(
384     */
385    
386    FUNCTION(pupa_gate_a20)
387            movl    %eax, %ecx
388    
389            call    gloop1
390    
391            movb    $0xd1, %al
392            outb    $0x64
393    
394    gloopint1:
395            inb     $0x64
396            andb    $0x02, %al
397            jnz     gloopint1
398    
399            movb    $0xdd, %al
400            testl   %ecx, %ecx
401            jz      gdoit
402    
403            orb     $0x02, %al
404    gdoit:
405            outb    $0x60
406    
407            call    gloop1
408    
409            /* output a dummy command (USB keyboard hack) */
410            movb    $0xff, %al
411            outb    $0x64
412            call    gloop1
413            
414            ret
415    
416    gloop1:
417            inb     $0x64
418            andb    $0x02, %al
419            jnz     gloop1
420    
421    gloop2:
422            inb     $0x64
423            andb    $0x01, %al
424            jz      gloop2ret
425            inb     $0x60
426            jmp     gloop2
427    
428    gloop2ret:
429            ret
430    
431    
432    #include "lzo1x.S"
433    
434    
435    /*
436   *  This call is special...  it never returns...  in fact it should simply   *  This call is special...  it never returns...  in fact it should simply
437   *  hang at this point!   *  hang at this point!
438   */   */
# Line 349  linux_setup_seg: Line 621  linux_setup_seg:
621    
622                                    
623  /*  /*
  *  These next two routines, "real_to_prot" and "prot_to_real" are structured  
  *  in a very specific way.  Be very careful when changing them.  
  *  
  *  NOTE:  Use of either one messes up %eax and %ebp.  
  */  
   
 real_to_prot:  
         .code16  
         cli  
   
         /* load the GDT register */  
         DATA32  ADDR32  lgdt    gdtdesc  
   
         /* turn on protected mode */  
         movl    %cr0, %eax  
         orl     $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax  
         movl    %eax, %cr0  
   
         /* jump to relocation, flush prefetch queue, and reload %cs */  
         DATA32  ljmp    $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg  
   
         .code32  
 protcseg:  
         /* reload other segment registers */  
         movw    $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax  
         movw    %ax, %ds  
         movw    %ax, %es  
         movw    %ax, %fs  
         movw    %ax, %gs  
         movw    %ax, %ss  
   
         /* put the return address in a known safe location */  
         movl    (%esp), %eax  
         movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK  
   
         /* get protected mode stack */  
         movl    protstack, %eax  
         movl    %eax, %esp  
         movl    %eax, %ebp  
   
         /* get return address onto the right stack */  
         movl    PUPA_MEMORY_MACHINE_REAL_STACK, %eax  
         movl    %eax, (%esp)  
   
         /* zero %eax */  
         xorl    %eax, %eax  
   
         /* return on the old (or initialized) stack! */  
         ret  
   
   
 prot_to_real:  
         /* just in case, set GDT */  
         lgdt    gdtdesc  
   
         /* save the protected mode stack */  
         movl    %esp, %eax  
         movl    %eax, protstack  
   
         /* get the return address */  
         movl    (%esp), %eax  
         movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK  
   
         /* set up new stack */  
         movl    $PUPA_MEMORY_MACHINE_REAL_STACK, %eax  
         movl    %eax, %esp  
         movl    %eax, %ebp  
   
         /* set up segment limits */  
         movw    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax  
         movw    %ax, %ds  
         movw    %ax, %es  
         movw    %ax, %fs  
         movw    %ax, %gs  
         movw    %ax, %ss  
   
         /* this might be an extra step */  
         /* jump to a 16 bit segment */  
         ljmp    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg  
   
 tmpcseg:  
         .code16  
   
         /* clear the PE bit of CR0 */  
         movl    %cr0, %eax  
         andl    $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax  
         movl    %eax, %cr0  
   
         /* flush prefetch queue, reload %cs */  
         DATA32  ljmp    $0, $realcseg  
   
 realcseg:  
         /* we are in real mode now  
          * set up the real mode segment registers : DS, SS, ES  
          */  
         /* zero %eax */  
         xorl    %eax, %eax  
   
         movw    %ax, %ds  
         movw    %ax, %es  
         movw    %ax, %fs  
         movw    %ax, %gs  
         movw    %ax, %ss  
   
         /* restore interrupts */  
         sti  
   
         /* return on new stack! */  
         DATA32  ret  
   
         .code32  
   
   
 /*  
624   *   int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)   *   int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
625   *   *
626   *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP   *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
# Line 932  xsmap: Line 1090  xsmap:
1090    
1091                    
1092  /*  /*
  * pupa_gate_a20(int on)  
  *  
  * Gate address-line 20 for high memory.  
  *  
  * This routine is probably overconservative in what it does, but so what?  
  *  
  * It also eats any keystrokes in the keyboard buffer.  :-(  
  */  
   
 FUNCTION(pupa_gate_a20)  
         pushl   %eax  
   
         call    gloop1  
   
         movb    $0xd1, %al  
         outb    $0x64  
   
 gloopint1:  
         inb     $0x64  
         andb    $0x02, %al  
         jnz     gloopint1  
   
         movb    $0xdd, %al  
         cmpb    $0, 0x8(%esp)  
         jz      gdoit  
   
         orb     $0x02, %al  
 gdoit:  
         outb    $0x60  
   
         call    gloop1  
   
         /* output a dummy command (USB keyboard hack) */  
         movb    $0xff, %al  
         outb    $0x64  
         call    gloop1  
           
         popl    %eax  
         ret  
   
 gloop1:  
         inb     $0x64  
         andb    $0x02, %al  
         jnz     gloop1  
   
 gloop2:  
         inb     $0x64  
         andb    $0x01, %al  
         jz      gloop2ret  
         inb     $0x60  
         jmp     gloop2  
   
 gloop2ret:  
         ret  
   
   
 /*  
1093   * void pupa_console_putchar (int c)   * void pupa_console_putchar (int c)
1094   *   *
1095   * Put the character C on the console. Because GRUB wants to write a   * Put the character C on the console. Because GRUB wants to write a
# Line 1413  FUNCTION(pupa_currticks) Line 1514  FUNCTION(pupa_currticks)
1514    
1515          popl    %ebp          popl    %ebp
1516          ret          ret
   
   
 /*  
  *  This is the area for all of the special variables.  
  */  
   
         .p2align        2       /* force 4-byte alignment */  
   
 protstack:  
         .long   PUPA_MEMORY_MACHINE_PROT_STACK  
   
 VARIABLE(pupa_boot_drive)  
         .long   0  
   
 VARIABLE(pupa_start_addr)  
         .long   START_SYMBOL  
   
 VARIABLE(pupa_end_addr)  
         .long   END_SYMBOL  
           
 VARIABLE(pupa_apm_bios_info)  
         .word   0       /* version */  
         .word   0       /* cseg */  
         .long   0       /* offset */  
         .word   0       /* cseg_16 */  
         .word   0       /* dseg_16 */  
         .word   0       /* cseg_len */  
         .word   0       /* cseg_16_len */  
         .word   0       /* dseg_16_len */  
           
 /*  
  * This is the Global Descriptor Table  
  *  
  *  An entry, a "Segment Descriptor", looks like this:  
  *  
  * 31          24         19   16                 7           0  
  * ------------------------------------------------------------  
  * |             | |B| |A|       | |   |1|0|E|W|A|            |  
  * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL|  TYPE   | BASE 23:16 |  
  * |             | |D| |L| 19..16| |   |1|1|C|R|A|            |  
  * ------------------------------------------------------------  
  * |                             |                            |  
  * |        BASE 15..0           |       LIMIT 15..0          |  
  * |                             |                            |  
  * ------------------------------------------------------------  
  *  
  *  Note the ordering of the data items is reversed from the above  
  *  description.  
  */  
   
         .p2align        2       /* force 4-byte alignment */  
 gdt:  
         .word   0, 0  
         .byte   0, 0, 0, 0  
   
         /* code segment */  
         .word   0xFFFF, 0  
         .byte   0, 0x9A, 0xCF, 0  
   
         /* data segment */  
         .word   0xFFFF, 0  
         .byte   0, 0x92, 0xCF, 0  
   
         /* 16 bit real mode CS */  
         .word   0xFFFF, 0  
         .byte   0, 0x9E, 0, 0  
   
         /* 16 bit real mode DS */  
         .word   0xFFFF, 0  
         .byte   0, 0x92, 0, 0  
   
   
 /* this is the GDT descriptor */  
 gdtdesc:  
         .word   0x27                    /* limit */  
         .long   gdt                     /* addr */  

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26