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 "mkdtimg_core.h" 18780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 19780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdio.h> 20780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdlib.h> 21780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <string.h> 22780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <stdint.h> 23780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include <unistd.h> 24780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 25780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include "libfdt.h" 26780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 27780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#include "dt_table.h" 28780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 29780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin#define DEBUG 0 30780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 31780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 32780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstruct dt_options { 33780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char id[OPTION_VALUE_SIZE_MAX]; 34780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char rev[OPTION_VALUE_SIZE_MAX]; 35780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char custom[4][OPTION_VALUE_SIZE_MAX]; 36780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}; 37780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 38780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstruct dt_global_options { 39780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_options default_options; 40780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t page_size; 41780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}; 42780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 43780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstruct dt_image_writer { 44780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin FILE *img_fp; 45780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 46780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_global_options global_options; 47780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_options entry_options; 48780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 49780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char entry_filename[1024]; 50780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t entry_count; 51780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t entry_offset; 52780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t dt_offset; 5397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu 5497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu char (*past_filenames)[1024]; 5597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu uint32_t *past_dt_offsets; 56780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin}; 57780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 58780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 59780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void init_dt_options(struct dt_options *options) { 60780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin memset(options, 0, sizeof(struct dt_options)); 61780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 62780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 63780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void init_dt_global_options(struct dt_global_options *options) { 64780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin init_dt_options(&options->default_options); 65780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin options->page_size = DT_TABLE_DEFAULT_PAGE_SIZE; 66780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 67780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 68780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic void copy_dt_options(struct dt_options *target, struct dt_options *options) { 69780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin memcpy(target, options, sizeof(struct dt_options)); 70780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 71780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 72780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic char *load_file_contents(FILE *fp, size_t *len_ptr) { 73780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin // Gets the file size. 74780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fseek(fp, 0, SEEK_END); 75780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin size_t len = ftell(fp); 76780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fseek(fp, 0, SEEK_SET); 77780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 78780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char *buf = malloc(len); 79780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (buf == NULL) { 80780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return NULL; 81780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 82780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 83780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (fread(buf, len, 1, fp) != 1) { 84780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin free(buf); 85780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return NULL; 86780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 87780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 88780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (len_ptr) { 89780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin *len_ptr = len; 90780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 91780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 92780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return buf; 93780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 94780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 95780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic char *load_file(const char *filename, size_t *len_ptr) { 96780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin FILE *fp = fopen(filename, "r"); 97780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (!fp) { 98780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return NULL; 99780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 100780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 101780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char *buf = load_file_contents(fp, len_ptr); 102780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 103780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fclose(fp); 104780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 105780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return buf; 106780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 107780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 108780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int split_str(char **lhs_ptr, char **rhs_ptr, char *string, char c) { 109780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char *middle_ptr = strchr(string, c); 110780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (middle_ptr == NULL) { 111780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return -1; 112780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 113780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 114780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin *middle_ptr = '\0'; 115780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 116780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin *lhs_ptr = string; 117780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin *rhs_ptr = middle_ptr + 1; 118780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 119780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 120780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 121780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 122780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint parse_option(char **option_ptr, char **value_ptr, char *line_str) { 123780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return split_str(option_ptr, value_ptr, line_str, '='); 124780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 125780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 126780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint parse_path(char **path_ptr, char **prop_ptr, char *value_str) { 127780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return split_str(path_ptr, prop_ptr, value_str, ':'); 128780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 129780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 130780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic fdt32_t get_fdt32_from_prop(void *fdt, const char *path, const char *prop) { 131780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin int node_off = fdt_path_offset(fdt, path); 132780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (node_off < 0) { 133780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "Can not find node: %s\n", path); 134780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 135780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 136780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 137780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin int len; 138780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fdt32_t *prop_value_ptr = (fdt32_t *)fdt_getprop(fdt, node_off, prop, &len); 139780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (prop_value_ptr == NULL) { 140780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "Can not find property: %s:%s\n", path, prop); 141780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 142780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 143780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 1447b226bf72a0fd3fefcf7daca4991818187e338f8SzuWei Lin fdt32_t value = *prop_value_ptr; 145780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* TODO: check len */ 146780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (DEBUG) printf("%s:%s => %08x\n", path, prop, fdt32_to_cpu(value)); 147780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 148780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return value; 149780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 150780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 151780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic fdt32_t get_fdt32_from_number_or_prop(void *fdt, char *value_str) { 152780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (value_str[0] == '/') { 153780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char *path, *prop; 154780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (parse_path(&path, &prop, value_str) != 0) { 155780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "Wrong syntax: %s\n", value_str); 156780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 157780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 158780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return get_fdt32_from_prop(fdt, path, prop); 159780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 160780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 161780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* It should be a number */ 162780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin char *end; 163780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t value = strtoul(value_str, &end, 0); 164780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* TODO: check end */ 165780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return cpu_to_fdt32(value); 166780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 167780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 168780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int output_img_header(FILE *img_fp, 169780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin uint32_t entry_count, uint32_t total_size, 170780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_global_options *options) { 171780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_table_header header; 172780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin dt_table_header_init(&header); 173780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin header.dt_entry_count = cpu_to_fdt32(entry_count); 174780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin header.total_size = cpu_to_fdt32(total_size); 175780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin header.page_size = cpu_to_fdt32(options->page_size); 176780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 177780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fseek(img_fp, 0, SEEK_SET); 178780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fwrite(&header, sizeof(header), 1, img_fp); 179780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 180780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 181780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 182780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 18397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhustatic int32_t output_img_entry(FILE *img_fp, size_t entry_offset, 18497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu size_t dt_offset, const char *fdt_filename, 18597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu struct dt_options *options, int reuse_fdt) { 18697a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu int32_t ret = -1; 187780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin void *fdt = NULL; 188780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 189780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin size_t fdt_file_size; 190780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fdt = load_file(fdt_filename, &fdt_file_size); 191780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (fdt == NULL) { 192780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "Can not read file: %s\n", fdt_filename); 193780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin goto end; 194780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 195780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 196780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (fdt_check_header(fdt) != 0) { 197780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "Bad FDT header: \n", fdt_filename); 198780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin goto end; 199780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 200780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 201780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin size_t fdt_size = fdt_totalsize(fdt); 202780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (fdt_size != fdt_file_size) { 203780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fprintf(stderr, "The file size and FDT size are not matched: %s\n", fdt_filename); 204780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin goto end; 205780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 206780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 207780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* Prepare dt_table_entry and output */ 208780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_table_entry entry; 209780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.dt_size = cpu_to_fdt32(fdt_size); 210780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.dt_offset = cpu_to_fdt32(dt_offset); 211780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.id = get_fdt32_from_number_or_prop(fdt, options->id); 212780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.rev = get_fdt32_from_number_or_prop(fdt, options->rev); 213780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.custom[0] = get_fdt32_from_number_or_prop(fdt, options->custom[0]); 214780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.custom[1] = get_fdt32_from_number_or_prop(fdt, options->custom[1]); 215780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.custom[2] = get_fdt32_from_number_or_prop(fdt, options->custom[2]); 216780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin entry.custom[3] = get_fdt32_from_number_or_prop(fdt, options->custom[3]); 217780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fseek(img_fp, entry_offset, SEEK_SET); 218780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fwrite(&entry, sizeof(entry), 1, img_fp); 219780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 220780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* Output FDT */ 22197a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!reuse_fdt) { 22297a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu fseek(img_fp, dt_offset, SEEK_SET); 22397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu fwrite(fdt, fdt_file_size, 1, img_fp); 22497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu ret = fdt_file_size; 22597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu } else { 22697a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu ret = 0; 22797a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu } 228780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 229780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linend: 230780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (fdt) free(fdt); 231780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 232780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return ret; 233780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 234780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 235780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 236780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstruct dt_image_writer *dt_image_writer_start(FILE *img_fp, uint32_t entry_count) { 237780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_image_writer *writer = malloc(sizeof(struct dt_image_writer)); 23897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!writer) goto error; 23997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu writer->past_filenames = calloc(entry_count, sizeof(*writer->past_filenames)); 24097a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!writer->past_filenames) goto error; 24197a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu writer->past_dt_offsets = 24297a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu calloc(entry_count, sizeof(*writer->past_dt_offsets)); 24397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!writer->past_dt_offsets) goto error; 244780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->img_fp = img_fp; 245780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin init_dt_global_options(&writer->global_options); 246780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin init_dt_options(&writer->entry_options); 247780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_filename[0] = '\0'; 248780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_count = entry_count; 249780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_offset = sizeof(struct dt_table_header); 250780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->dt_offset = 251780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_offset + sizeof(struct dt_table_entry) * entry_count; 252780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return writer; 25397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu 25497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhuerror: 25597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu fprintf(stderr, "Unable to start writer\n"); 25697a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!writer) return NULL; 25797a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (writer->past_filenames) free(writer->past_filenames); 25897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (writer->past_dt_offsets) free(writer->past_dt_offsets); 25997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu free(writer); 26097a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu return NULL; 261780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 262780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 263780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int set_dt_options(struct dt_options *options, 264780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin const char *option, const char *value) { 265780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (strcmp(option, "id") == 0) { 266780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->id, value, OPTION_VALUE_SIZE_MAX - 1); 267780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else if (strcmp(option, "rev") == 0) { 268780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->rev, value, OPTION_VALUE_SIZE_MAX - 1); 269780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else if (strcmp(option, "custom0") == 0) { 270780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->custom[0], value, OPTION_VALUE_SIZE_MAX - 1); 271780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else if (strcmp(option, "custom1") == 0) { 272780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->custom[1], value, OPTION_VALUE_SIZE_MAX - 1); 273780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else if (strcmp(option, "custom2") == 0) { 274780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->custom[2], value, OPTION_VALUE_SIZE_MAX - 1); 275780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else if (strcmp(option, "custom3") == 0) { 276780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy(options->custom[3], value, OPTION_VALUE_SIZE_MAX - 1); 277780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else { 278780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return -1; 279780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 280780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 281780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 282780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 283780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 284780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint set_global_options(struct dt_image_writer *writer, 285780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin const char *option, const char *value) { 286780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin struct dt_global_options *global_options = &writer->global_options; 287780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 288780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (strcmp(option, "page_size") == 0) { 289780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin global_options->page_size = strtoul(value, NULL, 0); 290780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } else { 291780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return set_dt_options(&global_options->default_options, option, value); 292780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 293780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 294780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 295780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 296780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 297780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint set_entry_options(struct dt_image_writer *writer, 298780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin const char *option, const char *value) { 299780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return set_dt_options(&writer->entry_options, option, value); 300780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 301780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 302780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linstatic int flush_entry_to_img(struct dt_image_writer *writer) { 303780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (writer->entry_filename[0] == '\0') { 304780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 305780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 306780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 30797a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu int reuse_fdt; 30897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu int fdt_idx; 30997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu uint32_t dt_offset; 31097a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu 31197a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu for (fdt_idx = 0; writer->past_filenames[fdt_idx][0] != '\0'; fdt_idx++) { 31297a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (strcmp(writer->past_filenames[fdt_idx], writer->entry_filename) == 0) 31397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu break; 31497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu } 31597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu 31697a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (writer->past_filenames[fdt_idx][0] != '\0') { 31797a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu reuse_fdt = 1; 31897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu dt_offset = writer->past_dt_offsets[fdt_idx]; 31997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu } else { 32097a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu reuse_fdt = 0; 32197a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu dt_offset = writer->dt_offset; 32297a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu } 32397a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu int32_t dt_size = output_img_entry(writer->img_fp, writer->entry_offset, 32497a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu dt_offset, writer->entry_filename, 32597a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu &writer->entry_options, reuse_fdt); 32697a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (dt_size == -1) return -1; 32797a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu 32897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu if (!reuse_fdt) { 32997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu strncpy(writer->past_filenames[fdt_idx], writer->entry_filename, 33097a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu sizeof(writer->past_filenames[fdt_idx]) - 1); 33197a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu writer->past_dt_offsets[fdt_idx] = dt_offset; 332780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 333780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 334780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_offset += sizeof(struct dt_table_entry); 335780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->dt_offset += dt_size; 336780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 337780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 338780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 339780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 340780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint dt_image_writer_add_entry(struct dt_image_writer *writer, 341780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin const char *fdt_filename) { 342780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (flush_entry_to_img(writer) != 0) { 343780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return -1; 344780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 345780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 346780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin strncpy( 347780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_filename, 348780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin fdt_filename, 349780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin sizeof(writer->entry_filename) - 1); 350780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 351780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin /* Copy the default_options as default */ 352780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin copy_dt_options( 353780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin &writer->entry_options, 354780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin &writer->global_options.default_options); 355780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 356780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return 0; 357780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 358780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 359780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linint dt_image_writer_end(struct dt_image_writer *writer) { 360780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin int ret = -1; 361780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 362780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (flush_entry_to_img(writer) != 0) { 363780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin goto end; 364780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 365780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 366780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin if (output_img_header( 367780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->img_fp, 368780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->entry_count, 369780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin writer->dt_offset, 370780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin &writer->global_options) != 0) { 371780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin goto end; 372780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin } 373780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 374780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin printf("Total %d entries.\n", writer->entry_count); 375780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin ret = 0; 376780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 377780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Linend: 37897a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu free(writer->past_filenames); 37997a832f2a345b6bb090dd4adc9f6e8b50e11b3daYueyao Zhu free(writer->past_dt_offsets); 380780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin free(writer); 381780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin 382780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin return ret; 383780c3b0fba4bb4dbd39091ebbd1ddc3eacb2deb9SzuWei Lin} 384