8100af14cdbc95b6b268d7c5668fb831a46143a7
[dragonfly.git] / tools / multimedia / cxm / extract_fw / cxm_extract_fw.c
1 /*-
2  * Copyright (c) 2003
3  *      John Wehle <john@feith.com>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Wehle.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Conexant MPEG-2 Codec firmware extraction program.
32  *
33  * Generates:
34  *
35  * - cxm_dec_fw.c and cxm_enc_fw.c from the
36  * Hauppauge PVR-250 / PVR-350 Microsoft Windows driver
37  * (i.e. hcwpvrp2.sys).
38  *
39  * - cxm_cx2584x_fw.c from the Hauppauge PVR-150 / PVR-500
40  * Microsoft Windows driver (i.e. HcwMakoC.ROM). (optional)
41  *
42  * This was written using the invaluable information
43  * compiled by The IvyTV Project (ivtv.sourceforge.net).
44  */
45
46 #include <sys/types.h>
47 #include <sys/mman.h>
48 #include <sys/param.h>
49 #include <sys/stat.h>
50
51 #include <err.h>
52 #include <fcntl.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 const uint8_t decoder_magic[] = {
59         0xa7, 0x03, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
60 };
61 const uint8_t encoder_magic[] = {
62         0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
63 };
64
65 static int
66 save_firmware(const char *name, const uint8_t *buf, size_t nbytes)
67 {
68         FILE *ofp;
69         char outfile[MAXPATHLEN];
70         size_t i;
71
72         if (nbytes > (256 * 1024))
73                 nbytes = 256 * 1024;
74
75         if ((size_t)snprintf(outfile, sizeof(outfile), "%s.c", name) >=
76             sizeof(outfile))
77                 errx(1, "save_firmware -- firmware name is too long");
78
79         if (!(ofp = fopen(outfile, "w")))
80                 err(1, "save_firmware -- can't open output file <%s>",
81                     outfile);
82
83         fprintf(ofp, "#include <sys/types.h>\n"
84             "\n"
85             "const uint8_t %s[] __attribute__ ((aligned(4))) = {",
86             name);
87
88         for (i = 0; i < nbytes; i++) {
89                 if (i)
90                         fputc(',', ofp);
91                 if ((i % 8) == 0)
92                         fputs("\n\t", ofp);
93                 else
94                         fputc(' ', ofp);
95                 fprintf(ofp, "0x%.2x", buf[i]);
96         }
97
98         fprintf(ofp, "\n};\n");
99
100         if (ferror(ofp)) {
101                 fclose(ofp);
102                 return -1;
103         }
104
105         fclose(ofp);
106         return 0;
107 }
108
109
110 int
111 main(int argc, char **argv)
112 {
113         uint8_t *end;
114         uint8_t *ptr;
115         uint8_t *start;
116         int decoder_fw_saved = 0;
117         int encoder_fw_saved = 0;
118         int fd, i;
119         struct stat statbuf;
120
121         if (argc != 2) {
122                 fprintf(stderr, "usage: cxm_extract_fw file\n");
123                 exit(1);
124         }
125
126         for (i = 1; i <= (argc - 1); i++) {
127                 /*
128                  * Open the file.
129                  */
130                 if ((fd = open(argv[i], O_RDONLY)) < 0)
131                 err(1, "can't open %s for reading", argv[i]);
132
133                 /*
134                  * Determine how big it is.
135                  */
136                 if (fstat(fd, &statbuf) < 0) {
137                         close(fd);
138                         err(1, "can't fstat %s", argv[i]);
139                 }
140
141                 /*
142                  * Map it into memory.
143                  */
144                 if (!(start = (uint8_t *)mmap(NULL, (size_t) statbuf.st_size,
145                             PROT_READ, MAP_SHARED, fd, (off_t) 0))) {
146                         close(fd);
147                         err(1, "can't mmap %s", argv[i]);
148                 }
149                 end = start + statbuf.st_size;
150
151                 close(fd);
152
153                 if (statbuf.st_size > 100000) {
154                         for (ptr = start; ptr != end; ptr++) {
155                                 if ((size_t)(end - ptr) >= sizeof(decoder_magic) &&
156                                     memcmp(ptr, decoder_magic, sizeof(decoder_magic)) == 0) {
157                                         if (!decoder_fw_saved) {
158                                                 if (save_firmware("cxm_dec_fw", ptr, end - ptr) < 0)
159                                                         errx(1, "save_firmware failed");
160                                                 decoder_fw_saved = 1;
161                                         } else {
162                                                 errx(1, "multiple decoder images present");
163                                         }
164                                 }
165                                 if ((size_t)(end - ptr) >= sizeof(encoder_magic) &&
166                                     memcmp(ptr, encoder_magic, sizeof(encoder_magic)) == 0) {
167                                         if (!encoder_fw_saved) {
168                                                 if (save_firmware("cxm_enc_fw", ptr, end - ptr) < 0)
169                                                         errx(1, "save_firmware failed");
170                                                 encoder_fw_saved = 1;
171                                         } else {
172                                                 errx(1, "multiple encoder images present");
173                                         }
174                                 }
175                         }
176                 } else {
177                         errx(1, "save_firmware failed");
178                 }
179
180                 munmap((caddr_t)start, (size_t)statbuf.st_size);
181
182                 if (!decoder_fw_saved)
183                         errx(1, "decoder image not present");
184
185                 if (!encoder_fw_saved)
186                         errx(1, "encoder image not present");
187
188                 if (!decoder_fw_saved || !encoder_fw_saved)
189                         exit(1);
190         }
191
192         exit(0);
193 }