1*13e8728fSAndroid Build Coastguard Worker /*
2*13e8728fSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*13e8728fSAndroid Build Coastguard Worker *
4*13e8728fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*13e8728fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*13e8728fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*13e8728fSAndroid Build Coastguard Worker *
8*13e8728fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*13e8728fSAndroid Build Coastguard Worker *
10*13e8728fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*13e8728fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*13e8728fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*13e8728fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*13e8728fSAndroid Build Coastguard Worker * limitations under the License.
15*13e8728fSAndroid Build Coastguard Worker */
16*13e8728fSAndroid Build Coastguard Worker
17*13e8728fSAndroid Build Coastguard Worker #include <ctype.h>
18*13e8728fSAndroid Build Coastguard Worker #include <getopt.h>
19*13e8728fSAndroid Build Coastguard Worker #include <stdio.h>
20*13e8728fSAndroid Build Coastguard Worker #include <stdlib.h>
21*13e8728fSAndroid Build Coastguard Worker #include <string.h>
22*13e8728fSAndroid Build Coastguard Worker #include <unistd.h>
23*13e8728fSAndroid Build Coastguard Worker
24*13e8728fSAndroid Build Coastguard Worker #include "dt_table.h"
25*13e8728fSAndroid Build Coastguard Worker #include "mkdtimg_core.h"
26*13e8728fSAndroid Build Coastguard Worker
27*13e8728fSAndroid Build Coastguard Worker
28*13e8728fSAndroid Build Coastguard Worker struct cfg_create_params {
29*13e8728fSAndroid Build Coastguard Worker const char *img_filename;
30*13e8728fSAndroid Build Coastguard Worker const char *cfg_filename;
31*13e8728fSAndroid Build Coastguard Worker const char *dtb_dir;
32*13e8728fSAndroid Build Coastguard Worker };
33*13e8728fSAndroid Build Coastguard Worker
34*13e8728fSAndroid Build Coastguard Worker static const char short_options[] = "d:";
35*13e8728fSAndroid Build Coastguard Worker static struct option options[] = {
36*13e8728fSAndroid Build Coastguard Worker { "dtb-dir", required_argument, NULL, 'd' },
37*13e8728fSAndroid Build Coastguard Worker { 0, 0, NULL, 0 }
38*13e8728fSAndroid Build Coastguard Worker };
39*13e8728fSAndroid Build Coastguard Worker
40*13e8728fSAndroid Build Coastguard Worker
trim_line(char * line)41*13e8728fSAndroid Build Coastguard Worker static char *trim_line(char *line) {
42*13e8728fSAndroid Build Coastguard Worker /* Find the end of the string or the first of '#' */
43*13e8728fSAndroid Build Coastguard Worker char *end = line;
44*13e8728fSAndroid Build Coastguard Worker while (*end != '\0' && *end != '#') {
45*13e8728fSAndroid Build Coastguard Worker end++;
46*13e8728fSAndroid Build Coastguard Worker }
47*13e8728fSAndroid Build Coastguard Worker do {
48*13e8728fSAndroid Build Coastguard Worker end--;
49*13e8728fSAndroid Build Coastguard Worker } while (end >= line && isspace(*end));
50*13e8728fSAndroid Build Coastguard Worker
51*13e8728fSAndroid Build Coastguard Worker *(end + 1) = '\0';
52*13e8728fSAndroid Build Coastguard Worker
53*13e8728fSAndroid Build Coastguard Worker while (isspace(*line)) {
54*13e8728fSAndroid Build Coastguard Worker line++;
55*13e8728fSAndroid Build Coastguard Worker }
56*13e8728fSAndroid Build Coastguard Worker return line;
57*13e8728fSAndroid Build Coastguard Worker }
58*13e8728fSAndroid Build Coastguard Worker
parse_config_entry_count(FILE * cfg_fp)59*13e8728fSAndroid Build Coastguard Worker static int parse_config_entry_count(FILE *cfg_fp) {
60*13e8728fSAndroid Build Coastguard Worker int count = 0;
61*13e8728fSAndroid Build Coastguard Worker
62*13e8728fSAndroid Build Coastguard Worker /* Any line without prefix spaces is entry filename */
63*13e8728fSAndroid Build Coastguard Worker char line[1024];
64*13e8728fSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), cfg_fp) != NULL) {
65*13e8728fSAndroid Build Coastguard Worker char c = line[0];
66*13e8728fSAndroid Build Coastguard Worker if (c == '\0' || isspace(c) || c == '#') continue;
67*13e8728fSAndroid Build Coastguard Worker count++;
68*13e8728fSAndroid Build Coastguard Worker }
69*13e8728fSAndroid Build Coastguard Worker
70*13e8728fSAndroid Build Coastguard Worker return count;
71*13e8728fSAndroid Build Coastguard Worker }
72*13e8728fSAndroid Build Coastguard Worker
output_img_with_config(FILE * img_fp,FILE * cfg_fp)73*13e8728fSAndroid Build Coastguard Worker static int output_img_with_config(FILE *img_fp, FILE *cfg_fp) {
74*13e8728fSAndroid Build Coastguard Worker int entry_count = parse_config_entry_count(cfg_fp);
75*13e8728fSAndroid Build Coastguard Worker struct dt_image_writer *writer = dt_image_writer_start(img_fp, entry_count);
76*13e8728fSAndroid Build Coastguard Worker
77*13e8728fSAndroid Build Coastguard Worker fseek(cfg_fp, 0, SEEK_SET); /* Reset the file pos to head */
78*13e8728fSAndroid Build Coastguard Worker
79*13e8728fSAndroid Build Coastguard Worker int is_entry = 0;
80*13e8728fSAndroid Build Coastguard Worker char line[1024];
81*13e8728fSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), cfg_fp) != NULL) {
82*13e8728fSAndroid Build Coastguard Worker char *trimmed = trim_line(line);
83*13e8728fSAndroid Build Coastguard Worker if (trimmed[0] == '\0') {
84*13e8728fSAndroid Build Coastguard Worker /* empty line, pass */
85*13e8728fSAndroid Build Coastguard Worker continue;
86*13e8728fSAndroid Build Coastguard Worker }
87*13e8728fSAndroid Build Coastguard Worker
88*13e8728fSAndroid Build Coastguard Worker if (trimmed == line) {
89*13e8728fSAndroid Build Coastguard Worker /* This line is a file name,
90*13e8728fSAndroid Build Coastguard Worker because it start from the first char of the line */
91*13e8728fSAndroid Build Coastguard Worker if (dt_image_writer_add_entry(writer, trimmed) != 0) {
92*13e8728fSAndroid Build Coastguard Worker return -1;
93*13e8728fSAndroid Build Coastguard Worker }
94*13e8728fSAndroid Build Coastguard Worker is_entry = 1;
95*13e8728fSAndroid Build Coastguard Worker continue;
96*13e8728fSAndroid Build Coastguard Worker }
97*13e8728fSAndroid Build Coastguard Worker
98*13e8728fSAndroid Build Coastguard Worker char *option, *value;
99*13e8728fSAndroid Build Coastguard Worker if (parse_option(&option, &value, trimmed) != 0) {
100*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Wrong syntax: %s\n", trimmed);
101*13e8728fSAndroid Build Coastguard Worker return -1;
102*13e8728fSAndroid Build Coastguard Worker }
103*13e8728fSAndroid Build Coastguard Worker
104*13e8728fSAndroid Build Coastguard Worker int ret = is_entry ?
105*13e8728fSAndroid Build Coastguard Worker set_entry_options(writer, option, value) :
106*13e8728fSAndroid Build Coastguard Worker set_global_options(writer, option, value);
107*13e8728fSAndroid Build Coastguard Worker if (ret != 0) {
108*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Unknown option: %s\n", option);
109*13e8728fSAndroid Build Coastguard Worker return -1;
110*13e8728fSAndroid Build Coastguard Worker }
111*13e8728fSAndroid Build Coastguard Worker }
112*13e8728fSAndroid Build Coastguard Worker
113*13e8728fSAndroid Build Coastguard Worker if (dt_image_writer_end(writer) != 0) {
114*13e8728fSAndroid Build Coastguard Worker return -1;
115*13e8728fSAndroid Build Coastguard Worker }
116*13e8728fSAndroid Build Coastguard Worker
117*13e8728fSAndroid Build Coastguard Worker return 0;
118*13e8728fSAndroid Build Coastguard Worker }
119*13e8728fSAndroid Build Coastguard Worker
process_command_cfg_create(const struct cfg_create_params * params)120*13e8728fSAndroid Build Coastguard Worker static int process_command_cfg_create(const struct cfg_create_params *params) {
121*13e8728fSAndroid Build Coastguard Worker int ret = -1;
122*13e8728fSAndroid Build Coastguard Worker FILE *cfg_fp = NULL;
123*13e8728fSAndroid Build Coastguard Worker FILE *img_fp = NULL;
124*13e8728fSAndroid Build Coastguard Worker
125*13e8728fSAndroid Build Coastguard Worker cfg_fp = fopen(params->cfg_filename, "r");
126*13e8728fSAndroid Build Coastguard Worker if (cfg_fp == NULL) {
127*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Can not open config file: %s\n", params->cfg_filename);
128*13e8728fSAndroid Build Coastguard Worker goto end;
129*13e8728fSAndroid Build Coastguard Worker }
130*13e8728fSAndroid Build Coastguard Worker
131*13e8728fSAndroid Build Coastguard Worker printf("create image file: %s...\n", params->img_filename);
132*13e8728fSAndroid Build Coastguard Worker
133*13e8728fSAndroid Build Coastguard Worker img_fp = fopen(params->img_filename, "wb");
134*13e8728fSAndroid Build Coastguard Worker if (img_fp == NULL) {
135*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Can not create file: %s\n", params->img_filename);
136*13e8728fSAndroid Build Coastguard Worker goto end;
137*13e8728fSAndroid Build Coastguard Worker }
138*13e8728fSAndroid Build Coastguard Worker
139*13e8728fSAndroid Build Coastguard Worker if (params->dtb_dir != NULL) {
140*13e8728fSAndroid Build Coastguard Worker if (chdir(params->dtb_dir) != 0) {
141*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Can not switch to directory: %s\n", params->dtb_dir);
142*13e8728fSAndroid Build Coastguard Worker goto end;
143*13e8728fSAndroid Build Coastguard Worker }
144*13e8728fSAndroid Build Coastguard Worker }
145*13e8728fSAndroid Build Coastguard Worker
146*13e8728fSAndroid Build Coastguard Worker ret = output_img_with_config(img_fp, cfg_fp);
147*13e8728fSAndroid Build Coastguard Worker if (ret < 0)
148*13e8728fSAndroid Build Coastguard Worker fprintf(stderr, "Can not output image with config: %s\n",
149*13e8728fSAndroid Build Coastguard Worker params->cfg_filename);
150*13e8728fSAndroid Build Coastguard Worker
151*13e8728fSAndroid Build Coastguard Worker end:
152*13e8728fSAndroid Build Coastguard Worker if (img_fp) {
153*13e8728fSAndroid Build Coastguard Worker fclose(img_fp);
154*13e8728fSAndroid Build Coastguard Worker if (ret < 0) unlink(params->img_filename);
155*13e8728fSAndroid Build Coastguard Worker }
156*13e8728fSAndroid Build Coastguard Worker if (cfg_fp) fclose(cfg_fp);
157*13e8728fSAndroid Build Coastguard Worker
158*13e8728fSAndroid Build Coastguard Worker return ret;
159*13e8728fSAndroid Build Coastguard Worker }
160*13e8728fSAndroid Build Coastguard Worker
handle_usage_cfg_create(FILE * out_fp,const char * prog_name)161*13e8728fSAndroid Build Coastguard Worker void handle_usage_cfg_create(FILE *out_fp, const char *prog_name) {
162*13e8728fSAndroid Build Coastguard Worker fprintf(out_fp, " %s cfg_create <image_file> <config_file> (<option>...)\n\n", prog_name);
163*13e8728fSAndroid Build Coastguard Worker fprintf(out_fp,
164*13e8728fSAndroid Build Coastguard Worker " options:\n"
165*13e8728fSAndroid Build Coastguard Worker " -d, --dtb-dir The path to load dtb files.\n"
166*13e8728fSAndroid Build Coastguard Worker " Default is load from the current path.\n");
167*13e8728fSAndroid Build Coastguard Worker }
168*13e8728fSAndroid Build Coastguard Worker
handle_command_cfg_create(int argc,char * argv[],int arg_start)169*13e8728fSAndroid Build Coastguard Worker int handle_command_cfg_create(int argc, char *argv[], int arg_start) {
170*13e8728fSAndroid Build Coastguard Worker if (argc - arg_start < 2) {
171*13e8728fSAndroid Build Coastguard Worker handle_usage_cfg_create(stderr, argv[0]);
172*13e8728fSAndroid Build Coastguard Worker return 1;
173*13e8728fSAndroid Build Coastguard Worker }
174*13e8728fSAndroid Build Coastguard Worker
175*13e8728fSAndroid Build Coastguard Worker struct cfg_create_params params;
176*13e8728fSAndroid Build Coastguard Worker memset(¶ms, 0, sizeof(params));
177*13e8728fSAndroid Build Coastguard Worker params.img_filename = argv[arg_start];
178*13e8728fSAndroid Build Coastguard Worker params.cfg_filename = argv[arg_start + 1];
179*13e8728fSAndroid Build Coastguard Worker
180*13e8728fSAndroid Build Coastguard Worker optind = arg_start + 2;
181*13e8728fSAndroid Build Coastguard Worker while (1) {
182*13e8728fSAndroid Build Coastguard Worker int c = getopt_long(argc, argv, short_options, options, NULL);
183*13e8728fSAndroid Build Coastguard Worker if (c == -1) {
184*13e8728fSAndroid Build Coastguard Worker break;
185*13e8728fSAndroid Build Coastguard Worker }
186*13e8728fSAndroid Build Coastguard Worker switch (c) {
187*13e8728fSAndroid Build Coastguard Worker case 'd':
188*13e8728fSAndroid Build Coastguard Worker params.dtb_dir = optarg;
189*13e8728fSAndroid Build Coastguard Worker break;
190*13e8728fSAndroid Build Coastguard Worker default:
191*13e8728fSAndroid Build Coastguard Worker /* Unknown option, return error */
192*13e8728fSAndroid Build Coastguard Worker return 1;
193*13e8728fSAndroid Build Coastguard Worker }
194*13e8728fSAndroid Build Coastguard Worker }
195*13e8728fSAndroid Build Coastguard Worker
196*13e8728fSAndroid Build Coastguard Worker return process_command_cfg_create(¶ms);
197*13e8728fSAndroid Build Coastguard Worker }
198