| /* |
| * Functions to support the virtual addressing method of relocation |
| * that Etherboot uses. |
| * |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER ) |
| |
| #include "librm.h" |
| |
| .arch i386 |
| .text |
| .code32 |
| |
| /**************************************************************************** |
| * _virt_to_phys (virtual addressing) |
| * |
| * Switch from virtual to flat physical addresses. %esp is adjusted |
| * to a physical value. Segment registers are set to flat physical |
| * selectors. All other registers are preserved. Flags are |
| * preserved. |
| * |
| * Parameters: none |
| * Returns: none |
| **************************************************************************** |
| */ |
| .globl _virt_to_phys |
| _virt_to_phys: |
| /* Preserve registers and flags */ |
| pushfl |
| pushl %eax |
| pushl %ebp |
| |
| /* Change return address to a physical address */ |
| movl virt_offset, %ebp |
| addl %ebp, 12(%esp) |
| |
| /* Switch to physical code segment */ |
| pushl $PHYSICAL_CS |
| leal 1f(%ebp), %eax |
| pushl %eax |
| lret |
| 1: |
| /* Reload other segment registers and adjust %esp */ |
| movl $PHYSICAL_DS, %eax |
| movl %eax, %ds |
| movl %eax, %es |
| movl %eax, %fs |
| movl %eax, %gs |
| movl %eax, %ss |
| addl %ebp, %esp |
| |
| /* Restore registers and flags, and return */ |
| popl %ebp |
| popl %eax |
| popfl |
| ret |
| |
| /**************************************************************************** |
| * _phys_to_virt (flat physical addressing) |
| * |
| * Switch from flat physical to virtual addresses. %esp is adjusted |
| * to a virtual value. Segment registers are set to virtual |
| * selectors. All other registers are preserved. Flags are |
| * preserved. |
| * |
| * Note that this depends on the GDT already being correctly set up |
| * (e.g. by a call to run_here()). |
| * |
| * Parameters: none |
| * Returns: none |
| **************************************************************************** |
| */ |
| .globl _phys_to_virt |
| _phys_to_virt: |
| /* Preserve registers and flags */ |
| pushfl |
| pushl %eax |
| pushl %ebp |
| |
| /* Switch to virtual code segment */ |
| ljmp $VIRTUAL_CS, $1f |
| 1: |
| /* Reload data segment registers */ |
| movl $VIRTUAL_DS, %eax |
| movl %eax, %ds |
| movl %eax, %es |
| movl %eax, %fs |
| movl %eax, %gs |
| |
| /* Reload stack segment and adjust %esp */ |
| movl virt_offset, %ebp |
| movl %eax, %ss |
| subl %ebp, %esp |
| |
| /* Change the return address to a virtual address */ |
| subl %ebp, 12(%esp) |
| |
| /* Restore registers and flags, and return */ |
| popl %ebp |
| popl %eax |
| popfl |
| ret |