ia64/xen-unstable

changeset 14882:c7c67a1a7077

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@xensource.com>
author Keir Fraser <keir@xensource.com>
date Thu Apr 19 21:06:29 2007 +0100 (2007-04-19)
parents 56fa8b1f8e08
children efdbf87d4741
files tools/firmware/hvmloader/32bitbios_support.c tools/firmware/hvmloader/util.c tools/firmware/hvmloader/util.h tools/firmware/rombios/32bit/32bitbios.c tools/firmware/rombios/32bit/jumptable.h
line diff
     1.1 --- a/tools/firmware/hvmloader/32bitbios_support.c	Thu Apr 19 19:32:10 2007 +0100
     1.2 +++ b/tools/firmware/hvmloader/32bitbios_support.c	Thu Apr 19 21:06:29 2007 +0100
     1.3 @@ -4,6 +4,9 @@
     1.4   * Stefan Berger, stefanb@us.ibm.com
     1.5   * Copyright (c) 2006, International Business Machines Corporation.
     1.6   *
     1.7 + * Keir Fraser, keir@xensource.com
     1.8 + * Copyright (c) 2007, XenSource Inc.
     1.9 + *
    1.10   * This program is free software; you can redistribute it and/or modify it
    1.11   * under the terms and conditions of the GNU General Public License,
    1.12   * version 2, as published by the Free Software Foundation.
    1.13 @@ -28,24 +31,94 @@
    1.14  #include "config.h"
    1.15  
    1.16  #include "../rombios/32bit/32bitbios_flat.h"
    1.17 -#include "../rombios/32bit/jumptable.h"
    1.18  
    1.19 -/* Relocate ELF file of type ET_REL */
    1.20 -static void relocate_elf(char *elfarray)
    1.21 +static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
    1.22  {
    1.23      Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
    1.24      Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
    1.25 -    Elf32_Sym  *syms, *sym;
    1.26 -    Elf32_Rel  *rels;
    1.27 -    char       *code;
    1.28 -    uint32_t   *loc, fix;
    1.29 -    int i, j;
    1.30 +    char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
    1.31 +    char *jump_table;
    1.32 +    uint32_t reloc_off, reloc_size;
    1.33 +    char *highbiosarea;
    1.34 +    int i, jump_sec_idx = 0;
    1.35  
    1.36 +    /*
    1.37 +     * Step 1. General elf cleanup, and compute total relocation size.
    1.38 +     */
    1.39 +    reloc_off = 0;
    1.40      for ( i = 0; i < ehdr->e_shnum; i++ )
    1.41 +    {
    1.42 +        /* By default all section data points into elf image data array. */
    1.43          shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
    1.44  
    1.45 +        if ( !strcmp(".biosjumptable", secstrings + shdr[i].sh_name) )
    1.46 +        {
    1.47 +            /* We do not relocate the BIOS jump table to high memory. */
    1.48 +            shdr[i].sh_flags &= ~SHF_ALLOC;
    1.49 +            jump_sec_idx = i;
    1.50 +        }
    1.51 +
    1.52 +        /* Fix up a corner case of address alignment. */
    1.53 +        if ( shdr[i].sh_addralign == 0 )
    1.54 +            shdr[i].sh_addralign = 1;
    1.55 +
    1.56 +        /* Any section which contains run-time data must be relocated. */
    1.57 +        if ( shdr[i].sh_flags & SHF_ALLOC )
    1.58 +        {
    1.59 +            uint32_t mask = shdr[i].sh_addralign - 1;
    1.60 +            reloc_off = (reloc_off + mask) & ~mask;
    1.61 +            reloc_off += shdr[i].sh_size;
    1.62 +        }
    1.63 +    }
    1.64 +
    1.65 +    /*
    1.66 +     * Step 2. Now we know the relocation size, allocate a chunk of high mem.
    1.67 +     */
    1.68 +    reloc_size = reloc_off;
    1.69 +    printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
    1.70 +    highbiosarea = (char *)(long)e820_malloc(reloc_size);
    1.71 +    BUG_ON(highbiosarea == NULL);
    1.72 +    printf("  Relocating to 0x%x-0x%x ... ",
    1.73 +           (uint32_t)&highbiosarea[0],
    1.74 +           (uint32_t)&highbiosarea[reloc_size]);
    1.75 +
    1.76 +    /*
    1.77 +     * Step 3. Copy run-time data into the newly-allocated high-memory chunk.
    1.78 +     */
    1.79 +    reloc_off = 0;
    1.80      for ( i = 0; i < ehdr->e_shnum; i++ )
    1.81      {
    1.82 +        uint32_t mask = shdr[i].sh_addralign - 1;
    1.83 +
    1.84 +        /* Nothing to do for non-run-time sections. */
    1.85 +        if ( !(shdr[i].sh_flags & SHF_ALLOC) )
    1.86 +            continue;
    1.87 +
    1.88 +        /* Copy from old location. */
    1.89 +        reloc_off = (reloc_off + mask) & ~mask;
    1.90 +        if ( shdr[i].sh_type == SHT_NOBITS )
    1.91 +            memset(&highbiosarea[reloc_off], 0, shdr[i].sh_size);
    1.92 +        else
    1.93 +            memcpy(&highbiosarea[reloc_off], (void *)shdr[i].sh_addr,
    1.94 +                   shdr[i].sh_size);
    1.95 +
    1.96 +        /* Update address to new location. */
    1.97 +        shdr[i].sh_addr = (Elf32_Addr)&highbiosarea[reloc_off];
    1.98 +        reloc_off += shdr[i].sh_size;
    1.99 +    }
   1.100 +    BUG_ON(reloc_off != reloc_size);
   1.101 +
   1.102 +    /*
   1.103 +     * Step 4. Perform relocations in high memory.
   1.104 +     */
   1.105 +    for ( i = 0; i < ehdr->e_shnum; i++ )
   1.106 +    {
   1.107 +        Elf32_Sym  *syms, *sym;
   1.108 +        Elf32_Rel  *rels;
   1.109 +        char       *code;
   1.110 +        uint32_t   *loc, fix;
   1.111 +        int         j;
   1.112 +
   1.113          if ( shdr[i].sh_type == SHT_RELA )
   1.114              printf("Unsupported section type SHT_RELA\n");
   1.115  
   1.116 @@ -74,65 +147,19 @@ static void relocate_elf(char *elfarray)
   1.117              }
   1.118          }
   1.119      }
   1.120 -}
   1.121 -
   1.122 -/* Scan the rombios for the destination of the jump table. */
   1.123 -static char *get_jump_table_start(void)
   1.124 -{
   1.125 -    char *bios_mem;
   1.126 -
   1.127 -    for ( bios_mem = (char *)ROMBIOS_BEGIN;
   1.128 -          bios_mem != (char *)ROMBIOS_END;
   1.129 -          bios_mem++ )
   1.130 -        if ( !strncmp(bios_mem, "___JMPT", 7) )
   1.131 -            return bios_mem;
   1.132 -
   1.133 -    return NULL;
   1.134 -}
   1.135 -
   1.136 -/* Copy relocated jumptable into the rombios. */
   1.137 -static void copy_jumptable(char *elfarray)
   1.138 -{
   1.139 -    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
   1.140 -    Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
   1.141 -    char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
   1.142 -    char *jump_table = get_jump_table_start();
   1.143 -    int i;
   1.144 -
   1.145 -    /* Find the section with the jump table and copy to lower BIOS memory. */
   1.146 -    for ( i = 0; i < ehdr->e_shnum; i++ )
   1.147 -        if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
   1.148 -            break;
   1.149  
   1.150 -    if ( i == ehdr->e_shnum )
   1.151 -    {
   1.152 -        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
   1.153 -        return;
   1.154 -    }
   1.155 -
   1.156 -    if ( jump_table == NULL )
   1.157 -    {
   1.158 -        printf("Could not find jump table in file.\n");
   1.159 -        return;
   1.160 -    }
   1.161 -
   1.162 -    memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size);
   1.163 -}
   1.164 +    /* Step 5. Find the ROMBIOS jump-table stub and copy in the real table. */
   1.165 +    for ( jump_table = (char *)ROMBIOS_BEGIN;
   1.166 +          jump_table != (char *)ROMBIOS_END;
   1.167 +          jump_table++ )
   1.168 +        if ( !strncmp(jump_table, "___JMPT", 7) )
   1.169 +            break;
   1.170 +    BUG_ON(jump_table == NULL);
   1.171 +    BUG_ON(jump_sec_idx == 0);
   1.172 +    memcpy(jump_table, (char *)shdr[jump_sec_idx].sh_addr,
   1.173 +           shdr[jump_sec_idx].sh_size);
   1.174  
   1.175 -static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
   1.176 -{
   1.177 -    char *highbiosarea;
   1.178 -
   1.179 -    highbiosarea = (char *)(long)e820_malloc(elfarraysize);
   1.180 -    if ( highbiosarea == NULL )
   1.181 -    {
   1.182 -        printf("No available memory for BIOS high memory area\n");
   1.183 -        return;
   1.184 -    }
   1.185 -
   1.186 -    memcpy(highbiosarea, elfarray, elfarraysize);
   1.187 -    relocate_elf(highbiosarea);
   1.188 -    copy_jumptable(highbiosarea);
   1.189 +    printf("done\n");
   1.190  }
   1.191  
   1.192  void highbios_setup(void)
     2.1 --- a/tools/firmware/hvmloader/util.c	Thu Apr 19 19:32:10 2007 +0100
     2.2 +++ b/tools/firmware/hvmloader/util.c	Thu Apr 19 21:06:29 2007 +0100
     2.3 @@ -335,12 +335,13 @@ uint32_t e820_malloc(uint32_t size)
     2.4          ent[i].addr = addr;
     2.5          ent[i].size = size;
     2.6          ent[i].type = E820_RESERVED;
     2.7 -        break;
     2.8 +
     2.9 +        e820_collapse();
    2.10 +
    2.11 +        return addr;
    2.12      }
    2.13  
    2.14 -    e820_collapse();
    2.15 -
    2.16 -    return addr;
    2.17 +    return 0;
    2.18  }
    2.19  
    2.20  uint32_t ioapic_read(uint32_t reg)
     3.1 --- a/tools/firmware/hvmloader/util.h	Thu Apr 19 19:32:10 2007 +0100
     3.2 +++ b/tools/firmware/hvmloader/util.h	Thu Apr 19 21:06:29 2007 +0100
     3.3 @@ -14,7 +14,8 @@ extern void __assert_failed(char *assert
     3.4  #define ASSERT(p) \
     3.5      do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
     3.6  extern void __bug(char *file, int line) __attribute__((noreturn));
     3.7 -#define BUG() __bug()
     3.8 +#define BUG() __bug(__FILE__, __LINE__)
     3.9 +#define BUG_ON(p) do { if (p) BUG(); } while (0)
    3.10  
    3.11  /* I/O output */
    3.12  void outb(uint16_t addr, uint8_t  val);
     4.1 --- a/tools/firmware/rombios/32bit/32bitbios.c	Thu Apr 19 19:32:10 2007 +0100
     4.2 +++ b/tools/firmware/rombios/32bit/32bitbios.c	Thu Apr 19 21:06:29 2007 +0100
     4.3 @@ -20,7 +20,6 @@
     4.4   * Author: Stefan Berger <stefanb@us.ibm.com>
     4.5   */
     4.6  #include "rombios_compat.h"
     4.7 -#include "jumptable.h"
     4.8  #include "32bitprotos.h"
     4.9  
    4.10  /*
    4.11 @@ -29,7 +28,7 @@
    4.12     here.
    4.13   */
    4.14  #define TABLE_ENTRY(idx, func) [idx] = (uint32_t)func
    4.15 -uint32_t jumptable[IDX_LAST+1] __attribute__((section (JUMPTABLE_SECTION_NAME))) =
    4.16 +uint32_t jumptable[IDX_LAST+1] __attribute__((section (".biosjumptable"))) =
    4.17  {
    4.18  	TABLE_ENTRY(IDX_TCPA_ACPI_INIT, tcpa_acpi_init),
    4.19  	TABLE_ENTRY(IDX_TCPA_EXTEND_ACPI_LOG, tcpa_extend_acpi_log),
     5.1 --- a/tools/firmware/rombios/32bit/jumptable.h	Thu Apr 19 19:32:10 2007 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,11 +0,0 @@
     5.4 -#ifndef JUMPTABLE_H
     5.5 -#define JUMPTABLE_H
     5.6 -
     5.7 -/*
     5.8 -   name of the section the 32bit BIOS must have and where the array of
     5.9 -   function poiners is built; hvmloader looks for this section and copies
    5.10 -   it into the lower BIOS in the 0xf000 segment
    5.11 - */
    5.12 -#define JUMPTABLE_SECTION_NAME ".biosjumptable"
    5.13 -
    5.14 -#endif