bcopy32: refactor the bcopy routine to be able to reuse the pm part
authorH. Peter Anvin <hpa@zytor.com>
Sat, 16 Feb 2008 02:10:54 +0000 (18:10 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 16 Feb 2008 06:54:01 +0000 (22:54 -0800)
Refactor the bcopy routine to be able to reuse the pm entry and exit
portion to call other "simple" protected-mode routines ("simple" in
the sense that no interrupt thunking support is present or expected.)

Note: consider whether or not it would be preferrable to move the
thunking support into low memory and have it be always present.

bcopy32.inc

index d0f8a46..056f29b 100644 (file)
@@ -71,6 +71,13 @@ bcopy_gdt:
        desc TSS
                dw 104-1, DummyTSS      ; 30h 32-bit task state segment
                dd 00008900h            ; present, dpl 0, 104 bytes @DummyTSS
+
+               ; 16-bit stack segment, which may have a different
+               ; base from DS16 (e.g. if we're booted from PXELINUX)
+       desc SS16
+               dd 0000ffffh            ; 38h Data segment, use16, read/write,
+               dd 00009300h            ; present, dpl 0, cover 64K
+
 bcopy_gdt_size:        equ $-bcopy_gdt
 
 ;
@@ -86,13 +93,33 @@ bcopy_gdt_size:     equ $-bcopy_gdt
 ; Outputs:
 ;      ESI     - first byte after source (garbage if ESI == -1 on entry)
 ;      EDI     - first byte after target
-;      ECX     - zero
 ;
-bcopy:         push eax
-               push ebx
-               push esi
-               push edi
-               push ecx
+bcopy:         pushad
+               mov bx,pm_bcopy
+               call simple_pm_call
+               popad
+               add edi,ecx
+               add esi,ecx
+               ret
+
+;
+; This routine is used to invoke a simple routine in 16-bit protected
+; mode (with 32-bit DS and ES, and working 16-bit stack.)
+; Note that all segment registers including CS, except possibly SS,
+; are zero-based in the protected-mode routine.
+;
+; No interrupt thunking services are provided; interrupts are disabled
+; for the duration of the routine.  Don't run for too long at a time.
+;
+; Inputs:
+;      BX      - routine to execute
+;      ECX, EDX, EBP, ESI and EDI passed to the called routine
+;
+; Outputs:
+;      EAX, EBX destroyed
+;      All other registers as returned from called function
+;
+simple_pm_call:
                pushf                   ; Saves, among others, the IF flag
                push ds
                push es
@@ -102,36 +129,73 @@ bcopy:            push eax
                cli
                call enable_a20
 
-               mov byte [bcopy_gdt.TSS+5],89h  ; Mark TSS unbusy
+               mov byte [cs:bcopy_gdt.TSS+5],89h       ; Mark TSS unbusy
 
-               mov bx,ss               ; Save the stack segment value!
+               ; Convert the stack segment to a base
+               xor eax,eax
+               mov ax,ss
+               shl eax,4
+               or eax,93000000h
+               mov [cs:bcopy_gdt.SS16+2],eax
 
+               push ss                 ; Save real-mode SS selector
+       
                o32 lgdt [cs:bcopy_gdt]
                mov eax,cr0
                or al,1
                mov cr0,eax             ; Enter protected mode
                jmp PM_CS16:.in_pm
+.in_pm:
+               mov ax,PM_SS16          ; Make stack usable
+               mov ss,ax
 
-.in_pm:                mov ax,PM_DS16_4G       ; Data segment selector
+               mov al,PM_DS16_4G       ; Data segment selector
                mov es,ax
                mov ds,ax
 
-               ; Set ss, fs, and gs, in case we're on a virtual machine
-               ; running on Intel VT hardware -- it can't deal with a
-               ; partial transition, for no good reason.  However,
-               ; ss is NOT zero in general, so we have to preserve
-               ; the value.
+               ; Set fs, gs, tr, and ldtr in case we're on a virtual
+               ; machine running on Intel VT hardware -- it can't
+               ; deal with a partial transition, for no good reason.
 
                mov al,PM_DS16_RM       ; Real-mode-like segment
                mov fs,ax
                mov gs,ax
-               mov ss,ax
-
                mov al,PM_TSS           ; Intel VT really doesn't want
                ltr ax                  ; an invalid TR and LDTR, so give
                xor ax,ax               ; it something that it can use...
                lldt ax                 ; (sigh)
 
+               call bx                 ; Call actual routine
+
+.exit:
+               mov ax,PM_DS16_RM       ; "Real-mode-like" data segment
+               mov es,ax
+               mov ds,ax
+
+               pop bx                  ; Previous value for ss
+
+               mov eax,cr0
+               and al,~1
+               mov cr0,eax             ; Disable protected mode
+               jmp 0:.in_rm
+
+.in_rm:                ; Back in real mode
+               mov ss,bx
+               pop gs
+               pop fs
+               pop es
+               pop ds
+               call disable_a20
+
+               popf                    ; Re-enables interrupts
+               ret
+
+;
+; pm_bcopy:
+;
+;      This is the protected-mode core of the "bcopy" routine.
+;
+pm_bcopy:
                cmp esi,-1
                je .bzero
 
@@ -147,7 +211,7 @@ bcopy:              push eax
 
                mov cl,al               ; Copy any fractional dword
                a32 rep movsb
-               jmp .exit
+               ret
 
 .reverse:
                std                     ; Reverse copy
@@ -166,7 +230,7 @@ bcopy:              push eax
                a32 rep movsd
 
                cld
-               jmp .exit
+               ret
 
 .bzero:
                xor eax,eax
@@ -177,34 +241,6 @@ bcopy:             push eax
 
                mov cx,si               ; Write fractional dword
                a32 rep stosb
-               ; jmp .exit
-
-.exit:
-               mov ax,PM_DS16_RM       ; "Real-mode-like" data segment
-               mov es,ax
-               mov ds,ax
-
-               mov eax,cr0
-               and al,~1
-               mov cr0,eax             ; Disable protected mode
-               jmp 0:.in_rm
-
-.in_rm:                ; Back in real mode
-               mov ss,bx
-               pop gs
-               pop fs
-               pop es
-               pop ds
-               call disable_a20
-
-               popf                    ; Re-enables interrupts
-               pop eax
-               pop edi
-               pop esi
-               add edi,eax
-               add esi,eax
-               pop ebx
-               pop eax
                ret
 
 ;