Added the elf2mzip tool.
parent
9896709f6f
commit
34ef9fa66e
@ -0,0 +1,23 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O2
|
||||
INCLUDES = -I.
|
||||
|
||||
OBJECTS = elf2mzip.o mzip.o
|
||||
|
||||
COMPILE = $(CC) $(CFLAGS) $(INCLUDES)
|
||||
|
||||
LDFLAGS = -lzip
|
||||
|
||||
IMAGENAME = elf2mzip
|
||||
|
||||
all: elf2mzip
|
||||
|
||||
elf2mzip: $(OBJECTS)
|
||||
$(COMPILE) $(OBJECTS) $(LDFLAGS) -o $(IMAGENAME)
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
clean:
|
||||
-rm -rf $(IMAGENAME)
|
||||
-rm -rf $(OBJECTS)
|
@ -0,0 +1,203 @@
|
||||
#ifndef _ELF_H
|
||||
#define _ELF_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/* ELF object file types */
|
||||
#define ELF_TYPE_NONE 0 /* no file type */
|
||||
#define ELF_TYPE_REL 1 /* relocatable file */
|
||||
#define ELF_TYPE_EXEC 2 /* executable file */
|
||||
#define ELF_TYPE_DYN 3 /* shared object file */
|
||||
#define ELF_TYPE_CORE 4 /* core file */
|
||||
#define ELF_TYPE_LOPROC 0xff00 /* cpu specific */
|
||||
#define ELF_TYPE_HIPROC 0xffff
|
||||
|
||||
/* ELF machine types */
|
||||
#define ELF_MACH_NONE 0 /* no machine type */
|
||||
#define ELF_MACH_M32 1 /* AT&T WE 32100 */
|
||||
#define ELF_MACH_SPARC 2 /* Sun SPARC */
|
||||
#define ELF_MACH_386 3 /* Intel i386 */
|
||||
#define ELF_MACH_68K 4 /* Motorola 68000 */
|
||||
#define ELF_MACH_88K 5 /* Motorola 88000 */
|
||||
#define ELF_MACH_860 7 /* Intel 80860 */
|
||||
#define ELF_MACH_MIPS 8 /* MIPS RS3000 Big-Endian */
|
||||
#define ELF_MACH_MIPS_R4K_BE 10 /* MIPS RS4000 Big-Endian */
|
||||
/* 11-16 are reserved */
|
||||
|
||||
/* ELF Version */
|
||||
#define ELF_VER_NONE 0 /* invalid version */
|
||||
#define ELF_VER_CURRENT 1 /* Current ELF version */
|
||||
|
||||
|
||||
/* ELF Header Structure */
|
||||
|
||||
#define ELF_IDENT_COUNT 16
|
||||
|
||||
struct elf32_header {
|
||||
uint8_t ident[ELF_IDENT_COUNT]; /* key fields */
|
||||
uint16_t type; /* object file type */
|
||||
uint16_t machine; /* architecture */
|
||||
uint32_t version; /* object file version */
|
||||
uint32_t entry; /* entry point */
|
||||
uint32_t phoff; /* program header offset */
|
||||
uint32_t shoff; /* section header offset */
|
||||
uint32_t flags; /* ELF file flags */
|
||||
uint16_t ehsize; /* ELF header size */
|
||||
uint16_t phentsize; /* size of a program header entry */
|
||||
uint16_t phnum; /* number of entries in the program header */
|
||||
uint16_t shentsize; /* size of a section header entry */
|
||||
uint16_t shnum; /* number of section header entries */
|
||||
uint16_t shstrndx; /* index of string table entry in the section hdr */
|
||||
};
|
||||
|
||||
/* ELF magic */
|
||||
#define ELF_MAGIC_1 0x7f
|
||||
#define ELF_MAGIC_2 0x45
|
||||
#define ELF_MAGIC_3 0x4c
|
||||
#define ELF_MAGIC_4 0x46
|
||||
|
||||
/* ELF class */
|
||||
#define ELF_CLASS_NONE 0
|
||||
#define ELF_CLASS_32 1
|
||||
#define ELF_CLASS_64 2
|
||||
|
||||
/* ELF Data Encoding */
|
||||
#define ELF_DATA_NONE 0 /* invalid */
|
||||
#define ELF_DATA_LSB 1 /* Little endian */
|
||||
#define ELF_DATA_MSB 2 /* big endian */
|
||||
|
||||
/* Offsets within the ident string */
|
||||
#define ELF_INDEX_MAGIC0 0
|
||||
#define ELF_INDEX_MAGIC1 1
|
||||
#define ELF_INDEX_MAGIC2 2
|
||||
#define ELF_INDEX_MAGIC3 3
|
||||
#define ELF_INDEX_CLASS 4 /* file class */
|
||||
#define ELF_INDEX_DATA 5 /* data encoding */
|
||||
#define ELF_INDEX_VERSION 6 /* file version */
|
||||
#define ELF_INDEX_PADDING 7 /* start of padding */
|
||||
|
||||
/* Special Section Header Indexes */
|
||||
#define ELF_SH_UNDEF 0 /* no section header present */
|
||||
#define ELF_SH_LORESERVE 0xff00 /* lower-bound of reserved indices */
|
||||
#define ELF_SH_LOPROC 0xff00 /* processor-specifc semantics low bound */
|
||||
#define ELF_SH_HIPROC 0xff1f /* processor-specific semantics high bound */
|
||||
#define ELF_SH_ABS 0xfff1 /* abs values for symbols in this section */
|
||||
#define ELF_SH_COMMON 0xfff2 /* Common Block/unallocated extern vars */
|
||||
#define ELF_SH_HIRESERVE 0xffff /* high value for reserved indices */
|
||||
|
||||
/* Section Header Structure */
|
||||
struct elf32_section_header {
|
||||
uint32_t name; /* index of the string table entry for this section */
|
||||
uint32_t type; /* section type */
|
||||
uint32_t flags; /* section flags */
|
||||
uint32_t addr; /* section address if in actual memory image */
|
||||
uint32_t offset; /* byte offset from beginning of file to start of sect. */
|
||||
uint32_t size; /* size of section in bytes */
|
||||
uint32_t link; /* section header table index link */
|
||||
uint32_t info; /* extra information */
|
||||
uint32_t addralign; /* alignment constraints */
|
||||
uint32_t entsize; /* per-entry size */
|
||||
};
|
||||
|
||||
/* Section Types */
|
||||
#define ELF_SHT_NULL 0 /* inactive/no associated section */
|
||||
#define ELF_SHT_PROGBITS 1 /* program-specific information */
|
||||
#define ELF_SHT_SYMTAB 2 /* Symbol table */
|
||||
#define ELF_SHT_STRTAB 3 /* string table */
|
||||
#define ELF_SHT_RELA 4 /* Relocation entries with explicit addends */
|
||||
#define ELF_SHT_HASH 5 /* symbol hash table */
|
||||
#define ELF_SHT_DYNAMIC 6 /* dynamic linking information */
|
||||
#define ELF_SHT_NOTE 7 /* notational marking */
|
||||
#define ELF_SHT_NOBITS 8 /* no space in file, looks like progbits */
|
||||
#define ELF_SHT_REL 9 /* relocation entires without explicit addends */
|
||||
#define ELF_SHT_SHLIB 10 /* reserved; non-ABI conformant code */
|
||||
#define ELF_SHT_DYNSYM 11 /* symbol table */
|
||||
#define ELF_SHT_LOPROC 0x70000000 /* region reserved for CPU-specific info */
|
||||
#define ELF_SHT_HIPROC 0x7fffffff
|
||||
#define ELF_SHT_LOUSER 0x80000000 /* section reseverd for prog. info */
|
||||
#define ELF_SHT_HIUSER 0xffffffff
|
||||
|
||||
/* Section header flags */
|
||||
#define ELF_SHF_WRITE 0x1 /* Contains writable data */
|
||||
#define ELF_SHF_ALLOC 0x2 /* occupies memory during exec */
|
||||
#define ELF_SHF_EXECINSTR 0x4 /* contains executable instructions */
|
||||
#define ELF_SHF_MASKPROC 0xf0000000 /* Processor-specific mask bits */
|
||||
|
||||
#define ELF_SHF_WRITABLE(x) ((x) & ELF_SHF_WRITE)
|
||||
#define ELF_SHF_ALLOCD(x) ((x) & ELF_SHF_ALLOC)
|
||||
#define ELF_SHF_EXECUTABLE(x) ((x) & ELF_SHF_EXECINSTR)
|
||||
|
||||
/* Symbol Table */
|
||||
#define ELF_STN_UNDEF 0
|
||||
|
||||
/* ELF Spec, p. 4-22 */
|
||||
struct elf32_sym_table_entry {
|
||||
uint32_t name; /* string table entry */
|
||||
uint32_t value; /* value of the symbol */
|
||||
uint32_t size; /* size of the symbol */
|
||||
uint8_t info; /* symbol's type and binding attribs */
|
||||
uint8_t other; /* no defined meaning */
|
||||
uint16_t shndx; /* associated section header table index */
|
||||
};
|
||||
|
||||
#define ELF_ST_BIND(i) ((i) >> 4)
|
||||
#define ELF_ST_TYPE(i) ((i) & 0xf)
|
||||
#define ELF_ST_INFO(b, t) (((b)<<4) + ((t) & 0xf))
|
||||
|
||||
/* symbol binding (use with ELF_ST_BIND */
|
||||
#define ELF_STB_LOCAL 0 /* not visible outside of this object file */
|
||||
#define ELF_STB_GLOBAL 1 /* visible to all object files being combined */
|
||||
#define ELF_STB_WEAK 2 /* Weak bound symbols (lower precedence than glbl */
|
||||
#define ELF_STB_LOPROC 13 /* Processor specific semantics range */
|
||||
#define ELF_STB_HIPROC 15
|
||||
|
||||
/* symbol type (use with ELF_ST_TYPE macro) */
|
||||
#define ELF_STT_NOTYPE 0 /* type is not specified */
|
||||
#define ELF_STT_OBJECT 1 /* symbol is associated with a data object */
|
||||
#define ELF_STT_FUNC 2 /* symbol is associated with executable code */
|
||||
#define ELF_STT_SECTION 3 /* symbol is associated with a section */
|
||||
#define ELF_STT_FILE 4 /* file symbol type */
|
||||
#define ELF_STT_LOPROC 13 /* processor specific semantics range */
|
||||
#define ELF_STT_HIPROC 15
|
||||
|
||||
/* Relocation Entries */
|
||||
struct elf32_rel {
|
||||
uint32_t offset; /* where to apply relocation action */
|
||||
uint32_t info; /* information about the symbol */
|
||||
};
|
||||
|
||||
struct elf32_rel_add {
|
||||
uint32_t offset; /* where to apply relocation action */
|
||||
uint32_t info; /* information about the symbol */
|
||||
uint32_t addend; /* constant addend */
|
||||
};
|
||||
|
||||
/* Info helper macros: */
|
||||
#define ELF_REL_SYM(i) ((i) >> 8)
|
||||
#define ELF_REL_TYPE(i) ((uint8_t)(i))
|
||||
#define ELF_REL_INFO(s, t) (((s) << 8) + (unsigned char)(t))
|
||||
|
||||
/* Program Header/Segments */
|
||||
struct elf32_phdr {
|
||||
uint32_t type; /* segment type */
|
||||
uint32_t offset; /* offset from beginning of file */
|
||||
uint32_t vaddr; /* virtual address of first byte of segment */
|
||||
uint32_t paddr; /* physical address of first byte of segment */
|
||||
uint32_t filesz; /* size in file of this segment */
|
||||
uint32_t memsz; /* Size of segment in memory image */
|
||||
uint32_t flags; /* segment flags */
|
||||
uint32_t align; /* alignment requirements for loading */
|
||||
};
|
||||
|
||||
/* Segment Types */
|
||||
#define ELF_PT_NULL 0 /* unused */
|
||||
#define ELF_PT_LOAD 1 /* loadable segment */
|
||||
#define ELF_PT_DYNAMIC 2 /* dynamic section */
|
||||
#define ELF_PT_INTERP 3 /* null-terminate path to an invokable interpreter */
|
||||
#define ELF_PT_NOTE 4 /* Auxiliary information */
|
||||
#define ELF_PT_SHLIB 5 /* Shared Library? No ABI conformity required */
|
||||
#define ELF_PT_PHDR 6 /* Program header table size */
|
||||
#define ELF_PT_LOPROC 0x70000000 /* processor-specific values */
|
||||
#define ELF_PT_HIPROC 0x7fffffff
|
||||
|
||||
#endif /* _ELF_H */
|
@ -0,0 +1,225 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <mzip.h>
|
||||
#include <elf.h>
|
||||
|
||||
void usage(const char *name)
|
||||
{
|
||||
printf("Usage: %s [file in] [file out]\n", name);
|
||||
printf("\t[file in] is the file to be converted to MZIP format\n");
|
||||
printf("\t[file out] is the name of the output MZIP file\n");
|
||||
printf("\nNote: the input ELF file needs a single LOADable section and \n");
|
||||
printf(" must be a 32-bit ELF file.\n");
|
||||
}
|
||||
|
||||
int main(const int argc, const char *argv[])
|
||||
{
|
||||
struct elf32_header elf_hdr;
|
||||
struct mzip_header mzip_hdr;
|
||||
FILE *fp_in, *fp_out;
|
||||
struct stat f_stat;
|
||||
bool endian_swap = FALSE;
|
||||
int i;
|
||||
|
||||
printf("elf2mzip version 0.1 - convert ELF files to MZIP files.\n");
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Error: no file arguments specified.\n");
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fp_in = fopen(argv[1], "rb")) == NULL) {
|
||||
printf("Error: unable to open specified input file %s.\n",
|
||||
argv[1]);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check if the input file exists. If it does, delete it. */
|
||||
if (stat(argv[2], &f_stat) != -1) {
|
||||
if (unlink(argv[2]) == -1) {
|
||||
/* check errno */
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
printf("Error: insufficient privileges to access the "
|
||||
"specified output file %s. Aborting.\n", argv[2]);
|
||||
break;
|
||||
case EBUSY:
|
||||
printf("Error: the specified file %s is currently in use.\n",
|
||||
argv[2]);
|
||||
break;
|
||||
case EPERM:
|
||||
printf("Error: the specified file %s is on a read-only file"
|
||||
"system.\n", argv[2]);
|
||||
break;
|
||||
default:
|
||||
printf("An unspecified error occurred. Aborting.\n");
|
||||
}
|
||||
|
||||
usage(argv[0]);
|
||||
fclose(fp_in);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((fp_out = fopen(argv[2], "wb+")) == NULL) {
|
||||
printf("Error: unable to open or create output file %s.\n",
|
||||
argv[2]);
|
||||
fclose(fp_in);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mzip_initialize(&mzip_hdr);
|
||||
|
||||
fseek(fp_in, 0, SEEK_SET);
|
||||
|
||||
/* read in ELF header */
|
||||
fread(&elf_hdr, sizeof(elf_hdr), 1, fp_in);
|
||||
|
||||
if (elf_hdr.ident[0] != ELF_MAGIC_1 || elf_hdr.ident[1] != ELF_MAGIC_2 ||
|
||||
elf_hdr.ident[2] != ELF_MAGIC_3 || elf_hdr.ident[3] != ELF_MAGIC_4)
|
||||
{
|
||||
printf("The specified input file is not an ELF file. Aborting.\n");
|
||||
fclose(fp_in);
|
||||
fclose(fp_out);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (elf_hdr.ident[ELF_INDEX_CLASS] != ELF_CLASS_32) {
|
||||
printf("The specified input file is a 64-bit ELF file. MZIP does not "
|
||||
"support 64-bit files for input.");
|
||||
fclose(fp_in);
|
||||
fclose(fp_out);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* determine endianess of the target machine */
|
||||
if (elf_hdr.ident[ELF_INDEX_DATA] == ELF_DATA_MSB) endian_swap = TRUE;
|
||||
|
||||
printf("DEBUG: endian_swap = %d\n", endian_swap);
|
||||
|
||||
printf("elf_hdr.phnum = %08x\n", elf_hdr.phnum);
|
||||
printf("elf_hdr.phoff = %08x\n", elf_hdr.phoff);
|
||||
|
||||
uint32_t ph_count = endian_swap ? SWAP_16(elf_hdr.phnum) : elf_hdr.phnum;
|
||||
uint32_t ph_offset = endian_swap ? SWAP_32(elf_hdr.phoff) : elf_hdr.phoff;
|
||||
|
||||
printf("DEBUG: segments: 0x%08x; segments offset: 0x%08x\n", ph_count,
|
||||
ph_offset);
|
||||
|
||||
fseek(fp_in, ph_offset, SEEK_SET);
|
||||
|
||||
int ph_loadable_count = 0;
|
||||
uint32_t ph_loc = 0;
|
||||
|
||||
struct elf32_phdr phdr;
|
||||
|
||||
for (i = 0; i < ph_count; i++) {
|
||||
fread(&phdr, 1, sizeof(struct elf32_phdr), fp_in);
|
||||
|
||||
uint32_t type = endian_swap ? SWAP_32(phdr.type) : phdr.type;
|
||||
|
||||
|
||||
if (type == ELF_PT_LOAD) {
|
||||
ph_loadable_count++;
|
||||
ph_loc = ftell(fp_in) - sizeof(struct elf32_phdr);
|
||||
}
|
||||
}
|
||||
|
||||
if (ph_loadable_count < 1) {
|
||||
printf("No loadable ELF sections were found in the input file.\n"
|
||||
"Are you sure this is a loadable image?\n");
|
||||
fclose(fp_in);
|
||||
fclose(fp_out);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ph_loadable_count > 1) {
|
||||
printf("Too many loadable ELF sections were found in the input file. "
|
||||
"Found %d sections.\n", ph_loadable_count);
|
||||
fclose(fp_in);
|
||||
fclose(fp_out);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create an in-memory image of the single section header */
|
||||
fseek(fp_in, ph_loc, SEEK_SET);
|
||||
fread(&phdr, sizeof(struct elf32_phdr), 1, fp_in);
|
||||
|
||||
uint32_t im_offset = endian_swap ? SWAP_32(phdr.offset) : phdr.offset;
|
||||
uint32_t im_file_size = endian_swap ? SWAP_32(phdr.filesz) :
|
||||
phdr.filesz;
|
||||
void *image = malloc(im_file_size);
|
||||
|
||||
printf("DEBUG: allocated %08x byte image\n", im_file_size);
|
||||
printf("DEBUG: offset in file: %08x\n", im_offset);
|
||||
|
||||
|
||||
/* seek to offset of data within ELF image, read it in */
|
||||
fseek(fp_in, im_offset, SEEK_SET);
|
||||
fread(image, 1, im_file_size, fp_in);
|
||||
|
||||
mzip_hdr.hdr_flags1 = endian_swap ? SWAP_32(0x1u) : 0x1u;
|
||||
mzip_hdr.hdr_flags2 = endian_swap ? SWAP_32(0x1u) : 0x1u;
|
||||
|
||||
mzip_hdr.hdr_version = endian_swap ? SWAP_32(0x1u) : 0x1u;
|
||||
mzip_hdr.hdr_entrypt = elf_hdr.entry;
|
||||
|
||||
mzip_hdr.hdr_header_size = endian_swap ? SWAP_32(0x70u) : 0x70u;
|
||||
mzip_hdr.hdr_loader_addr = phdr.paddr;
|
||||
mzip_hdr.hdr_code_unpacked_size = phdr.filesz;
|
||||
mzip_hdr.hdr_memory_image_size = phdr.memsz;
|
||||
|
||||
printf("DEBUG: phdr.paddr = %08x\n", phdr.paddr);
|
||||
printf("DEBUG: phdr.filesz = %08x\n", phdr.filesz);
|
||||
|
||||
/* populate the CRCs of the inputs: */
|
||||
uint16_t mzip_hdr_crc = 0;
|
||||
|
||||
void *mzip_code_seg;
|
||||
uint32_t mzip_code_seg_size = 0;
|
||||
|
||||
/* build code segment in buffer */
|
||||
mzip_codeseg_build(image, im_file_size, &mzip_code_seg,
|
||||
&mzip_code_seg_size);
|
||||
|
||||
mzip_hdr.hdr_code_packed_size = endian_swap ?
|
||||
SWAP_32(mzip_code_seg_size) : mzip_code_seg_size;
|
||||
|
||||
uint16_t mzip_body_crc = 0;
|
||||
|
||||
mzip_calculate_crc(&mzip_hdr, mzip_code_seg, mzip_code_seg_size,
|
||||
&mzip_body_crc);
|
||||
|
||||
mzip_hdr.hdr_crc_code = endian_swap ? SWAP_16(mzip_body_crc) :
|
||||
mzip_body_crc;
|
||||
|
||||
mzip_hdr.hdr_crc_header = endian_swap ? SWAP_16(mzip_hdr.hdr_crc_header) :
|
||||
mzip_hdr.hdr_crc_header;
|
||||
|
||||
mzip_calculate_hdr_crc(&mzip_hdr, &mzip_hdr_crc);
|
||||
mzip_hdr.hdr_crc_header = endian_swap ? SWAP_16(mzip_hdr_crc) :
|
||||
mzip_hdr_crc;
|
||||
|
||||
printf("DEBUG: CRCs: header: %04x file: %04x\n", mzip_hdr_crc,
|
||||
mzip_body_crc);
|
||||
|
||||
mzip_print_header(&mzip_hdr);
|
||||
|
||||
mzip_write_header(fp_out, &mzip_hdr);
|
||||
mzip_write_codeseg(fp_out, mzip_code_seg, mzip_code_seg_size);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,279 @@
|
||||
/* MZIP file manipulation routines
|
||||
* (c) 2008 Philippe Vachon <philippe@cowpig.ca>
|
||||
* Licensed under the GNU General Public License 2.0 or later.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zip.h>
|
||||
|
||||
#include <mzip.h>
|
||||
|
||||
/**
|
||||
* Initialize an mzip_header struct. If hdr is null, returns a new
|
||||
* heap-allocated instance of an mzip_header
|
||||
* @param hdr The header to be initialized to default values. If this value
|
||||
* is NULL, creates a new instance of struct mzip_header on the heap.
|
||||
* @return pointer to hdr; if hdr was NULL, contains a pointer to a new heap-
|
||||
* allocated instance of a struct mzip_header
|
||||
*/
|
||||
struct mzip_header *mzip_initialize(struct mzip_header *hdr)
|
||||
{
|
||||
struct mzip_header *mhdr = hdr;
|
||||
if (mhdr == NULL) {
|
||||
if(!(mhdr = (struct mzip_header *)malloc(MZIP_HDR_SIZE)))
|
||||
{
|
||||
/* unexpected error on allocating memory! */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memset((void *)mhdr, 0x0, MZIP_HDR_SIZE);
|
||||
|
||||
mhdr->hdr_magic[0] = 'M';
|
||||
mhdr->hdr_magic[1] = 'Z';
|
||||
mhdr->hdr_magic[2] = 'I';
|
||||
mhdr->hdr_magic[3] = 'P';
|
||||
|
||||
mhdr->hdr_version = 0x1u;
|
||||
|
||||
return mhdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an MZIP code segment; compresses code segment using ZIP
|
||||
* @param buffer Buffer containing uncompressed data
|
||||
* @param buf_size Size of buffer in bytes
|
||||
* @param out_seg Pointer to pointer to output buffer
|
||||
* @param seg_size size of compressed data stream (pass by reference)
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int mzip_codeseg_build(void *buffer, uint32_t buf_size, void **out_buf,
|
||||
uint32_t *seg_size)
|
||||
{
|
||||
assert(buffer != NULL || out_buf != NULL || seg_size != NULL);
|
||||
|
||||
char tempfile[] = "/tmp/mzipXXXXXX";
|
||||
int errorp = 0;
|
||||
|
||||
/* get a temporary file */
|
||||
mktemp(tempfile);
|
||||
|
||||
/* create the temporary ZIP archive */
|
||||
struct zip *archive = zip_open(tempfile, ZIP_CREATE | ZIP_EXCL, &errorp);
|
||||
|
||||
if (archive == NULL)
|
||||
return -1;
|
||||
|
||||
struct zip_source *source = zip_source_buffer(archive, buffer,
|
||||
buf_size, 0);
|
||||
|
||||
if (source == NULL) {
|
||||
zip_close(archive);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_add(archive, "-", source) < 0) {
|
||||
zip_source_free(source);
|
||||
zip_close(archive);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_close(archive);
|
||||
|
||||
/* now re-read the contents of the archive */
|
||||
FILE *fp = fopen(tempfile, "rb");
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
|
||||
if (stat(tempfile, &st) == -1) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate a buffer to store the contents of the archive: */
|
||||
void *buf = malloc(st.st_size);
|
||||
if (buf == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread(buf, st.st_size, 1, fp);
|
||||
|
||||
*out_buf = buf;
|
||||
*seg_size = st.st_size;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local method to calculate the CRC of a given memory buffer
|
||||
*/
|
||||
static uint16_t calculate_crc(void *buffer, uint32_t offset, uint32_t length,
|
||||
uint16_t remainder)
|
||||
{
|
||||
uint16_t crc_table[256], ent;
|
||||
uint16_t crc = ~remainder;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ent = (uint16_t)i << 8;
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (ent & 0x8000) ent = (ent << 1) ^ 0x1021;
|
||||
else ent <<= 1;
|
||||
}
|
||||
|
||||
crc_table[i] = ent;
|
||||
}
|
||||
|
||||
for (i = offset; i < length; i++) {
|
||||
crc = crc_table[((crc >> 8) ^ ((uint8_t *)buffer)[i]) & 0xff]
|
||||
^ (crc << 8);
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the MZIP CRC for the given buffer
|
||||
* @param buffer Buffer containing data to have the CRC computed
|
||||
* @param buf_size Size of buffer to have the CRC computed on
|
||||
* @param crc output of CRC of buffer. Should be initialized with remainder.
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int mzip_calculate_crc(struct mzip_header *hdr, void *buffer,
|
||||
uint32_t buf_size, uint16_t *crc)
|
||||
{
|
||||
assert(buffer != NULL && crc != NULL);
|
||||
|
||||
uint16_t rem = calculate_crc((void *)hdr, 0x38, 0x70, 0);
|
||||
*crc = calculate_crc((void *)buffer, 0, buf_size, rem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the CRC of the mzip header and the remainder of the mzip
|
||||
* header.
|
||||
*/
|
||||
int mzip_calculate_hdr_crc(struct mzip_header *hdr, uint16_t *hdr_crc)
|
||||
{
|
||||
assert(hdr != NULL);
|
||||
assert(hdr_crc != NULL);
|
||||
|
||||
*hdr_crc = calculate_crc((void *)hdr, 0, 0x36, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an MZIP header to the given file pointer
|
||||
* @param fp File pointer for the file to write the header out to
|
||||
* @param hdr MZIP header to be written out
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int mzip_write_header(FILE *fp, struct mzip_header *hdr)
|
||||
{
|
||||
assert(hdr != NULL && fp != NULL);
|
||||
|
||||
/* TODO: better sanity checks */
|
||||
rewind(fp);
|
||||
fwrite((void *)hdr, MZIP_HDR_SIZE, 1, fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the MZIP code segment.
|
||||
* @param fp File pointer
|
||||
* @param buffer Code segment buffer to be written out
|
||||
* @param buf_size Size of code segment buffer
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int mzip_write_codeseg(FILE *fp, void *buffer, uint32_t buf_size)
|
||||
{
|
||||
assert(fp != NULL && buffer != NULL);
|
||||
|
||||
/* TODO: better sanity checks */
|
||||
|
||||
fseek(fp, MZIP_HDR_SIZE, SEEK_SET);
|
||||
fwrite(buffer, buf_size, 1, fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write MZIP footer tuples
|
||||
* @param fp file handle for output file
|
||||
* @param footer the footer tuples
|
||||
* @param num_entries the number of footer tuple intries
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int mzip_write_footer(FILE *fp, char **footer, uint32_t num_entries)
|
||||
{
|
||||
int length, i;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
for (i = 0; i < num_entries; i++) {
|
||||
length = strlen(footer[i]);
|
||||
fwrite(footer[i], length, 1, fp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a full MZIP file out
|
||||
* @param fp file handle for output file
|
||||
* @param hdr MZIP file header
|
||||
* @param buffer the code segment for the MZIP file
|
||||
* @param buf_size size of code segment buffer
|
||||
* @param footer footer tuple values
|
||||
* @param num_entries number of footer tuple values
|
||||
*/
|
||||
int mzip_write(FILE *fp, struct mzip_header *hdr, void *buffer,
|
||||
uint32_t buf_size, char **footer, uint32_t num_entries)
|
||||
{
|
||||
assert(fp != NULL && hdr != NULL && buffer != NULL && footer != NULL);
|
||||
|
||||
mzip_write_header(fp, hdr);
|
||||
mzip_write_codeseg(fp, buffer, buf_size);
|
||||
mzip_write_footer(fp, footer, num_entries);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out contents of a struct mzip_hdr
|
||||
* @param hdr Pointer to struct mzip_hdr instance
|
||||
*/
|
||||
|
||||
void mzip_print_header(struct mzip_header *hdr)
|
||||
{
|
||||
printf("Magic: %c%c%c%c\n", hdr->hdr_magic[0], hdr->hdr_magic[1],
|
||||
hdr->hdr_magic[2], hdr->hdr_magic[3]);
|
||||
printf("Version: %08x\n", hdr->hdr_version);
|
||||
printf("Entry Point: %08x\n", hdr->hdr_entrypt);
|
||||
printf("Flags 1: %08x\n", hdr->hdr_flags1);
|
||||
printf("Flags 2: %08x\n", hdr->hdr_flags2);
|
||||
printf("CRC Code Segment: %04x\n", hdr->hdr_crc_code);
|
||||
printf("CRC Header: %04x\n", hdr->hdr_crc_header);
|
||||
printf("Header Size: %08x\n", hdr->hdr_header_size);
|
||||
printf("Loader Address: %08x\n", hdr->hdr_loader_addr);
|
||||
printf("Flags 3: %08x\n", hdr->hdr_flags3);
|
||||
printf("Code size (packed): %08x\n", hdr->hdr_code_packed_size);
|
||||
printf("Code size (unpacked): %08x\n", hdr->hdr_code_unpacked_size);
|
||||
printf("Memory Image Size: %08x\n", hdr->hdr_memory_image_size);
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#ifndef __INCLUDE_MZIP_H
|
||||
#define __INCLUDE_MZIP_H
|
||||
|
||||
#include <types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct mzip_header {
|
||||
char hdr_magic[4];
|
||||
uint32_t hdr_version;
|
||||
uint32_t hdr_entrypt;
|
||||
uint32_t hdr_flags1;
|
||||
uint32_t hdr_flags2;
|
||||
uint32_t hdr_padding1[8];
|
||||
uint16_t hdr_crc_code;
|
||||
uint16_t hdr_crc_header;
|
||||
uint32_t hdr_header_size;
|
||||
uint32_t hdr_loader_addr;
|
||||
uint32_t hdr_flags3;
|
||||
uint32_t hdr_code_packed_size;
|
||||
uint32_t hdr_code_unpacked_size;
|
||||
uint32_t hdr_memory_image_size;
|
||||
uint32_t hdr_padding2[8];
|
||||
};
|
||||
|
||||
#define MZIP_HDR_SIZE (sizeof(struct mzip_header))
|
||||
|
||||
/* TODO: define macros to set values of flags fields */
|
||||
|
||||
struct mzip_header *mzip_initialize(struct mzip_header *hdr);
|
||||
|
||||
int mzip_codeseg_build(void *buffer, uint32_t buf_size, void **out_buf,
|
||||
uint32_t *seg_size);
|
||||
|
||||
int mzip_calculate_crc(struct mzip_header *hdr, void *buffer,
|
||||
uint32_t buf_size, uint16_t *crc);
|
||||
|
||||
int mzip_calculate_hdr_crc(struct mzip_header *hdr, uint16_t *hdr_crc);
|
||||
|
||||
int mzip_write_header(FILE *fp, struct mzip_header *hdr);
|
||||
|
||||
int mzip_write_codeseg(FILE *fp, void *buffer, uint32_t buf_size);
|
||||
|
||||
int mzip_write_footer(FILE *fp, char **footer, uint32_t num_entries);
|
||||
|
||||
int mzip_write(FILE *fp, struct mzip_header *hdr, void *buffer,
|
||||
uint32_t buf_size, char **footer, uint32_t num_entries);
|
||||
|
||||
void mzip_print_header(struct mzip_header *hdr);
|
||||
|
||||
#endif /* __INCLUDE_MZIP_H */
|
@ -0,0 +1,36 @@
|
||||
#ifndef _TYPES_H
|
||||
#define _TYPES_H
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
typedef char bool;
|
||||
|
||||
/* define some convenience types */
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
|
||||
/* endianess changes */
|
||||
#define SWAP_32(x) \
|
||||
((uint32_t)( \
|
||||
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
|
||||
|
||||
#define SWAP_16(x) \
|
||||
((uint16_t) (\
|
||||
(((uint16_t)(x) & (uint16_t)0x00ff) << 8) | \
|
||||
(((uint16_t)(x) & (uint16_t)0xff00) >> 8)))
|
||||
|
||||
|
||||
#endif /* _TYPES_H */
|
Loading…
Reference in New Issue