1 /* 2 * Common Option ROM Functions 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 * 17 * Copyright Novell Inc, 2009 18 * Authors: Alexander Graf <agraf@suse.de> 19 */ 20 21 22 #define FW_CFG_KERNEL_ADDR 0x07 23 #define FW_CFG_KERNEL_SIZE 0x08 24 #define FW_CFG_KERNEL_CMDLINE 0x09 25 #define FW_CFG_INITRD_ADDR 0x0a 26 #define FW_CFG_INITRD_SIZE 0x0b 27 #define FW_CFG_KERNEL_ENTRY 0x10 28 #define FW_CFG_KERNEL_DATA 0x11 29 #define FW_CFG_INITRD_DATA 0x12 30 #define FW_CFG_CMDLINE_ADDR 0x13 31 #define FW_CFG_CMDLINE_SIZE 0x14 32 #define FW_CFG_CMDLINE_DATA 0x15 33 #define FW_CFG_SETUP_ADDR 0x16 34 #define FW_CFG_SETUP_SIZE 0x17 35 #define FW_CFG_SETUP_DATA 0x18 36 37 #define BIOS_CFG_IOPORT_CFG 0x510 38 #define BIOS_CFG_IOPORT_DATA 0x511 39 40 #define FW_CFG_DMA_CTL_ERROR 0x01 41 #define FW_CFG_DMA_CTL_READ 0x02 42 #define FW_CFG_DMA_CTL_SKIP 0x04 43 #define FW_CFG_DMA_CTL_SELECT 0x08 44 #define FW_CFG_DMA_CTL_WRITE 0x10 45 46 #define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */ 47 48 #define BIOS_CFG_DMA_ADDR_HIGH 0x514 49 #define BIOS_CFG_DMA_ADDR_LOW 0x518 50 51 /* Break the translation block flow so -d cpu shows us values */ 52 #define DEBUG_HERE \ 53 jmp 1f; \ 54 1: 55 56 /* 57 * Read a variable from the fw_cfg device. 58 * Clobbers: %edx 59 * Out: %eax 60 */ 61 .macro read_fw VAR 62 mov $\VAR, %ax 63 mov $BIOS_CFG_IOPORT_CFG, %dx 64 outw %ax, (%dx) 65 mov $BIOS_CFG_IOPORT_DATA, %dx 66 inb (%dx), %al 67 shl $8, %eax 68 inb (%dx), %al 69 shl $8, %eax 70 inb (%dx), %al 71 shl $8, %eax 72 inb (%dx), %al 73 bswap %eax 74 .endm 75 76 77 /* 78 * Read data from the fw_cfg device using DMA. 79 * Clobbers: %edx, %eax, ADDR, SIZE, memory[%esp-16] to memory[%esp] 80 */ 81 .macro read_fw_dma VAR, SIZE, ADDR 82 /* Address */ 83 bswapl \ADDR 84 pushl \ADDR 85 86 /* We only support 32 bit target addresses */ 87 xorl %eax, %eax 88 pushl %eax 89 mov $BIOS_CFG_DMA_ADDR_HIGH, %dx 90 outl %eax, (%dx) 91 92 /* Size */ 93 bswapl \SIZE 94 pushl \SIZE 95 96 /* Control */ 97 movl $(\VAR << 16) | (FW_CFG_DMA_CTL_READ | FW_CFG_DMA_CTL_SELECT), %eax 98 bswapl %eax 99 pushl %eax 100 101 movl %esp, %eax /* Address of the struct we generated */ 102 bswapl %eax 103 mov $BIOS_CFG_DMA_ADDR_LOW, %dx 104 outl %eax, (%dx) /* Initiate DMA */ 105 106 1: mov (%esp), %eax /* Wait for completion */ 107 bswapl %eax 108 testl $~FW_CFG_DMA_CTL_ERROR, %eax 109 jnz 1b 110 addl $16, %esp 111 .endm 112 113 114 /* 115 * Read a blob from the fw_cfg device using DMA 116 * Requires _ADDR, _SIZE and _DATA values for the parameter. 117 * 118 * Clobbers: %eax, %edx, %es, %ecx, %edi and adresses %esp-20 to %esp 119 */ 120 #ifdef USE_FW_CFG_DMA 121 #define read_fw_blob_dma(var) \ 122 read_fw var ## _SIZE; \ 123 mov %eax, %ecx; \ 124 read_fw var ## _ADDR; \ 125 mov %eax, %edi ; \ 126 read_fw_dma var ## _DATA, %ecx, %edi 127 #else 128 #define read_fw_blob_dma(var) read_fw_blob(var) 129 #endif 130 131 #define read_fw_blob_pre(var) \ 132 read_fw var ## _SIZE; \ 133 mov %eax, %ecx; \ 134 mov $var ## _DATA, %ax; \ 135 mov $BIOS_CFG_IOPORT_CFG, %edx; \ 136 outw %ax, (%dx); \ 137 mov $BIOS_CFG_IOPORT_DATA, %dx; \ 138 cld 139 140 /* 141 * Read a blob from the fw_cfg device. 142 * Requires _ADDR, _SIZE and _DATA values for the parameter. 143 * 144 * Clobbers: %eax, %edx, %es, %ecx, %edi 145 */ 146 #define read_fw_blob(var) \ 147 read_fw var ## _ADDR; \ 148 mov %eax, %edi; \ 149 read_fw_blob_pre(var); \ 150 /* old as(1) doesn't like this insn so emit the bytes instead: \ 151 rep insb (%dx), %es:(%edi); \ 152 */ \ 153 .dc.b 0xf3,0x6c 154 155 /* 156 * Read a blob from the fw_cfg device in forced addr32 mode. 157 * Requires _ADDR, _SIZE and _DATA values for the parameter. 158 * 159 * Clobbers: %eax, %edx, %es, %ecx, %edi 160 */ 161 #define read_fw_blob_addr32(var) \ 162 read_fw var ## _ADDR; \ 163 mov %eax, %edi; \ 164 read_fw_blob_pre(var); \ 165 /* old as(1) doesn't like this insn so emit the bytes instead: \ 166 addr32 rep insb (%dx), %es:(%edi); \ 167 */ \ 168 .dc.b 0x67,0xf3,0x6c 169 170 /* 171 * Read a blob from the fw_cfg device in forced addr32 mode, address is in %edi. 172 * Requires _SIZE and _DATA values for the parameter. 173 * 174 * Clobbers: %eax, %edx, %edi, %es, %ecx 175 */ 176 #define read_fw_blob_addr32_edi(var) \ 177 read_fw_blob_pre(var); \ 178 /* old as(1) doesn't like this insn so emit the bytes instead: \ 179 addr32 rep insb (%dx), %es:(%edi); \ 180 */ \ 181 .dc.b 0x67,0xf3,0x6c 182 183 #define OPTION_ROM_START \ 184 .code16; \ 185 .text; \ 186 .global _start; \ 187 _start:; \ 188 .short 0xaa55; \ 189 .byte (_end - _start) / 512; 190 191 #define BOOT_ROM_START \ 192 OPTION_ROM_START \ 193 lret; \ 194 .org 0x18; \ 195 .short 0; \ 196 .short _pnph; \ 197 _pnph: \ 198 .ascii "$PnP"; \ 199 .byte 0x01; \ 200 .byte ( _pnph_len / 16 ); \ 201 .short 0x0000; \ 202 .byte 0x00; \ 203 .byte 0x00; \ 204 .long 0x00000000; \ 205 .short _manufacturer; \ 206 .short _product; \ 207 .long 0x00000000; \ 208 .short 0x0000; \ 209 .short 0x0000; \ 210 .short _bev; \ 211 .short 0x0000; \ 212 .short 0x0000; \ 213 .equ _pnph_len, . - _pnph; \ 214 _bev:; \ 215 /* DS = CS */ \ 216 movw %cs, %ax; \ 217 movw %ax, %ds; 218 219 #define OPTION_ROM_END \ 220 .byte 0; \ 221 .align 512, 0; \ 222 _end: 223 224 #define BOOT_ROM_END \ 225 _manufacturer:; \ 226 .asciz "QEMU"; \ 227 _product:; \ 228 .asciz BOOT_ROM_PRODUCT; \ 229 OPTION_ROM_END 230 231