From 34ef9fa66e0b275333f94d585b1bb7d1453f0266 Mon Sep 17 00:00:00 2001 From: Philippe Vachon Date: Thu, 1 Jan 2009 14:56:20 -0500 Subject: [PATCH] Added the elf2mzip tool. --- elf2mzip/Makefile | 23 ++++ elf2mzip/elf.h | 203 ++++++++++++++++++++++++++++++++ elf2mzip/elf2mzip.c | 225 +++++++++++++++++++++++++++++++++++ elf2mzip/mzip.c | 279 ++++++++++++++++++++++++++++++++++++++++++++ elf2mzip/mzip.h | 50 ++++++++ elf2mzip/types.h | 36 ++++++ include/types.h | 2 +- 7 files changed, 817 insertions(+), 1 deletion(-) create mode 100644 elf2mzip/Makefile create mode 100644 elf2mzip/elf.h create mode 100644 elf2mzip/elf2mzip.c create mode 100644 elf2mzip/mzip.c create mode 100644 elf2mzip/mzip.h create mode 100644 elf2mzip/types.h diff --git a/elf2mzip/Makefile b/elf2mzip/Makefile new file mode 100644 index 0000000..7150826 --- /dev/null +++ b/elf2mzip/Makefile @@ -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) diff --git a/elf2mzip/elf.h b/elf2mzip/elf.h new file mode 100644 index 0000000..5d18759 --- /dev/null +++ b/elf2mzip/elf.h @@ -0,0 +1,203 @@ +#ifndef _ELF_H +#define _ELF_H + +#include + +/* 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 */ diff --git a/elf2mzip/elf2mzip.c b/elf2mzip/elf2mzip.c new file mode 100644 index 0000000..d9238e9 --- /dev/null +++ b/elf2mzip/elf2mzip.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include + +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; +} diff --git a/elf2mzip/mzip.c b/elf2mzip/mzip.c new file mode 100644 index 0000000..5dc5589 --- /dev/null +++ b/elf2mzip/mzip.c @@ -0,0 +1,279 @@ +/* MZIP file manipulation routines + * (c) 2008 Philippe Vachon + * Licensed under the GNU General Public License 2.0 or later. + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +/** + * 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); +} diff --git a/elf2mzip/mzip.h b/elf2mzip/mzip.h new file mode 100644 index 0000000..24a589b --- /dev/null +++ b/elf2mzip/mzip.h @@ -0,0 +1,50 @@ +#ifndef __INCLUDE_MZIP_H +#define __INCLUDE_MZIP_H + +#include +#include + +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 */ diff --git a/elf2mzip/types.h b/elf2mzip/types.h new file mode 100644 index 0000000..68a5b42 --- /dev/null +++ b/elf2mzip/types.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 */ diff --git a/include/types.h b/include/types.h index 1d244be..7901978 100644 --- a/include/types.h +++ b/include/types.h @@ -5,7 +5,7 @@ #define NULL 0 typedef unsigned char uint8_t; -typedef char int8_t; +typedef signed char int8_t; typedef unsigned short uint16_t; typedef short int16_t;