Do garbage collection of unused sections.
[seabios.git] / src / romlayout.S
index 4e3cdab4275d8943a95e1f036b50d18d62a0f354..cbd9483681749555a102ee617742a81246eda408 100644 (file)
@@ -1,16 +1,10 @@
 // Rom layout and bios assembler to C interface.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
-#include "config.h" // CONFIG_*
-#include "ioport.h" // PORT_A20
-#include "bregs.h" // CR0_*
-#include "cmos.h" // CMOS_RESET_CODE
-#include "../out/asm-offsets.h" // BREGS_*
-
 
 /****************************************************************
  * Include of 16bit C code
         .code16gcc
 .include "out/ccode.16.s"
 
-
-/****************************************************************
- * Entry macros
- ****************************************************************/
-
-        // Call a C function - this does the minimal work necessary to
-        // call into C.  It sets up %ds, backs up %es, and backs up
-        // those registers that are call clobbered by the C compiler.
-        .macro ENTRY cfunc
-        cld
-        pushl %eax              // Save registers clobbered by C code
-        pushl %ecx
-        pushl %edx
-        pushw %es
-        pushw %ds
-        movw %ss, %ax           // Move %ss to %ds
-        movw %ax, %ds
-        pushl %esp              // Backup %esp, then clear high bits
-        movzwl %sp, %esp
-        calll \cfunc
-        popl %esp               // Restore %esp (including high bits)
-        popw %ds                // Restore registers saved above
-        popw %es
-        popl %edx
-        popl %ecx
-        popl %eax
-        .endm
-
-        // Call a C function with current register list as an
-        // argument.  This backs up the registers and sets %eax
-        // to point to the backup.  On return, the registers are
-        // restored from the structure.
-        .macro ENTRY_ARG cfunc
-        cld
-        pushl %eax              // Save registers (matches struct bregs)
-        pushl %ecx
-        pushl %edx
-        pushl %ebx
-        pushl %esi
-        pushl %edi
-        pushw %es
-        pushw %ds
-        movw %ss, %ax           // Move %ss to %ds
-        movw %ax, %ds
-        movl %esp, %ebx         // Backup %esp, then zero high bits
-        movzwl %sp, %esp
-        movl %esp, %eax         // First arg is pointer to struct bregs
-        calll \cfunc
-        movl %ebx, %esp         // Restore %esp (including high bits)
-        popw %ds                // Restore registers (from struct bregs)
-        popw %es
-        popl %edi
-        popl %esi
-        popl %ebx
-        popl %edx
-        popl %ecx
-        popl %eax
-        .endm
-
-        // As above, but don't mangle %esp
-        .macro ENTRY_ARG_ESP cfunc
-        cld
-        pushl %eax              // Save registers (matches struct bregs)
-        pushl %ecx
-        pushl %edx
-        pushl %ebx
-        pushl %esi
-        pushl %edi
-        pushw %es
-        pushw %ds
-        movw %ss, %ax           // Move %ss to %ds
-        movw %ax, %ds
-        movl %esp, %eax         // First arg is pointer to struct bregs
-        calll \cfunc
-        popw %ds                // Restore registers (from struct bregs)
-        popw %es
-        popl %edi
-        popl %esi
-        popl %ebx
-        popl %edx
-        popl %ecx
-        popl %eax
-        .endm
-
-        // Macro to reset the 16bit stack
-        // Clobbers %ax
-        .macro RESET_STACK
-        xorw %ax, %ax
-        movw %ax, %ss
-        movl $ BUILD_STACK_ADDR , %esp
-        cld
-        .endm
-
-        // Declare a function
-        .macro DECLFUNC func
-        .section .text.asm.\func
-        .global \func
-        .endm
-
-
-/****************************************************************
- * POST handler
- ****************************************************************/
-
-        DECLFUNC entry_post
-entry_post:
-        // enable cache
-        movl %cr0, %eax
-        andl $~(CR0_CD|CR0_NW), %eax
-        movl %eax, %cr0
-
-        // Check for restart indicator.
-        movl $CMOS_RESET_CODE, %eax
-        outb %al, $PORT_CMOS_INDEX
-        inb $PORT_CMOS_DATA, %al
-        cmpb $0x0, %al
-        jnz 1f
-
-        // Normal entry point
-        RESET_STACK
-        pushl $_code32__start
-        jmp transition32
-
-        // Entry point when a post call looks like a resume.
-1:
-        // Save old shutdown status.
-        movl %eax, %ebx
-
-        // Clear shutdown status register.
-        movl $CMOS_RESET_CODE, %eax
-        outb %al, $PORT_CMOS_INDEX
-        xorl %eax, %eax
-        outb %al, $PORT_CMOS_DATA
-
-        // Use a stack in EBDA
-        movw $SEG_BDA, %ax
-        movw %ax, %ds
-        movw BDA_ebda_seg, %ax
-        // XXX - should verify ebda_seg looks sane.
-        movw %ax, %ds
-        movw %ax, %ss
-        movl $EBDA_OFFSET_TOP_STACK, %esp
-
-        // Call handler.
-        movl %ebx, %eax
-        cld
-        cli
-        jmp handle_resume
+#include "config.h" // CONFIG_*
+#include "ioport.h" // PORT_A20
+#include "bregs.h" // CR0_*
+#include "cmos.h" // CMOS_RESET_CODE
+#include "../out/asm-offsets.h" // BREGS_*
+#include "entryfuncs.S" // ENTRY_*
 
 
 /****************************************************************
@@ -174,11 +26,19 @@ entry_post:
  ****************************************************************/
 
 // Place CPU into 32bit mode from 16bit mode.
