ia64/xen-unstable

view xen/arch/x86/boot/mkelf32.c @ 3689:ef95f070a233

bitkeeper revision 1.1159.223.74 (420757a9FtyPHOdlg42s6EIT2DD1zw)

Pad Xen image to end on a page boundary. Avoids kexec bug.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Mon Feb 07 11:57:29 2005 +0000 (2005-02-07)
parents 3857ec2f2189
children 177865f3143e ef622cae68c4
line source
1 /******************************************************************************
2 * mkelf32.c
3 *
4 * Usage: elf-prefix <in-image> <out-image> <load-base>
5 *
6 * Converts an Elf32 or Elf64 executable binary <in-image> into a simple Elf32
7 * image <out-image> comprising a single chunk to be loaded at <load-base>.
8 */
10 #include <errno.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
19 /*
20 * Here I'm taking care not to conflict with possible typedef's in
21 * standard headers by instead using the macro namespace.
22 */
23 #undef u8
24 #undef u16
25 #undef u32
26 #undef u64
27 #undef s8
28 #undef s16
29 #undef s32
30 #undef s64
31 #define u8 unsigned char
32 #define u16 unsigned short
33 #define u32 unsigned int
34 #define s8 signed char
35 #define s16 signed short
36 #define s32 signed int
37 #if defined(__i386__)
38 #define u64 unsigned long long
39 #define s64 signed long long
40 #else
41 #define u64 unsigned long
42 #define s64 signed long
43 #endif
45 #include "../../../include/xen/elf.h"
47 #define DYNAMICALLY_FILLED 0
48 #define RAW_OFFSET 128
50 static Elf32_Ehdr out_ehdr = {
51 { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, /* EI_MAG{0-3} */
52 ELFCLASS32, /* EI_CLASS */
53 ELFDATA2LSB, /* EI_DATA */
54 EV_CURRENT, /* EI_VERSION */
55 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* e_ident */
56 ET_EXEC, /* e_type */
57 EM_386, /* e_machine */
58 EV_CURRENT, /* e_version */
59 DYNAMICALLY_FILLED, /* e_entry */
60 sizeof(Elf32_Ehdr), /* e_phoff */
61 DYNAMICALLY_FILLED, /* e_shoff */
62 0, /* e_flags */
63 sizeof(Elf32_Ehdr), /* e_ehsize */
64 sizeof(Elf32_Phdr), /* e_phentsize */
65 1, /* e_phnum */
66 sizeof(Elf32_Shdr), /* e_shentsize */
67 3, /* e_shnum */
68 2 /* e_shstrndx */
69 };
71 static Elf32_Phdr out_phdr = {
72 PT_LOAD, /* p_type */
73 RAW_OFFSET, /* p_offset */
74 DYNAMICALLY_FILLED, /* p_vaddr */
75 DYNAMICALLY_FILLED, /* p_paddr */
76 DYNAMICALLY_FILLED, /* p_filesz */
77 DYNAMICALLY_FILLED, /* p_memsz */
78 PF_R|PF_W|PF_X, /* p_flags */
79 64 /* p_align */
80 };
82 static u8 out_shstrtab[] = "\0.text\0.shstrtab";
84 static Elf32_Shdr out_shdr[] = {
85 { 0 },
86 { 1, /* sh_name */
87 SHT_PROGBITS, /* sh_type */
88 SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR, /* sh_flags */
89 DYNAMICALLY_FILLED, /* sh_addr */
90 RAW_OFFSET, /* sh_offset */
91 DYNAMICALLY_FILLED, /* sh_size */
92 0, /* sh_link */
93 0, /* sh_info */
94 64, /* sh_addralign */
95 0 /* sh_entsize */
96 },
97 { 7, /* sh_name */
98 SHT_STRTAB, /* sh_type */
99 0, /* sh_flags */
100 0, /* sh_addr */
101 DYNAMICALLY_FILLED, /* sh_offset */
102 sizeof(out_shstrtab), /* sh_size */
103 0, /* sh_link */
104 0, /* sh_info */
105 1, /* sh_addralign */
106 0 /* sh_entsize */
107 }
108 };
110 static void do_write(int fd, void *data, int len)
111 {
112 int done, left = len;
113 char *p = data;
115 while ( left != 0 )
116 {
117 if ( (done = write(fd, p, left)) == -1 )
118 {
119 if ( errno == EINTR )
120 continue;
121 fprintf(stderr, "Error writing output image: %d (%s).\n",
122 errno, strerror(errno));
123 exit(1);
124 }
126 left -= done;
127 p += done;
128 }
129 }
131 static void do_read(int fd, void *data, int len)
132 {
133 int done, left = len;
134 char *p = data;
136 while ( left != 0 )
137 {
138 if ( (done = read(fd, p, left)) == -1 )
139 {
140 if ( errno == EINTR )
141 continue;
142 fprintf(stderr, "Error reading input image: %d (%s).\n",
143 errno, strerror(errno));
144 exit(1);
145 }
147 left -= done;
148 p += done;
149 }
150 }
152 int main(int argc, char **argv)
153 {
154 u32 loadbase, dat_siz, mem_siz;
155 char *inimage, *outimage;
156 int infd, outfd;
157 char buffer[1024];
158 int bytes, todo;
160 Elf32_Ehdr in32_ehdr;
161 Elf32_Phdr in32_phdr;
163 Elf64_Ehdr in64_ehdr;
164 Elf64_Phdr in64_phdr;
166 if ( argc != 4 )
167 {
168 fprintf(stderr, "Usage: mkelf32 <in-image> <out-image> <load-base>\n");
169 return 1;
170 }
172 inimage = argv[1];
173 outimage = argv[2];
174 loadbase = strtoul(argv[3], NULL, 16);
176 infd = open(inimage, O_RDONLY);
177 if ( infd == -1 )
178 {
179 fprintf(stderr, "Failed to open input image '%s': %d (%s).\n",
180 inimage, errno, strerror(errno));
181 return 1;
182 }
184 do_read(infd, &in32_ehdr, sizeof(in32_ehdr));
185 if ( !IS_ELF(in32_ehdr) ||
186 (in32_ehdr.e_ident[EI_DATA] != ELFDATA2LSB) )
187 {
188 fprintf(stderr, "Input image must be a little-endian Elf image.\n");
189 return 1;
190 }
192 switch ( in32_ehdr.e_ident[EI_CLASS] )
193 {
194 case ELFCLASS32:
195 if ( in32_ehdr.e_phentsize != sizeof(in32_phdr) )
196 {
197 fprintf(stderr, "Bad program header size (%d != %d).\n",
198 (int)in32_ehdr.e_phentsize, (int)sizeof(in32_phdr));
199 return 1;
200 }
202 if ( in32_ehdr.e_phnum != 1 )
203 {
204 fprintf(stderr, "Expect precisely 1 program header; found %d.\n",
205 (int)in32_ehdr.e_phnum);
206 return 1;
207 }
209 (void)lseek(infd, in32_ehdr.e_phoff, SEEK_SET);
210 do_read(infd, &in32_phdr, sizeof(in32_phdr));
212 (void)lseek(infd, in32_phdr.p_offset, SEEK_SET);
213 dat_siz = (u32)in32_phdr.p_filesz;
214 mem_siz = (u32)in32_phdr.p_memsz;
215 break;
217 case ELFCLASS64:
218 (void)lseek(infd, 0, SEEK_SET);
219 do_read(infd, &in64_ehdr, sizeof(in64_ehdr));
221 if ( in64_ehdr.e_phentsize != sizeof(in64_phdr) )
222 {
223 fprintf(stderr, "Bad program header size (%d != %d).\n",
224 (int)in64_ehdr.e_phentsize, (int)sizeof(in64_phdr));
225 return 1;
226 }
228 if ( in64_ehdr.e_phnum != 1 )
229 {
230 fprintf(stderr, "Expect precisly 1 program header; found %d.\n",
231 (int)in64_ehdr.e_phnum);
232 return 1;
233 }
235 (void)lseek(infd, in64_ehdr.e_phoff, SEEK_SET);
236 do_read(infd, &in64_phdr, sizeof(in64_phdr));
238 (void)lseek(infd, in64_phdr.p_offset, SEEK_SET);
239 dat_siz = (u32)in64_phdr.p_filesz;
240 mem_siz = (u32)in64_phdr.p_memsz;
241 break;
243 default:
244 fprintf(stderr, "Input image must be a 32- or 64-bit Elf image.\n");
245 return 1;
246 }
248 /*
249 * End the image on a page boundary. This gets round alignment bugs
250 * in the boot- or chain-loader (e.g., kexec on the XenoBoot CD).
251 */
252 mem_siz += -(loadbase + mem_siz) & 0xfff;
254 out_ehdr.e_entry = loadbase;
255 out_ehdr.e_shoff = RAW_OFFSET + dat_siz;
257 out_phdr.p_vaddr = loadbase;
258 out_phdr.p_paddr = loadbase;
259 out_phdr.p_filesz = dat_siz;
260 out_phdr.p_memsz = mem_siz;
262 out_shdr[1].sh_addr = loadbase;
263 out_shdr[1].sh_size = dat_siz;
264 out_shdr[2].sh_offset = RAW_OFFSET + dat_siz + sizeof(out_shdr);
266 outfd = open(outimage, O_WRONLY|O_CREAT|O_TRUNC, 0775);
267 if ( outfd == -1 )
268 {
269 fprintf(stderr, "Failed to open output image '%s': %d (%s).\n",
270 outimage, errno, strerror(errno));
271 return 1;
272 }
274 do_write(outfd, &out_ehdr, sizeof(out_ehdr));
275 do_write(outfd, &out_phdr, sizeof(out_phdr));
277 if ( (bytes = RAW_OFFSET - sizeof(out_ehdr) - sizeof(out_phdr)) < 0 )
278 {
279 fprintf(stderr, "Header overflow.\n");
280 return 1;
281 }
282 do_write(outfd, buffer, bytes);
284 for ( bytes = 0; bytes < dat_siz; bytes += todo )
285 {
286 todo = ((dat_siz - bytes) > sizeof(buffer)) ?
287 sizeof(buffer) : (dat_siz - bytes);
288 do_read(infd, buffer, todo);
289 do_write(outfd, buffer, todo);
290 }
292 do_write(outfd, &out_shdr[0], sizeof(out_shdr));
293 do_write(outfd, out_shstrtab, sizeof(out_shstrtab));
294 do_write(outfd, buffer, 4-((sizeof(out_shstrtab)+dat_siz)&3));
296 close(infd);
297 close(outfd);
299 return 0;
300 }