| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include "dt_table.h" |
| #include "mkdtimg_core.h" |
| |
| |
| static int calculate_args_entry_count(int argc, char *argv[], int arg_start) { |
| int count = 0; |
| |
| int i; |
| for (i = arg_start; i < argc; i++) { |
| const char *arg = argv[i]; |
| char c = arg[0]; |
| /* Skip options starting with -- */ |
| if (c == '-') continue; |
| count++; |
| } |
| |
| return count; |
| } |
| |
| static int parse_arg(char **option, char **value, char *arg) { |
| if (arg[0] != '-') { |
| /* This is not a option */ |
| *option = NULL; |
| return 0; |
| } |
| |
| /* An option must start with -- */ |
| if (arg[1] != '-') { |
| return -1; |
| } |
| |
| return parse_option(option, value, arg + 2); |
| } |
| |
| static int output_img_with_args(FILE *img_fp, int argc, char *argv[], int arg_start) { |
| int entry_count = calculate_args_entry_count(argc, argv, arg_start); |
| struct dt_image_writer *writer = dt_image_writer_start(img_fp, entry_count); |
| |
| int is_entry = 0; |
| int i; |
| for (i = arg_start; i < argc; i++) { |
| char *arg = argv[i]; |
| char *option, *value; |
| if (parse_arg(&option, &value, arg) != 0) { |
| fprintf(stderr, "Wrong syntax: %s\n", arg); |
| return -1; |
| } |
| |
| if (option == NULL) { |
| /* This is a file name */ |
| if (dt_image_writer_add_entry(writer, arg) != 0) { |
| return -1; |
| } |
| is_entry = 1; |
| continue; |
| } |
| |
| int ret = is_entry ? |
| set_entry_options(writer, option, value) : |
| set_global_options(writer, option, value); |
| if (ret != 0) { |
| fprintf(stderr, "Unknown option: %s\n", option); |
| return -1; |
| } |
| } /* for all argv */ |
| |
| if (dt_image_writer_end(writer) != 0) { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| void handle_usage_create(FILE *out_fp, const char *prog_name) { |
| fprintf(out_fp, " %s create <image_file> (<global_option>...) (<dtb_file> (<entry_option>...) ...)\n\n", prog_name); |
| fprintf(out_fp, |
| " global_options:\n" |
| " --dt_type=<type> Device Tree type (dtb|acpi). Default:" |
| " dtb\n" |
| " --page_size=<number> Output page size. Default: 2048\n" |
| " --version=<version> DTBO version. Default: 0\n" |
| " --id=<number|path> The default value to set property id " |
| "in dt_table_entry. Default: 0\n" |
| " --rev=<number|path>\n" |
| " --custom0=<number|path>\n" |
| " --custom1=<number|path>\n" |
| " --custom2=<number|path>\n" |
| " --custom3=<number|path>\n\n" |
| " The value could be a number or a DT node path.\n" |
| " <number> could be a 32-bits digit or hex value, ex. 68000, " |
| "0x6800.\n" |
| " <path> format is <full_node_path>:<property_name>, ex. " |
| "/board/:id,\n" |
| " will read the value in given FTB file with the path.\n"); |
| } |
| |
| int handle_command_create(int argc, char *argv[], int arg_start) { |
| int ret = -1; |
| FILE *img_fp = NULL; |
| |
| if (argc - arg_start < 1) { |
| handle_usage_create(stderr, argv[0]); |
| goto end; |
| } |
| |
| const char *img_filename = argv[arg_start]; |
| |
| printf("create image file: %s...\n", img_filename); |
| |
| img_fp = fopen(img_filename, "wb"); |
| if (img_fp == NULL) { |
| fprintf(stderr, "Can not create file: %s\n", img_filename); |
| goto end; |
| } |
| |
| ret = output_img_with_args(img_fp, argc, argv, arg_start + 1); |
| if (ret < 0) fprintf(stderr, "Can not output image with args\n"); |
| |
| end: |
| if (img_fp) { |
| fclose(img_fp); |
| if (ret < 0) unlink(img_filename); |
| } |
| |
| return ret; |
| } |