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