rtlfw.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012-2013 Intel Corporation
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <string.h>
  19. #include <getopt.h>
  20. #include <stdlib.h>
  21. #include <stdint.h>
  22. #include <sys/stat.h>
  23. #include <sys/mman.h>
  24. #include <src/shared/util.h>
  25. #define CONFIG_MAGIC 0x8723ab55
  26. static const char *offset_to_str(uint16_t offset)
  27. {
  28. switch (offset) {
  29. case 0x00f4:
  30. return "PCM_SETTING";
  31. case 0x000c:
  32. return "UART_CONFIG";
  33. case 0x003c:
  34. return "BD_ADDR";
  35. }
  36. return NULL;
  37. }
  38. static void analyze_memory(const uint8_t *buf, size_t len)
  39. {
  40. const uint8_t *ptr = buf;
  41. uint32_t magic;
  42. uint16_t datalen;
  43. if (len < 6) {
  44. fprintf(stderr, "Invalid file length of %zu bytes\n", len);
  45. return;
  46. }
  47. magic = get_le32(ptr);
  48. datalen = get_le16(ptr + 4);
  49. printf("Signature: 0x%8.8x\n", magic);
  50. printf("Data len: %u\n", datalen);
  51. if (magic != CONFIG_MAGIC) {
  52. fprintf(stderr, "Unsupported file signature\n");
  53. return;
  54. }
  55. ptr += 6;
  56. while (ptr < buf + datalen + 6) {
  57. uint16_t offset;
  58. uint8_t plen;
  59. const char *str;
  60. unsigned int i;
  61. offset = get_le16(ptr);
  62. plen = get_u8(ptr + 2);
  63. if (ptr + plen + 3 > buf + datalen + 6) {
  64. fprintf(stderr, "Invalid config entry size\n");
  65. break;
  66. }
  67. str = offset_to_str(offset);
  68. printf("len=%-3u offset=%4.4x,{ ", plen, offset);
  69. for (i = 0; i < plen; i++)
  70. printf("%2.2x ", ptr[3 + i]);
  71. printf("}%s%s\n", str ? "," : "", str ? : "");
  72. ptr += plen + 3;
  73. }
  74. }
  75. static void analyze_file(const char *pathname)
  76. {
  77. struct stat st;
  78. void *map;
  79. int fd;
  80. printf("Analyzing %s\n", pathname);
  81. fd = open(pathname, O_RDONLY | O_CLOEXEC);
  82. if (fd < 0) {
  83. perror("Failed to open file");
  84. return;
  85. }
  86. if (fstat(fd, &st) < 0) {
  87. fprintf(stderr, "Failed get file size\n");
  88. close(fd);
  89. return;
  90. }
  91. if (st.st_size == 0) {
  92. fprintf(stderr, "Empty file\n");
  93. close(fd);
  94. return;
  95. }
  96. map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
  97. if (!map || map == MAP_FAILED) {
  98. fprintf(stderr, "Failed to map file\n");
  99. close(fd);
  100. return;
  101. }
  102. analyze_memory(map, st.st_size);
  103. munmap(map, st.st_size);
  104. close(fd);
  105. }
  106. static void usage(void)
  107. {
  108. printf("Realtek Bluetooth firmware analyzer\n"
  109. "Usage:\n");
  110. printf("\trtlfw [options] <file>\n");
  111. printf("Options:\n"
  112. "\t-h, --help Show help options\n");
  113. }
  114. static const struct option main_options[] = {
  115. { "version", no_argument, NULL, 'v' },
  116. { "help", no_argument, NULL, 'h' },
  117. { }
  118. };
  119. int main(int argc, char *argv[])
  120. {
  121. int i;
  122. for (;;) {
  123. int opt;
  124. opt = getopt_long(argc, argv, "vh", main_options, NULL);
  125. if (opt < 0)
  126. break;
  127. switch (opt) {
  128. case 'v':
  129. printf("%s\n", VERSION);
  130. return EXIT_SUCCESS;
  131. case 'h':
  132. usage();
  133. return EXIT_SUCCESS;
  134. default:
  135. return EXIT_FAILURE;
  136. }
  137. }
  138. if (argc - optind < 1) {
  139. fprintf(stderr, "No input firmware files provided\n");
  140. return EXIT_FAILURE;
  141. }
  142. for (i = optind; i < argc; i++)
  143. analyze_file(argv[i]);
  144. return EXIT_SUCCESS;
  145. }