[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-3.0.5-testing] hvmloader: Fix ROMBIOS highmem relocation. Only SHF_ALLOC sections



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1177013189 -3600
# Node ID c7c67a1a70777b934cba17d01b7437558ef4f336
# Parent  56fa8b1f8e08b5186ad8110881f779cb13a34190
hvmloader: Fix ROMBIOS highmem relocation. Only SHF_ALLOC sections
should be relocated. SHT_NOBITS must be handled properly (space
explicitly allocated and zeroed).
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/firmware/rombios/32bit/jumptable.h     |   11 -
 tools/firmware/hvmloader/32bitbios_support.c |  157 +++++++++++++++------------
 tools/firmware/hvmloader/util.c              |   13 +-
 tools/firmware/hvmloader/util.h              |    3 
 tools/firmware/rombios/32bit/32bitbios.c     |    3 
 5 files changed, 102 insertions(+), 85 deletions(-)

diff -r 56fa8b1f8e08 -r c7c67a1a7077 
tools/firmware/hvmloader/32bitbios_support.c
--- a/tools/firmware/hvmloader/32bitbios_support.c      Thu Apr 19 19:32:10 
2007 +0100
+++ b/tools/firmware/hvmloader/32bitbios_support.c      Thu Apr 19 21:06:29 
2007 +0100
@@ -3,6 +3,9 @@
  *
  * Stefan Berger, stefanb@xxxxxxxxxx
  * Copyright (c) 2006, International Business Machines Corporation.
+ *
+ * Keir Fraser, keir@xxxxxxxxxxxxx
+ * Copyright (c) 2007, XenSource Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -28,24 +31,94 @@
 #include "config.h"
 
 #include "../rombios/32bit/32bitbios_flat.h"
-#include "../rombios/32bit/jumptable.h"
 
-/* Relocate ELF file of type ET_REL */
-static void relocate_elf(char *elfarray)
+static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
 {
     Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
     Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
-    Elf32_Sym  *syms, *sym;
-    Elf32_Rel  *rels;
-    char       *code;
-    uint32_t   *loc, fix;
-    int i, j;
+    char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
+    char *jump_table;
+    uint32_t reloc_off, reloc_size;
+    char *highbiosarea;
+    int i, jump_sec_idx = 0;
 
+    /*
+     * Step 1. General elf cleanup, and compute total relocation size.
+     */
+    reloc_off = 0;
     for ( i = 0; i < ehdr->e_shnum; i++ )
+    {
+        /* By default all section data points into elf image data array. */
         shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
 
+        if ( !strcmp(".biosjumptable", secstrings + shdr[i].sh_name) )
+        {
+            /* We do not relocate the BIOS jump table to high memory. */
+            shdr[i].sh_flags &= ~SHF_ALLOC;
+            jump_sec_idx = i;
+        }
+
+        /* Fix up a corner case of address alignment. */
+        if ( shdr[i].sh_addralign == 0 )
+            shdr[i].sh_addralign = 1;
+
+        /* Any section which contains run-time data must be relocated. */
+        if ( shdr[i].sh_flags & SHF_ALLOC )
+        {
+            uint32_t mask = shdr[i].sh_addralign - 1;
+            reloc_off = (reloc_off + mask) & ~mask;
+            reloc_off += shdr[i].sh_size;
+        }
+    }
+
+    /*
+     * Step 2. Now we know the relocation size, allocate a chunk of high mem.
+     */
+    reloc_size = reloc_off;
+    printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
+    highbiosarea = (char *)(long)e820_malloc(reloc_size);
+    BUG_ON(highbiosarea == NULL);
+    printf("  Relocating to 0x%x-0x%x ... ",
+           (uint32_t)&highbiosarea[0],
+           (uint32_t)&highbiosarea[reloc_size]);
+
+    /*
+     * Step 3. Copy run-time data into the newly-allocated high-memory chunk.
+     */
+    reloc_off = 0;
     for ( i = 0; i < ehdr->e_shnum; i++ )
     {
+        uint32_t mask = shdr[i].sh_addralign - 1;
+
+        /* Nothing to do for non-run-time sections. */
+        if ( !(shdr[i].sh_flags & SHF_ALLOC) )
+            continue;
+
+        /* Copy from old location. */
+        reloc_off = (reloc_off + mask) & ~mask;
+        if ( shdr[i].sh_type == SHT_NOBITS )
+            memset(&highbiosarea[reloc_off], 0, shdr[i].sh_size);
+        else
+            memcpy(&highbiosarea[reloc_off], (void *)shdr[i].sh_addr,
+                   shdr[i].sh_size);
+
+        /* Update address to new location. */
+        shdr[i].sh_addr = (Elf32_Addr)&highbiosarea[reloc_off];
+        reloc_off += shdr[i].sh_size;
+    }
+    BUG_ON(reloc_off != reloc_size);
+
+    /*
+     * Step 4. Perform relocations in high memory.
+     */
+    for ( i = 0; i < ehdr->e_shnum; i++ )
+    {
+        Elf32_Sym  *syms, *sym;
+        Elf32_Rel  *rels;
+        char       *code;
+        uint32_t   *loc, fix;
+        int         j;
+
         if ( shdr[i].sh_type == SHT_RELA )
             printf("Unsupported section type SHT_RELA\n");
 
@@ -74,65 +147,19 @@ static void relocate_elf(char *elfarray)
             }
         }
     }
