|  | @@ -0,0 +1,141 @@
 | 
		
	
		
			
			|  | 1 | +/*
 | 
		
	
		
			
			|  | 2 | + * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
 | 
		
	
		
			
			|  | 3 | + *
 | 
		
	
		
			
			|  | 4 | + * This program is free software; you can redistribute it and/or
 | 
		
	
		
			
			|  | 5 | + * modify it under the terms of the GNU General Public License as
 | 
		
	
		
			
			|  | 6 | + * published by the Free Software Foundation; either version 2 of the
 | 
		
	
		
			
			|  | 7 | + * License, or any later version.
 | 
		
	
		
			
			|  | 8 | + *
 | 
		
	
		
			
			|  | 9 | + * This program is distributed in the hope that it will be useful, but
 | 
		
	
		
			
			|  | 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
		
	
		
			
			|  | 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
		
	
		
			
			|  | 12 | + * 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, write to the Free Software
 | 
		
	
		
			
			|  | 16 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
		
	
		
			
			|  | 17 | + *
 | 
		
	
		
			
			|  | 18 | + */
 | 
		
	
		
			
			|  | 19 | +
 | 
		
	
		
			
			|  | 20 | +FILE_LICENCE ( GPL2_OR_LATER )
 | 
		
	
		
			
			|  | 21 | +
 | 
		
	
		
			
			|  | 22 | +	.arch i386
 | 
		
	
		
			
			|  | 23 | +
 | 
		
	
		
			
			|  | 24 | +#define CR0_PE 1
 | 
		
	
		
			
			|  | 25 | +
 | 
		
	
		
			
			|  | 26 | +/****************************************************************************
 | 
		
	
		
			
			|  | 27 | + * flatten_real_mode (real-mode far call)
 | 
		
	
		
			
			|  | 28 | + *
 | 
		
	
		
			
			|  | 29 | + * Set up 4GB segment limits
 | 
		
	
		
			
			|  | 30 | + *
 | 
		
	
		
			
			|  | 31 | + * Parameters:
 | 
		
	
		
			
			|  | 32 | + *   none
 | 
		
	
		
			
			|  | 33 | + * Returns:
 | 
		
	
		
			
			|  | 34 | + *   none
 | 
		
	
		
			
			|  | 35 | + * Corrupts:
 | 
		
	
		
			
			|  | 36 | + *   none
 | 
		
	
		
			
			|  | 37 | + ****************************************************************************
 | 
		
	
		
			
			|  | 38 | + */
 | 
		
	
		
			
			|  | 39 | +	/* GDT for protected-mode calls */
 | 
		
	
		
			
			|  | 40 | +	.section ".text16.early.data", "aw", @progbits
 | 
		
	
		
			
			|  | 41 | +	.align 16
 | 
		
	
		
			
			|  | 42 | +flatten_gdt:
 | 
		
	
		
			
			|  | 43 | +flatten_gdt_limit:	.word flatten_gdt_length - 1
 | 
		
	
		
			
			|  | 44 | +flatten_gdt_base:	.long 0
 | 
		
	
		
			
			|  | 45 | +			.word 0 /* padding */
 | 
		
	
		
			
			|  | 46 | +flatten_cs:	/* 16-bit protected-mode flat code segment */
 | 
		
	
		
			
			|  | 47 | +	.equ    FLAT_CS, flatten_cs - flatten_gdt
 | 
		
	
		
			
			|  | 48 | +	.word   0xffff, 0
 | 
		
	
		
			
			|  | 49 | +	.byte   0, 0x9b, 0x8f, 0
 | 
		
	
		
			
			|  | 50 | +flatten_ss:	/* 16-bit protected-mode flat stack segment */
 | 
		
	
		
			
			|  | 51 | +	.equ    FLAT_SS, flatten_ss - flatten_gdt
 | 
		
	
		
			
			|  | 52 | +	.word   0xffff, 0
 | 
		
	
		
			
			|  | 53 | +	.byte   0, 0x93, 0x8f, 0
 | 
		
	
		
			
			|  | 54 | +flatten_gdt_end:
 | 
		
	
		
			
			|  | 55 | +	.equ	flatten_gdt_length, . - flatten_gdt
 | 
		
	
		
			
			|  | 56 | +	.size	flatten_gdt, . - flatten_gdt
 | 
		
	
		
			
			|  | 57 | +
 | 
		
	
		
			
			|  | 58 | +	.section ".text16.early.data", "aw", @progbits
 | 
		
	
		
			
			|  | 59 | +	.align 16
 | 
		
	
		
			
			|  | 60 | +flatten_saved_gdt:
 | 
		
	
		
			
			|  | 61 | +	.long	0, 0
 | 
		
	
		
			
			|  | 62 | +	.size	flatten_saved_gdt, . - flatten_saved_gdt
 | 
		
	
		
			
			|  | 63 | +
 | 
		
	
		
			
			|  | 64 | +	.section ".text16.early", "awx", @progbits
 | 
		
	
		
			
			|  | 65 | +	.code16
 | 
		
	
		
			
			|  | 66 | +	.globl	flatten_real_mode
 | 
		
	
		
			
			|  | 67 | +flatten_real_mode:
 | 
		
	
		
			
			|  | 68 | +	/* Preserve registers and flags */
 | 
		
	
		
			
			|  | 69 | +	pushfl
 | 
		
	
		
			
			|  | 70 | +	pushl	%eax
 | 
		
	
		
			
			|  | 71 | +	pushw	%si
 | 
		
	
		
			
			|  | 72 | +	pushw	%gs
 | 
		
	
		
			
			|  | 73 | +	pushw	%fs
 | 
		
	
		
			
			|  | 74 | +	pushw	%es
 | 
		
	
		
			
			|  | 75 | +	pushw	%ds
 | 
		
	
		
			
			|  | 76 | +	pushw	%ss
 | 
		
	
		
			
			|  | 77 | +
 | 
		
	
		
			
			|  | 78 | +	/* Set %ds for access to .text16.early.data variables */
 | 
		
	
		
			
			|  | 79 | +	pushw	%cs
 | 
		
	
		
			
			|  | 80 | +	popw	%ds
 | 
		
	
		
			
			|  | 81 | +
 | 
		
	
		
			
			|  | 82 | +	/* Preserve original GDT */
 | 
		
	
		
			
			|  | 83 | +	sgdt flatten_saved_gdt
 | 
		
	
		
			
			|  | 84 | +
 | 
		
	
		
			
			|  | 85 | +	/* Set up GDT bases */
 | 
		
	
		
			
			|  | 86 | +	xorl	%eax, %eax
 | 
		
	
		
			
			|  | 87 | +	movw	%cs, %ax
 | 
		
	
		
			
			|  | 88 | +	shll	$4, %eax
 | 
		
	
		
			
			|  | 89 | +	addl	$flatten_gdt, %eax
 | 
		
	
		
			
			|  | 90 | +	movl	%eax, flatten_gdt_base
 | 
		
	
		
			
			|  | 91 | +	movw	%cs, %ax
 | 
		
	
		
			
			|  | 92 | +	movw	$flatten_cs, %si
 | 
		
	
		
			
			|  | 93 | +	call	set_seg_base
 | 
		
	
		
			
			|  | 94 | +	movw	%ss, %ax
 | 
		
	
		
			
			|  | 95 | +	movw	$flatten_ss, %si
 | 
		
	
		
			
			|  | 96 | +	call	set_seg_base
 | 
		
	
		
			
			|  | 97 | +
 | 
		
	
		
			
			|  | 98 | +	/* Switch temporarily to protected mode and set segment registers */
 | 
		
	
		
			
			|  | 99 | +	pushw	%cs
 | 
		
	
		
			
			|  | 100 | +	pushw	$2f
 | 
		
	
		
			
			|  | 101 | +	cli
 | 
		
	
		
			
			|  | 102 | +	data32 lgdt flatten_gdt
 | 
		
	
		
			
			|  | 103 | +	movl	%cr0, %eax
 | 
		
	
		
			
			|  | 104 | +	orb	$CR0_PE, %al
 | 
		
	
		
			
			|  | 105 | +	movl	%eax, %cr0
 | 
		
	
		
			
			|  | 106 | +	ljmp	$FLAT_CS, $1f
 | 
		
	
		
			
			|  | 107 | +1:	movw	$FLAT_SS, %ax
 | 
		
	
		
			
			|  | 108 | +	movw	%ax, %ss
 | 
		
	
		
			
			|  | 109 | +	movw	%ax, %ds
 | 
		
	
		
			
			|  | 110 | +	movw	%ax, %es
 | 
		
	
		
			
			|  | 111 | +	movw	%ax, %fs
 | 
		
	
		
			
			|  | 112 | +	movw	%ax, %gs
 | 
		
	
		
			
			|  | 113 | +	movl	%cr0, %eax
 | 
		
	
		
			
			|  | 114 | +	andb	$0!CR0_PE, %al
 | 
		
	
		
			
			|  | 115 | +	movl	%eax, %cr0
 | 
		
	
		
			
			|  | 116 | +	lret
 | 
		
	
		
			
			|  | 117 | +2:	/* lret will ljmp to here */
 | 
		
	
		
			
			|  | 118 | +
 | 
		
	
		
			
			|  | 119 | +	/* Restore GDT, registers and flags */
 | 
		
	
		
			
			|  | 120 | +	data32 lgdt flatten_saved_gdt
 | 
		
	
		
			
			|  | 121 | +	popw	%ss
 | 
		
	
		
			
			|  | 122 | +	popw	%ds
 | 
		
	
		
			
			|  | 123 | +	popw	%es
 | 
		
	
		
			
			|  | 124 | +	popw	%fs
 | 
		
	
		
			
			|  | 125 | +	popw	%gs
 | 
		
	
		
			
			|  | 126 | +	popw	%si
 | 
		
	
		
			
			|  | 127 | +	popl	%eax
 | 
		
	
		
			
			|  | 128 | +	popfl
 | 
		
	
		
			
			|  | 129 | +	lret
 | 
		
	
		
			
			|  | 130 | +	.size flatten_real_mode, . - flatten_real_mode
 | 
		
	
		
			
			|  | 131 | +
 | 
		
	
		
			
			|  | 132 | +	.section ".text16.early", "awx", @progbits
 | 
		
	
		
			
			|  | 133 | +	.code16
 | 
		
	
		
			
			|  | 134 | +set_seg_base:
 | 
		
	
		
			
			|  | 135 | +	rolw	$4, %ax
 | 
		
	
		
			
			|  | 136 | +	movw	%ax, 2(%si)
 | 
		
	
		
			
			|  | 137 | +	andw	$0xfff0, 2(%si)
 | 
		
	
		
			
			|  | 138 | +	movb	%al, 4(%si)
 | 
		
	
		
			
			|  | 139 | +	andb	$0x0f, 4(%si)
 | 
		
	
		
			
			|  | 140 | +	ret
 | 
		
	
		
			
			|  | 141 | +	.size set_seg_base, . - set_seg_base
 |