Przeglądaj źródła

This should be much more elegant: we use flat real mode for the

highmem data, so decompress16 will be able to unpack blocks bigger
than 64kB.
tags/v0.9.3
Michael Brown 18 lat temu
rodzic
commit
d081d65d48
1 zmienionych plików z 219 dodań i 130 usunięć
  1. 219
    130
      src/arch/i386/prefix/libprefix.S

+ 219
- 130
src/arch/i386/prefix/libprefix.S Wyświetl plik

@@ -1,178 +1,267 @@
1
+/*
2
+ * Copyright (C) 2006 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
+ */
1 19
 
2 20
 #define CR0_PE 1
3
-	
4
-	
21
+
5 22
 	.arch i386
6
-	.section ".prefix", "awx", @progbits
23
+	.section ".prefix.lib", "awx", @progbits
7 24
 
8 25
 /****************************************************************************
9
- * alloc_basemem (real-mode near call)
26
+ * install_block (real-mode near call)
10 27
  *
11
- * Allocate space from base memory via the BIOS free base memory
12
- * counter at 40: 13
28
+ * Install block to specified address
13 29
  *
14
- * Parameters: 
15
- *   %cx : Number of bytes to allocate
30
+ * Parameters:
31
+ *   %esi : byte offset within loaded image (must be a multiple of 16)
32
+ *   %es:edi : destination address
33
+ *   %ecx : length to install
16 34
  * Returns:
17
- *   %es : Segment address of newly allocated memory
35
+ *   none
36
+ * Corrupts:
37
+ *   %esi, %edi, %ecx
18 38
  ****************************************************************************
19 39
  */
20
-	.section ".prefix"
40
+	.section ".prefix.lib"
21 41
 	.code16
22
-alloc_basemem:
42
+install_block:
23 43
 	/* Preserve registers */
24
-	pushw	%cx
44
+	pushw	%ds
25 45
 	pushw	%ax
26 46
 	
27
-	/* %fs = 0x40, %ax = fbms */
47
+	/* Starting segment => %ds */
48
+	movw	%cs, %ax
49
+	shrl	$4, %esi
50
+	addw	%si, %ax
51
+	movw	%ax, %ds
52
+	xorl	%esi, %esi
53
+
54
+	/* Do the copy */
55
+	cld
56
+	addr32 rep movsb /* or "call decompress16" */
57
+
58
+	/* Restore registers */
59
+	popw	%ax
60
+	popw	%ds
61
+	ret
62
+	.size install_block, . - install_block
63
+	
64
+/****************************************************************************
65
+ * alloc_basemem (real-mode near call)
66
+ *
67
+ * Allocate space for .text16 and .data16 from top of base memory.
68
+ * Memory is allocated using the BIOS free base memory counter at
69
+ * 0x40:13.
70
+ *
71
+ * Parameters: 
72
+ *   none
73
+ * Returns:
74
+ *   %ax : .text16 segment address
75
+ *   %bx : .data16 segment address
76
+ * Corrupts:
77
+ *   none
78
+ ****************************************************************************
79
+ */
80
+	.section ".prefix.lib"
81
+	.code16
82
+alloc_basemem:
83
+	/* FBMS => %ax as segment address */
28 84
 	movw	$40, %ax
29 85
 	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 86
 	movw	%fs:0x13, %ax
36
-	subw	%cx, %ax
37
-	movw	%ax, %fs:0x13
38
-
39
-	/* Convert to segment address in %es */
40 87
 	shlw	$6, %ax
41
-	movw	%ax, %es
42 88
 
43
-	/* Restore registers and return */
89
+	/* .data16 segment address */
90
+	subw	$_data16_size, %ax
91
+	pushw	%ax
92
+
93
+	/* .text16 segment address */
94
+	subw	$_text16_size, %ax
95
+	pushw	%ax
96
+
97
+	/* Update FBMS */
98
+	shrw	$6, %ax
99
+	movw	%ax, %fs:0x13
100
+
101
+	/* Return */
44 102
 	popw	%ax
45
-	popw	%cx
103
+	popw	%bx
46 104
 	ret
105
+	.size alloc_basemem, . - alloc_basemem
47 106
 
107
+/****************************************************************************
108
+ * install_basemem (real-mode near call)
109
+ *
110
+ * Install .text16 and .data16 into base memory
111
+ *
112
+ * Parameters: 
113
+ *   %ax : .text16 segment address
114
+ *   %bx : .data16 segment address
115
+ * Returns:
116
+ *   none
117
+ * Corrupts:
118
+ *   none
119
+ ****************************************************************************
120
+ */
121
+	.section ".prefix.lib"
122
+	.code16
123
+install_basemem:
124
+	/* Preserve registers */
125
+	pushw	%es
126
+	pushl	%esi
127
+	pushl	%edi
128
+	pushl	%ecx
129
+
130
+	/* Install .text16 */
131
+	movw	%ax, %es
132
+	xorl	%edi, %edi
133
+	movl	$_text16_load_offset, %esi
134
+	movl	$_text16_size, %ecx
135
+	call	install_block
48 136
 
