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 } 194