EMILE/tools/read_vmlinuz.c

90 lines
2.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include "zlib.h"
gzFile ZEXPORT gzopen (char*, char*);
#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;
unsigned long min_addr, max_addr, kernel_size;
int i;
char * base;
in = gzopen("vmlinux.gz", "rb");
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;
}
gzseek(in, elf_header.e_phoff, SEEK_SET);
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: %ld\n", kernel_size);
fprintf(stderr, "Base address: 0x%lx\n", min_addr);
fprintf(stderr, "Entry point: 0x%lx\n", (long)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);
gzseek(in, program_header[i].p_offset, SEEK_SET);
gzread(in, base + program_header[i].p_vaddr - PAGE_SIZE,
program_header[i].p_filesz);
}
write(STDOUT_FILENO, base, kernel_size);
gzclose(in);
return 0;
}