1 #include <errno.h>
2 #include <fcntl.h>
3 #include <inttypes.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <stdarg.h>
9
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/mman.h>
13
14 #include <xen/xen.h>
15 #include <xenctrl.h>
16 #include <xenguest.h>
17
18 #include <xen/libelf/libelf.h>
19
20 static xc_interface *xch;
21
22 /* According to the implemation of xc_dom_probe_bzimage_kernel() function */
23 /* We add support of bzImage kernel */
24 /* Copied from tools/libxc/xc_doom_bzImageloader.c */
25 struct setup_header {
26 uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */
27 uint8_t setup_sects;
28 uint16_t root_flags;
29 uint32_t syssize;
30 uint16_t ram_size;
31 uint16_t vid_mode;
32 uint16_t root_dev;
33 uint16_t boot_flag;
34 uint16_t jump;
35 uint32_t header;
36 #define HDR_MAGIC "HdrS"
37 #define HDR_MAGIC_SZ 4
38 uint16_t version;
39 #define VERSION(h,l) (((h)<<8) | (l))
40 uint32_t realmode_swtch;
41 uint16_t start_sys;
42 uint16_t kernel_version;
43 uint8_t type_of_loader;
44 uint8_t loadflags;
45 uint16_t setup_move_size;
46 uint32_t code32_start;
47 uint32_t ramdisk_image;
48 uint32_t ramdisk_size;
49 uint32_t bootsect_kludge;
50 uint16_t heap_end_ptr;
51 uint16_t _pad1;
52 uint32_t cmd_line_ptr;
53 uint32_t initrd_addr_max;
54 uint32_t kernel_alignment;
55 uint8_t relocatable_kernel;
56 uint8_t _pad2[3];
57 uint32_t cmdline_size;
58 uint32_t hardware_subarch;
59 uint64_t hardware_subarch_data;
60 uint32_t payload_offset;
61 uint32_t payload_length;
62 } __attribute__((packed));
63
print_string_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)64 static void print_string_note(const char *prefix, struct elf_binary *elf,
65 ELF_HANDLE_DECL(elf_note) note)
66 {
67 printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
68 }
69
print_numeric_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)70 static void print_numeric_note(const char *prefix, struct elf_binary *elf,
71 ELF_HANDLE_DECL(elf_note) note)
72 {
73 uint64_t value = elf_note_numeric(elf, note);
74 unsigned descsz = elf_uval(elf, note, descsz);
75
76 printf("%s: %#*" PRIx64 " (%d bytes)\n",
77 prefix, 2+2*descsz, value, descsz);
78 }
79
print_l1_mfn_valid_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)80 static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
81 ELF_HANDLE_DECL(elf_note) note)
82 {
83 unsigned descsz = elf_uval(elf, note, descsz);
84 elf_ptrval desc = elf_note_desc(elf, note);
85
86 /* XXX should be able to cope with a list of values. */
87 switch ( descsz / 2 )
88 {
89 case 8:
90 printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
91 elf_access_unsigned(elf, desc, 0, 8),
92 elf_access_unsigned(elf, desc, 8, 8));
93 break;
94 case 4:
95 printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
96 (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
97 (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
98 break;
99 }
100
101 }
102
print_notes(struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)start,ELF_HANDLE_DECL (elf_note)end)103 static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
104 {
105 ELF_HANDLE_DECL(elf_note) note;
106 unsigned notes_found = 0;
107 const char *this_note_name;
108
109 for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
110 {
111 this_note_name = elf_note_name(elf, note);
112 if (NULL == this_note_name)
113 continue;
114 if (0 != strcmp(this_note_name, "Xen"))
115 continue;
116
117 notes_found++;
118
119 switch(elf_uval(elf, note, type))
120 {
121 case XEN_ELFNOTE_INFO:
122 print_string_note("INFO", elf , note);
123 break;
124 case XEN_ELFNOTE_ENTRY:
125 print_numeric_note("ENTRY", elf , note);
126 break;
127 case XEN_ELFNOTE_HYPERCALL_PAGE:
128 print_numeric_note("HYPERCALL_PAGE", elf , note);
129 break;
130 case XEN_ELFNOTE_VIRT_BASE:
131 print_numeric_note("VIRT_BASE", elf , note);
132 break;
133 case XEN_ELFNOTE_PADDR_OFFSET:
134 print_numeric_note("PADDR_OFFSET", elf , note);
135 break;
136 case XEN_ELFNOTE_XEN_VERSION:
137 print_string_note("XEN_VERSION", elf , note);
138 break;
139 case XEN_ELFNOTE_GUEST_OS:
140 print_string_note("GUEST_OS", elf , note);
141 break;
142 case XEN_ELFNOTE_GUEST_VERSION:
143 print_string_note("GUEST_VERSION", elf , note);
144 break;
145 case XEN_ELFNOTE_LOADER:
146 print_string_note("LOADER", elf , note);
147 break;
148 case XEN_ELFNOTE_PAE_MODE:
149 print_string_note("PAE_MODE", elf , note);
150 break;
151 case XEN_ELFNOTE_FEATURES:
152 print_string_note("FEATURES", elf , note);
153 break;
154 case XEN_ELFNOTE_HV_START_LOW:
155 print_numeric_note("HV_START_LOW", elf , note);
156 break;
157 case XEN_ELFNOTE_SUSPEND_CANCEL:
158 print_numeric_note("SUSPEND_CANCEL", elf, note);
159 break;
160 case XEN_ELFNOTE_L1_MFN_VALID:
161 print_l1_mfn_valid_note("L1_MFN_VALID", elf , note);
162 break;
163 case XEN_ELFNOTE_PHYS32_ENTRY:
164 print_numeric_note("PHYS32_ENTRY", elf , note);
165 break;
166 default:
167 printf("unknown note type %#x\n",
168 (unsigned)elf_uval(elf, note, type));
169 break;
170 }
171 }
172 return notes_found;
173 }
174
main(int argc,char ** argv)175 int main(int argc, char **argv)
176 {
177 const char *f;
178 int fd;
179 unsigned h,size,usize,count;
180 void *image,*tmp;
181 struct stat st;
182 struct elf_binary elf;
183 ELF_HANDLE_DECL(elf_shdr) shdr;
184 unsigned notes_found = 0;
185
186 struct setup_header *hdr;
187 uint64_t payload_offset, payload_length;
188
189 if (argc != 2)
190 {
191 fprintf(stderr, "Usage: readnotes <elfimage>\n");
192 return 1;
193 }
194 f = argv[1];
195
196 xch = xc_interface_open(0,0,XC_OPENFLAG_DUMMY);
197
198 fd = open(f, O_RDONLY);
199 if (fd == -1)
200 {
201 fprintf(stderr, "Unable to open %s: %s\n", f, strerror(errno));
202 return 1;
203 }
204 if (fstat(fd, &st) == -1)
205 {
206 fprintf(stderr, "Unable to determine size of %s: %s\n",
207 f, strerror(errno));
208 return 1;
209 }
210
211 image = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
212 if (image == MAP_FAILED)
213 {
214 fprintf(stderr, "Unable to map %s: %s\n", f, strerror(errno));
215 return 1;
216 }
217
218 /* Check the magic of bzImage kernel */
219 hdr = (struct setup_header *)image;
220 if ( memcmp(&hdr->header, HDR_MAGIC, HDR_MAGIC_SZ) == 0 )
221 {
222 if ( hdr->version < VERSION(2,8) )
223 {
224 printf("%s: boot protocol too old (%04x)", __FUNCTION__, hdr->version);
225 return 1;
226 }
227
228 /* upcast to 64 bits to avoid overflow */
229 /* setup_sects is u8 and so cannot overflow */
230 payload_offset = (hdr->setup_sects + 1) * 512;
231 payload_offset += hdr->payload_offset;
232 payload_length = hdr->payload_length;
233
234 if ( payload_offset >= st.st_size )
235 {
236 printf("%s: payload offset overflow", __FUNCTION__);
237 return 1;
238 }
239 if ( (payload_offset + payload_length) > st.st_size )
240 {
241 printf("%s: payload length overflow", __FUNCTION__);
242 return 1;
243 }
244
245 image = image + payload_offset;
246 size = payload_length;
247 } else {
248 size = st.st_size;
249 }
250
251 usize = xc_dom_check_gzip(xch, image, size);
252 if (usize)
253 {
254 tmp = malloc(usize);
255 xc_dom_do_gunzip(xch, image, size, tmp, usize);
256 image = tmp;
257 size = usize;
258 }
259
260 if (0 != elf_init(&elf, image, size))
261 {
262 fprintf(stderr, "File %s is not an ELF image\n", f);
263 return 1;
264 }
265 xc_elf_set_logfile(xch, &elf, 0);
266
267 count = elf_phdr_count(&elf);
268 for ( h=0; h < count; h++)
269 {
270 ELF_HANDLE_DECL(elf_phdr) phdr;
271 phdr = elf_phdr_by_index(&elf, h);
272 if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
273 continue;
274
275 /* Some versions of binutils do not correctly set
276 * p_offset for note segments.
277 */
278 if (elf_uval(&elf, phdr, p_offset) == 0)
279 continue;
280
281 notes_found = print_notes(&elf,
282 ELF_MAKE_HANDLE(elf_note, elf_segment_start(&elf, phdr)),
283 ELF_MAKE_HANDLE(elf_note, elf_segment_end(&elf, phdr)));
284 }
285
286 if ( notes_found == 0 )
287 {
288 count = elf_shdr_count(&elf);
289 for ( h=0; h < count; h++)
290 {
291 ELF_HANDLE_DECL(elf_shdr) shdr;
292 shdr = elf_shdr_by_index(&elf, h);
293 if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
294 continue;
295 notes_found = print_notes(&elf,
296 ELF_MAKE_HANDLE(elf_note, elf_section_start(&elf, shdr)),
297 ELF_MAKE_HANDLE(elf_note, elf_section_end(&elf, shdr)));
298 if ( notes_found )
299 fprintf(stderr, "using notes from SHT_NOTE section\n");
300
301 }
302 }
303
304 shdr = elf_shdr_by_name(&elf, "__xen_guest");
305 if (ELF_HANDLE_VALID(shdr))
306 printf("__xen_guest: %s\n",
307 elf_strfmt(&elf, elf_section_start(&elf, shdr)));
308
309 if (elf_check_broken(&elf))
310 printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
311
312 return 0;
313 }
314
315
316