debuggers.hg

view tools/firmware/hvmloader/32bitbios_support.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 790c2f0eaf7c
line source
1 /*
2 * 32bitbios_support.c - relocation of 32bit BIOS implementation
3 *
4 * Stefan Berger, stefanb@us.ibm.com
5 * Copyright (c) 2006, International Business Machines Corporation.
6 *
7 * Keir Fraser, keir@xensource.com
8 * Copyright (c) 2007, XenSource Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms and conditions of the GNU General Public License,
12 * version 2, as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 * Place - Suite 330, Boston, MA 02111-1307 USA.
22 */
24 #include <inttypes.h>
25 #include <elf.h>
26 #ifdef __sun__
27 #include <sys/machelf.h>
28 #endif
30 #include "util.h"
31 #include "config.h"
33 #include "../rombios/32bit/32bitbios_flat.h"
35 static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
36 {
37 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
38 Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
39 char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
40 char *jump_table;
41 uint32_t reloc_off, reloc_size;
42 char *highbiosarea;
43 int i, jump_sec_idx = 0;
45 /*
46 * Step 1. General elf cleanup, and compute total relocation size.
47 */
48 reloc_off = 0;
49 for ( i = 0; i < ehdr->e_shnum; i++ )
50 {
51 /* By default all section data points into elf image data array. */
52 shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
54 if ( !strcmp(".biosjumptable", secstrings + shdr[i].sh_name) )
55 {
56 /* We do not relocate the BIOS jump table to high memory. */
57 shdr[i].sh_flags &= ~SHF_ALLOC;
58 jump_sec_idx = i;
59 }
61 /* Fix up a corner case of address alignment. */
62 if ( shdr[i].sh_addralign == 0 )
63 shdr[i].sh_addralign = 1;
65 /* Any section which contains run-time data must be relocated. */
66 if ( shdr[i].sh_flags & SHF_ALLOC )
67 {
68 uint32_t mask = shdr[i].sh_addralign - 1;
69 reloc_off = (reloc_off + mask) & ~mask;
70 reloc_off += shdr[i].sh_size;
71 }
72 }
74 /*
75 * Step 2. Now we know the relocation size, allocate a chunk of high mem.
76 */
77 reloc_size = reloc_off;
78 printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
79 highbiosarea = (char *)(long)e820_malloc(reloc_size);
80 BUG_ON(highbiosarea == NULL);
81 printf(" Relocating to 0x%x-0x%x ... ",
82 (uint32_t)&highbiosarea[0],
83 (uint32_t)&highbiosarea[reloc_size]);
85 /*
86 * Step 3. Copy run-time data into the newly-allocated high-memory chunk.
87 */
88 reloc_off = 0;
89 for ( i = 0; i < ehdr->e_shnum; i++ )
90 {
91 uint32_t mask = shdr[i].sh_addralign - 1;
93 /* Nothing to do for non-run-time sections. */
94 if ( !(shdr[i].sh_flags & SHF_ALLOC) )
95 continue;
97 /* Copy from old location. */
98 reloc_off = (reloc_off + mask) & ~mask;
99 if ( shdr[i].sh_type == SHT_NOBITS )
100 memset(&highbiosarea[reloc_off], 0, shdr[i].sh_size);
101 else
102 memcpy(&highbiosarea[reloc_off], (void *)shdr[i].sh_addr,
103 shdr[i].sh_size);
105 /* Update address to new location. */
106 shdr[i].sh_addr = (Elf32_Addr)&highbiosarea[reloc_off];
107 reloc_off += shdr[i].sh_size;
108 }
109 BUG_ON(reloc_off != reloc_size);
111 /*
112 * Step 4. Perform relocations in high memory.
113 */
114 for ( i = 0; i < ehdr->e_shnum; i++ )
115 {
116 Elf32_Sym *syms, *sym;
117 Elf32_Rel *rels;
118 char *code;
119 uint32_t *loc, fix;
120 int j;
122 if ( shdr[i].sh_type == SHT_RELA )
123 printf("Unsupported section type SHT_RELA\n");
125 if ( shdr[i].sh_type != SHT_REL )
126 continue;
128 syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr;
129 rels = (Elf32_Rel *)shdr[i].sh_addr;
130 code = (char *)shdr[shdr[i].sh_info].sh_addr;
132 for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
133 {
134 sym = &syms[ELF32_R_SYM(rels[j].r_info)];
135 loc = (uint32_t *)&code[rels[j].r_offset];
136 fix = shdr[sym->st_shndx].sh_addr + sym->st_value;
138 switch ( ELF32_R_TYPE(rels[j].r_info) )
139 {
140 case R_386_PC32:
141 *loc += fix - (uint32_t)loc;
142 break;
144 case R_386_32:
145 *loc += fix;
146 break;
147 }
148 }
149 }
151 /* Step 5. Find the ROMBIOS jump-table stub and copy in the real table. */
152 for ( jump_table = (char *)ROMBIOS_BEGIN;
153 jump_table != (char *)ROMBIOS_END;
154 jump_table++ )
155 if ( !strncmp(jump_table, "___JMPT", 7) )
156 break;
157 BUG_ON(jump_table == NULL);
158 BUG_ON(jump_sec_idx == 0);
159 memcpy(jump_table, (char *)shdr[jump_sec_idx].sh_addr,
160 shdr[jump_sec_idx].sh_size);
162 printf("done\n");
163 }
165 void highbios_setup(void)
166 {
167 relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
168 }