diff options
author | Daniel Drake <dsd@laptop.org> | 2009-12-21 20:23:48 (GMT) |
---|---|---|
committer | Daniel Drake <dsd@laptop.org> | 2009-12-21 20:23:48 (GMT) |
commit | b802b6641dff5c6e7d903e8d41116b8c2133ea25 (patch) | |
tree | 656774343a78fe36e7220579879ff53f43279908 /bin |
Initial import
Basic functionality is working, needs more testing and a comparison
to the OLPC OS 10.1.0 release.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/Makefile | 13 | ||||
-rw-r--r-- | bin/crc32.c | 19 | ||||
-rw-r--r-- | bin/crc32.h | 14 | ||||
-rw-r--r-- | bin/crcimg.c | 96 | ||||
-rw-r--r-- | bin/zhashfs.c | 158 |
5 files changed, 300 insertions, 0 deletions
diff --git a/bin/Makefile b/bin/Makefile new file mode 100644 index 0000000..d1cfc3b --- /dev/null +++ b/bin/Makefile @@ -0,0 +1,13 @@ +CC=gcc + +all: crcimg zhashfs + +crcimg: crc32.c crcimg.c + $(CC) $^ -o $@ + +zhashfs: zhashfs.c + $(CC) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DARGTYPE=1 $^ -o $@ -I/usr/include/tomcrypt -ltomcrypt -lz + +clean: + rm -f crcimg zhashfs + diff --git a/bin/crc32.c b/bin/crc32.c new file mode 100644 index 0000000..ac3eab8 --- /dev/null +++ b/bin/crc32.c @@ -0,0 +1,19 @@ +/* Ripped from the linux kernel crc32 code + * + * This source code is licensed under the GNU General Public License, + * Version 2. + */ + +#include "crc32.h" + +u32 crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + return crc; +} + diff --git a/bin/crc32.h b/bin/crc32.h new file mode 100644 index 0000000..d2a65fe --- /dev/null +++ b/bin/crc32.h @@ -0,0 +1,14 @@ +/* Ripped from the linux kernel crc32 code + * + * This source code is licensed under the GNU General Public License, + * Version 2. + */ +#include <stdint.h> +#include <stddef.h> + +typedef uint32_t u32; + +extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len); +#define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length) +#define CRCPOLY_LE 0xedb88320 + diff --git a/bin/crcimg.c b/bin/crcimg.c new file mode 100644 index 0000000..46a918e --- /dev/null +++ b/bin/crcimg.c @@ -0,0 +1,96 @@ +/* + * crcimg - calculates a CRC32 for each 0x20000 block of the input file + * Used for checking JFFS2 NAND FLASH installation images. + * Copyright 2007, Mitch Bradley + * License: GPL v2 + * Tip 'o the hat to Richard Smith + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> + +#include "crc32.h" + +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 0 + +#define EBSIZE 0x20000 + +static unsigned char buf[EBSIZE]; +static FILE *imagefile; +static FILE *crcfile; +char outfilename[FILENAME_MAX]; + +void usage(const char *name) +{ + printf("%s Ver: %d.%d.%d\n",name,VER_MAJOR,VER_MINOR,VER_RELEASE); + printf("usage: %s [file.img]\n", name); + printf("Creates file.crc containing CRCs for each 0x20000 byte block in file.img\n"); + printf("With no arguments, filters standard input, writing CRC list to standard output\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int opt=0; + int option_index = 0; + size_t bytes_read=0; + + static struct option long_options[]= { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + setbuf(stdout, NULL); + while ((opt = getopt_long(argc, argv, "h", long_options, + &option_index)) != EOF) { + switch (opt) { + case 'h': + default: + usage(argv[0]); + break; + } + } + + char *filename = NULL; + + if (optind < argc) { + /* Filename supplied */ + filename = argv[optind++]; + if ((strlen(filename) >= 4) && (strcmp(filename + strlen(filename) - 4, ".img") == 0)) { + strncpy(outfilename, filename, FILENAME_MAX); + strcpy(outfilename + strlen(filename) - 4, ".crc"); + } else { + strncpy(outfilename, filename, FILENAME_MAX); + strncat(outfilename, ".crc", FILENAME_MAX - strlen(outfilename)); + } + if ((imagefile = fopen(filename, "r+")) == NULL) { + perror(filename); + exit(1); + } + if ((crcfile = fopen(outfilename, "w+")) == NULL) { + perror(outfilename); + exit(1); + } + } else { + /* Use standard in/out */ + imagefile = stdin; + crcfile = stdout; + } + + while ((bytes_read = fread(buf, sizeof(char), EBSIZE, imagefile)) == EBSIZE) { + fprintf(crcfile, "%08lx\n", (unsigned long)~crc32(0xffffffff, buf, EBSIZE)); + } + + if (bytes_read != 0) { + printf("Input file size is not a multiple of 0x%x - residue 0x%x\n", EBSIZE, bytes_read); + fclose(crcfile); + exit(1); + } + + fclose(crcfile); + return 0; +} diff --git a/bin/zhashfs.c b/bin/zhashfs.c new file mode 100644 index 0000000..7f7bcc0 --- /dev/null +++ b/bin/zhashfs.c @@ -0,0 +1,158 @@ +// Handle partitions +#include <stdio.h> + +#define TFM_DESC +#include <tomcrypt.h> +#include "zlib.h" + +#define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x); } while (0); +void run_cmd(int res, int line, char *file, char *cmd) +{ + if (res != CRYPT_OK) { + fprintf(stderr, "%s (%d)\n%s:%d:%s\n", error_to_string(res), res, file, line, cmd); + if (res != CRYPT_NOP) { + exit(EXIT_FAILURE); + } + } +} + +int main(int argc, char **argv) +{ + char *fname; + char *hashname; + unsigned char *buf; // EBLOCKSIZE + unsigned char md[MAXBLOCKSIZE], sig[512]; + unsigned long mdlen; + FILE *infile, *outfile; + long eblocks = -1; + long i; + long zblocksize, zbufsize; + off_t insize; + int hashid, readlen; + int j; + + int allf; + int zresult; + FILE *zfile; + uLongf zlen; + unsigned char *p; + unsigned char *zbuf; // ZBUFSIZE + + if (argc < 6) { + fprintf(stderr, "%s: zblocksize hashname signed_file_name spec_file_name zdata_file_name [ #blocks ]\n", argv[0]); + return EXIT_FAILURE; + } + + if (argc == 7) + eblocks = strtol(argv[6], 0, 0); + + zblocksize = strtol(argv[1], 0, 0); + + buf = malloc(zblocksize); + LTC_ARGCHK(buf != 0); + + /* + * For zlib compress, the destination buffer needs to be 1.001 x the + * src buffer size plus 12 bytes + */ + zbufsize = ((zblocksize * 102) / 100) + 12; + zbuf = malloc(zbufsize); + LTC_ARGCHK(zbuf != 0); + + LTC_ARGCHK(register_hash(&sha256_desc) != -1); + LTC_ARGCHK(register_hash(&rmd160_desc) != -1); + LTC_ARGCHK(register_hash(&md5_desc) != -1); + + hashname = argv[2]; + hashid = find_hash(hashname); + LTC_ARGCHK(hashid >= 0); + + /* open filesystem image file */ + infile = fopen(argv[3], "rb"); + LTC_ARGCHK(infile != NULL); + + /* open output file */ + outfile = fopen(argv[4], "wb"); + LTC_ARGCHK(outfile != NULL); + + /* open zdata file */ + zfile = fopen(argv[5], "wb"); + LTC_ARGCHK(zfile != NULL); + + if (eblocks == -1) { + (void)fseek(infile, 0L, SEEK_END); + insize = ftello(infile); + (void)fseek(infile, 0L, SEEK_SET); + + eblocks = (insize + zblocksize - 1) / zblocksize; +// LTC_ARGCHK((eblocks * zblocksize) == insize); + } + + /* Remove possible path prefix */ + fname = strrchr(argv[5], '/'); + if (fname == NULL) + fname = argv[5]; + else + ++fname; + + fprintf(outfile, "data: %s\n", fname); + fprintf(outfile, "zblocks: %x %x\n", zblocksize, eblocks); + fprintf(zfile, "zblocks: %x %x\n", zblocksize, eblocks); + + fprintf(stdout, "Total blocks: %d\n", eblocks); + + /* make a hash of the file */ + for (i=0; i < eblocks; i++) { + readlen = fread(buf, 1, zblocksize, infile); + if (readlen != zblocksize && readlen && i == eblocks-1) { + for (p = &buf[readlen]; p < &buf[zblocksize]; p++) { + *p = 0xff; + } + readlen = zblocksize; + } + LTC_ARGCHK(readlen == zblocksize); + +#ifdef notdef + allf = 1; + for (p = (unsigned char *)buf; p < &buf[zblocksize]; p++) { + if (*p != 0xff) { + allf = 0; + break; + } + } +#else + allf = 0; +#endif + + if (!allf) { + mdlen = sizeof(md); + DO(hash_memory(hashid, buf, zblocksize, md, &mdlen)); + + zlen = zbufsize; + if ((zresult = compress(zbuf, &zlen, buf, zblocksize)) != Z_OK) { + fprintf(stderr, "Compress failure at block 0x%x - %d\n", i, zresult); + } + + fprintf(outfile, "zblock: %x %x %s ", i, zlen, hashname); + for(j=0; j<mdlen; j++) + fprintf(outfile,"%02x",md[j]); + fprintf(outfile, "\n"); + + fprintf(zfile, "zblock: %x %x %s ", i, zlen, hashname); + for(j=0; j<mdlen; j++) + fprintf(zfile,"%02x",md[j]); + fprintf(zfile, "\n"); + fwrite(zbuf, sizeof(char), zlen, zfile); + fprintf(zfile, "\n"); + } + fprintf(stdout, "\r%d", i); fflush(stdout); + } + fprintf(outfile, "zblocks-end:\n"); + fprintf(zfile, "zblocks-end:\n"); + + fclose(infile); + fclose(outfile); + + putchar('\n'); + return EXIT_SUCCESS; +} |