diff options
Diffstat (limited to 'qemu/roms/openbios/arch/amd64/segment.c')
-rw-r--r-- | qemu/roms/openbios/arch/amd64/segment.c | 134 |
1 files changed, 0 insertions, 134 deletions
diff --git a/qemu/roms/openbios/arch/amd64/segment.c b/qemu/roms/openbios/arch/amd64/segment.c deleted file mode 100644 index 09763bd14..000000000 --- a/qemu/roms/openbios/arch/amd64/segment.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Segmentation of the AMD64 architecture. - * - * 2003-07 by SONE Takeshi - */ - -#include "config.h" -#include "kernel/kernel.h" -#include "libopenbios/sys_info.h" -#include "relocate.h" -#include "segment.h" - -#define printf printk -#ifdef CONFIG_DEBUG_BOOT -#define debug printk -#else -#define debug(x...) -#endif - -/* i386 lgdt argument */ -struct gdtarg { - unsigned short limit; - unsigned int base; -} __attribute__((packed)); - -/* How far the virtual address (used in C) is different from physical - * address. Since we start in flat mode, the initial value is zero. */ -unsigned long virt_offset = 0; - -/* GDT, the global descriptor table */ -struct segment_desc gdt[NUM_SEG] = { - /* 0x00: null segment */ - {0, 0, 0, 0, 0, 0}, - /* 0x08: flat code segment */ - {0xffff, 0, 0, 0x9f, 0xcf, 0}, - /* 0x10: flat data segment */ - {0xffff, 0, 0, 0x93, 0xcf, 0}, - /* 0x18: code segment for relocated execution */ - {0xffff, 0, 0, 0x9f, 0xcf, 0}, - /* 0x20: data segment for relocated execution */ - {0xffff, 0, 0, 0x93, 0xcf, 0}, -}; - -extern char _start[], _end[]; - -void relocate(struct sys_info *info) -{ - int i; - unsigned long prog_addr; - unsigned long prog_size; - unsigned long addr, new_base; - unsigned long long segsize; - unsigned long new_offset; - unsigned d0, d1, d2; - struct gdtarg gdtarg; -#define ALIGNMENT 16 - - prog_addr = virt_to_phys(&_start); - prog_size = virt_to_phys(&_end) - virt_to_phys(&_start); - debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1); - - new_base = 0; - for (i = 0; i < info->n_memranges; i++) { - if (info->memrange[i].base >= 1ULL<<32) - continue; - segsize = info->memrange[i].size; - if (info->memrange[i].base + segsize > 1ULL<<32) - segsize = (1ULL<<32) - info->memrange[i].base; - if (segsize < prog_size+ALIGNMENT) - continue; - addr = info->memrange[i].base + segsize - prog_size; - addr &= ~(ALIGNMENT-1); - if (addr >= prog_addr && addr < prog_addr + prog_size) - continue; - if (prog_addr >= addr && prog_addr < addr + prog_size) - continue; - if (addr > new_base) - new_base = addr; - } - if (new_base == 0) { - printf("Can't find address to relocate\n"); - return; - } - - debug("Relocating to %#lx-%#lx... ", - new_base, new_base + prog_size - 1); - - /* New virtual address offset */ - new_offset = new_base - (unsigned long) &_start; - - /* Tweak the GDT */ - gdt[RELOC_CODE].base_0 = (unsigned short) new_offset; - gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16); - gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24); - gdt[RELOC_DATA].base_0 = (unsigned short) new_offset; - gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16); - gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24); - - /* Load new GDT and reload segments */ - gdtarg.base = new_offset + (unsigned long) gdt; - gdtarg.limit = GDT_LIMIT; - __asm__ __volatile__ ( - "rep; movsb\n\t" /* copy everything */ - "lgdt %3\n\t" - "ljmp %4, $1f\n1:\t" - "movw %5, %%ds\n\t" - "movw %5, %%es\n\t" - "movw %5, %%fs\n\t" - "movw %5, %%gs\n\t" - "movw %5, %%ss\n" - : "=&S" (d0), "=&D" (d1), "=&c" (d2) - : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS), - "0" (&_start), "1" (new_base), "2" (prog_size)); - - virt_offset = new_offset; - debug("ok\n"); -} - -#if 0 -/* Copy GDT to new location and reload it */ -void move_gdt(unsigned long newgdt) -{ - struct gdtarg gdtarg; - - debug("Moving GDT to %#lx...", newgdt); - memcpy(phys_to_virt(newgdt), gdt, sizeof gdt); - gdtarg.base = newgdt; - gdtarg.limit = GDT_LIMIT; - debug("reloading GDT..."); - __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); - debug("reloading CS for fun..."); - __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS)); - debug("ok\n"); -} -#endif |