/*************************************************************** * * OpenPCD.org - main entry for LPC flashing tool * * Copyright 2010 Milosch Meriac * Copyright 2010 Henryk Plötz * *************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Library includes. */ #include #include #include #include #include #include /* static buffer for the maximal flash size: 32 kibibytes */ static uint8_t data[32 * 1024]; static void print_usage(char *progname) { fprintf(stderr, "usage: %s inputfirmware.bin \"/media/CRP DISABLD/firmware.bin\"\n\n" "Either or both input and output may be -, which indicates to work\n" "on stdin or stdout\n\n", progname); } static int parse_arguments(int argc, char **argv, int *input, int *output) { if (argc != 3) { print_usage(argv[0]); return 0; } /* open input file */ if (strcmp(argv[1], "-") != 0) { if ((*input = open(argv[1], O_RDONLY)) == -1) { perror("Can't open input file for reading"); return 0; } } else { *input = 0; } /* open output file */ if (strcmp(argv[2], "-") != 0) { if ((*output = open(argv[2], O_WRONLY | O_CREAT, 00664)) == -1) { perror("Can't open output file for writing"); close(*input); return 0; } } else { *output = 1; } return 1; } /** * Converts Little-Endian data to host byte order * \param ledata is a 32-bit integer stored in little endian order * \return \e ledata converted to host byte order */ uint32_t letohl(uint32_t ledata) { /* first convert input to big endian, then use ntohl */ uint32_t bedata = (((ledata >> 0) & 0xff) << 24) | (((ledata >> 8) & 0xff) << 16) | (((ledata >> 16) & 0xff) << 8) | (((ledata >> 24) & 0xff) << 0); return ntohl(bedata); } /** * Converts host byte order data to Little-Endian * \param hdata is a 32-bit integer stored in host byte order * \return \e hdata converted to little endian order */ uint32_t htolel(uint32_t hdata) { /* use htonl, then convert from big endian */ uint32_t bedata = htonl(hdata); return (((bedata >> 0) & 0xff) << 24) | (((bedata >> 8) & 0xff) << 16) | (((bedata >> 16) & 0xff) << 8) | (((bedata >> 24) & 0xff) << 0); } int main(int argc, char **argv) { int input = -1, output = -1; if (!parse_arguments(argc, argv, &input, &output)) { return 1; } /* Read in the entire input file */ ssize_t len_read, input_size = 0; while ((len_read = read(input, data + input_size, sizeof(data) - input_size)) > 0) { input_size += len_read; } if (input_size < 8 * 4) { fprintf(stderr, "Error: Input file is too small, does not contain \n" "at least 8 interrupt vectors\n"); print_usage(argv[0]); return 2; } /* Now sum over the first 7 ISR values */ uint32_t accumulator = 0, isr_value; for (int i = 0; i < 7; i++) { isr_value = ((uint32_t *) data)[i]; /* The contents in the file are stored in little endian, need to * convert to host byte order. */ isr_value = letohl(isr_value); accumulator += isr_value; } /* The checksum is the twos complement of the sum */ uint32_t checksum = ~accumulator + 1; /* Needs to be converted to little endian when storing */ ((uint32_t *) data)[7] = htolel(checksum); /* Now write out the whole file */ ssize_t len_written, output_size = 0; while ((len_written = write(output, data + output_size, input_size - output_size)) > 0) { output_size += len_written; } if (output_size != input_size) { perror("couldn't write complete output file, flash size might be" "smaller than input size"); } /* close & flush files */ close(input); fsync(output); close(output); return 0; }