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