1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4 ;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
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.
12 ;; -----------------------------------------------------------------------
20 ; 32-bit bcopy routine
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
27 ; It also really needs to live all in a single segment, for the
28 ; address calculcations to actually work.
37 ; This is the protected-mode core of the "bcopy" routine.
38 ; Try to do aligned transfers; if the src and dst are relatively
39 ; misaligned, align the dst.
41 ; ECX is guaranteed to not be zero on entry.
43 ; Clobbers ESI, EDI, ECX.
54 cmp esi,edi ; If source < destination, we might
55 jb .reverse ; have to copy backwards
76 mov al,cl ; Save low bits
77 shr ecx,2 ; Convert to dwords
78 rep movsd ; Do our business
79 ; At this point ecx == 0
97 lea eax,[esi+ecx-1] ; Point to final byte
99 ja .forward ; No overlap, do forward copy
127 mov al,cl ; Save low bits
170 mov bl,cl ; Save low bits
188 ; This routine is used to shuffle memory around, followed by
189 ; invoking an entry point somewhere in low memory. This routine
190 ; can clobber any memory outside the bcopy special area.
192 ; IMPORTANT: This routine does not set up any registers.
193 ; It is the responsibility of the caller to generate an appropriate entry
194 ; stub; *especially* when going to real mode.
197 ; ESI -> Pointer to list of (dst, src, len) pairs(*)
198 ; EDI -> Pointer to safe area for list + shuffler
199 ; (must not overlap this code nor the RM stack)
200 ; ECX -> Byte count of list area (for initial copy)
202 ; If src == -1: then the memory pointed to by (dst, len) is bzeroed;
203 ; this is handled inside the bcopy routine.
205 ; If len == 0: this marks the end of the list; dst indicates
206 ; the entry point and src the mode (0 = pm, 1 = rm)
208 ; (*) dst, src, and len are four bytes each
210 ; do_raw_shuffle_and_boot is the same entry point, but with a C ABI:
211 ; do_raw_shuffle_and_boot(safearea, descriptors, bytecount)
213 global do_raw_shuffle_and_boot
214 do_raw_shuffle_and_boot:
219 cli ; End interrupt service (for good)
220 mov ebx,edi ; EBX <- descriptor list
221 lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to
222 and edx,~15 ; Align 16 to benefit the GDT
224 mov esi,__bcopyxx_start ; Absolute source address
225 mov edi,edx ; Absolute target address
226 sub edx,esi ; EDX <- address delta
227 mov ecx,__bcopyxx_dwords
228 lea eax,[edx+.safe] ; Resume point
231 jmp eax ; Jump to safe location
233 ; Give ourselves a safe stack
234 lea esp,[edx+bcopyxx_stack+__bcopyxx_end]
235 add edx,bcopy_gdt ; EDX <- new GDT
236 mov [edx+2],edx ; GDT self-pointer
237 lgdt [edx] ; Switch to local GDT
239 ; Now for the actual shuffling...
249 lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT
250 push ecx ; == 0, for cleaning the flags register
253 popfd ; Clean the flags
254 jmp edi ; Protected mode entry
256 ; We have a 16-bit entry point, so we need to return
257 ; to 16-bit mode. Note: EDX already points to the GDT.
260 mov [edx+PM_CS16+2],ax
261 mov [edx+PM_DS16+2],ax
263 mov [edx+PM_CS16+4],al
264 mov [edx+PM_CS16+7],ah
265 mov [edx+PM_DS16+4],al
266 mov [edx+PM_DS16+7],ah
269 popfd ; Clean the flags
270 ; No flag-changing instructions below...
279 section .bcopyxx.data
282 ; GDT descriptor entry
285 PM_%1 equ bcopy_gdt.%1-bcopy_gdt
289 dw bcopy_gdt_size-1 ; Null descriptor - contains GDT
290 dd bcopy_gdt ; pointer for LGDT instruction
293 ; TSS segment to keep Intel VT happy. Intel VT is
294 ; unhappy about anything that doesn't smell like a
295 ; full-blown 32-bit OS.
297 dw 104-1, DummyTSS ; 08h 32-bit task state segment
298 dd 00008900h ; present, dpl 0, 104 bytes @DummyTSS
301 dd 0000ffffh ; 10h Code segment, use16, readable,
302 dd 00009b00h ; present, dpl 0, cover 64K
304 dd 0000ffffh ; 18h Data segment, use16, read/write,
305 dd 00009300h ; present, dpl 0, cover 64K
307 dd 0000ffffh ; 20h Code segment, use32, readable,
308 dd 00cf9b00h ; present, dpl 0, cover all 4G
310 dd 0000ffffh ; 28h Data segment, use32, read/write,
311 dd 00cf9300h ; present, dpl 0, cover all 4G
313 bcopy_gdt_size: equ $-bcopy_gdt
315 ; Space for a dummy task state segment. It should never be actually
316 ; accessed, but just in case it is, point to a chunk of memory that
317 ; has a chance to not be used for anything real...
322 RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU)
325 bcopyxx_stack equ 128 ; We want this much stack