|  | /* | 
|  | * Common Option ROM Functions | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or modify | 
|  | * it under the terms of the GNU General Public License as published by | 
|  | * the Free Software Foundation; either version 2 of the License, or | 
|  | * (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program; if not, see <http://www.gnu.org/licenses/>. | 
|  | * | 
|  | * Copyright Novell Inc, 2009 | 
|  | *   Authors: Alexander Graf <agraf@suse.de> | 
|  | */ | 
|  |  | 
|  |  | 
|  | #define NO_QEMU_PROTOS | 
|  | #include "../../hw/fw_cfg.h" | 
|  |  | 
|  | #define BIOS_CFG_IOPORT_CFG	0x510 | 
|  | #define BIOS_CFG_IOPORT_DATA	0x511 | 
|  |  | 
|  | /* Break the translation block flow so -d cpu shows us values */ | 
|  | #define DEBUG_HERE \ | 
|  | jmp		1f;				\ | 
|  | 1: | 
|  |  | 
|  | /* | 
|  | * Read a variable from the fw_cfg device. | 
|  | * Clobbers:	%edx | 
|  | * Out:		%eax | 
|  | */ | 
|  | .macro read_fw VAR | 
|  | mov		$\VAR, %ax | 
|  | mov		$BIOS_CFG_IOPORT_CFG, %dx | 
|  | outw		%ax, (%dx) | 
|  | mov		$BIOS_CFG_IOPORT_DATA, %dx | 
|  | inb		(%dx), %al | 
|  | shl		$8, %eax | 
|  | inb		(%dx), %al | 
|  | shl		$8, %eax | 
|  | inb		(%dx), %al | 
|  | shl		$8, %eax | 
|  | inb		(%dx), %al | 
|  | bswap		%eax | 
|  | .endm | 
|  |  | 
|  | /* | 
|  | * Read a blob from the fw_cfg device. | 
|  | * Requires _ADDR, _SIZE and _DATA values for the parameter. | 
|  | * | 
|  | * Clobbers:	%eax, %edx, %es, %ecx, %edi | 
|  | */ | 
|  | #define read_fw_blob(var)				\ | 
|  | read_fw		var ## _ADDR;			\ | 
|  | mov		%eax, %edi;			\ | 
|  | read_fw		var ## _SIZE;			\ | 
|  | mov		%eax, %ecx;			\ | 
|  | mov		$var ## _DATA, %ax;		\ | 
|  | mov		$BIOS_CFG_IOPORT_CFG, %edx;	\ | 
|  | outw		%ax, (%dx);			\ | 
|  | mov		$BIOS_CFG_IOPORT_DATA, %dx;	\ | 
|  | cld;						\ | 
|  | /* old as(1) doesn't like this insn so emit the bytes instead: \ | 
|  | rep insb	(%dx), %es:(%edi);		\ | 
|  | */						\ | 
|  | .dc.b		0x67,0xf3,0x6c | 
|  |  | 
|  | #define OPTION_ROM_START					\ | 
|  | .code16;						\ | 
|  | .text;						\ | 
|  | .global 	_start;				\ | 
|  | _start:;						\ | 
|  | .short		0xaa55;				\ | 
|  | .byte		(_end - _start) / 512; | 
|  |  | 
|  | #define BOOT_ROM_START					\ | 
|  | OPTION_ROM_START				\ | 
|  | push		%eax;				\ | 
|  | push		%ds;				\ | 
|  | \ | 
|  | /* setup ds so we can access the IVT */		\ | 
|  | xor		%ax, %ax;			\ | 
|  | mov		%ax, %ds;			\ | 
|  | \ | 
|  | /* install our int 19 handler */		\ | 
|  | movw		$int19_handler, (0x19*4);	\ | 
|  | mov		%cs, (0x19*4+2);		\ | 
|  | \ | 
|  | pop		%ds;				\ | 
|  | pop		%eax;				\ | 
|  | lret;						\ | 
|  | \ | 
|  | int19_handler:;					\ | 
|  | /* DS = CS */					\ | 
|  | movw		%cs, %ax;			\ | 
|  | movw		%ax, %ds; | 
|  |  | 
|  | #define OPTION_ROM_END					\ | 
|  | .align 512, 0;					\ | 
|  | _end: | 
|  |  | 
|  | #define BOOT_ROM_END					\ | 
|  | OPTION_ROM_END | 
|  |  |