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