diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index ecef56d8..4decb013 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -233,156 +233,128 @@ print_kill_line: .size print_kill_line, . - print_kill_line /**************************************************************************** - * pm_call (real-mode near call) + * flatten_real_mode * - * Call routine in 16-bit protected mode for access to extended memory + * Set up 4GB segment limits * * Parameters: - * %ax : address of routine to call in 16-bit protected mode + * none * Returns: * none * Corrupts: - * %ax - * - * The specified routine is called in 16-bit protected mode, with: - * - * %cs : 16-bit code segment with base matching real-mode %cs - * %ss : 16-bit data segment with base matching real-mode %ss - * %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit - * + * none **************************************************************************** */ - #ifndef KEEP_IT_REAL /* GDT for protected-mode calls */ .section ".prefix.lib", "awx", @progbits .align 16 -pm_call_vars: -gdt: -gdt_limit: .word gdt_length - 1 -gdt_base: .long 0 +flatten_vars: +flatten_gdt: +flatten_gdt_limit: .word flatten_gdt_length - 1 +flatten_gdt_base: .long 0 .word 0 /* padding */ -pm_cs: /* 16-bit protected-mode flat code segment */ - .equ PM_CS, pm_cs - gdt +flatten_cs: /* 16-bit protected-mode flat code segment */ + .equ FLAT_CS, flatten_cs - flatten_gdt .word 0xffff, 0 .byte 0, 0x9b, 0x8f, 0 -pm_ss: /* 16-bit protected-mode flat stack segment */ - .equ PM_SS, pm_ss - gdt +flatten_ss: /* 16-bit protected-mode flat stack segment */ + .equ FLAT_SS, flatten_ss - flatten_gdt .word 0xffff, 0 .byte 0, 0x93, 0x8f, 0 -pm_ds: /* 32-bit protected-mode flat data segment */ - .equ PM_DS, pm_ds - gdt - .word 0xffff, 0 - .byte 0, 0x93, 0xcf, 0 -gdt_end: - .equ gdt_length, . - gdt - .size gdt, . - gdt +flatten_gdt_end: + .equ flatten_gdt_length, . - flatten_gdt + .size flatten_gdt, . - flatten_gdt .section ".prefix.lib", "awx", @progbits .align 16 -pm_saved_gdt: +flatten_saved_gdt: .long 0, 0 - .size pm_saved_gdt, . - pm_saved_gdt + .size flatten_saved_gdt, . - flatten_saved_gdt - .equ pm_call_vars_size, . - pm_call_vars -#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) ) + .equ flatten_vars_size, . - flatten_vars +#define FLATTEN_VAR(x) ( -flatten_vars_size + ( (x) - flatten_vars ) ) .section ".prefix.lib", "awx", @progbits .code16 -pm_call: - /* Preserve registers, flags, and RM return point */ +flatten_real_mode: + /* Preserve registers and flags, allocate local variable block */ pushw %bp movw %sp, %bp - subw $pm_call_vars_size, %sp + subw $flatten_vars_size, %sp andw $0xfff0, %sp pushfl + pushl %eax + pushl %edi + pushw %si + pushw %cx pushw %gs pushw %fs pushw %es pushw %ds pushw %ss - pushw %cs - pushw $99f - /* Set up local variable block, and preserve GDT */ - pushw %cx - pushw %si - pushw %di + /* Fill local variable block and preserve GDT */ pushw %ss popw %es - movw $pm_call_vars, %si - leaw PM_CALL_VAR(pm_call_vars)(%bp), %di - movw $pm_call_vars_size, %cx + movw $flatten_vars, %si + leaw FLATTEN_VAR(flatten_vars)(%bp), %di + movw $flatten_vars_size, %cx cs rep movsb - popw %di - popw %si - popw %cx - sgdt PM_CALL_VAR(pm_saved_gdt)(%bp) + sgdt FLATTEN_VAR(flatten_saved_gdt)(%bp) /* Set up GDT bases */ - pushl %eax - pushl %edi xorl %eax, %eax movw %ss, %ax shll $4, %eax movzwl %bp, %edi - addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax - movl %eax, PM_CALL_VAR(gdt_base)(%bp) + addr32 leal FLATTEN_VAR(flatten_gdt)(%eax, %edi), %eax + movl %eax, FLATTEN_VAR(flatten_gdt_base)(%bp) movw %cs, %ax - movw $PM_CALL_VAR(pm_cs), %di + movw $FLATTEN_VAR(flatten_cs), %di call set_seg_base movw %ss, %ax - movw $PM_CALL_VAR(pm_ss), %di + movw $FLATTEN_VAR(flatten_ss), %di call set_seg_base - popl %edi - popl %eax - /* Switch CPU to protected mode and load up segment registers */ - pushl %eax + /* Switch temporarily to protected mode and set segment registers */ + pushw %cs + pushw $2f cli - data32 lgdt PM_CALL_VAR(gdt)(%bp) + data32 lgdt FLATTEN_VAR(flatten_gdt)(%bp) movl %cr0, %eax orb $CR0_PE, %al movl %eax, %cr0 - ljmp $PM_CS, $1f -1: movw $PM_SS, %ax + ljmp $FLAT_CS, $1f +1: movw $FLAT_SS, %ax movw %ax, %ss - movw $PM_DS, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs - popl %eax - - /* Call PM routine */ - call *%ax - - /* Set real-mode segment limits on %ds, %es, %fs and %gs */ - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - - /* Return CPU to real mode */ movl %cr0, %eax andb $0!CR0_PE, %al movl %eax, %cr0 + lret +2: /* lret will ljmp to here */ - /* Restore registers and flags */ - lret /* will ljmp to 99f */ -99: popw %ss + /* Restore GDT, registers and flags */ + data32 lgdt FLATTEN_VAR(flatten_saved_gdt)(%bp) + popw %ss popw %ds popw %es popw %fs popw %gs - data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp) + popw %cx + popw %si + popl %edi + popl %eax popfl movw %bp, %sp popw %bp ret - .size pm_call, . - pm_call + .size flatten_real_mode, . - flatten_real_mode set_seg_base: rolw $4, %ax @@ -396,7 +368,7 @@ set_seg_base: #endif /* KEEP_IT_REAL */ /**************************************************************************** - * copy_bytes (real-mode or 16-bit protected-mode near call) + * copy_bytes * * Copy bytes * @@ -411,6 +383,7 @@ set_seg_base: * None **************************************************************************** */ +#if ! COMPRESS .section ".prefix.lib", "awx", @progbits .code16 copy_bytes: @@ -419,9 +392,10 @@ copy_bytes: popl %ecx ret .size copy_bytes, . - copy_bytes +#endif /* COMPRESS */ /**************************************************************************** - * install_block (real-mode near call) + * install_block * * Install block to specified address * @@ -439,39 +413,22 @@ copy_bytes: .section ".prefix.lib", "awx", @progbits .code16 install_block: - -#ifdef KEEP_IT_REAL - /* Preserve registers */ pushw %ds pushw %es pushl %ecx pushl %edi - /* Convert %esi and %edi to segment registers */ + /* Convert %esi and %edi to %ds:esi and %es:edi */ shrl $4, %esi movw %si, %ds xorw %si, %si + shll $4, %esi shrl $4, %edi movw %di, %es xorw %di, %di + shll $4, %edi -#else /* KEEP_IT_REAL */ - - /* Call self in protected mode */ - pushw %ax - movw $1f, %ax - call pm_call - popw %ax - ret -1: - /* Preserve registers */ - pushl %ecx - pushl %edi - -#endif /* KEEP_IT_REAL */ - - #if COMPRESS /* Decompress source to destination */ call decompress16 @@ -492,33 +449,22 @@ install_block: addl $0xf, %esi andl $~0xf, %esi - -#ifdef KEEP_IT_REAL - /* Convert %ds:esi back to a physical address */ - movzwl %ds, %cx + xorl %ecx, %ecx + movw %ds, %cx shll $4, %ecx addl %ecx, %esi - /* Restore registers */ + /* Restore registers and return */ popl %edi popl %ecx popw %es popw %ds - -#else /* KEEP_IT_REAL */ - - /* Restore registers */ - popl %edi - popl %ecx - -#endif - ret .size install_block, . - install_block - + /**************************************************************************** - * alloc_basemem (real-mode near call) + * alloc_basemem * * Allocate space for .text16 and .data16 from top of base memory. * Memory is allocated using the BIOS free base memory counter at @@ -568,7 +514,7 @@ alloc_basemem: .size alloc_basemem, . - alloc_basemem /**************************************************************************** - * free_basemem (real-mode near call) + * free_basemem * * Free space allocated with alloc_basemem. * @@ -620,7 +566,7 @@ hooked_bios_interrupts: .size hooked_bios_interrupts, . - hooked_bios_interrupts /**************************************************************************** - * install (real-mode near call) + * install * * Install all text and data segments. * @@ -655,7 +601,7 @@ install: .size install, . - install /**************************************************************************** - * install_prealloc (real-mode near call) + * install_prealloc * * Install all text and data segments. * @@ -680,6 +626,11 @@ install_prealloc: /* Sanity: clear the direction flag asap */ cld +#ifndef KEEP_IT_REAL + /* Flatten real mode */ + call flatten_real_mode +#endif + /* Calculate physical address of payload (i.e. first source) */ testl %esi, %esi jnz 1f @@ -732,16 +683,15 @@ install_prealloc: /* Copy code to new location */ pushl %edi - pushw %ax - movw $copy_bytes, %ax - call pm_call - popw %ax + xorw %ax, %ax + movw %ax, %es + es rep addr32 movsb popl %edi /* Initialise librm at new location */ lcall *init_librm_vector - #endif + /* Restore registers */ popw %es popw %ds @@ -749,7 +699,9 @@ install_prealloc: ret .size install_prealloc, . - install_prealloc - /* Vectors for far calls to .text16 functions */ + /* Vectors for far calls to .text16 functions. Must be in + * .data16, since .prefix may not be writable. + */ .section ".data16", "aw", @progbits #ifdef KEEP_IT_REAL init_libkir_vector: @@ -768,7 +720,7 @@ prot_call_vector: #endif /**************************************************************************** - * uninstall (real-mode near call) + * uninstall * * Uninstall all text and data segments. *