.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
#endif /* KEEP_IT_REAL */
/****************************************************************************
- * copy_bytes (real-mode or 16-bit protected-mode near call)
+ * copy_bytes
*
* Copy bytes
*
* None
****************************************************************************
*/
+#if ! COMPRESS
.section ".prefix.lib", "awx", @progbits
.code16
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
*
.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
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
.size alloc_basemem, . - alloc_basemem
/****************************************************************************
- * free_basemem (real-mode near call)
+ * free_basemem
*
* Free space allocated with alloc_basemem.
*
.size hooked_bios_interrupts, . - hooked_bios_interrupts
/****************************************************************************
- * install (real-mode near call)
+ * install
*
* Install all text and data segments.
*
.size install, . - install
/****************************************************************************
- * install_prealloc (real-mode near call)
+ * install_prealloc
*
* Install all text and data segments.
*
/* 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
/* 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
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:
#endif
/****************************************************************************
- * uninstall (real-mode near call)
+ * uninstall
*
* Uninstall all text and data segments.
*