Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 1 | // Rom layout and bios assembler to C interface. |
| 2 | // |
Kevin O'Connor | dab0a74 | 2013-12-03 11:50:49 -0500 | [diff] [blame] | 3 | // Copyright (C) 2009-2013 Kevin O'Connor <kevin@koconnor.net> |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 4 | // |
| 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. |
| 6 | |
| 7 | |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 8 | #include "asm-offsets.h" // BREGS_* |
Julian Pidancet | 7c6509c | 2011-12-19 05:07:55 +0000 | [diff] [blame] | 9 | #include "config.h" // CONFIG_* |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 10 | #include "entryfuncs.S" // ENTRY_* |
| 11 | |
| 12 | |
| 13 | /**************************************************************** |
| 14 | * Rom Header |
| 15 | ****************************************************************/ |
| 16 | |
| 17 | .section .rom.header |
David Woodhouse | 67fd42c | 2014-06-03 17:28:58 +0100 | [diff] [blame] | 18 | .code16 |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 19 | .global _rom_header, _rom_header_size, _rom_header_checksum |
| 20 | _rom_header: |
| 21 | .word 0xaa55 |
| 22 | _rom_header_size: |
| 23 | .byte 0 |
| 24 | _rom_header_entry: |
| 25 | jmp _optionrom_entry |
| 26 | _rom_header_checksum: |
Kevin O'Connor | c9d3c2d | 2010-01-01 12:53:32 -0500 | [diff] [blame] | 27 | .byte 0 |
| 28 | _rom_header_other: |
Julian Pidancet | 7c6509c | 2011-12-19 05:07:55 +0000 | [diff] [blame] | 29 | .space 17 |
| 30 | _rom_header_pcidata: |
| 31 | #if CONFIG_VGA_PCI == 1 |
| 32 | .word rom_pci_data |
| 33 | #else |
| 34 | .word 0 |
| 35 | #endif |
| 36 | _rom_header_pnpdata: |
| 37 | .word 0 |
Kevin O'Connor | 72b5e45 | 2011-12-23 23:01:48 -0500 | [diff] [blame] | 38 | _rom_header_other2: |
| 39 | .word 0 |
| 40 | _rom_header_signature: |
| 41 | .asciz "IBM" |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 42 | |
| 43 | |
| 44 | /**************************************************************** |
| 45 | * Entry points |
| 46 | ****************************************************************/ |
| 47 | |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 48 | // Force a fault if found to be running on broken x86emu versions. |
| 49 | DECLFUNC x86emu_fault |
Kevin O'Connor | 3c37cdb | 2014-05-12 01:26:26 -0400 | [diff] [blame] | 50 | msg: .ascii "SeaVGABIOS: x86emu leal trap!\n" |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 51 | x86emu_fault: |
Kevin O'Connor | 3c37cdb | 2014-05-12 01:26:26 -0400 | [diff] [blame] | 52 | #if CONFIG_DEBUG_IO |
| 53 | movw %cs:DebugOutputPort, %dx |
| 54 | movw $msg, %si |
| 55 | 1: movb %cs:(%si), %al |
| 56 | outb %al, (%dx) |
| 57 | incw %si |
| 58 | cmpw $x86emu_fault, %si |
| 59 | jl 1b |
| 60 | #endif |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 61 | 1: hlt |
| 62 | jmp 1b |
| 63 | |
| 64 | // This macro implements a call while avoiding instructions |
| 65 | // that old versions of x86emu have problems with. |
| 66 | .macro VGA_CALLL cfunc |
| 67 | // Make sure leal instruction works. |
| 68 | movl $0x8000, %ecx |
| 69 | leal (%ecx, %ecx, 1), %ecx |
| 70 | cmpl $0x10000, %ecx |
| 71 | jne x86emu_fault |
| 72 | // Use callw instead of calll |
| 73 | push %ax |
| 74 | callw \cfunc |
| 75 | .endm |
| 76 | |
| 77 | // This macro is the same as ENTRY_ARG except VGA_CALLL is used. |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 78 | .macro ENTRY_ARG_VGA cfunc |
| 79 | cli |
| 80 | cld |
| 81 | PUSHBREGS |
| 82 | movw %ss, %ax // Move %ss to %ds |
| 83 | movw %ax, %ds |
| 84 | movl %esp, %ebx // Backup %esp, then zero high bits |
| 85 | movzwl %sp, %esp |
| 86 | movl %esp, %eax // First arg is pointer to struct bregs |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 87 | VGA_CALLL \cfunc |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 88 | movl %ebx, %esp // Restore %esp (including high bits) |
| 89 | POPBREGS |
| 90 | .endm |
| 91 | |
Kevin O'Connor | 9961f99 | 2012-01-21 11:53:44 -0500 | [diff] [blame] | 92 | DECLFUNC entry_104f05 |
| 93 | entry_104f05: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 94 | ENTRY_ARG_VGA vbe_104f05 |
Kevin O'Connor | 9961f99 | 2012-01-21 11:53:44 -0500 | [diff] [blame] | 95 | lretw |
| 96 | |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 97 | DECLFUNC _optionrom_entry |
| 98 | _optionrom_entry: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 99 | ENTRY_ARG_VGA vga_post |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 100 | lretw |
| 101 | |
Kevin O'Connor | 9f193b9 | 2009-05-16 23:31:27 -0400 | [diff] [blame] | 102 | DECLFUNC entry_10 |
| 103 | entry_10: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 104 | ENTRY_ARG_VGA handle_10 |
Kevin O'Connor | 9f193b9 | 2009-05-16 23:31:27 -0400 | [diff] [blame] | 105 | iretw |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 106 | |
| 107 | // Entry point using extra stack |
| 108 | DECLFUNC entry_10_extrastack |
| 109 | entry_10_extrastack: |
| 110 | cli |
| 111 | cld |
| 112 | pushw %ds // Set %ds:%eax to space on ExtraStack |
| 113 | pushl %eax |
Kevin O'Connor | feb0284 | 2013-12-09 20:30:30 -0500 | [diff] [blame] | 114 | movw %cs:ExtraStackSeg, %ds |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 115 | movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-16), %eax |
Kevin O'Connor | 46000f5 | 2014-10-21 02:23:02 -0400 | [diff] [blame] | 116 | SAVEBREGS_POP_DSEAX // Save registers on extra stack |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 117 | movl %esp, PUSHBREGS_size+8(%eax) |
| 118 | movw %ss, PUSHBREGS_size+12(%eax) |
Kevin O'Connor | 41c6061 | 2013-12-09 17:27:54 -0500 | [diff] [blame] | 119 | popl BREGS_code(%eax) |
| 120 | popw BREGS_flags(%eax) |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 121 | |
| 122 | movw %ds, %dx // Setup %ss/%esp and call function |
| 123 | movw %dx, %ss |
| 124 | movl %eax, %esp |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 125 | VGA_CALLL handle_10 |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 126 | |
| 127 | movl %esp, %eax // Restore registers and return |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 128 | movw PUSHBREGS_size+12(%eax), %ss |
| 129 | movl PUSHBREGS_size+8(%eax), %esp |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 130 | popl %edx |
| 131 | popw %dx |
| 132 | pushw BREGS_flags(%eax) |
| 133 | pushl BREGS_code(%eax) |
Kevin O'Connor | 46000f5 | 2014-10-21 02:23:02 -0400 | [diff] [blame] | 134 | RESTOREBREGS_DSEAX |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 135 | iretw |
Kevin O'Connor | b4eb6fc | 2014-10-17 22:15:42 -0400 | [diff] [blame] | 136 | |
| 137 | // Timer irq handling |
| 138 | DECLFUNC entry_timer_hook |
| 139 | entry_timer_hook: |
| 140 | ENTRY handle_timer_hook |
| 141 | ljmpw *%cs:Timer_Hook_Resume |
| 142 | |
| 143 | // Timer irq handling on extra stack |
| 144 | DECLFUNC entry_timer_hook_extrastack |
| 145 | entry_timer_hook_extrastack: |
| 146 | cli |
| 147 | cld |
| 148 | pushw %ds // Set %ds:%eax to space on ExtraStack |
| 149 | pushl %eax |
| 150 | movw %cs:ExtraStackSeg, %ds |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 151 | movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-8), %eax |
Kevin O'Connor | b4eb6fc | 2014-10-17 22:15:42 -0400 | [diff] [blame] | 152 | SAVEBREGS_POP_DSEAX |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 153 | movl %esp, PUSHBREGS_size(%eax) |
| 154 | movw %ss, PUSHBREGS_size+4(%eax) |
Kevin O'Connor | b4eb6fc | 2014-10-17 22:15:42 -0400 | [diff] [blame] | 155 | |
| 156 | movw %ds, %dx // Setup %ss/%esp and call function |
| 157 | movw %dx, %ss |
| 158 | movl %eax, %esp |
| 159 | calll handle_timer_hook |
| 160 | |
| 161 | movl %esp, %eax // Restore registers and return |
Kevin O'Connor | aa66d65 | 2014-11-05 09:05:36 -0500 | [diff] [blame] | 162 | movw PUSHBREGS_size+4(%eax), %ss |
| 163 | movl PUSHBREGS_size(%eax), %esp |
Kevin O'Connor | b4eb6fc | 2014-10-17 22:15:42 -0400 | [diff] [blame] | 164 | RESTOREBREGS_DSEAX |
| 165 | ljmpw *%cs:Timer_Hook_Resume |