-// Clobbers: %eax, flags, stack registers, cr0, idt/gdt
+// Clobbers: flags, segment registers, cr0, idt/gdt
         DECLFUNC transition32
 transition32:
-        // Disable irqs
+        pushl %eax
+
+        // Disable irqs (and clear direction flag)
         cli
+        cld
+
+        // Disable nmi
+        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
+        outb %al, $PORT_CMOS_INDEX
+        inb $PORT_CMOS_DATA, %al
 
         // enable a20
         inb $PORT_A20, %al
@@ -207,11 +67,12 @@ transition32:
         movw %ax, %fs
         movw %ax, %gs
 
+        popl %eax
         retl
 
 // Call a 16bit function from 32bit mode.
 // %eax = address of struct bregs
-// Clobbers: all gp registers, flags, stack registers, cr0, idt/gdt
+// Clobbers: %e[bcd]x, %e[ds]i, flags, segment registers, idt/gdt
         DECLFUNC __call16_from32
         .global __call16big_from32
 __call16_from32:
@@ -225,10 +86,12 @@ __call16_from32:
         movw %ax, %fs
         movw %ax, %gs
 
+#if CONFIG_DISABLE_A20
         // disable a20
         inb $PORT_A20, %al
         andb $~A20_ENABLE_BIT, %al
         outb %al, $PORT_A20
+#endif
 
         // Jump to 16bit mode
         ljmpw $SEG32_MODE16_CS, $1f
@@ -278,10 +141,11 @@ __call16big_from32:
 
 // Call a 16bit function from 16bit mode with a specified cpu register state
 // %eax = address of struct bregs
-// Clobbers: all gp registers, es
+// Clobbers: %e[bcd]x, %e[ds]i, flags
         DECLFUNC __call16
 __call16:
-        // Save eax
+        // Save %eax, %ebp
+        pushl %ebp
         pushl %eax
 
         // Setup for iretw call
@@ -293,6 +157,7 @@ __call16:
         // Load calling registers.
         movl BREGS_edi(%eax), %edi
         movl BREGS_esi(%eax), %esi
+        movl BREGS_ebp(%eax), %ebp
         movl BREGS_ebx(%eax), %ebx
         movl BREGS_edx(%eax), %edx
         movl BREGS_ecx(%eax), %ecx
