1 /* 2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3 * 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18 * USA 19 */ 20 21 #include "dtc.h" 22 #include "srcpos.h" 23 24 extern FILE *yyin; 25 extern int yyparse(void); 26 extern YYLTYPE yylloc; 27 28 struct boot_info *the_boot_info; 29 bool treesource_error; 30 31 struct boot_info *dt_from_source(const char *fname) 32 { 33 the_boot_info = NULL; 34 treesource_error = false; 35 36 srcfile_push(fname); 37 yyin = current_srcfile->f; 38 yylloc.file = current_srcfile; 39 40 if (yyparse() != 0) 41 die("Unable to parse input tree\n"); 42 43 if (treesource_error) 44 die("Syntax error parsing input tree\n"); 45 46 return the_boot_info; 47 } 48 49 static void write_prefix(FILE *f, int level) 50 { 51 int i; 52 53 for (i = 0; i < level; i++) 54 fputc('\t', f); 55 } 56 57 static bool isstring(char c) 58 { 59 return (isprint((unsigned char)c) 60 || (c == '\0') 61 || strchr("\a\b\t\n\v\f\r", c)); 62 } 63 64 static void write_propval_string(FILE *f, struct data val) 65 { 66 const char *str = val.val; 67 int i; 68 struct marker *m = val.markers; 69 70 assert(str[val.len-1] == '\0'); 71 72 while (m && (m->offset == 0)) { 73 if (m->type == LABEL) 74 fprintf(f, "%s: ", m->ref); 75 m = m->next; 76 } 77 fprintf(f, "\""); 78 79 for (i = 0; i < (val.len-1); i++) { 80 char c = str[i]; 81 82 switch (c) { 83 case '\a': 84 fprintf(f, "\\a"); 85 break; 86 case '\b': 87 fprintf(f, "\\b"); 88 break; 89 case '\t': 90 fprintf(f, "\\t"); 91 break; 92 case '\n': 93 fprintf(f, "\\n"); 94 break; 95 case '\v': 96 fprintf(f, "\\v"); 97 break; 98 case '\f': 99 fprintf(f, "\\f"); 100 break; 101 case '\r': 102 fprintf(f, "\\r"); 103 break; 104 case '\\': 105 fprintf(f, "\\\\"); 106 break; 107 case '\"': 108 fprintf(f, "\\\""); 109 break; 110 case '\0': 111 fprintf(f, "\", "); 112 while (m && (m->offset <= (i + 1))) { 113 if (m->type == LABEL) { 114 assert(m->offset == (i+1)); 115 fprintf(f, "%s: ", m->ref); 116 } 117 m = m->next; 118 } 119 fprintf(f, "\""); 120 break; 121 default: 122 if (isprint((unsigned char)c)) 123 fprintf(f, "%c", c); 124 else 125 fprintf(f, "\\x%02hhx", c); 126 } 127 } 128 fprintf(f, "\""); 129 130 /* Wrap up any labels at the end of the value */ 131 for_each_marker_of_type(m, LABEL) { 132 assert (m->offset == val.len); 133 fprintf(f, " %s:", m->ref); 134 } 135 } 136 137 static void write_propval_cells(FILE *f, struct data val) 138 { 139 void *propend = val.val + val.len; 140 cell_t *cp = (cell_t *)val.val; 141 struct marker *m = val.markers; 142 143 fprintf(f, "<"); 144 for (;;) { 145 while (m && (m->offset <= ((char *)cp - val.val))) { 146 if (m->type == LABEL) { 147 assert(m->offset == ((char *)cp - val.val)); 148 fprintf(f, "%s: ", m->ref); 149 } 150 m = m->next; 151 } 152 153 fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); 154 if ((void *)cp >= propend) 155 break; 156 fprintf(f, " "); 157 } 158 159 /* Wrap up any labels at the end of the value */ 160 for_each_marker_of_type(m, LABEL) { 161 assert (m->offset == val.len); 162 fprintf(f, " %s:", m->ref); 163 } 164 fprintf(f, ">"); 165 } 166 167 static void write_propval_bytes(FILE *f, struct data val) 168 { 169 void *propend = val.val + val.len; 170 const char *bp = val.val; 171 struct marker *m = val.markers; 172 173 fprintf(f, "["); 174 for (;;) { 175 while (m && (m->offset == (bp-val.val))) { 176 if (m->type == LABEL) 177 fprintf(f, "%s: ", m->ref); 178 m = m->next; 179 } 180 181 fprintf(f, "%02hhx", (unsigned char)(*bp++)); 182 if ((const void *)bp >= propend) 183 break; 184 fprintf(f, " "); 185 } 186 187 /* Wrap up any labels at the end of the value */ 188 for_each_marker_of_type(m, LABEL) { 189 assert (m->offset == val.len); 190 fprintf(f, " %s:", m->ref); 191 } 192 fprintf(f, "]"); 193 } 194 195 static void write_propval(FILE *f, struct property *prop) 196 { 197 int len = prop->val.len; 198 const char *p = prop->val.val; 199 struct marker *m = prop->val.markers; 200 int nnotstring = 0, nnul = 0; 201 int nnotstringlbl = 0, nnotcelllbl = 0; 202 int i; 203 204 if (len == 0) { 205 fprintf(f, ";\n"); 206 return; 207 } 208 209 for (i = 0; i < len; i++) { 210 if (! isstring(p[i])) 211 nnotstring++; 212 if (p[i] == '\0') 213 nnul++; 214 } 215 216 for_each_marker_of_type(m, LABEL) { 217 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 218 nnotstringlbl++; 219 if ((m->offset % sizeof(cell_t)) != 0) 220 nnotcelllbl++; 221 } 222 223 fprintf(f, " = "); 224 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) 225 && (nnotstringlbl == 0)) { 226 write_propval_string(f, prop->val); 227 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 228 write_propval_cells(f, prop->val); 229 } else { 230 write_propval_bytes(f, prop->val); 231 } 232 233 fprintf(f, ";\n"); 234 } 235 236 static void write_tree_source_node(FILE *f, struct node *tree, int level) 237 { 238 struct property *prop; 239 struct node *child; 240 struct label *l; 241 242 write_prefix(f, level); 243 for_each_label(tree->labels, l) 244 fprintf(f, "%s: ", l->label); 245 if (tree->name && (*tree->name)) 246 fprintf(f, "%s {\n", tree->name); 247 else 248 fprintf(f, "/ {\n"); 249 250 for_each_property(tree, prop) { 251 write_prefix(f, level+1); 252 for_each_label(prop->labels, l) 253 fprintf(f, "%s: ", l->label); 254 fprintf(f, "%s", prop->name); 255 write_propval(f, prop); 256 } 257 for_each_child(tree, child) { 258 fprintf(f, "\n"); 259 write_tree_source_node(f, child, level+1); 260 } 261 write_prefix(f, level); 262 fprintf(f, "};\n"); 263 } 264 265 266 void dt_to_source(FILE *f, struct boot_info *bi) 267 { 268 struct reserve_info *re; 269 270 fprintf(f, "/dts-v1/;\n\n"); 271 272 for (re = bi->reservelist; re; re = re->next) { 273 struct label *l; 274 275 for_each_label(re->labels, l) 276 fprintf(f, "%s: ", l->label); 277 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 278 (unsigned long long)re->re.address, 279 (unsigned long long)re->re.size); 280 } 281 282 write_tree_source_node(f, bi->dt, 0); 283 } 284 285