1 static const char *title =\
2 "Broadcom Consumer Router Firmware Header Dump"
4 static const float VERSION = 1.0f;
6 static const char *copyright = \
7 "Copyright 2015-2016 TJ <hacker@iam.tj>\n"
8 "Licensed on the terms of the GNU General Public License version 3\n"
11 static const char *help = \
12 "For routers using the Broadcom CFE ((Customer Premises Equipment) CPE Firmware Environment) and firmware update files.\n\n"
14 "Displays the fields of the firmware update file header structure.\n\n"
21 #include <sys/types.h>
25 #include <arpa/inet.h>
29 #define BCMTAG_EXE_USE 1
31 #include "heap_reap.h"
34 static unsigned int MESSAGE_SIZE = 1024;
41 " -h show additional help\n"
49 pr_error_exit(unsigned int usage, const char *error, ...)
52 char error_message[MESSAGE_SIZE + 1];
56 va_start(args, error);
57 (void) vsnprintf(error_message, MESSAGE_SIZE + 1, error, args);
59 fprintf(stderr, "Error: %s\n", error_message);
61 if (usage) pr_usage(usage);
63 heap_and_reap(NULL-1, 0, 0);
67 /* calculate standard CRC32
69 * @param data pointer to start of input data
70 * @param len length in bytes of data to be checksummed
71 * @param crc32 seed value (Broadcom use 0xffffffff)
73 unsigned int crc32(const unsigned char *data, ssize_t len, unsigned int crc)
75 for ( ; len > 0; --len ) {
76 crc = (crc >> 8) ^ Crc32_table[ (crc ^ *data++) & 0xff ];
83 main(int argc, char **argv)
85 unsigned int arg, crc;
86 char *filename = NULL;
88 unsigned char *buffer = NULL;
89 unsigned long header_len = sizeof(FILE_TAG);
90 char *format_spec_user = "%-12s Manufacturer: %s Model: %s CRC32: %08x Length: %ld File: %s\n";
91 char *format_spec_test = "%-12s %s %s %08x %ld\n";
92 char *format_spec = format_spec_user; // default output format
94 unsigned int opt_quiet;
98 fprintf(stderr, "%s\nVersion: %0.2f\n%s\n", title, VERSION, copyright);
100 for (arg = 1; arg < (unsigned) argc; ++arg) {
102 size_t arg_len = strlen(p);
112 pr_error_exit(0, "cannot read data from stdin; provide a filename");
116 else if (!filename) { // remaining non-option must be the filename
120 fprintf(stderr, "Can only process one file; ignoring '%s'\n", p);
128 if ((fd = open(filename, fd_mode)) > 0) {
129 if ( (buffer = heap_and_reap(NULL, header_len, 1)) != NULL) {
131 if ( (qty = read(fd, buffer, header_len)) < header_len) {
133 fprintf(stderr, "warning: only able to read %ld of %ld bytes\n", qty, header_len);
138 pr_error_exit(0, "unable to allocate memory (%ld bytes)\n", header_len);
141 PFILE_TAG header = (PFILE_TAG) buffer;
142 printf("%04lx Tag Version: %s\n"
143 "%04lx Signature 1: %s\n"
144 "%04lx Signature 2: %s\n"
145 "%04lx Chip ID: %s\n"
146 "%04lx Board ID: %s\n"
147 "%04lx Big Endian: %s\n"
148 "%04lx Image Len: %s (0x%08lx)\n"
149 "%04lx CFE Address: %s (0x%08lx)\n"
150 "%04lx CFE Len: %s (0x%08lx)\n"
151 "%04lx Root FS Address: %s (0x%08lx)\n"
152 "%04lx Root FS Len: %s (0x%08lx)\n"
153 "%04lx Kernel Address: %s (0x%08lx)\n"
154 "%04lx Kernel Len: %s (0x%08lx)\n"
155 "%04lx Image Sequence: %s (0x%08x)\n"
156 "%04lx External Version: %s\n"
157 "%04lx Internal Version: %s\n"
158 "%04lx Image Next: %u\n"
159 "%04lx Image Validation Token: 0x%0x\n"
160 "%04lx Tag Validation Token: 0x%0x\n"
162 offsetof(struct _FILE_TAG, tagVersion), header->tagVersion,
163 offsetof(struct _FILE_TAG, signiture_1), header->signiture_1,
164 offsetof(struct _FILE_TAG, signiture_2), header->signiture_2,
165 offsetof(struct _FILE_TAG, chipId), header->chipId,
166 offsetof(struct _FILE_TAG, boardId), header->boardId,
167 offsetof(struct _FILE_TAG, bigEndian), *header->bigEndian == '1' ? "Yes" : "No",
168 offsetof(struct _FILE_TAG, totalImageLen), header->totalImageLen, atol(header->totalImageLen),
169 offsetof(struct _FILE_TAG, cfeAddress), header->cfeAddress, atol(header->cfeAddress),
170 offsetof(struct _FILE_TAG, cfeLen), header->cfeLen, atol(header->cfeLen),
171 offsetof(struct _FILE_TAG, rootfsAddress), header->rootfsAddress, atol(header->rootfsAddress),
172 offsetof(struct _FILE_TAG, rootfsLen), header->rootfsLen, atol(header->rootfsLen),
173 offsetof(struct _FILE_TAG, kernelAddress), header->kernelAddress, atol(header->kernelAddress),
174 offsetof(struct _FILE_TAG, kernelLen), header->kernelLen, atol(header->kernelLen),
175 offsetof(struct _FILE_TAG, imageSequence), header->imageSequence, atoi(header->imageSequence),
176 offsetof(struct _FILE_TAG, externalversion), header->externalversion,
177 offsetof(struct _FILE_TAG, internalversion), header->internalversion,
178 offsetof(struct _FILE_TAG, imageNext), (unsigned int)*(unsigned char *)(header->imageNext),
179 offsetof(struct _FILE_TAG, imageValidationToken), ntohl( *((unsigned int *)(header->imageValidationToken)) ),
180 offsetof(struct _FILE_TAG, tagValidationToken), ntohl( *((unsigned int *)(header->tagValidationToken)) )
183 heap_and_reap(buffer, 0, 0);
186 fprintf(stderr, "Unable to open for %s (%s)\n", "reading" , filename );
193 heap_and_reap(NULL-1, 0, 0);