@@ -320,17 +185,92 @@ __call16:
         movw %es, BREGS_es(%eax)
         movl %edi, BREGS_edi(%eax)
         movl %esi, BREGS_esi(%eax)
+        movl %ebp, BREGS_ebp(%eax)
         movl %ebx, BREGS_ebx(%eax)
         movl %edx, BREGS_edx(%eax)
 
-        // Remove %eax
+        // Remove %eax, restore %ebp
         popl %eax
+        popl %ebp
+
+        retl
+
+// IRQ trampolines
+        .macro IRQ_TRAMPOLINE num
+        DECLFUNC irq_trampoline_0x\num
+        irq_trampoline_0x\num :
+        int $0x\num
+        lretw
+        .endm
+
+        IRQ_TRAMPOLINE 10
+        IRQ_TRAMPOLINE 13
+        IRQ_TRAMPOLINE 15
+        IRQ_TRAMPOLINE 16
+        IRQ_TRAMPOLINE 18
+        IRQ_TRAMPOLINE 19
+
 
+/****************************************************************
+ * POST entry point
+ ****************************************************************/
+
+        DECLFUNC entry_post
+entry_post:
+        // Enable cache
+        movl %cr0, %eax
+        andl $~(CR0_CD|CR0_NW), %eax
+        movl %eax, %cr0
+
+        // Disable interrupts
+        cli
         cld
 
-        retl
+        // Check for restart indicator.
+        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
+        outb %al, $PORT_CMOS_INDEX
+        inb $PORT_CMOS_DATA, %al
+        cmpb $0x0, %al
+        jnz 1f
+
+        // Normal entry point
+        ENTRY_INTO32 _start
+
+        // Entry point when a post call looks like a resume.
+1:
+        // Save old shutdown status.
+        movl %eax, %ebx
 
-// PnP trampolines
+        // Clear shutdown status register.
+        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
+        outb %al, $PORT_CMOS_INDEX
+        xorl %eax, %eax
+        outb %al, $PORT_CMOS_DATA
+
+        // Use a stack in EBDA
+        movw $SEG_BDA, %ax
+        movw %ax, %ds
+        movw BDA_ebda_seg, %ax
+
+        cmpw $EBDA_SEGMENT_START, %ax
+        jle 2f
+        // EBDA segment doesn't look valid - use startup value.
+        movw $EBDA_SEGMENT_START, %ax
+
+2:      movw %ax, %ds
+        movw %ax, %ss
+        movl $EBDA_OFFSET_TOP_STACK, %esp
+
+        // Call handler.
+        movl %ebx, %eax
+        jmp handle_resume
+
+
+/****************************************************************
+ * Misc. entry points.
+ ****************************************************************/
+
+// PnP entry points
         DECLFUNC entry_pnp_real
         .global entry_pnp_prot
 entry_pnp_prot:
@@ -360,7 +300,7 @@ entry_pnp_real:
         popl %esp
         lretw
 
-// APM trampolines
+// APM entry points
         DECLFUNC apm16protected_entry
 apm16protected_entry:
         pushfw          // save flags
@@ -392,42 +332,23 @@ apm32protected_entry:
         lretl
 
 // 32bit elf entry point
-        DECLFUNC post32
+        EXPORTFUNC post32
 post32:
         cli
         cld
         lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
         lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
+        movl $SEG32_MODE32_DS, %eax
+        movw %ax, %ds
+        movw %ax, %es
+        movw %ax, %fs
+        movw %ax, %gs
+        movw %ax, %ss
         movl $BUILD_STACK_ADDR, %esp
-        ljmpl $SEG32_MODE32_CS, $_code32__start
+        ljmpl $SEG32_MODE32_CS, $_start
 
         .code16gcc
 
