From 71478fd62d8483483abb34609cdabb7f9cbadfd6 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 19 Dec 2015 14:18:43 +0000 Subject: Add hostTools from https://github.com/Noltari/cfe_bcm63xx --- hostTools/cmplzma.cpp | 431 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 hostTools/cmplzma.cpp (limited to 'hostTools/cmplzma.cpp') diff --git a/hostTools/cmplzma.cpp b/hostTools/cmplzma.cpp new file mode 100644 index 0000000..29fe406 --- /dev/null +++ b/hostTools/cmplzma.cpp @@ -0,0 +1,431 @@ +/* +<:copyright-broadcom + + Copyright (c) 2002 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +/*************************************************************************** + * File Name : cmplzma.c + * + * Description: This program compress binary file with lzma compression method + * It requires big endian mips32 ELF and the bin files as the input + * for CFE and vmlinux. + * + * For CFE RAM compress: + * Command: cmplzma [-t] -c -2 cfe cfe.bin flashimg.S + * where cfe is elf, cfe.bin is + * binary file to be compressed and flashimg.S is Asm data array for + * the compressed binary to be linked in as data. + * + * For vmlinux: + * Command: cmplzma [-t] -k -2 vmlinux vmlinux.bin vmlinux.lz + * where vmlinux is the elf file, vmliux.bin the binary file + * and vmlinux.lz is the compressed output + * + * Updates : 04/08/2003 seanl. Created. + * + ***************************************************************************/ + +/* Includes. */ +#include +#include +#include +#include +#include +#include +#include + +#include "7z.h" + + +// elf structs and defines from CFE + +/* p_type */ +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved, unspecified semantics */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_LOPROC 0x70000000 /* Processor-specific */ +#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */ + +#define CFE_ERR_NOTELF -11 +#define CFE_ERR_NOT32BIT -12 +#define CFE_ERR_WRONGENDIAN -13 +#define CFE_ERR_BADELFVERS -14 +#define CFE_ERR_NOTMIPS -15 +#define CFE_ERR_BADELFFMT -16 +#define CFE_ERR_BADADDR -17 + +/* e_indent */ +#define EI_MAG0 0 /* File identification byte 0 index */ +#define EI_MAG1 1 /* File identification byte 1 index */ +#define EI_MAG2 2 /* File identification byte 2 index */ +#define EI_MAG3 3 /* File identification byte 3 index */ +#define EI_CLASS 4 /* File class */ + +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define EI_DATA 5 /* Data encoding */ + +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define EI_VERSION 6 /* File version */ +#define EI_PAD 7 /* Start of padding bytes */ + +#define ELFMAG0 0x7F /* Magic number byte 0 */ +#define ELFMAG1 'E' /* Magic number byte 1 */ +#define ELFMAG2 'L' /* Magic number byte 2 */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +typedef unsigned short Elf32_Half; +typedef unsigned int Elf32_Word; +typedef signed int Elf32_Sword; +typedef unsigned int Elf32_Off; +typedef unsigned int Elf32_Addr; +typedef unsigned char Elf_Char; +/* + * ELF File Header + */ +#define EI_NIDENT 16 +typedef struct { + Elf_Char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* + * Program Header + */ +typedef struct { + Elf32_Word p_type; /* Identifies program segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment, file & memory */ +} Elf32_Phdr; + +int getElfInfo(char *elfFile, Elf32_Addr *eEntry, Elf32_Addr *pVaddr); + +// Check the elf file validity and extract the program entry and text +// start address +int getElfInfo(char *elfFile, Elf32_Addr *eEntry, Elf32_Addr *pVaddr) +{ + Elf32_Ehdr *ep; + Elf32_Phdr *phtab = 0; + unsigned int nbytes; + int i; + Elf32_Ehdr ehdr; + FILE *hInput; + + if ((hInput = fopen(elfFile, "rb")) == NULL) + { + printf("Error open file: %s\n", elfFile); + return -1; + } + + if (fread((char *) &ehdr, sizeof(char), sizeof(ehdr), hInput) != sizeof(ehdr)) + { + printf("Error reading file: %s\n", elfFile); + return -1; + } + + ep = &ehdr; + + *eEntry = ep->e_entry; + + /* check header validity */ + if (ep->e_ident[EI_MAG0] != ELFMAG0 || + ep->e_ident[EI_MAG1] != ELFMAG1 || + ep->e_ident[EI_MAG2] != ELFMAG2 || + ep->e_ident[EI_MAG3] != ELFMAG3) + { + printf("Not ELF file\n"); + return CFE_ERR_NOTELF; + } + + if (ep->e_ident[EI_CLASS] != ELFCLASS32) + { + printf("Not 32 bit elf\n"); + return CFE_ERR_NOT32BIT; + } + + if (ep->e_ident[EI_DATA] != ELFDATA2MSB) + { + printf("Not BIG Endian\n"); + return CFE_ERR_WRONGENDIAN; /* big endian */ + } + + /* Is there a program header? */ + if (ep->e_phoff == 0 || ep->e_phnum == 0) + { + printf("No program header? Wrong elf file\n"); + return CFE_ERR_BADELFFMT; + } + + /* Load program header */ + ep->e_phnum = htons(ep->e_phnum); + ep->e_phoff = htonl(ep->e_phoff); + nbytes = ep->e_phnum * sizeof(Elf32_Phdr); + phtab = (Elf32_Phdr *) malloc(nbytes); + if (!phtab) + { + printf("Failed to malloc memory!\n"); + return -1; + } + + if (fseek(hInput, ep->e_phoff, SEEK_SET)!= 0) + { + free(phtab); + printf("File seek error\n"); + return -1; + } + if (fread((unsigned char *)phtab, sizeof(char), nbytes, hInput) != nbytes) + { + free(phtab); + printf("File read error\n"); + return -1; + } + + for (i = 0; i < ep->e_phnum; i++) + { + Elf32_Off lowest_offset = ~0; + Elf32_Phdr *ph = 0; + ph = &phtab[i]; + phtab[i].p_offset = htonl(phtab[i].p_offset); + phtab[i].p_type = htonl(phtab[i].p_type); + if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) + { + ph = &phtab[i]; + lowest_offset = ph->p_offset; + *pVaddr = ph->p_vaddr; // found the text start address + return 0; + } + } + printf("No text start address found! Wrong elf file ?\n"); + return -1; +} + +void usage(char *pName) +{ + printf("Example:\n"); + printf("To compress CFE ram : %s -c -2 inputElfFile inputBinFile outputAsmFile\n", pName); + printf("To compress linux Kernel: %s -k -2 inputElfFile inputBinFile outputCompressedFile\n\n", pName); + printf("NOTE: -2 is the default compression level. Allowable levels are -1 through -3\n"); + printf("where -3 may yield better compression ratio but slower. For faster compression, use -1\n"); + exit(-1); +} + +/************************************************************* + * Function Name: main + * Description : Program entry point that parses command line parameters + * and calls a function to create the image. + * Returns : 0 + ***************************************************************************/ +int main (int argc, char **argv) +{ + FILE *hInput = NULL, *hOutput = NULL; + struct stat StatBuf; + char inputElfFile[256], inputBinFile[256], outputFile[256], segment[6]; + unsigned char *inData, *outData; + bool status; + unsigned long outLen, inLen; + int cmpKernel = 0; + Elf32_Addr entryPoint; + Elf32_Addr textAddr; + unsigned lzma_algo; + unsigned lzma_dictsize; + unsigned lzma_fastbytes; + int lzma_compression_level; + int ret; + char *pgmName = argv[0]; + + if (argc == 7 && strcmp(argv[1], "-t") == 0) + { + strcpy(segment, ".text"); + argc--; + argv++; + } + else + strcpy(segment, ".data"); + + if (argc != 6) + usage(pgmName); + + if (strcmp(argv[1], "-k") == 0) + cmpKernel = 1; + else if (strcmp(argv[1], "-c") != 0) + usage(pgmName); + + if (strcmp(argv[2], "-1") == 0) + lzma_compression_level = 1; + else if (strcmp(argv[2], "-2") == 0) + lzma_compression_level = 2; + else if (strcmp(argv[2], "-3") == 0) + lzma_compression_level = 3; + else + usage(pgmName); + + strcpy(inputElfFile, argv[3]); + strcpy(inputBinFile, argv[4]); + strcpy(outputFile, argv[5]); + + if ((ret = getElfInfo(inputElfFile, &entryPoint, &textAddr)) != 0) + return -1; + + printf("Code text starts: textAddr=0x%08X Program entry point: 0x%08X,\n", + (unsigned int)(htonl(textAddr)), (unsigned int)(htonl(entryPoint))); + + if (stat(inputBinFile, &StatBuf ) == 0 && (hInput = fopen(inputBinFile, "rb" )) == NULL) + { + printf( "Error opening input file %s.\n\n", inputBinFile); + return -1; + } + + inData = (unsigned char *) malloc(StatBuf.st_size); + outData = (unsigned char *) malloc((StatBuf.st_size+2) * 5); // make sure we have enough output buf + + if (!inData || !outData) + { + printf( "Memory allocation error, in=0x%8.8lx, out=0x%8.8lx.\n\n", + (unsigned long) inData, (unsigned long) outData); + fclose( hInput ); + return -1; + } + + if (fread(inData, sizeof(char), StatBuf.st_size, hInput) != StatBuf.st_size) + { + printf( "Error read input file %s.\n\n", inputBinFile); + return -1; + } + + inLen = StatBuf.st_size; + + // compression function + switch (lzma_compression_level) + { + case 1 : + lzma_algo = 1; + lzma_dictsize = 1 << 20; + lzma_fastbytes = 64; + break; + case 2 : + lzma_algo = 2; + lzma_dictsize = 1 << 22; + lzma_fastbytes = 128; + break; + case 3 : + lzma_algo = 2; + lzma_dictsize = 1 << 24; + lzma_fastbytes = 255; + break; + default : + printf("Invalid LZMA compression level."); + } + outLen = 23*1024*1024; + status = compress_lzma_7z((const unsigned char*) inData, + (unsigned) inLen, + (unsigned char*) outData, + (unsigned &) outLen, + lzma_algo, + lzma_dictsize, + lzma_fastbytes); + if (status != true) + { + /* this should NEVER happen */ + printf("Internal error - LZMA compression failed.\n"); + return false; + } + + /* Open output file. */ + if ((hOutput = fopen(outputFile, "w+" )) == NULL) + { + printf ("Error opening output file %s.\n\n", outputFile); + return -1; + } + + if (cmpKernel) + { + unsigned long swapedOutLen = htonl(outLen); //little Endia on build host and big Endia on target + if (fwrite(&textAddr, sizeof(Elf32_Addr), 1, hOutput) != 1 || + fwrite(&entryPoint, sizeof(Elf32_Addr), 1, hOutput) != 1 || + fwrite(&swapedOutLen, sizeof(unsigned long), 1, hOutput) != 1 || + fwrite(outData, sizeof(char), outLen, hOutput) != outLen) + printf( "Error writing to output file.\n\n" ); + } + else // write the asm file for CFE + { + struct tm *newtime; + time_t aclock; + int i; + unsigned char *curPtr = outData, *endPtr = outData + outLen; + unsigned char *entryPtr = (unsigned char*) &entryPoint; + + time( &aclock ); /* Get time in seconds */ + newtime = localtime( &aclock ); /* Convert time to struct */ + fprintf(hOutput, "/* Convert binary to asm\n Input file : %s\n Output file: %s\n Date : %s*/\n" + , inputBinFile, outputFile, asctime(newtime)); + fprintf(hOutput, "%s", "\t.globl _binArrayStart\n"); + fprintf(hOutput, "%s", "\t.globl _binArrayEnd\n"); + fprintf(hOutput, "\t%s\n\n", segment); + fprintf(hOutput, "%s", "_binArrayStart:"); + // write 4 bytes of entry point first + fprintf(hOutput, "%s%04o", "\n\t\t.byte ", (unsigned int) *entryPtr++); + fprintf(hOutput, ",%04o", (unsigned int) *entryPtr++); + fprintf(hOutput, ",%04o", (unsigned int) *entryPtr++); + fprintf(hOutput, ",%04o", (unsigned int) *entryPtr); + i = 4; + for (; curPtr < endPtr; curPtr++) + { + if (i == 0) + fprintf(hOutput, "%s%04o", "\n\t\t.byte ", (unsigned int) *curPtr); + else + fprintf(hOutput, ",%04o", (unsigned int) *curPtr); + if (++i == 16) + i = 0; + } + fprintf(hOutput, "%s", "\n_binArrayEnd:\n"); + } + + fclose( hOutput ); + + printf("Before compression: %ld After compression (level=%d): %ld\n\r", inLen, lzma_compression_level, outLen); + printf("Percent Compression = %.2f\n\r", (float)((float)(inLen - outLen)/(float)inLen)*(float)100); + + if(inData) + free(inData); + if(outData) + free(outData); + fclose(hInput); + + return(0); +} + + -- cgit v1.2.3