49
-	.section ".prefix"
137
+	/* Install .data16 */
138
+	movw	%bx, %es
139
+	xorl	%edi, %edi	
140
+	movl	$_data16_load_offset_pgh, %esi
141
+	movl	$_data16_progbits_size, %ecx
142
+	call	install_block
143
+
144
+	/* Restore registers */
145
+	popl	%ecx
146
+	popl	%edi
147
+	popl	%esi
148
+	popw	%es
149
+	ret
150
+	.size install_basemem, . - install_basemem
151
+
152
+/****************************************************************************
153
+ * GDT for flat real mode
154
+ *
155
+ * We only ever use this GDT to set segment limits; the bases are
156
+ * unused.  Also, we only flatten data segments, so we don't need to
157
+ * worry about the code or stack segments.  This makes everything much
158
+ * simpler.
159
+ ****************************************************************************
160
+ */
161
+	.section ".prefix.lib"
50 162
 	.align 16
51 163
 gdt:
52 164
 gdt_limit:		.word gdt_length - 1
53
-gdt_base:		.long gdt
165
+gdt_base:		.long 0
54 166
 			.word 0 /* padding */
55 167
 
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
168
+real_ds:	/* Genuine real mode data segment */
169
+	.equ	REAL_DS, real_ds - gdt
63 170
 	.word	0xffff, 0
64 171
 	.byte	0, 0x93, 0, 0
65 172
 
66
-flat_ds:	/* 16 bit data segment, zero base, 4GB limit */
173
+flat_ds:	/* Flat real mode data segment */
67 174
 	.equ	FLAT_DS, flat_ds - gdt
68 175
 	.word	0xffff, 0
69
-	.byte	0, 0x9f, 0xcf, 0
70
-	
176
+	.byte	0, 0x93, 0xcf, 0
177
+
71 178
 gdt_end:
72 179
 	.equ	gdt_length, gdt_end - gdt
180
+	.size gdt, . - gdt
73 181
 
74
-
75
-
76
-	
77
-	.section ".prefix"
182
+/****************************************************************************
183
+ * set_segment_limits (real-mode near call)
184
+ *
185
+ * Sets limits on the data segments %ds and %es.
186
+ *
187
+ * Parameters: 
188
+ *   %cx : Segment limit ($REAL_DS or $FLAT_DS)
189
+ ****************************************************************************
190
+ */
191
+	.section ".prefix.lib"
78 192
 	.code16
79
-prot16_call:
80
-
193
+set_segment_limits:
194
+	/* Preserve real-mode segment values and temporary registers */
195
+	pushw	%es
196
+	pushw	%ds
197
+	pushl	%eax
81 198
 
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
199
+	/* Set GDT base and load GDT */
116 200
 	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
201
+	movw	%cs, %ax
202
+	shrl	$4, %eax
203
+	addl	$gdt, %eax
204
+	movl	%eax, %cs:gdt_base
205
+	lgdt	%cs:gdt
206
+
207
+	/* Switch to protected mode, set segment limits, switch back */
126 208
 	movl	%cr0, %eax
127 209
 	orb	$CR0_PE, %al
128 210
 	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
211
+	movw	%cx, %ds
212
+	movw	%cx, %es
156 213
 	andb	$0!CR0_PE, %al
157 214
 	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 215
 
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
-	
216
+	/* Restore real-mode segment values and temporary registers */
217
+	popl	%eax
218
+	popw	%ds
219
+	popw	%es
176 220
 	ret
221
+	.size set_segment_limits, . - set_segment_limits
177 222
 	
223
+/****************************************************************************
224
+ * install_highmem (real-mode near call)
225
+ *
226
+ * Install .text and .data into high memory
227
+ *
228
+ * Parameters:
229
+ *   %edi : physical address in high memory
230
+ * Returns:
231
+ *   none
232
+ * Corrupts:
233
+ *   none
234
+ ****************************************************************************
235
+ */
236
+	.section ".prefix.lib"
237
+	.code16
238
+install_highmem:
239
+	/* Preserve registers and interrupt status */
240
+	pushfl
241
+	pushl	%esi
242
+	pushl	%edi
243
+	pushl	%ecx
244
+		
245
+	/* Disable interrupts and flatten real mode */
246
+	cli
247
+	movw	$FLAT_DS, %cx
248
+	call	set_segment_limits
249
+
250
+	/* Install .text and .data to specified address */
251
+	xorw	%ax, %ax
252
+	movw	%ax, %es
253
+	movl	$_text_load_offset, %esi
254
+	movl	$_text_and_data_progbits_size, %ecx
255
+	call	install_block
178 256
 
257
+	/* Unflatten real mode */
258
+	movw	$REAL_DS, %cx
259
+	call	set_segment_limits
260
+
261
+	/* Restore registers and interrupt status */
262
+	popl	%ecx
263
+	popl	%edi
264
+	popl	%esi
265
+	popfl
266
+	ret
267
+	.size install_highmem, . - install_highmem

Ładowanie…
Anuluj
Zapisz