⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 32bitgateway.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* *  Implementation of a gateway into 32bit space. Stub functions *  can be called from Bochs BIOS which call functions with a compatible *  signature in 32bit space. All interrupts are disabled while in *  32 bit mode. * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Lesser General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. * *  This library 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 *  Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * * Copyright (C) IBM Corporation, 2006 * * Author: Stefan Berger <stefanb@us.ibm.com> *//* * Note: *  BCC's ABI does not require to preserve any 16bit registers ax, bx, cs, dx *  by a called function. So these registers need not be preserved while *  calling a function in 32bit space, either. * *  When bcc calls a function with 16bit parameters it pushes 2 bytes onto *  the stack for such a parameter. GCC, however, expects 32bit parameters *  (4 bytes) even for uint16_t, so casting to 32bit from bcc is a good idea. */#define SEGMENT_OFFSET  0xf0000#define REAL_MODE_CODE_SEGMENT  0xf000#define START_PM_CODE  USE32#define END_PM_CODE    USE16/* definition of used code/data segment descriptors */#define PM_NORMAL_CS (gdt_entry_pm_cs       - gdt_base)#define PM_16BIT_CS  (gdt_entry_pm_16bit_cs - gdt_base)#define PM_32BIT_DS  (gdt_entry_pm_32bit_ds - gdt_base)  ASM_START    ; Switch into protected mode to allow access to 32 bit addresses.    ; This function allows switching into protected mode.    ; (the specs says big real mode, but that will not work)    ;    ; preserves all registers and prepares cs, ds, es, ss for usage    ; in protected mode; while in prot.mode interrupts remain disabledswitch_to_protmode:    cli    ; have to fix the stack for proper return address in 32 bit mode    push WORD #(REAL_MODE_CODE_SEGMENT>>12)	;extended return address    push bp					;pop@A1    mov bp, sp    push eax					;pop@A2    mov eax, 2[bp]				; fix return address    rol eax, #16    mov 2[bp], eax    mov eax, esp    ror eax, #16				; hi(esp)    push bx					; preserve before function call    push cx    push dx    push ax					; prepare stack for    push es					; call    push ds    push cs    push ss    call _store_segment_registers    add sp, #10					; pop ax,es-ss    pop dx					; restore after function call    pop cx    pop bx    ; calculate protected-mode esp from ss:sp    and esp, #0xffff    xor eax, eax    mov ax, ss    rol eax, #4    add eax, esp    mov esp, eax    seg cs    lgdt my_gdtdesc				; switch to own table    mov eax, cr0    or	al, #0x1				; protected mode 'on'    mov cr0, eax    jmpf DWORD (SEGMENT_OFFSET | switch_to_protmode_goon_1), #PM_NORMAL_CS    START_PM_CODEswitch_to_protmode_goon_1:    mov ax, #PM_32BIT_DS			; 32 bit segment that allows    mov ds, ax					; to reach all 32 bit    mov es, ax					; addresses    mov ss, ax    pop eax					;@A2    pop bp					;@A1    ret    END_PM_CODE    .align 16gdt_base:    ; see Intel SW Dev. Manuals section 3.4.5, Volume 3 for meaning of bits    .word 0,0    .byte 0,0,0,0gdt_entry_pm_cs:    ; 32 bit code segment for protected mode    .word 0xffff, 0x0000    .byte 0x00, 0x9a, 0xcf, 0x00gdt_entry_pm_16bit_cs:    ; temp. 16 bit code segment used while in protected mode    .word 0xffff, 0x0000    .byte SEGMENT_OFFSET >> 16, 0x9a, 0x0, 0x0gdt_entry_pm_32bit_ds:    ; (32 bit) data segment (r/w) reaching all possible areas in 32bit memory    ; 4kb granularity    .word 0xffff, 0x0000    .byte 0x0, 0x92, 0xcf, 0x0gdt_entry_end:my_gdtdesc:    .word (gdt_entry_end - gdt_base) - 1    .long gdt_base | SEGMENT_OFFSETrealmode_gdtdesc:				;to be used in real mode    .word 0xffff    .long 0x0switch_to_realmode:    ; Implementation of switching from protected mode to real mode    ; prepares cs, es, ds, ss to be used in real mode    ; spills   eax    START_PM_CODE    ; need to fix up the stack to return in 16 bit mode    ; currently the 32 bit return address is on the stack    pop eax    push ax    push bx					;pop@1    push si					;pop@2    call _ebda_ss_offset32			; get the offset of the ss    mov bx, ax					; entry within the ebda.    jmpf switch_to_realmode_goon_1, #PM_16BIT_CS    END_PM_CODEswitch_to_realmode_goon_1:    mov eax, cr0    and al, #0xfe				; protected mode 'off'    mov cr0, eax    jmpf switch_to_realmode_goon_2, #REAL_MODE_CODE_SEGMENTswitch_to_realmode_goon_2:    ; get orig. 'ss' without using the stack (no 'call'!)    xor eax, eax			; clear upper 16 bits (and lower)    mov ax, #0x40			; where is the ebda located?    mov ds, ax    mov si, #0xe    seg ds    mov ax, [si]			; ax = segment of ebda    mov ds, ax				; segment of ebda    seg ds    mov ax, [bx]			; stack segment - bx has been set above    mov ss, ax    ; from esp and ss calculate real-mode sp    rol eax, #4    sub esp, eax    push dx				;preserve before call(s)    push cx    push bx    call _get_register_ds		; get orig. 'ds'    mov ds, ax    call _get_register_es		; get orig. 'es'    mov es, ax    call _get_register_esp_hi		; fix the upper 16 bits of esp    ror esp, #16    mov sp, ax    rol esp, #16    pop bx    pop cx    pop dx    seg cs    lgdt realmode_gdtdesc    sti						; allow interrupts    pop si					;@2    pop bx					;@1    ret    ASM_END/* * Helper function to get the offset of the reg_ss within the ebda struct * Only 'C' can tell the offset. */Bit16uebda_ss_offset32(){    ASM_START    START_PM_CODE				// need to have this    ASM_END					// compiled for protected mode    return &EbdaData->upcall.reg_ss;		// 'C' knows the offset!    ASM_START    END_PM_CODE    ASM_END}/* * Two often-used functions */Bit16uread_word_from_ebda(offset)    Bit16u offset;{	Bit16u ebda_seg = read_word(0x0040, 0x000E);	return read_word(ebda_seg, offset);}Bit32uread_dword_from_ebda(offset)    Bit16u offset;{	Bit16u ebda_seg = read_word(0x0040, 0x000E);	return read_dword(ebda_seg, offset);}/* * Store registers in the EBDA; used to keep the registers' * content in a well-defined place during protected mode execution */  voidstore_segment_registers(ss, cs, ds, es, esp_hi)  Bit16u ss, cs, ds, es, esp_hi;{	Bit16u ebda_seg = read_word(0x0040, 0x000E);	write_word(ebda_seg, &EbdaData->upcall.reg_ss, ss);	write_word(ebda_seg, &EbdaData->upcall.reg_cs, cs);	write_word(ebda_seg, &EbdaData->upcall.reg_ds, ds);	write_word(ebda_seg, &EbdaData->upcall.reg_es, es);	write_word(ebda_seg, &EbdaData->upcall.esp_hi, esp_hi);}  voidstore_returnaddress(retaddr)   Bit16u retaddr;{	Bit16u ebda_seg = read_word(0x0040, 0x000E);	write_word(ebda_seg, &EbdaData->upcall.retaddr, retaddr);}Bit16uget_returnaddress(){	return read_word_from_ebda(&EbdaData->upcall.retaddr);}/* * get the segment register 'cs' value from the EBDA */Bit16uget_register_cs(){	return read_word_from_ebda(&EbdaData->upcall.reg_cs);}/* * get the segment register 'ds' value from the EBDA */Bit16uget_register_ds(){	return read_word_from_ebda(&EbdaData->upcall.reg_ds);}/* * get the segment register 'es' value from the EBDA */Bit16uget_register_es(){	return read_word_from_ebda(&EbdaData->upcall.reg_es);}/* * get the upper 16 bits of the esp from the EBDA */Bit16uget_register_esp_hi(){	return read_word_from_ebda(&EbdaData->upcall.esp_hi);}/********************************************************/ASM_STARTUpcall:	; do the upcall into 32 bit space	; clear the stack frame so that 32 bit space sees all the parameters	; on the stack as if they were prepared for it	; ---> take the 16 bit return address off the stack and remember it	;	; Input:	; bx: index of function to call	; Ouput:	; dx, ax: 32 bit result of call (even if 'void' is expected)	push bp				;pop @1	mov bp, sp	push si				;pop @2	mov ax, 2[bp]			; 16 bit return address	push ax	call _store_returnaddress	; store away	pop ax	; XXX GDT munging requires ROM to be writable!	call _enable_rom_write_access	rol bx, #2	mov si, #jmptable	seg cs	mov eax, dword ptr [si+bx]	; address to call from table	pop si				;@2	pop bp				;@1	add sp, #2			; remove 16bit return address from stack	call switch_to_protmode	START_PM_CODE	call eax			; call 32bit function	push eax			; preserve result	call switch_to_realmode		; back to realmode	END_PM_CODE	pop eax				; get result	push word 0x0000		; placeholder for 16 bit return address	push bp	mov bp,sp	push eax			; preserve work register	call _disable_rom_write_access	call _get_returnaddress	mov 2[bp], ax			; 16bit return address onto stack	pop eax	pop bp	ror eax, #16			; result into dx/ax	mov dx, ax			; hi(res) -> dx	ror eax, #16	ret/* macro for functions to declare their call into 32bit space */MACRO DoUpcall	mov bx, #?1	jmp UpcallMENDASM_END#include "32bitprotos.h"#include "32bitgateway.h"#include "tcgbios.c"Bit32u get_s3_waking_vector(){	ASM_START	DoUpcall(IDX_GET_S3_WAKING_VECTOR)	ASM_END}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -