14f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin/*
24f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Copyright (C) 2017 The Android Open Source Project
34f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
44f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Licensed under the Apache License, Version 2.0 (the "License");
54f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * you may not use this file except in compliance with the License.
64f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * You may obtain a copy of the License at
74f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
84f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *      http://www.apache.org/licenses/LICENSE-2.0
94f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
104f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Unless required by applicable law or agreed to in writing, software
114f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * distributed under the License is distributed on an "AS IS" BASIS,
124f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * See the License for the specific language governing permissions and
144f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * limitations under the License.
154f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin */
164f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin
17780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <getopt.h>
18780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdio.h>
19780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdlib.h>
20780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdint.h>
21780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
22780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include "libfdt.h"
23780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
24780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include "dt_table.h"
25780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
26780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
27780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstruct dump_params {
28780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  const char *img_filename;
29780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  const char *out_filename;
30780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  const char *out_dtb_filename;
31780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin};
32780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
33780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic const char short_options[] = "o:b:";
34780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic struct option options[] = {
35780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  { "output",   required_argument, NULL, 'o' },
36780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  { "dtb",      required_argument, NULL, 'b' },
37780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  { 0,          0,                 NULL, 0 }
38780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin};
39780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
40780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
41780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void *read_fdt_from_image(FILE *img_fp,
42780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin                                 uint32_t dt_offset, uint32_t dt_size) {
43780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  void *fdt = NULL;
44780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
45780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fdt = malloc(dt_size);
46780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
47780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fseek(img_fp, dt_offset, SEEK_SET);
48780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (fread(fdt, dt_size, 1, img_fp) == 0) {
49780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Read FDT data error.\n");
50780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
51780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    free(fdt);
52780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    return NULL;
53780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
54780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
55780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return fdt;
56780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
57780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
58780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int write_fdt_to_file(const char *filename, const void *fdt) {
59780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  int ret = -1;
60780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  FILE *out_fp = NULL;
61780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
62780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  out_fp = fopen(filename, "wb");
63780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (!out_fp) {
64780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Can not create file: %s\n", filename);
65780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    goto end;
66780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
67780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
68780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  size_t fdt_size = fdt_totalsize(fdt);
69780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (fwrite(fdt, fdt_size, 1, out_fp) < 1) {
70780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Write FDT data error.\n");
71780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    goto end;
72780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
73780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
74780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  ret = 0;
75780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
76780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linend:
77780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (out_fp) fclose(out_fp);
78780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
79780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return ret;
80780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
81780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
82780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void free_fdt(void *fdt) {
83780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (fdt == NULL) {
84780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    /* do nothing */
85780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    return;
86780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
87780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
88780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  free(fdt);
89780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
90780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
91780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
92780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_prop_int(FILE *out_fp, const char *name, uint32_t value) {
93780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "%+20s = %d\n", name, fdt32_to_cpu(value));
94780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
95780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
96780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_prop_int_cpu(FILE *out_fp, const char *name, uint32_t value) {
97780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "%+20s = %d\n", name, value);
98780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
99780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
100780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_prop_hex(FILE *out_fp, const char *name, uint32_t value) {
101780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "%+20s = %08x\n", name, fdt32_to_cpu(value));
102780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
103780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
104780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_prop_str(FILE *out_fp, const char *name, const char *value) {
105780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "%+20s = %s\n", name, value);
106780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
107780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
108780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_table_header(FILE *out_fp, const struct dt_table_header *header) {
109780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "dt_table_header:\n");
110780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "magic", header->magic);
111780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "total_size", header->total_size);
112780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "header_size", header->header_size);
113780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "dt_entry_size", header->dt_entry_size);
114780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "dt_entry_count", header->dt_entry_count);
115780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "dt_entries_offset", header->dt_entries_offset);
116780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "page_size", header->page_size);
117780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "reserved[0]", header->reserved[0]);
118780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
119780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
120780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void output_table_entry(FILE *out_fp, int index, const struct dt_table_entry *entry) {
121780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "dt_table_entry[%d]:\n", index);
122780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "dt_size", entry->dt_size);
123780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int(out_fp, "dt_offset", entry->dt_offset);
124780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "id", entry->id);
125780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "rev", entry->rev);
126780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "custom[0]", entry->custom[0]);
127780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "custom[1]", entry->custom[1]);
128780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "custom[2]", entry->custom[2]);
129780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_hex(out_fp, "custom[3]", entry->custom[3]);
130780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
131780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
132780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int output_fdt_info(FILE *out_fp, void *fdt) {
133780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  size_t fdt_size = fdt_totalsize(fdt);
134780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_int_cpu(out_fp, "(FDT)size", fdt_size);
135780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
136780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  int root_node_off = fdt_path_offset(fdt, "/");
137780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (root_node_off < 0) {
138780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Can not get the root node.\n");
139780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    return -1;
140780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
141780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
142780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  const char *compatible =
143780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    (const char *)fdt_getprop(fdt, root_node_off, "compatible", NULL);
144780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_prop_str(out_fp, "(FDT)compatible", compatible ? compatible : "(unknown)");
145780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
146780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return 0;
147780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
148780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
149780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int dump_image_from_fp(FILE *out_fp, FILE *img_fp,
150780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin                              const struct dump_params *params) {
151780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  struct dt_table_header header;
152780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (fread(&header, sizeof(header), 1, img_fp) != 1) {
153780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Read error.\n");
154780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    return -1;
155780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
156780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  /* TODO: check header */
157780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  output_table_header(out_fp, &header);
158780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
159780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  uint32_t entry_size = fdt32_to_cpu(header.dt_entry_size);
160780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  uint32_t entry_offset = fdt32_to_cpu(header.dt_entries_offset);
161780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  uint32_t entry_count = fdt32_to_cpu(header.dt_entry_count);
162780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  uint32_t i;
163780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  for (i = 0; i < entry_count; i++) {
164780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    struct dt_table_entry entry;
165780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fseek(img_fp, entry_offset, SEEK_SET);
166780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fread(&entry, sizeof(entry), 1, img_fp);
167780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    output_table_entry(out_fp, i, &entry);
168780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
169780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    uint32_t dt_size = fdt32_to_cpu(entry.dt_size);
170780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    uint32_t dt_offset = fdt32_to_cpu(entry.dt_offset);
171780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    if (dt_size > 0 && dt_offset > 0) {
172780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      void *fdt = read_fdt_from_image(img_fp, dt_offset, dt_size);
173780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      output_fdt_info(out_fp, fdt);
174780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
175780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      if (params->out_dtb_filename != NULL) {
176780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        char filename[256];
177780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        snprintf(filename, sizeof(filename), "%s.%d",
178780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin                 params->out_dtb_filename, i);
179780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        write_fdt_to_file(filename, fdt);
180780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      }
181780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
182780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      free_fdt(fdt);
183780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    }
184780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
185780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    entry_offset += entry_size;
186780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
187780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
188780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return 0;
189780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
190780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
191780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int process_command_dump(const struct dump_params *params) {
192780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  int ret = -1;
193780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  FILE *out_fp = NULL;
194780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  FILE *img_fp = NULL;
195780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
196780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  img_fp = fopen(params->img_filename, "rb");
197780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (img_fp == NULL) {
198780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    fprintf(stderr, "Can not open image file: %s\n", params->img_filename);
199780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    goto end;
200780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
201780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
202780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (params->out_filename != NULL) {
203780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    out_fp = fopen(params->out_filename, "w");
204780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    if (out_fp == NULL) {
205780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      fprintf(stderr, "Can not create file: %s\n", params->out_filename);
206780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      goto end;
207780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    }
208780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
209780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
210780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  ret = dump_image_from_fp(out_fp ? out_fp : stdout, img_fp, params);
211780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
212780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linend:
213780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (img_fp) fclose(img_fp);
214780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (out_fp) fclose(out_fp);
215780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
216780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return ret;
217780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
218780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
219780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linvoid handle_usage_dump(FILE *out_fp, const char *prog_name) {
220780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp, "  %s dump <image_file> (<option>...)\n\n", prog_name);
221780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  fprintf(out_fp,
222780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    "    options:\n"
223780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    "      -o, --output <filename>  Output file name.\n"
224780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    "                               Default is output to stdout.\n"
225780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    "      -b, --dtb <filename>     Dump dtb/dtbo files from image.\n"
226780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    "                               Will output to <filename>.0, <filename>.1, etc.\n");
227780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
228780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
229780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint handle_command_dump(int argc, char *argv[], int arg_start) {
230780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  if (argc - arg_start < 1) {
231780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    handle_usage_dump(stderr, argv[0]);
232780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    return 1;
233780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
234780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
235780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  struct dump_params params;
236780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  memset(&params, 0, sizeof(params));
237780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  params.img_filename = argv[arg_start];
238780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
239780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  optind = arg_start + 1;
240780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  while (1) {
241780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    int c = getopt_long(argc, argv, short_options, options, NULL);
242780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    if (c == -1) {
243780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      break;
244780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    }
245780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    switch (c) {
246780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      case 'o':
247780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        params.out_filename = optarg;
248780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        break;
249780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      case 'b':
250780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        params.out_dtb_filename = optarg;
251780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        break;
252780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin      default:
253780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        /* Unknown option, return error */
254780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin        return 1;
255780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin    }
256780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  }
257780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin
258780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin  return process_command_dump(&params);
259780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}
260