video: tegra: host: power module before access
[linux-2.6.git] / firmware / ihex2fw.c
index 9e77cd2..cf38e15 100644 (file)
@@ -20,6 +20,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
 
 struct ihex_binrec {
        struct ihex_binrec *next; /* not part of the real data structure */
@@ -51,34 +54,53 @@ static void file_record(struct ihex_binrec *record);
 static int output_records(int outfd);
 
 static int sort_records = 0;
+static int wide_records = 0;
+static int include_jump = 0;
+
+static int usage(void)
+{
+       fprintf(stderr, "ihex2fw: Convert ihex files into binary "
+               "representation for use by Linux kernel\n");
+       fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n");
+       fprintf(stderr, "       -w: wide records (16-bit length)\n");
+       fprintf(stderr, "       -s: sort records by address\n");
+       fprintf(stderr, "       -j: include records for CS:IP/EIP address\n");
+       return 1;
+}
 
 int main(int argc, char **argv)
 {
        int infd, outfd;
        struct stat st;
        uint8_t *data;
+       int opt;
 
-       if (argc == 4 && !strcmp(argv[1], "-s")) {
-               sort_records = 1;
-               argc--;
-               argv++;
-       }
-       if (argc != 3) {
-       usage:
-               fprintf(stderr, "ihex2fw: Convert ihex files into binary "
-                               "representation for use by Linux kernel\n");
-               fprintf(stderr, "usage: ihex2fw [-s] <src.HEX> <dst.fw>\n");
-               fprintf(stderr, "       -s: sort records by address\n");
-               return 1;
+       while ((opt = getopt(argc, argv, "wsj")) != -1) {
+               switch (opt) {
+               case 'w':
+                       wide_records = 1;
+                       break;
+               case 's':
+                       sort_records = 1;
+                       break;
+               case 'j':
+                       include_jump = 1;
+                       break;
+                       return usage();
+               }
        }
-       if (!strcmp(argv[1], "-"))
+
+       if (optind + 2 != argc)
+               return usage();
+
+       if (!strcmp(argv[optind], "-"))
            infd = 0;
        else
-               infd = open(argv[1], O_RDONLY);
+               infd = open(argv[optind], O_RDONLY);
        if (infd == -1) {
                fprintf(stderr, "Failed to open source file: %s",
                        strerror(errno));
-               goto usage;
+               return usage();
        }
        if (fstat(infd, &st)) {
                perror("stat");
@@ -90,26 +112,26 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       if (!strcmp(argv[2], "-"))
+       if (!strcmp(argv[optind+1], "-"))
            outfd = 1;
        else
-               outfd = open(argv[2], O_TRUNC|O_CREAT|O_WRONLY, 0644);
+               outfd = open(argv[optind+1], O_TRUNC|O_CREAT|O_WRONLY, 0644);
        if (outfd == -1) {
                fprintf(stderr, "Failed to open destination file: %s",
                        strerror(errno));
-               goto usage;
+               return usage();
        }
        if (process_ihex(data, st.st_size))
                return 1;
 
-       output_records(outfd);
-       return 0;
+       return output_records(outfd);
 }
 
 static int process_ihex(uint8_t *data, ssize_t size)
 {
        struct ihex_binrec *record;
        uint32_t offset = 0;
+       uint32_t data32;
        uint8_t type, crc = 0, crcbyte = 0;
        int i, j;
        int line = 1;
@@ -130,7 +152,10 @@ next_record:
        }
 
        len = hex(data + i, &crc); i += 2;
-
+       if (wide_records) {
+               len <<= 8;
+               len += hex(data + i, &crc); i += 2;
+       }
        record = malloc((sizeof (*record) + len + 3) & ~3);
        if (!record) {
                fprintf(stderr, "out of memory for records\n");
@@ -202,8 +227,14 @@ next_record:
                        return -EINVAL;
                }
 
+               memcpy(&data32, &record->data[0], sizeof(data32));
+               data32 = htonl(data32);
+               memcpy(&record->data[0], &data32, sizeof(data32));
+
                /* These records contain the CS/IP or EIP where execution
-                * starts. Don't really know what to do with them. */
+                * starts. If requested output this as a record. */
+               if (include_jump)
+                       file_record(record);
                goto next_record;
 
        default:
@@ -229,19 +260,21 @@ static void file_record(struct ihex_binrec *record)
 
 static int output_records(int outfd)
 {
-       unsigned char zeroes[5] = {0, 0, 0, 0, 0};
+       unsigned char zeroes[6] = {0, 0, 0, 0, 0, 0};
        struct ihex_binrec *p = records;
 
        while (p) {
                uint16_t writelen = (p->len + 9) & ~3;
 
                p->addr = htonl(p->addr);
-               p->len = htonl(p->len);
-               write(outfd, &p->addr, writelen);
+               p->len = htons(p->len);
+               if (write(outfd, &p->addr, writelen) != writelen)
+                       return 1;
                p = p->next;
        }
        /* EOF record is zero length, since we don't bother to represent
           the type field in the binary version */
-       write(outfd, zeroes, 5);
+       if (write(outfd, zeroes, 6) != 6)
+               return 1;
        return 0;
 }