unpackdtbhimg.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright 2018, The LineageOS Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <stdint.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <sys/stat.h>
  24. #include <sys/types.h>
  25. #define DEFAULT_PAGE_SIZE 2048
  26. #define DT_NAME_LEN 64
  27. struct dt_entry {
  28. uint32_t chip;
  29. uint32_t platform;
  30. uint32_t subtype;
  31. uint32_t hw_rev;
  32. uint32_t hw_rev_end;
  33. uint32_t offset;
  34. uint32_t size; /* including padding */
  35. uint32_t space;
  36. };
  37. struct dtbh_header {
  38. uint32_t magic;
  39. uint32_t version;
  40. uint32_t entry_count;
  41. struct dt_entry entries[];
  42. };
  43. static void show_dt_entry(struct dt_entry *ent) {
  44. printf("chip: %u, platform: 0x%x, subtype: 0x%x, hw_rev: %u, hw_rev_end: %u, offset: %u, "
  45. "size: %u, space: %u\n", ent->chip, ent->platform, ent->subtype, ent->hw_rev,
  46. ent->hw_rev_end, ent->offset, ent->size, ent->space);
  47. }
  48. static void dump_dtb(void *buffer, uint32_t size, char *dest)
  49. {
  50. FILE *output;
  51. ssize_t len;
  52. output = fopen(dest, "wb");
  53. if (output == NULL) {
  54. fprintf(stderr, "error: could not open %s\n", dest);
  55. return;
  56. }
  57. len = fwrite(buffer, size, 1, output);
  58. fclose(output);
  59. if (len < 0) {
  60. printf("error: failed to write %s (%s)\n", dest, strerror(errno));
  61. return;
  62. }
  63. printf("Successfully dumped %s (size=%zu)\n", dest, size);
  64. }
  65. int usage(void)
  66. {
  67. fprintf(stderr,"usage: unpackdtbhimg\n"
  68. " -i|--input <dtbh image path>\n"
  69. " -o|--output <directory>\n"
  70. " -p|--pagesize <pagesize>\n"
  71. );
  72. return 1;
  73. }
  74. int main(int argc, char *argv[]) {
  75. char *dtbhimg = 0;
  76. char *output_dir = 0;
  77. FILE *dtbhimg_fp;
  78. ssize_t len;
  79. int page_size = DEFAULT_PAGE_SIZE;
  80. struct dtbh_header *header;
  81. void *dt_blob;
  82. argc--;
  83. argv++;
  84. while (argc > 0){
  85. char *arg = argv[0];
  86. char *val = argv[1];
  87. if (argc < 1) {
  88. return usage();
  89. }
  90. argc -= 2;
  91. argv += 2;
  92. if (!strcmp(arg, "--input") || !strcmp(arg, "-i")) {
  93. dtbhimg = val;
  94. } else if (!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
  95. output_dir = val;
  96. } else if (!strcmp(arg, "--pagesize") || !strcmp(arg, "-p")) {
  97. page_size = atoi(val);
  98. }
  99. }
  100. if (dtbhimg == 0) {
  101. fprintf(stderr,"error: no input filename specified\n");
  102. return usage();
  103. }
  104. if (output_dir == 0) {
  105. fprintf(stderr,"error: no output path specified\n");
  106. return usage();
  107. }
  108. printf("using page_size: %d\n", page_size);
  109. dtbhimg_fp = fopen(dtbhimg, "r");
  110. if (dtbhimg_fp == NULL) {
  111. fprintf(stderr, "error: could not open %s\n", dtbhimg);
  112. goto err_open;
  113. }
  114. header = calloc(page_size, 1);
  115. if (header == NULL) {
  116. goto err_calloc;
  117. }
  118. len = fread(header, page_size, 1, dtbhimg_fp);
  119. if (len != 1) {
  120. fprintf(stderr, "Failed to read DTBH header: %s\n", strerror(errno));
  121. goto err_read;
  122. }
  123. printf("DTBH_MAGIC = '%.4s'\n", &header->magic);
  124. printf("DTBH_VERSION = %u\n", header->version);
  125. printf("Number of entries: %u\n", header->entry_count);
  126. for (uint32_t i = 0; i < header->entry_count; i++) {
  127. printf("DTB %d: ", i);
  128. show_dt_entry(&header->entries[i]);
  129. dt_blob = malloc(header->entries[i].size);
  130. if (fseek(dtbhimg_fp, header->entries[i].offset, SEEK_SET) != 0) {
  131. fprintf(stderr, "failed to set offset to 0x%x: %s\n", header->entries[i].offset,
  132. strerror(errno));
  133. goto err_loop;
  134. }
  135. len = fread(dt_blob, header->entries[i].size, 1, dtbhimg_fp);
  136. if (len != 1) {
  137. fprintf(stderr, "Failed to read DTB: %s\n", strerror(errno));
  138. }
  139. size_t dest_file_len = DT_NAME_LEN + strlen(output_dir);
  140. char dest_file[dest_file_len];
  141. snprintf(dest_file, dest_file_len, "%s/chip%u-0x%x-0x%x_rev%u-%u.dtb", output_dir,
  142. header->entries[i].chip, header->entries[i].platform, header->entries[i].subtype,
  143. header->entries[i].hw_rev, header->entries[i].hw_rev_end);
  144. dump_dtb(dt_blob, header->entries[i].size, dest_file);
  145. free(dt_blob);
  146. }
  147. free(header);
  148. fclose(dtbhimg_fp);
  149. return 0;
  150. err_loop:
  151. free(dt_blob);
  152. err_read:
  153. free(header);
  154. err_calloc:
  155. fclose(dtbhimg_fp);
  156. err_open:
  157. return 1;
  158. }