-}
 
-/* Scan the rombios for the destination of the jump table. */
-static char *get_jump_table_start(void)
-{
-    char *bios_mem;
+    /* Step 5. Find the ROMBIOS jump-table stub and copy in the real table. */
+    for ( jump_table = (char *)ROMBIOS_BEGIN;
+          jump_table != (char *)ROMBIOS_END;
+          jump_table++ )
+        if ( !strncmp(jump_table, "___JMPT", 7) )
+            break;
+    BUG_ON(jump_table == NULL);
+    BUG_ON(jump_sec_idx == 0);
+    memcpy(jump_table, (char *)shdr[jump_sec_idx].sh_addr,
+           shdr[jump_sec_idx].sh_size);
 
-    for ( bios_mem = (char *)ROMBIOS_BEGIN;
-          bios_mem != (char *)ROMBIOS_END;
-          bios_mem++ )
-        if ( !strncmp(bios_mem, "___JMPT", 7) )
-            return bios_mem;
-
-    return NULL;
-}
-
-/* Copy relocated jumptable into the rombios. */
-static void copy_jumptable(char *elfarray)
-{
-    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
-    Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
-    char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
-    char *jump_table = get_jump_table_start();
-    int i;
-
-    /* Find the section with the jump table and copy to lower BIOS memory. */
-    for ( i = 0; i < ehdr->e_shnum; i++ )
-        if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
-            break;
-
-    if ( i == ehdr->e_shnum )
-    {
-        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
-        return;
-    }
-
-    if ( jump_table == NULL )
-    {
-        printf("Could not find jump table in file.\n");
-        return;
-    }
-
-    memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size);
-}
-
-static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
-{
-    char *highbiosarea;
-
-    highbiosarea = (char *)(long)e820_malloc(elfarraysize);
-    if ( highbiosarea == NULL )
-    {
-        printf("No available memory for BIOS high memory area\n");
-        return;
-    }
-
-    memcpy(highbiosarea, elfarray, elfarraysize);
-    relocate_elf(highbiosarea);
-    copy_jumptable(highbiosarea);
+    printf("done\n");
 }
 
 void highbios_setup(void)
diff -r 56fa8b1f8e08 -r c7c67a1a7077 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Thu Apr 19 19:32:10 2007 +0100
+++ b/tools/firmware/hvmloader/util.c   Thu Apr 19 21:06:29 2007 +0100
@@ -335,12 +335,13 @@ uint32_t e820_malloc(uint32_t size)
         ent[i].addr = addr;
         ent[i].size = size;
         ent[i].type = E820_RESERVED;
-        break;
-    }
-
-    e820_collapse();
-
-    return addr;
+
+        e820_collapse();
+
+        return addr;
+    }
+
+    return 0;
 }
 
 uint32_t ioapic_read(uint32_t reg)
diff -r 56fa8b1f8e08 -r c7c67a1a7077 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Thu Apr 19 19:32:10 2007 +0100
+++ b/tools/firmware/hvmloader/util.h   Thu Apr 19 21:06:29 2007 +0100
@@ -14,7 +14,8 @@ extern void __assert_failed(char *assert
 #define ASSERT(p) \
     do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
 extern void __bug(char *file, int line) __attribute__((noreturn));
-#define BUG() __bug()
+#define BUG() __bug(__FILE__, __LINE__)
+#define BUG_ON(p) do { if (p) BUG(); } while (0)
 
 /* I/O output */
 void outb(uint16_t addr, uint8_t  val);
diff -r 56fa8b1f8e08 -r c7c67a1a7077 tools/firmware/rombios/32bit/32bitbios.c
--- a/tools/firmware/rombios/32bit/32bitbios.c  Thu Apr 19 19:32:10 2007 +0100
+++ b/tools/firmware/rombios/32bit/32bitbios.c  Thu Apr 19 21:06:29 2007 +0100
@@ -20,7 +20,6 @@
  * Author: Stefan Berger <stefanb@xxxxxxxxxx>
  */
 #include "rombios_compat.h"
-#include "jumptable.h"
 #include "32bitprotos.h"
 
 /*
@@ -29,7 +28,7 @@
    here.
  */
 #define TABLE_ENTRY(idx, func) [idx] = (uint32_t)func
-uint32_t jumptable[IDX_LAST+1] __attribute__((section 
(JUMPTABLE_SECTION_NAME))) =
+uint32_t jumptable[IDX_LAST+1] __attribute__((section (".biosjumptable"))) =
 {
        TABLE_ENTRY(IDX_TCPA_ACPI_INIT, tcpa_acpi_init),
        TABLE_ENTRY(IDX_TCPA_EXTEND_ACPI_LOG, tcpa_extend_acpi_log),
diff -r 56fa8b1f8e08 -r c7c67a1a7077 tools/firmware/rombios/32bit/jumptable.h
--- a/tools/firmware/rombios/32bit/jumptable.h  Thu Apr 19 19:32:10 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-#ifndef JUMPTABLE_H
-#define JUMPTABLE_H
-
-/*
-   name of the section the 32bit BIOS must have and where the array of
-   function poiners is built; hvmloader looks for this section and copies
-   it into the lower BIOS in the 0xf000 segment
- */
-#define JUMPTABLE_SECTION_NAME ".biosjumptable"
-
-#endif

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.