--- trunk/mkinitrd-magellan/isolinux/com32.inc 2010/08/19 08:27:19 1132 +++ trunk/mkinitrd-magellan/isolinux/com32.inc 2010/08/19 09:50:43 1133 @@ -1,7 +1,6 @@ -;; $Id: com32.inc,v 1.1 2007-09-01 22:44:04 niro Exp $ ;; ----------------------------------------------------------------------- -;; -;; Copyright 1994-2003 H. Peter Anvin - All Rights Reserved +;; +;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -27,12 +26,21 @@ ; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the ; program with an error if run in 16-bit mode. ; -pm_idt: equ 0x100000 -pm_entry: equ 0x101000 + + ; We need to make this a proper section rather + ; than using absolute numbers, in order to work + ; around a bug in GNU ld 2.17, which is still in + ; use as of this writing in the form of Debian + ; 4.0 (etch). + bits 32 + section .com32 exec write nobits align=16 +pm_idt equ 0x100000 ; Needs to be absolute... + resb 4096 +pm_entry: ; Needs to not be... bits 16 section .data - align 2, db 0 + alignz 2 com32_pmidt: dw 8*256 ; Limit dd pm_idt ; Address @@ -44,8 +52,7 @@ section .text is_com32_image: push si ; Save file handle - push dx ; File length held in DX:AX - push ax + push eax ; Save file length call make_plain_cmdline ; Copy the command line into the low cmdline buffer @@ -58,15 +65,18 @@ sub cx,si fs rep movsb - call highmemsize ; We need the high memory size... + mov si,KernelCName + mov di,Com32Name + call strcpy + call comboot_setup_api ; Set up the COMBOOT-style API mov edi,pm_entry ; Load address pop eax ; File length pop si ; File handle xor dx,dx ; No padding + mov bx,abort_check ; Don't print dots, but allow abort call load_high - call crlf com32_start: mov ebx,com32_call_start ; Where to go in PM @@ -75,32 +85,38 @@ cli mov ax,cs mov ds,ax - mov [SavedSSSP],sp - mov [SavedSSSP+2],ss + mov [RealModeSSSP],sp + mov [RealModeSSSP+2],ss cld call a20_test jnz .a20ok call enable_a20 .a20ok: + mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy + lgdt [bcopy_gdt] ; We can use the same GDT just fine lidt [com32_pmidt] ; Set up the IDT mov eax,cr0 or al,1 mov cr0,eax ; Enter protected mode - jmp 20h:.in_pm - + jmp PM_CS32:.in_pm + bits 32 .in_pm: xor eax,eax ; Available for future use... mov fs,eax mov gs,eax + lldt ax - mov al,28h ; Set up data segments + mov al,PM_DS32 ; Set up data segments mov es,eax mov ds,eax mov ss,eax + mov al,PM_TSS ; Be nice to Intel's VT by + ltr ax ; giving it a valid TR + mov esp,[PMESP] ; Load protmode %esp if available jmp ebx ; Go to where we need to go @@ -110,9 +126,10 @@ ; com32_call_start: ; - ; Point the stack to the end of high memory + ; Point the stack to the end of (permitted) high memory ; - mov esp,[word HighMemSize] + mov esp,[word HighMemRsvd] + xor sp,sp ; Align to a 64K boundary ; ; Set up the protmode IDT and the interrupt jump buffers @@ -159,12 +176,15 @@ ; Now everything is set up for interrupts... + push dword Com32Name ; Module filename + push dword [HighMemSize] ; Memory managed by Syslinux + push dword com32_cfarcall ; Cfarcall entry point push dword com32_farcall ; Farcall entry point push dword (1 << 16) ; 64K bounce buffer - push dword (comboot_seg << 4) ; Bounce buffer address + push dword (xfer_buf_seg << 4) ; Bounce buffer address push dword com32_intcall ; Intcall entry point push dword command_line ; Command line pointer - push dword 5 ; Argument count + push dword 8 ; Argument count sti ; Interrupts OK now call pm_entry ; Run the program... ; ... on return, fall through to com32_exit ... @@ -177,11 +197,11 @@ cld mov [PMESP],esp ; Save exit %esp xor esp,esp ; Make sure the high bits are zero - jmp 08h:.in_pm16 ; Return to 16-bit mode first + jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first bits 16 .in_pm16: - mov ax,18h ; Real-mode-like segment + mov ax,PM_DS16 ; Real-mode-like segment mov es,ax mov ds,ax mov ss,ax @@ -200,11 +220,10 @@ mov es,ax mov fs,ax mov gs,ax - lss sp,[SavedSSSP] ; Restore stack + lss sp,[RealModeSSSP] ; Restore stack jmp bx ; Go to whereever we need to go... com32_done: - call disable_a20 sti jmp enter_command @@ -227,7 +246,7 @@ jmp com32_enter_pm ; Go back to PM ; -; 16-bit system call handling code +; 16-bit intcall/farcall handling code ; com32_sys_rm: pop gs @@ -248,7 +267,18 @@ push es push fs push gs - mov ebx,com32_sys_resume + mov ebx,com32_syscall.resume + jmp com32_enter_pm + +; +; 16-bit cfarcall handing code +; +com32_cfar_rm: + retf +.return: + mov sp,[cs:Com32SysSP] + mov [cs:RealModeEAX],eax + mov ebx,com32_cfarcall.resume jmp com32_enter_pm ; @@ -303,10 +333,10 @@ com32_syscall: cld - movzx edi,word [word SavedSSSP] - movzx ebx,word [word SavedSSSP+2] + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] sub edi,54 ; Allocate 54 bytes - mov [word SavedSSSP],di + mov [word RealModeSSSP],di shl ebx,4 add edi,ebx ; Create linear address @@ -330,9 +360,9 @@ ; On return, the 44-byte return structure is on the ; real-mode stack, plus the 10 additional bytes used ; by the target address (see above.) -com32_sys_resume: - movzx esi,word [word SavedSSSP] - movzx eax,word [word SavedSSSP+2] +.resume: + movzx esi,word [word RealModeSSSP] + movzx eax,word [word RealModeSSSP+2] mov edi,[esp+12*4] ; Dest regs shl eax,4 add esi,eax ; Create linear address @@ -343,17 +373,68 @@ mov cl,11 ; 44 bytes rep movsd ; Copy register block - add dword [word SavedSSSP],54 ; Remove from stack + add dword [word RealModeSSSP],54 ; Remove from stack popad popfd ret ; Return to 32-bit program +; +; Cfarcall invocation. We copy the stack frame to the real-mode stack, +; followed by the return CS:IP and the CS:IP of the target function. +; +com32_cfarcall: + pushfd + pushad + + cld + mov ecx,[esp+12*4] ; Size of stack frame + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + mov [word Com32SysSP],di + sub edi,ecx ; Allocate space for stack frame + and edi,~3 ; Round + sub edi,4*2 ; Return pointer, return value + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov eax,[esp+10*4] ; CS:IP + stosd ; Save to stack frame + mov eax,com32_cfar_rm.return ; Return seg:off + stosd + mov esi,[esp+11*4] ; Stack frame + mov eax,ecx ; Copy the stack frame + shr ecx,2 + rep movsd + mov ecx,eax + and ecx,3 + rep movsb + + mov bx,com32_cfar_rm + jmp com32_enter_rm + +.resume: + popad + mov eax,[word RealModeEAX] + popfd + ret + bits 16 - section .bss + section .bss1 alignb 4 +RealModeSSSP resd 1 ; Real-mode SS:SP +RealModeEAX resd 1 ; Real mode EAX PMESP resd 1 ; Protected-mode ESP Com32SysSP resw 1 ; SP saved during COM32 syscall + section .uibss +%if IS_SYSLINUX +Com32Name resb FILENAME_MAX+2 +%else +Com32Name resb FILENAME_MAX +%endif + section .text