tools: Add utitlity for analyzing Broadcom HCD firmware files
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 4 Jun 2018 19:06:56 +0000 (21:06 +0200)
committerhimanshu <h.himanshu@samsung.com>
Tue, 11 Feb 2020 08:58:20 +0000 (14:28 +0530)
Change-Id: Ia5d4ba6388a3f822f54bde8295cdc09c05a49dba
Signed-off-by: himanshu <h.himanshu@samsung.com>
Makefile.tools
tools/bcmfw.c [new file with mode: 0644]

index 5a39bcb..39c7da2 100755 (executable)
@@ -331,7 +331,7 @@ noinst_PROGRAMS += tools/bdaddr tools/avinfo tools/avtest \
                        tools/btproxy \
                        tools/btiotest tools/bneptest tools/mcaptest \
                        tools/cltest tools/oobtest tools/seq2bseq \
-                       tools/nokfw tools/create-image \
+                       tools/nokfw tools/bcmfw tools/create-image \
                        tools/eddystone tools/ibeacon \
                        tools/btgatt-client tools/btgatt-server \
                        tools/test-runner tools/check-selftest
diff --git a/tools/bcmfw.c b/tools/bcmfw.c
new file mode 100644 (file)
index 0000000..ff94c4f
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012-2013  Intel Corporation
+ *
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+static void print_cmd(uint16_t opcode, const uint8_t *buf, uint8_t plen)
+{
+       switch (opcode) {
+       case 0xfc4c:
+               printf(" Write_RAM [address=0x%08x]",
+                       buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24);
+               break;
+       case 0xfc4e:
+               printf(" Launch_RAM [address=0x%08x]",
+                       buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24);
+               break;
+       }
+}
+
+static void analyze_memory(const uint8_t *buf, size_t len)
+{
+       const uint8_t *ptr = buf;
+
+       while (len >= 3) {
+               uint16_t opcode = ptr[0] | ptr[1] << 8;
+               uint8_t plen = ptr[2];
+
+               ptr += 3;
+               len -= 3;
+
+               if (len < plen) {
+                       fprintf(stderr, "Corrupted file\n");
+                       break;
+               }
+
+               printf("opcode=0x%04x plen=%-3u", opcode, plen);
+               print_cmd(opcode, ptr + 3, plen);
+               printf("\n");
+
+               ptr += plen;
+               len -= plen;
+       }
+}
+
+static void analyze_file(const char *pathname)
+{
+       struct stat st;
+       void *map;
+       int fd;
+
+       printf("Analyzing %s\n", pathname);
+
+       fd = open(pathname, O_RDONLY | O_CLOEXEC);
+       if (fd < 0) {
+               perror("Failed to open file");
+               return;
+       }
+
+       if (fstat(fd, &st) < 0) {
+               fprintf(stderr, "Failed get file size\n");
+               close(fd);
+               return;
+       }
+
+       if (st.st_size == 0) {
+               fprintf(stderr, "Empty file\n");
+               close(fd);
+               return;
+       }
+
+       map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+       if (!map || map == MAP_FAILED) {
+               fprintf(stderr, "Failed to map file\n");
+               close(fd);
+               return;
+        }
+
+       analyze_memory(map, st.st_size);
+
+       munmap(map, st.st_size);
+       close(fd);
+}
+
+static void usage(void)
+{
+       printf("Broadcom Bluetooth firmware analyzer\n"
+               "Usage:\n");
+       printf("\tbcmfw [options] <file>\n");
+       printf("Options:\n"
+               "\t-h, --help             Show help options\n");
+}
+
+static const struct option main_options[] = {
+       { "version", no_argument,       NULL, 'v' },
+       { "help",    no_argument,       NULL, 'h' },
+       { }
+};
+
+int main(int argc, char *argv[])
+{
+       int i;
+
+       for (;;) {
+               int opt;
+
+               opt = getopt_long(argc, argv, "vh", main_options, NULL);
+               if (opt < 0)
+                       break;
+
+               switch (opt) {
+               case 'v':
+                       printf("%s\n", VERSION);
+                       return EXIT_SUCCESS;
+               case 'h':
+                       usage();
+                       return EXIT_SUCCESS;
+               default:
+                       return EXIT_FAILURE;
+               }
+       }
+
+       if (argc - optind < 1) {
+               fprintf(stderr, "No input firmware files provided\n");
+               return EXIT_FAILURE;
+       }
+
+       for (i = optind; i < argc; i++)
+               analyze_file(argv[i]);
+
+       return EXIT_SUCCESS;
+}