From a4920c16bd1bff5d0edfbc2b88dcabc5aa546489 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 9 Apr 2005 10:49:26 +0000 Subject: Moved relocate.c to arch-specific dir, since it involves arch-specific logic (e.g. avoiding memory regions with A20=0). --- src/arch/i386/core/relocate.c | 104 ++++++++++++++++++++++++++++++++++++++++++ src/core/relocate.c | 104 ------------------------------------------ 2 files changed, 104 insertions(+), 104 deletions(-) create mode 100644 src/arch/i386/core/relocate.c delete mode 100644 src/core/relocate.c (limited to 'src') diff --git a/src/arch/i386/core/relocate.c b/src/arch/i386/core/relocate.c new file mode 100644 index 000000000..436432e5c --- /dev/null +++ b/src/arch/i386/core/relocate.c @@ -0,0 +1,104 @@ +#ifndef NORELOCATE + +#include "etherboot.h" +#include "memsizes.h" + +/* by Eric Biederman */ + +/* On some platforms etherboot is compiled as a shared library, and we use + * the ELF pic support to make it relocateable. This works very nicely + * for code, but since no one has implemented PIC data yet pointer + * values in variables are a a problem. Global variables are a + * pain but the return addresses on the stack are the worst. On these + * platforms relocate_to will restart etherboot, to ensure the stack + * is reinitialize and hopefully get the global variables + * appropriately reinitialized as well. + * + */ + +void relocate(void) +{ + unsigned long addr, eaddr, size; + unsigned i; + /* Walk through the memory map and find the highest address + * below 4GB that etherboot will fit into. Ensure etherboot + * lies entirely within a range with A20=0. This means that + * even if something screws up the state of the A20 line, the + * etherboot code is still visible and we have a chance to + * diagnose the problem. + */ + /* First find the size of etherboot */ + addr = virt_to_phys(_text); + eaddr = virt_to_phys(_end); + size = (eaddr - addr + 0xf) & ~0xf; + + /* If the current etherboot is beyond MAX_ADDR pretend it is + * at the lowest possible address. + */ + if (eaddr > MAX_ADDR) { + eaddr = 0; + } + + for(i = 0; i < meminfo.map_count; i++) { + unsigned long r_start, r_end; + if (meminfo.map[i].type != E820_RAM) { + continue; + } + if (meminfo.map[i].addr > MAX_ADDR) { + continue; + } + if (meminfo.map[i].size > MAX_ADDR) { + continue; + } + r_start = meminfo.map[i].addr; + r_end = r_start + meminfo.map[i].size; + /* Make the addresses 16 byte (128 bit) aligned */ + r_start = (r_start + 15) & ~15; + r_end = r_end & ~15; + if (r_end < r_start) { + r_end = MAX_ADDR; + } + if (r_end < size) { + /* Avoid overflow weirdness when r_end - size < 0 */ + continue; + } + /* Shrink the range down to use only even megabytes + * (i.e. A20=0). + */ + if ( r_end & 0x100000 ) { + /* If r_end is in an odd megabyte, round down + * r_end to the top of the next even megabyte. + */ + r_end = r_end & ~0xfffff; + } else if ( ( r_end - size ) & 0x100000 ) { + /* If r_end is in an even megabyte, but the + * start of Etherboot would be in an odd + * megabyte, round down to the top of the next + * even megabyte. + */ + r_end = ( r_end - 0x100000 ) & ~0xfffff; + } + /* If we have rounded down r_end below r_ start, skip + * this block. + */ + if ( r_end < r_start ) { + continue; + } + if (eaddr < r_end - size) { + addr = r_end - size; + eaddr = r_end; + } + } + if (addr != virt_to_phys(_text)) { + unsigned long old_addr = virt_to_phys(_text); + printf("Relocating _text from: [%lx,%lx) to [%lx,%lx)\n", + old_addr, virt_to_phys(_end), + addr, eaddr); + /* arch_relocate_to ( addr ) */ + cleanup(); + relocate_to(addr); + /* arch_relocated_from ( addr ) */ + } +} + +#endif /* NORELOCATE */ diff --git a/src/core/relocate.c b/src/core/relocate.c deleted file mode 100644 index 436432e5c..000000000 --- a/src/core/relocate.c +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef NORELOCATE - -#include "etherboot.h" -#include "memsizes.h" - -/* by Eric Biederman */ - -/* On some platforms etherboot is compiled as a shared library, and we use - * the ELF pic support to make it relocateable. This works very nicely - * for code, but since no one has implemented PIC data yet pointer - * values in variables are a a problem. Global variables are a - * pain but the return addresses on the stack are the worst. On these - * platforms relocate_to will restart etherboot, to ensure the stack - * is reinitialize and hopefully get the global variables - * appropriately reinitialized as well. - * - */ - -void relocate(void) -{ - unsigned long addr, eaddr, size; - unsigned i; - /* Walk through the memory map and find the highest address - * below 4GB that etherboot will fit into. Ensure etherboot - * lies entirely within a range with A20=0. This means that - * even if something screws up the state of the A20 line, the - * etherboot code is still visible and we have a chance to - * diagnose the problem. - */ - /* First find the size of etherboot */ - addr = virt_to_phys(_text); - eaddr = virt_to_phys(_end); - size = (eaddr - addr + 0xf) & ~0xf; - - /* If the current etherboot is beyond MAX_ADDR pretend it is - * at the lowest possible address. - */ - if (eaddr > MAX_ADDR) { - eaddr = 0; - } - - for(i = 0; i < meminfo.map_count; i++) { - unsigned long r_start, r_end; - if (meminfo.map[i].type != E820_RAM) { - continue; - } - if (meminfo.map[i].addr > MAX_ADDR) { - continue; - } - if (meminfo.map[i].size > MAX_ADDR) { - continue; - } - r_start = meminfo.map[i].addr; - r_end = r_start + meminfo.map[i].size; - /* Make the addresses 16 byte (128 bit) aligned */ - r_start = (r_start + 15) & ~15; - r_end = r_end & ~15; - if (r_end < r_start) { - r_end = MAX_ADDR; - } - if (r_end < size) { - /* Avoid overflow weirdness when r_end - size < 0 */ - continue; - } - /* Shrink the range down to use only even megabytes - * (i.e. A20=0). - */ - if ( r_end & 0x100000 ) { - /* If r_end is in an odd megabyte, round down - * r_end to the top of the next even megabyte. - */ - r_end = r_end & ~0xfffff; - } else if ( ( r_end - size ) & 0x100000 ) { - /* If r_end is in an even megabyte, but the - * start of Etherboot would be in an odd - * megabyte, round down to the top of the next - * even megabyte. - */ - r_end = ( r_end - 0x100000 ) & ~0xfffff; - } - /* If we have rounded down r_end below r_ start, skip - * this block. - */ - if ( r_end < r_start ) { - continue; - } - if (eaddr < r_end - size) { - addr = r_end - size; - eaddr = r_end; - } - } - if (addr != virt_to_phys(_text)) { - unsigned long old_addr = virt_to_phys(_text); - printf("Relocating _text from: [%lx,%lx) to [%lx,%lx)\n", - old_addr, virt_to_phys(_end), - addr, eaddr); - /* arch_relocate_to ( addr ) */ - cleanup(); - relocate_to(addr); - /* arch_relocated_from ( addr ) */ - } -} - -#endif /* NORELOCATE */ -- cgit v1.2.3-55-g7522