mirror of
				https://gitlab.com/qemu-project/qboot.git
				synced 2024-02-13 08:33:40 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Our pretty trivial BIOS emulation
 | |
|  */
 | |
| 
 | |
| #include "assembly.h"
 | |
| #include "processor-flags.h"
 | |
| 
 | |
| 	.org 0
 | |
| 	.code16gcc
 | |
| 
 | |
| /*
 | |
|  * handy BIOS macros
 | |
|  */
 | |
| 
 | |
| /* If you change these macros, remember to update 'struct biosregs' */
 | |
| .macro SAVE_BIOSREGS
 | |
| 	pushl	%fs
 | |
| 	pushl	%es
 | |
| 	pushl	%ds
 | |
| 	pushl	%edi
 | |
| 	pushl	%esi
 | |
| 	pushl	%ebp
 | |
| 	pushl	%esp
 | |
| 	pushl	%edx
 | |
| 	pushl	%ecx
 | |
| 	pushl	%ebx
 | |
| 	pushl	%eax
 | |
| .endm
 | |
| 
 | |
| .macro RESTORE_BIOSREGS
 | |
| 	popl	%eax
 | |
| 	popl	%ebx
 | |
| 	popl	%ecx
 | |
| 	popl	%edx
 | |
| 	popl	%esp
 | |
| 	popl	%ebp
 | |
| 	popl	%esi
 | |
| 	popl	%edi
 | |
| 	popl	%ds
 | |
| 	popl	%es
 | |
| 	popl	%fs
 | |
| .endm
 | |
| 
 | |
| ENTRY(bios_irq)
 | |
| 	pushw	%ax
 | |
| 	mov	$0x20, %al
 | |
| 	out	%al, $0x20
 | |
| 	popw	%ax
 | |
| 	IRET
 | |
| ENTRY_END(bios_irq)
 | |
| 
 | |
| /*
 | |
|  * fake interrupt handler, nothing can be faster ever
 | |
|  */
 | |
| ENTRY(bios_intfake)
 | |
| 	/*
 | |
| 	 * Set CF to indicate failure. We don't want callers to think that the
 | |
| 	 * interrupt handler succeeded and then treat the return values in
 | |
| 	 * registers as valid data.
 | |
| 	 */
 | |
| 	orb	$X86_EFLAGS_CF, 0x4(%esp)
 | |
| 
 | |
| 	IRET
 | |
| ENTRY_END(bios_intfake)
 | |
| 
 | |
| /*
 | |
|  * int 10 - video - service
 | |
|  */
 | |
| ENTRY(bios_int10)
 | |
| 	andb	$~X86_EFLAGS_CF, 0x4(%esp)
 | |
| 	SAVE_BIOSREGS
 | |
| 
 | |
| 	movl		%esp, %eax
 | |
| 	/* this is way easier than doing it in assembly */
 | |
| 	/* just push all the regs and jump to a C handler */
 | |
| 	call	int10_handler
 | |
| 
 | |
| 	RESTORE_BIOSREGS
 | |
| 
 | |
| 	IRET
 | |
| ENTRY_END(bios_int10)
 | |
| 
 | |
| ENTRY(bios_int15)
 | |
| 	andb	$~X86_EFLAGS_CF, 0x4(%esp)
 | |
| 	SAVE_BIOSREGS
 | |
| 
 | |
| 	movl	%esp, %eax
 | |
| 	call	int15_handler
 | |
| 
 | |
| 	RESTORE_BIOSREGS
 | |
| 
 | |
| 	IRET
 | |
| ENTRY_END(bios_int15)
 | |
| 
 | |
| 	.code32
 | |
| ENTRY(pcibios_entry)
 | |
| 	clc
 | |
| 	pushfl
 | |
| 	SAVE_BIOSREGS
 | |
| 
 | |
| 	movl	%esp, %eax
 | |
| 	call	pcibios_handler
 | |
| 
 | |
| 	RESTORE_BIOSREGS
 | |
| 	popfl
 | |
| 	lretl
 | |
| ENTRY_END(pcibios_entry)
 | |
| 
 | |
| ENTRY(bios32_entry)
 | |
| 	pushfl
 | |
| 	testl	%ebx, %ebx	   /* BIOS32 service directory? */
 | |
| 	jnz	2f
 | |
| 	cmp	$0x49435024, %eax  /* "$PCI"? */
 | |
| 	movb	$0x80, %al	   /* service not present */
 | |
| 	jne	1f
 | |
| 	xorl	%ebx, %ebx	   /* fill in base/length/entry */
 | |
| 	movl	$(1 << 20), %ecx
 | |
| 	movl	$pcibios_entry, %edx
 | |
| 	movb	$0x00, %al	   /* service present */
 | |
| 1:
 | |
| 	popfl
 | |
| 	lretl
 | |
| 2:
 | |
| 	movb	$0x81, %al	   /* unimplemented function */
 | |
| 	popfl
 | |
| 	lretl
 | |
| ENTRY_END(bios32_entry)
 | |
| 
 | |
| ENTRY(pic_base)
 | |
| 	call 1f
 | |
| 2:
 | |
| 	ret
 | |
| 1:
 | |
| 	popl	%eax
 | |
| 	pushl	%eax
 | |
| 	subl	$2b, %eax
 | |
| 	ret			   /* return to 2b */
 | |
| ENTRY_END(pic_base)
 | 
