diff --git a/tools/read_vmlinuz.c b/tools/read_vmlinuz.c new file mode 100644 index 0000000..32f920d --- /dev/null +++ b/tools/read_vmlinuz.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#include + +#include "zlib.h" + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) + +int main(int argc, char **argv) +{ + gzFile in; + Elf32_Ehdr elf_header; + Elf32_Phdr *program_header; + int ret; + unsigned long min_addr, max_addr, kernel_size; + int i; + char * base; + + in = gzopen("vmlinux.gz", "rb"); + ret = gzread(in, &elf_header, sizeof(Elf32_Ehdr)); + + if (elf_header.e_machine != EM_68K) + { + fprintf(stderr, "Not MC680x0 architecture\n"); + return 1; + } + + if (elf_header.e_type != ET_EXEC) + { + fprintf(stderr, "Not an executable file\n"); + return 2; + } + + program_header = (Elf32_Phdr *)malloc(elf_header.e_phnum * + sizeof (Elf32_Phdr)); + if (program_header == NULL) + { + fprintf(stderr, "Cannot allocate memory\n"); + return 3; + } + + ret = gzseek(in, elf_header.e_phoff, SEEK_SET); + + ret = gzread(in, program_header, elf_header.e_phnum * sizeof(Elf32_Phdr)); + min_addr = 0xffffffff; + max_addr = 0; + for (i = 0; i < elf_header.e_phnum; i++) + { + min_addr = (min_addr > program_header[i].p_vaddr) ? + program_header[i].p_vaddr : min_addr; + max_addr = (max_addr < program_header[i].p_vaddr + program_header[i].p_memsz) ? + program_header[i].p_vaddr + program_header[i].p_memsz: max_addr; + } + if (min_addr == 0) + { + min_addr = PAGE_SIZE; + program_header[0].p_vaddr += PAGE_SIZE; + program_header[0].p_offset += PAGE_SIZE; + program_header[0].p_filesz -= PAGE_SIZE; + program_header[0].p_memsz -= PAGE_SIZE; + } + kernel_size = max_addr - min_addr; + fprintf(stderr, "Kernel memory footprint: %d\n", kernel_size); + fprintf(stderr, "Base address: 0x%lx\n", min_addr); + fprintf(stderr, "Entry point: 0x%lx\n", elf_header.e_entry); + + base = (char*)malloc(kernel_size); + memset(base, 0, kernel_size); + for (i = 0; i < elf_header.e_phnum; i++) + { + fprintf(stderr, "Reading Program Section #%d, " + "offset 0x%lx, (0x%lx,%lx)\n", + i, (long)program_header[i].p_offset, + program_header[i].p_vaddr - PAGE_SIZE, + (long)program_header[i].p_filesz); + ret = gzseek(in, program_header[i].p_offset, SEEK_SET); + ret = gzread(in, base + program_header[i].p_vaddr - PAGE_SIZE, program_header[i].p_filesz); + } + write(STDOUT_FILENO, base, kernel_size); + + ret = gzclose(in); + + return 0; +}