-// Shutdown a CPU.  We want this in the 0xf000 section to ensure that
-// the code wont be overwritten with something else.  (Should
-// something spurious wake up the CPU, we want to be sure that the hlt
-// insn will still be present and will shutdown the CPU.)
-        DECLFUNC permanent_halt
-permanent_halt:
-        cli
-1:      hlt
-        jmp 1b
-
-        // IRQ trampolines
-        .macro IRQ_TRAMPOLINE num
-        DECLFUNC irq_trampoline_0x\num
-        irq_trampoline_0x\num :
-        int $0x\num
-        lretw
-        .endm
-
-        IRQ_TRAMPOLINE 10
-        IRQ_TRAMPOLINE 13
-        IRQ_TRAMPOLINE 15
-        IRQ_TRAMPOLINE 16
-        IRQ_TRAMPOLINE 18
-        IRQ_TRAMPOLINE 19
-
 
 /****************************************************************
  * Interrupt entry points
@@ -437,33 +358,41 @@ permanent_halt:
         .macro IRQ_ENTRY num
         .global entry_\num
         entry_\num :
-        cli         // In case something far-calls instead of using "int"
-        ENTRY handle_\num
-        iretw
+        pushl $ handle_\num
+        jmp irqentry
         .endm
 
         // Define an entry point for an interrupt (can read/modify args).
         .macro IRQ_ENTRY_ARG num
         .global entry_\num
         entry_\num :
-        cli         // In case something far-calls instead of using "int"
-        ENTRY_ARG handle_\num
-        iretw
+        pushl $ handle_\num
+        jmp irqentryarg
         .endm
 
         // Macros that put each handler into its own section
         .macro DECL_IRQ_ENTRY num
-        .section .text.asm.entry_\num
+        DECLFUNC entry_\num
         IRQ_ENTRY \num
         .endm
         .macro DECL_IRQ_ENTRY_ARG num
-        .section .text.asm.entry_\num
+        DECLFUNC entry_\num
         IRQ_ENTRY_ARG \num
         .endm
 
+        // Main entry point for interrupts without args
+        DECLFUNC irqentry
+irqentry:
+        ENTRY_ST
+        iretw
+
+        // Main entry point for interrupts with args
+        DECLFUNC irqentryarg
+irqentryarg:
+        ENTRY_ARG_ST
+        iretw
+
         DECL_IRQ_ENTRY_ARG 13
-        DECL_IRQ_ENTRY_ARG 12
-        DECL_IRQ_ENTRY_ARG 11
         DECL_IRQ_ENTRY 76
         DECL_IRQ_ENTRY 70
         DECL_IRQ_ENTRY 74
@@ -471,18 +400,14 @@ permanent_halt:
         DECL_IRQ_ENTRY hwpic1
         DECL_IRQ_ENTRY hwpic2
 
-        // int 18/19 are special - they reset the stack and do not return.
+        // int 18/19 are special - they reset stack and call into 32bit mode.
         DECLFUNC entry_19
 entry_19:
-        RESET_STACK
-        pushl $_code32_handle_19
-        jmp transition32
+        ENTRY_INTO32 handle_19
 
         DECLFUNC entry_18
 entry_18:
-        RESET_STACK
-        pushl $_code32_handle_18
-        jmp transition32
+        ENTRY_INTO32 handle_18
 
 
 /****************************************************************
@@ -499,7 +424,7 @@ entry_post_official:
         jmp entry_post
 
         ORG 0xe2c3
-        IRQ_ENTRY nmi
+        IRQ_ENTRY 02
 
         ORG 0xe3fe
         .global entry_13_official
@@ -548,14 +473,10 @@ entry_10_0x0f:
         // 0xf0a4 - VideoParams in misc.c
 
         ORG 0xf841
-        .global entry_12_official
-entry_12_official:
-        jmp entry_12
+        IRQ_ENTRY_ARG 12
 
         ORG 0xf84d
-        .global entry_11_official
-entry_11_official:
-        jmp entry_11
+        IRQ_ENTRY_ARG 11
 
         ORG 0xf859
         IRQ_ENTRY_ARG 15