Annotation of /trunk/mkinitrd-magellan/isolinux/bcopyxx.inc
Parent Directory | Revision Log
Revision 1133 -
(hide annotations)
(download)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
File size: 6584 byte(s)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
File size: 6584 byte(s)
-updated to isolinux-3.86
1 | niro | 1133 | ;; ----------------------------------------------------------------------- |
2 | ;; | ||
3 | ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved | ||
4 | ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin | ||
5 | ;; | ||
6 | ;; This program is free software; you can redistribute it and/or modify | ||
7 | ;; it under the terms of the GNU General Public License as published by | ||
8 | ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, | ||
9 | ;; Boston MA 02111-1307, USA; either version 2 of the License, or | ||
10 | ;; (at your option) any later version; incorporated herein by reference. | ||
11 | ;; | ||
12 | ;; ----------------------------------------------------------------------- | ||
13 | |||
14 | ;; | ||
15 | ;; bcopy32xx.inc | ||
16 | ;; | ||
17 | |||
18 | |||
19 | ; | ||
20 | ; 32-bit bcopy routine | ||
21 | ; | ||
22 | ; This is the actual 32-bit portion of the bcopy and shuffle and boot | ||
23 | ; routines. ALL THIS CODE NEEDS TO BE POSITION-INDEPENDENT, with the | ||
24 | ; sole exception being the actual relocation code at the beginning of | ||
25 | ; pm_shuffle_boot. | ||
26 | ; | ||
27 | ; It also really needs to live all in a single segment, for the | ||
28 | ; address calculcations to actually work. | ||
29 | ; | ||
30 | |||
31 | bits 32 | ||
32 | section .bcopyxx | ||
33 | align 16 | ||
34 | bcopyxx_start equ $ | ||
35 | ; | ||
36 | ; pm_bcopy: | ||
37 | ; | ||
38 | ; This is the protected-mode core of the "bcopy" routine. | ||
39 | ; Try to do aligned transfers; if the src and dst are relatively | ||
40 | ; misaligned, align the dst. | ||
41 | ; | ||
42 | ; ECX is guaranteed to not be zero on entry. | ||
43 | ; | ||
44 | ; Clobbers ESI, EDI, ECX. | ||
45 | ; | ||
46 | |||
47 | pm_bcopy: | ||
48 | push ebx | ||
49 | push edx | ||
50 | push eax | ||
51 | |||
52 | cmp esi,-1 | ||
53 | je .bzero | ||
54 | |||
55 | cmp esi,edi ; If source < destination, we might | ||
56 | jb .reverse ; have to copy backwards | ||
57 | |||
58 | .forward: | ||
59 | ; Initial alignment | ||
60 | mov edx,edi | ||
61 | shr edx,1 | ||
62 | jnc .faa1 | ||
63 | movsb | ||
64 | dec ecx | ||
65 | .faa1: | ||
66 | mov al,cl | ||
67 | cmp ecx,2 | ||
68 | jb .f_tiny | ||
69 | |||
70 | shr edx,1 | ||
71 | jnc .faa2 | ||
72 | movsw | ||
73 | sub ecx,2 | ||
74 | .faa2: | ||
75 | |||
76 | ; Bulk transfer | ||
77 | mov al,cl ; Save low bits | ||
78 | shr ecx,2 ; Convert to dwords | ||
79 | rep movsd ; Do our business | ||
80 | ; At this point ecx == 0 | ||
81 | |||
82 | test al,2 | ||
83 | jz .fab2 | ||
84 | movsw | ||
85 | .fab2: | ||
86 | .f_tiny: | ||
87 | test al,1 | ||
88 | jz .fab1 | ||
89 | movsb | ||
90 | .fab1: | ||
91 | .done: | ||
92 | pop eax | ||
93 | pop edx | ||
94 | pop ebx | ||
95 | ret | ||
96 | |||
97 | .reverse: | ||
98 | std ; Reverse copy | ||
99 | |||
100 | lea esi,[esi+ecx-1] ; Point to final byte | ||
101 | lea edi,[edi+ecx-1] | ||
102 | |||
103 | ; Initial alignment | ||
104 | mov edx,edi | ||
105 | shr edx,1 | ||
106 | jc .raa1 | ||
107 | movsb | ||
108 | dec ecx | ||
109 | .raa1: | ||
110 | |||
111 | dec esi | ||
112 | dec edi | ||
113 | mov al,cl | ||
114 | cmp ecx,2 | ||
115 | jb .r_tiny | ||
116 | shr edx,1 | ||
117 | jc .raa2 | ||
118 | movsw | ||
119 | sub ecx,2 | ||
120 | .raa2: | ||
121 | |||
122 | ; Bulk copy | ||
123 | sub esi,2 | ||
124 | sub edi,2 | ||
125 | mov al,cl ; Save low bits | ||
126 | shr ecx,2 | ||
127 | rep movsd | ||
128 | |||
129 | ; Final alignment | ||
130 | .r_final: | ||
131 | add esi,2 | ||
132 | add edi,2 | ||
133 | test al,2 | ||
134 | jz .rab2 | ||
135 | movsw | ||
136 | .rab2: | ||
137 | .r_tiny: | ||
138 | inc esi | ||
139 | inc edi | ||
140 | test al,1 | ||
141 | jz .rab1 | ||
142 | movsb | ||
143 | .rab1: | ||
144 | cld | ||
145 | jmp short .done | ||
146 | |||
147 | .bzero: | ||
148 | xor eax,eax | ||
149 | |||
150 | ; Initial alignment | ||
151 | mov edx,edi | ||
152 | shr edx,1 | ||
153 | jnc .zaa1 | ||
154 | stosb | ||
155 | dec ecx | ||
156 | .zaa1: | ||
157 | |||
158 | mov bl,cl | ||
159 | cmp ecx,2 | ||
160 | jb .z_tiny | ||
161 | shr edx,1 | ||
162 | jnc .zaa2 | ||
163 | stosw | ||
164 | sub ecx,2 | ||
165 | .zaa2: | ||
166 | |||
167 | ; Bulk | ||
168 | mov bl,cl ; Save low bits | ||
169 | shr ecx,2 | ||
170 | rep stosd | ||
171 | |||
172 | test bl,2 | ||
173 | jz .zab2 | ||
174 | stosw | ||
175 | .zab2: | ||
176 | .z_tiny: | ||
177 | test bl,1 | ||
178 | jz .zab1 | ||
179 | stosb | ||
180 | .zab1: | ||
181 | jmp short .done | ||
182 | |||
183 | ; | ||
184 | ; shuffle_and_boot: | ||
185 | ; | ||
186 | ; This routine is used to shuffle memory around, followed by | ||
187 | ; invoking an entry point somewhere in low memory. This routine | ||
188 | ; can clobber any memory outside the bcopy special area. | ||
189 | ; | ||
190 | ; IMPORTANT: This routine does not set up any registers. | ||
191 | ; It is the responsibility of the caller to generate an appropriate entry | ||
192 | ; stub; *especially* when going to real mode. | ||
193 | ; | ||
194 | ; Inputs: | ||
195 | ; ESI -> Pointer to list of (dst, src, len) pairs(*) | ||
196 | ; EDI -> Pointer to safe area for list + shuffler | ||
197 | ; (must not overlap this code nor the RM stack) | ||
198 | ; ECX -> Byte count of list area (for initial copy) | ||
199 | ; | ||
200 | ; If src == -1: then the memory pointed to by (dst, len) is bzeroed; | ||
201 | ; this is handled inside the bcopy routine. | ||
202 | ; | ||
203 | ; If len == 0: this marks the end of the list; dst indicates | ||
204 | ; the entry point and src the mode (0 = pm, 1 = rm) | ||
205 | ; | ||
206 | pm_shuffle: | ||
207 | mov ebx,edi ; EBX <- descriptor list | ||
208 | lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to | ||
209 | and edx,~15 ; Align 16 to benefit the GDT | ||
210 | call pm_bcopy | ||
211 | mov edi,edx | ||
212 | mov esi,bcopyxx_start | ||
213 | mov ecx,bcopyxx_dwords | ||
214 | lea eax,[edx+.safe-bcopyxx_start] ; Resume point | ||
215 | ; Relocate this code | ||
216 | rep movsd | ||
217 | jmp eax ; Jump to safe location | ||
218 | .safe: | ||
219 | ; Give ourselves a safe stack | ||
220 | lea esp,[edx+bcopyxx_stack+bcopyxx_end-bcopyxx_start] | ||
221 | add edx,bcopy_gdt-bcopyxx_start | ||
222 | mov [edx+2],edx ; GDT self-pointer | ||
223 | lgdt [edx] ; Switch to local GDT | ||
224 | |||
225 | ; Now for the actual shuffling... | ||
226 | .loop: | ||
227 | mov edi,[ebx] | ||
228 | mov esi,[ebx+4] | ||
229 | mov ecx,[ebx+8] | ||
230 | add ebx,12 | ||
231 | jecxz .done | ||
232 | call pm_bcopy | ||
233 | jmp .loop | ||
234 | .done: | ||
235 | push ecx ; == 0, for cleaning the flags register | ||
236 | and esi,esi | ||
237 | jz pm_shuffle_real_mode | ||
238 | popfd ; Clean the flags | ||
239 | jmp edi ; Protected mode entry | ||
240 | |||
241 | ; We have a real-mode entry point, so we need to return | ||
242 | ; to real mode. Note: EDX already points to the GDT. | ||
243 | pm_shuffle_real_mode: | ||
244 | mov eax,edi | ||
245 | mov [edx+PM_CS16+2],ax | ||
246 | mov [edx+PM_DS16+2],ax | ||
247 | shr eax,16 | ||
248 | mov [edx+PM_CS16+4],al | ||
249 | mov [edx+PM_CS16+7],ah | ||
250 | mov [edx+PM_DS16+4],al | ||
251 | mov [edx+PM_DS16+7],ah | ||
252 | mov eax,cr0 | ||
253 | and al,~1 | ||
254 | popfd ; Clean the flags | ||
255 | ; No flag-changing instructions below... | ||
256 | mov dx,PM_DS16 | ||
257 | mov ds,edx | ||
258 | mov es,edx | ||
259 | mov fs,edx | ||
260 | mov gs,edx | ||
261 | mov ss,edx | ||
262 | jmp PM_CS16:0 | ||
263 | |||
264 | align 16 | ||
265 | ; GDT descriptor entry | ||
266 | %macro desc 1 | ||
267 | bcopy_gdt.%1: | ||
268 | PM_%1 equ bcopy_gdt.%1-bcopy_gdt | ||
269 | %endmacro | ||
270 | |||
271 | bcopy_gdt: | ||
272 | dw bcopy_gdt_size-1 ; Null descriptor - contains GDT | ||
273 | dd bcopy_gdt ; pointer for LGDT instruction | ||
274 | dw 0 | ||
275 | |||
276 | ; TSS segment to keep Intel VT happy. Intel VT is | ||
277 | ; unhappy about anything that doesn't smell like a | ||
278 | ; full-blown 32-bit OS. | ||
279 | desc TSS | ||
280 | dw 104-1, DummyTSS ; 08h 32-bit task state segment | ||
281 | dd 00008900h ; present, dpl 0, 104 bytes @DummyTSS | ||
282 | |||
283 | desc CS16 | ||
284 | dd 0000ffffh ; 10h Code segment, use16, readable, | ||
285 | dd 00009b00h ; present, dpl 0, cover 64K | ||
286 | desc DS16 | ||
287 | dd 0000ffffh ; 18h Data segment, use16, read/write, | ||
288 | dd 00009300h ; present, dpl 0, cover 64K | ||
289 | desc CS32 | ||
290 | dd 0000ffffh ; 20h Code segment, use32, readable, | ||
291 | dd 00cf9b00h ; present, dpl 0, cover all 4G | ||
292 | desc DS32 | ||
293 | dd 0000ffffh ; 28h Data segment, use32, read/write, | ||
294 | dd 00cf9300h ; present, dpl 0, cover all 4G | ||
295 | |||
296 | bcopy_gdt_size: equ $-bcopy_gdt | ||
297 | |||
298 | alignz 4 | ||
299 | bcopyxx_end equ $ ; *Must* be dword-aligned! | ||
300 | bcopyxx_len equ $-bcopyxx_start | ||
301 | bcopyxx_dwords equ bcopyxx_len >> 2 | ||
302 | |||
303 | bcopyxx_stack equ 128 ; We want this much stack | ||
304 | ; The +15 is for alignment | ||
305 | bcopyxx_safe equ bcopyxx_len + bcopyxx_stack + 15 | ||
306 | |||
307 | ; | ||
308 | ; Space for a dummy task state segment. It should never be actually | ||
309 | ; accessed, but just in case it is, point to a chunk of memory that | ||
310 | ; has a chance to not be used for anything real... | ||
311 | ; | ||
312 | DummyTSS equ 0x580 | ||
313 | |||
314 | bits 16 | ||
315 | section .text |