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 |
Kevin O'Connor | 36feea9 | 2012-02-11 10:49:45 -0500 | [diff] [blame] | 18 | .code16gcc |
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 |
| 50 | x86emu_fault: |
| 51 | 1: hlt |
| 52 | jmp 1b |
| 53 | |
| 54 | // This macro implements a call while avoiding instructions |
| 55 | // that old versions of x86emu have problems with. |
| 56 | .macro VGA_CALLL cfunc |
| 57 | // Make sure leal instruction works. |
| 58 | movl $0x8000, %ecx |
| 59 | leal (%ecx, %ecx, 1), %ecx |
| 60 | cmpl $0x10000, %ecx |
| 61 | jne x86emu_fault |
| 62 | // Use callw instead of calll |
| 63 | push %ax |
| 64 | callw \cfunc |
| 65 | .endm |
| 66 | |
| 67 | // 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] | 68 | .macro ENTRY_ARG_VGA cfunc |
| 69 | cli |
| 70 | cld |
| 71 | PUSHBREGS |
| 72 | movw %ss, %ax // Move %ss to %ds |
| 73 | movw %ax, %ds |
| 74 | movl %esp, %ebx // Backup %esp, then zero high bits |
| 75 | movzwl %sp, %esp |
| 76 | movl %esp, %eax // First arg is pointer to struct bregs |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 77 | VGA_CALLL \cfunc |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 78 | movl %ebx, %esp // Restore %esp (including high bits) |
| 79 | POPBREGS |
| 80 | .endm |
| 81 | |
Kevin O'Connor | 9961f99 | 2012-01-21 11:53:44 -0500 | [diff] [blame] | 82 | DECLFUNC entry_104f05 |
| 83 | entry_104f05: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 84 | ENTRY_ARG_VGA vbe_104f05 |
Kevin O'Connor | 9961f99 | 2012-01-21 11:53:44 -0500 | [diff] [blame] | 85 | lretw |
| 86 | |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 87 | DECLFUNC _optionrom_entry |
| 88 | _optionrom_entry: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 89 | ENTRY_ARG_VGA vga_post |
Kevin O'Connor | 1f2c307 | 2009-05-06 23:35:59 -0400 | [diff] [blame] | 90 | lretw |
| 91 | |
Kevin O'Connor | 9f193b9 | 2009-05-16 23:31:27 -0400 | [diff] [blame] | 92 | DECLFUNC entry_10 |
| 93 | entry_10: |
Kevin O'Connor | 9332f9b | 2013-11-30 12:52:44 -0500 | [diff] [blame] | 94 | ENTRY_ARG_VGA handle_10 |
Kevin O'Connor | 9f193b9 | 2009-05-16 23:31:27 -0400 | [diff] [blame] | 95 | iretw |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 96 | |
| 97 | // Entry point using extra stack |
| 98 | DECLFUNC entry_10_extrastack |
| 99 | entry_10_extrastack: |
| 100 | cli |
| 101 | cld |
| 102 | pushw %ds // Set %ds:%eax to space on ExtraStack |
| 103 | pushl %eax |
Kevin O'Connor | feb0284 | 2013-12-09 20:30:30 -0500 | [diff] [blame] | 104 | movw %cs:ExtraStackSeg, %ds |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 105 | movl $(CONFIG_VGA_EXTRA_STACK_SIZE-BREGS_size-8), %eax |
| 106 | popl BREGS_eax(%eax) // Backup registers |
| 107 | popw BREGS_ds(%eax) |
| 108 | movl %edi, BREGS_edi(%eax) |
| 109 | movl %esi, BREGS_esi(%eax) |
| 110 | movl %ebp, BREGS_ebp(%eax) |
| 111 | movl %ebx, BREGS_ebx(%eax) |
| 112 | movl %edx, BREGS_edx(%eax) |
| 113 | movl %ecx, BREGS_ecx(%eax) |
| 114 | movw %es, BREGS_es(%eax) |
| 115 | movl %esp, BREGS_size+0(%eax) |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 116 | movw %ss, BREGS_size+4(%eax) |
Kevin O'Connor | 41c6061 | 2013-12-09 17:27:54 -0500 | [diff] [blame] | 117 | popl BREGS_code(%eax) |
| 118 | popw BREGS_flags(%eax) |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 119 | |
| 120 | movw %ds, %dx // Setup %ss/%esp and call function |
| 121 | movw %dx, %ss |
| 122 | movl %eax, %esp |
Kevin O'Connor | 8032b8a | 2014-02-05 22:47:29 -0500 | [diff] [blame] | 123 | VGA_CALLL handle_10 |
Kevin O'Connor | 4a8b58c | 2013-11-30 19:16:15 -0500 | [diff] [blame] | 124 | |
| 125 | movl %esp, %eax // Restore registers and return |
| 126 | movw BREGS_size+4(%eax), %ss |
| 127 | movl BREGS_size+0(%eax), %esp |
| 128 | popl %edx |
| 129 | popw %dx |
| 130 | pushw BREGS_flags(%eax) |
| 131 | pushl BREGS_code(%eax) |
| 132 | movl BREGS_edi(%eax), %edi |
| 133 | movl BREGS_esi(%eax), %esi |
| 134 | movl BREGS_ebp(%eax), %ebp |
| 135 | movl BREGS_ebx(%eax), %ebx |
| 136 | movl BREGS_edx(%eax), %edx |
| 137 | movl BREGS_ecx(%eax), %ecx |
| 138 | movw BREGS_es(%eax), %es |
| 139 | pushw BREGS_ds(%eax) |
| 140 | pushl BREGS_eax(%eax) |
| 141 | popl %eax |
| 142 | popw %ds |
| 143 | iretw |