Procházet zdrojové kódy

Checking in because I don't want to lose this rather neat code for

running the decompresser in 16:16 protected mode using the real-mode
stack.  However, there's an even simpler way to do it...
tags/v0.9.3
Michael Brown před 18 roky
rodič
revize
cc8821a443
1 změnil soubory, kde provedl 178 přidání a 0 odebrání
  1. 178
    0
      src/arch/i386/prefix/libprefix.S

+ 178
- 0
src/arch/i386/prefix/libprefix.S Zobrazit soubor

@@ -0,0 +1,178 @@
1
+
2
+#define CR0_PE 1
3
+	
4
+	
5
+	.arch i386
6
+	.section ".prefix", "awx", @progbits
7
+
8
+/****************************************************************************
9
+ * alloc_basemem (real-mode near call)
10
+ *
11
+ * Allocate space from base memory via the BIOS free base memory
12
+ * counter at 40: 13
13
+ *
14
+ * Parameters: 
15
+ *   %cx : Number of bytes to allocate
16
+ * Returns:
17
+ *   %es : Segment address of newly allocated memory
18
+ ****************************************************************************
19
+ */
20
+	.section ".prefix"
21
+	.code16
22
+alloc_basemem:
23
+	/* Preserve registers */
24
+	pushw	%cx
25
+	pushw	%ax
26
+	
27
+	/* %fs = 0x40, %ax = fbms */
28
+	movw	$40, %ax
29
+	movw	%ax, %fs
30
+
31
+	/* Round up %cx to nearest kB, subtract from FBMS */
32
+	addw	$0x03ff, %cx
33
+	andw	$0xfc00, %cx
34
+	shrw	$10, %cx
35
+	movw	%fs:0x13, %ax
36
+	subw	%cx, %ax
37
+	movw	%ax, %fs:0x13
38
+
39
+	/* Convert to segment address in %es */
40
+	shlw	$6, %ax
41
+	movw	%ax, %es
42
+
43
+	/* Restore registers and return */
44
+	popw	%ax
45
+	popw	%cx
46
+	ret
47
+
48
+
49
+	.section ".prefix"
50
+	.align 16
51
+gdt:
52
+gdt_limit:		.word gdt_length - 1
53
+gdt_base:		.long gdt
54
+			.word 0 /* padding */
55
+
56
+cs16: 		/* 16 bit code segment, base at real-mode %cs:0000 */
57
+	.equ	CS16, cs16 - gdt
58
+	.word	0xffff, 0
59
+	.byte	0, 0x9b, 0, 0
60
+	
61
+ss16:		/* 16 bit stack segment, base at real-mode %ss:0000 */
62
+	.equ	SS16, ss16 - gdt
63
+	.word	0xffff, 0
64
+	.byte	0, 0x93, 0, 0
65
+
66
+flat_ds:	/* 16 bit data segment, zero base, 4GB limit */
67
+	.equ	FLAT_DS, flat_ds - gdt
68
+	.word	0xffff, 0
69
+	.byte	0, 0x9f, 0xcf, 0
70
+	
71
+gdt_end:
72
+	.equ	gdt_length, gdt_end - gdt
73
+
74
+
75
+
76
+	
77
+	.section ".prefix"
78
+	.code16
79
+prot16_call:
80
+
81
+
82
+	/* Install .data16 to top of base memory */
83
+	movw	%cs, %ax
84
+	addw	$_data16_load_offset_pgh, %ax
85
+	movw	%ax, %ds
86
+	movw	$_data16_size, %cx
87
+	call	alloc_basemem
88
+	xorw	%si, %si
89
+	xorw	%di, %di	
90
+	movw	$_data16_progbits_size, %cx
91
+	rep movsb /* or "call decompress16" */
92
+
93
+	/* Install .code16 to top of base memory */
94
+	movw	%cs, %ax
95
+	addw	$_code16_load_offset_pgh, %ax
96
+	movw	%ax, %ds
97
+	movw	$_code16_size, %cx
98
+	call	alloc_basemem
99
+	xorw	%si, %si
100
+	xorw	%di, %di	
101
+	rep movsb /* or "call decompress16" */
102
+	
103
+	/* Push flags and real-mode segment registers */
104
+	pushfl
105
+	push	%gs
106
+	push	%fs
107
+	push	%es
108
+	push	%ds
109
+	push	%ss
110
+	push	%cs
111
+
112
+	/* Physical address of %cs:0000 to %ebx, of %ss:0000 to %eax */
113
+	xorl	%ebx, %ebx
114
+	movw	%cs, %bx
115
+	shll	$4, %ebx
116
+	xorl	%eax, %eax
117
+	movw	%ss, %ax
118
+	shll	$4, %eax
119
+	
120
+	/* Set up GDT and switch to protected mode */
121
+	addl	%ebx, %cs:gdt_base
122
+	orl	%ebx, %cs:(cs16+2)
123
+	orl	%eax, %cs:(ss16+2)
124
+	cli
125
+	data32 lgdt	%cs:gdt
126
+	movl	%cr0, %eax
127
+	orb	$CR0_PE, %al
128
+	movl	%eax, %cr0
129
+	data32 ljmp	$CS16, $1f
130
+1:	movw	$SS16, %ax
131
+	movw	%ax, %ss
132
+	movw	$FLAT_DS, %ax
133
+	movw	%ax, %ds
134
+	movw	%ax, %es
135
+	movw	%ax, %fs
136
+	movw	%ax, %gs
137
+
138
+	/* Install .text and .data to 2MB mark.  Use 2MB to avoid
139
+	 * having to deal with A20.
140
+	 */
141
+	leal	_text_load_offset(%ebx), %esi
142
+	movl	$( 2 * 1024 * 1024 ), %edi
143
+	movl	$_text_and_data_progbits_size, %ecx
144
+	addr32 rep movsb /* or "call decompress16" */
145
+	
146
+	/* Restore real-mode segment limits */
147
+	movw	%ss, %ax
148
+	movw	%ax, %ds
149
+	movw	%ax, %es
150
+	movw	%ax, %fs
151
+	movw	%ax, %gs
152
+	
153
+	/* Return to real mode, restore segment registers and flags */
154
+	pushw	$1f
155
+	movl	%cr0, %eax
156
+	andb	$0!CR0_PE, %al
157
+	movl	%eax, %cr0
158
+	lret	/* used as equivalent of pop %cs */
159
+1:	pop	%ss
160
+	pop	%ds
161
+	pop	%es
162
+	pop	%fs
163
+	pop	%gs
164
+	popfl
165
+
166
+	/* Call init_gdt */
167
+	pushw	%cs
168
+	pushw	$1f
169
+	pushw	%es
170
+	pushw	$init_gdt
171
+	lret /* lcall %es:init_gdt */
172
+1:	
173
+	
174
+
175
+	
176
+	ret
177
+	
178
+

Načítá se…
Zrušit
Uložit