blob: 8cc71494454f3a6f6745fce8b0442cbe2f506a63 [file] [log] [blame]
Peer Chen8d782ee2011-01-18 21:34:18 -05001/**
Peer Chen6f2cbc72012-03-13 11:12:39 +08002 * Copyright (c) 2012 NVIDIA Corporation. All rights reserved.
Peer Chen8d782ee2011-01-18 21:34:18 -05003 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23/*
24 * parse.c - Parsing support for the cbootimage tool
25 */
26
Peer Chen6f2cbc72012-03-13 11:12:39 +080027#include <ctype.h>
Peer Chen8d782ee2011-01-18 21:34:18 -050028#include "parse.h"
29#include "cbootimage.h"
30#include "data_layout.h"
31#include "crypto.h"
32#include "set.h"
33
34/*
35 * Function prototypes
36 *
37 * ParseXXX() parses XXX in the input
38 * SetXXX() sets state based on the parsing results but does not perform
39 * any parsing of its own
40 * A ParseXXX() function may call other parse functions and set functions.
41 * A SetXXX() function may not call any parseing functions.
42 */
43
Peer Chen6f2cbc72012-03-13 11:12:39 +080044static int
45set_array(build_image_context *context,
46 u_int32_t index,
47 parse_token token,
48 u_int32_t value);
49static char *parse_u32(char *str, u_int32_t *val);
50static char *parse_u8(char *str, u_int32_t *val);
51static char *parse_filename(char *str, char *name, int chars_remaining);
Peer Chen7557d9b2011-02-24 09:29:23 -080052static char *parse_enum(build_image_context *context,
Peer Chen6f2cbc72012-03-13 11:12:39 +080053 char *str,
Peer Chen7557d9b2011-02-24 09:29:23 -080054 enum_item *table,
55 u_int32_t *val);
56static char
57*parse_field_name(char *rest, field_item *field_table, field_item **field);
58static char
Anton Staafe517a4f2011-03-14 12:28:06 -070059*parse_field_value(build_image_context *context,
Peer Chen7557d9b2011-02-24 09:29:23 -080060 char *rest,
61 field_item *field,
62 u_int32_t *value);
Peer Chen8d782ee2011-01-18 21:34:18 -050063static int
64parse_array(build_image_context *context, parse_token token, char *rest);
65static int
66parse_bootloader(build_image_context *context, parse_token token, char *rest);
67static int
68parse_value_u32(build_image_context *context, parse_token token, char *rest);
69static int
70parse_bct_file(build_image_context *context, parse_token token, char *rest);
Peer Chen8d782ee2011-01-18 21:34:18 -050071static char
Peer Chen6f2cbc72012-03-13 11:12:39 +080072*parse_end_state(char *str, char *uname, int chars_remaining);
Peer Chen7557d9b2011-02-24 09:29:23 -080073static int
74parse_dev_param(build_image_context *context, parse_token token, char *rest);
Peer Chen3a834ed2011-03-04 09:30:05 -080075static int
76parse_sdram_param(build_image_context *context, parse_token token, char *rest);
Peer Chen7557d9b2011-02-24 09:29:23 -080077
Peer Chen6f2cbc72012-03-13 11:12:39 +080078static int process_statement(build_image_context *context,
79 char *str,
80 u_int8_t simple_parse);
Peer Chen8d782ee2011-01-18 21:34:18 -050081
Peer Chen6f2cbc72012-03-13 11:12:39 +080082static parse_item parse_simple_items[] =
Peer Chen7557d9b2011-02-24 09:29:23 -080083{
Peer Chen6f2cbc72012-03-13 11:12:39 +080084 { "Bctfile=", token_bct_file, parse_bct_file },
85 { "BootLoader=", token_bootloader, parse_bootloader },
86 { "Redundancy=", token_redundancy, parse_value_u32 },
87 { "Bctcopy=", token_bct_copy, parse_value_u32 },
88 { "Version=", token_version, parse_value_u32 },
Stephen Warrenf13abb02012-05-16 14:56:55 -060089 { "PreBctPadBlocks=", token_pre_bct_pad_blocks, parse_value_u32 },
Peer Chen6f2cbc72012-03-13 11:12:39 +080090 { NULL, 0, NULL } /* Must be last */
Peer Chen7557d9b2011-02-24 09:29:23 -080091};
92
Peer Chen6f2cbc72012-03-13 11:12:39 +080093static parse_item s_top_level_items[] = {
Peer Chen053d5782011-03-03 10:12:58 -080094 { "Bctfile=", token_bct_file, parse_bct_file },
95 { "Attribute=", token_attribute, parse_value_u32 },
96 { "Attribute[", token_attribute, parse_array },
97 { "PageSize=", token_page_size, parse_value_u32 },
98 { "BlockSize=", token_block_size, parse_value_u32 },
99 { "PartitionSize=", token_partition_size, parse_value_u32 },
100 { "DevType[", token_dev_type, parse_array },
101 { "DeviceParam[", token_dev_param, parse_dev_param },
Peer Chen3a834ed2011-03-04 09:30:05 -0800102 { "SDRAM[", token_sdram, parse_sdram_param },
Peer Chen053d5782011-03-03 10:12:58 -0800103 { "BootLoader=", token_bootloader, parse_bootloader },
104 { "Redundancy=", token_redundancy, parse_value_u32 },
Peer Chen56f40482011-07-27 02:59:41 -0400105 { "Bctcopy=", token_bct_copy, parse_value_u32 },
Peer Chen053d5782011-03-03 10:12:58 -0800106 { "Version=", token_version, parse_value_u32 },
Stephen Warrenfb4793a2012-05-16 14:38:17 -0600107 { "OdmData=", token_odm_data, parse_value_u32 },
Peer Chen8d782ee2011-01-18 21:34:18 -0500108 { NULL, 0, NULL } /* Must be last */
109};
110
111/* Macro to simplify parser code a bit. */
112#define PARSE_COMMA(x) if (*rest != ',') return (x); rest++
113
Peer Chen6f2cbc72012-03-13 11:12:39 +0800114/*
115 * Parse the given string and find the u32 dec/hex number.
116 *
117 * @param str String to parse
118 * @param val Returns value that was parsed
119 * @return the remainder of the string after the number was parsed
120 */
Peer Chen8d782ee2011-01-18 21:34:18 -0500121static char *
Peer Chen6f2cbc72012-03-13 11:12:39 +0800122parse_u32(char *str, u_int32_t *val)
Peer Chen8d782ee2011-01-18 21:34:18 -0500123{
124 u_int32_t value = 0;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800125 u_int32_t digit;
Peer Chen8d782ee2011-01-18 21:34:18 -0500126
Peer Chen6f2cbc72012-03-13 11:12:39 +0800127 while (*str == '0')
128 str++;
Peer Chen8d782ee2011-01-18 21:34:18 -0500129
Peer Chen6f2cbc72012-03-13 11:12:39 +0800130 if (tolower(*str) == 'x') {
131 str++;
132 while (isxdigit(*str)) {
Peer Chen8d782ee2011-01-18 21:34:18 -0500133 value *= 16;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800134 digit = tolower(*str);
135 value += digit <= '9' ? digit - '0' : digit - 'a' + 10;
136 str++;
Peer Chen8d782ee2011-01-18 21:34:18 -0500137 }
138 } else {
Peer Chen6f2cbc72012-03-13 11:12:39 +0800139 while (*str >= '0' && *str <= '9') {
140 value = value*10 + (*str - '0');
141 str++;
Peer Chen8d782ee2011-01-18 21:34:18 -0500142 }
143 }
144 *val = value;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800145 return str;
Peer Chen8d782ee2011-01-18 21:34:18 -0500146}
147
Peer Chen6f2cbc72012-03-13 11:12:39 +0800148/*
149 * Parse the given string and find the u8 dec/hex number.
150 *
151 * @param str String to parse
152 * @param val Returns value that was parsed
153 * @return the remainder of the string after the number was parsed
154 */
155static char *
156parse_u8(char *str, u_int32_t *val)
Peer Chen7557d9b2011-02-24 09:29:23 -0800157{
158 char *retval;
159
Peer Chen6f2cbc72012-03-13 11:12:39 +0800160 retval = parse_u32(str, val);
Peer Chen7557d9b2011-02-24 09:29:23 -0800161
162 if (*val > 0xff) {
163 printf("Warning: Parsed 8-bit value that exceeded 8-bits.\n");
164 printf(" Parsed value = %d. Remaining text = %s\n",
165 *val, retval);
166 }
167
168 return retval;
169}
170
171
Peer Chen6f2cbc72012-03-13 11:12:39 +0800172/*
173 * Parse the given string and find the file name then
174 * return the rest of the string.
175 *
176 * @param str String to parse
177 * @param name Returns the filename that was parsed
178 * @param chars_remaining The maximum length of filename
179 * @return the remainder of the string after the name was parsed
180 */
Peer Chen8d782ee2011-01-18 21:34:18 -0500181static char *
Peer Chen6f2cbc72012-03-13 11:12:39 +0800182parse_filename(char *str, char *name, int chars_remaining)
Peer Chen8d782ee2011-01-18 21:34:18 -0500183{
Peer Chen6f2cbc72012-03-13 11:12:39 +0800184 /*
185 * Check if the filename buffer is out of space, preserving one
186 * character to null terminate the string.
187 */
188 while (isalnum(*str) || strchr("\\/~_-+:.", *str)) {
189
Peer Chen8d782ee2011-01-18 21:34:18 -0500190 chars_remaining--;
191
192 if (chars_remaining < 1)
193 return NULL;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800194 *name++ = *str++;
Peer Chen8d782ee2011-01-18 21:34:18 -0500195 }
196
197 /* Null terminate the filename. */
198 *name = '\0';
199
Peer Chen6f2cbc72012-03-13 11:12:39 +0800200 return str;
Peer Chen8d782ee2011-01-18 21:34:18 -0500201}
202
Peer Chen6f2cbc72012-03-13 11:12:39 +0800203/*
204 * Parse the given string and find the match field name listed
205 * in field table.
206 *
207 * @param rest String to parse
208 * @param field_table The field table to parse
209 * @param field Returns the field item that was parsed
210 * @return NULL or the remainder of the string after the field item was parsed
211 */
Peer Chen7557d9b2011-02-24 09:29:23 -0800212static char
213*parse_field_name(char *rest, field_item *field_table, field_item **field)
214{
215 u_int32_t i;
216 u_int32_t field_name_len = 0;
217
218 assert(field_table != NULL);
219 assert(rest != NULL);
220 assert(field != NULL);
221
Peer Chen6f2cbc72012-03-13 11:12:39 +0800222 while (rest[field_name_len] != '=')
Peer Chen7557d9b2011-02-24 09:29:23 -0800223 field_name_len++;
224
225 /* Parse the field name. */
226 for (i = 0; field_table[i].name != NULL; i++) {
227 if ((strlen(field_table[i].name) == field_name_len) &&
228 !strncmp(field_table[i].name,
229 rest,
230 field_name_len)) {
231
232 *field = &(field_table[i]);
233 rest = rest + field_name_len;
234 return rest;
235 }
236 }
237
238 /* Field wasn't found or a parse error occurred. */
239 return NULL;
240}
241
Peer Chen6f2cbc72012-03-13 11:12:39 +0800242/*
243 * Parse the value based on the field table
244 *
245 * @param context The main context pointer
246 * @param rest String to parse
247 * @param field Field item to parse
248 * @param value Returns the value that was parsed
249 * @return the remainder of the string after the value was parsed
250 */
Peer Chen7557d9b2011-02-24 09:29:23 -0800251static char
Peer Chen6f2cbc72012-03-13 11:12:39 +0800252*parse_field_value(build_image_context *context,
Peer Chen7557d9b2011-02-24 09:29:23 -0800253 char *rest,
254 field_item *field,
255 u_int32_t *value)
256{
257 assert(rest != NULL);
258 assert(field != NULL);
259 assert((field->type != field_type_enum)
260 || (field->enum_table != NULL));
261
262 switch (field->type) {
263 case field_type_enum:
264 rest = parse_enum(context, rest, field->enum_table, value);
265 break;
266
267 case field_type_u32:
268 rest = parse_u32(rest, value);
269 break;
270
271 case field_type_u8:
272 rest = parse_u8(rest, value);
273 break;
274
275 default:
276 printf("Unexpected field type %d at line %d\n",
277 field->type, __LINE__);
278 rest = NULL;
279 break;
280 }
281
282 return rest;
283}
284
Peer Chen6f2cbc72012-03-13 11:12:39 +0800285/*
286 * Parse the given string and find the match enum item listed
287 * in table.
288 *
289 * @param context The main context pointer
290 * @param str String to parse
291 * @param table Enum item table to parse
292 * @param value Returns the value that was parsed
293 * @return the remainder of the string after the item was parsed
294 */
Peer Chen7557d9b2011-02-24 09:29:23 -0800295static char *
296parse_enum(build_image_context *context,
Peer Chen6f2cbc72012-03-13 11:12:39 +0800297 char *str,
Peer Chen7557d9b2011-02-24 09:29:23 -0800298 enum_item *table,
299 u_int32_t *val)
300{
301 int i;
302 char *rest;
Peer Chen7557d9b2011-02-24 09:29:23 -0800303
304 for (i = 0; table[i].name != NULL; i++) {
Peer Chen6f2cbc72012-03-13 11:12:39 +0800305 if (!strncmp(table[i].name, str,
Peer Chen7557d9b2011-02-24 09:29:23 -0800306 strlen(table[i].name))) {
Peer Chen6f2cbc72012-03-13 11:12:39 +0800307 *val = table[i].value;
308 rest = str + strlen(table[i].name);
309 return rest;
Peer Chen7557d9b2011-02-24 09:29:23 -0800310 }
311 }
Peer Chen6f2cbc72012-03-13 11:12:39 +0800312 return parse_u32(str, val);
Peer Chen7557d9b2011-02-24 09:29:23 -0800313
314}
Peer Chen6f2cbc72012-03-13 11:12:39 +0800315
Peer Chen8d782ee2011-01-18 21:34:18 -0500316/*
Peer Chen6f2cbc72012-03-13 11:12:39 +0800317 * Parse the given string and find the bootloader file name, load address and
318 * entry point information then call set_bootloader function.
319 *
320 * @param context The main context pointer
321 * @param token The parse token value
322 * @param rest String to parse
323 * @return 0 and 1 for success and failure
Peer Chen8d782ee2011-01-18 21:34:18 -0500324 */
325static int parse_bootloader(build_image_context *context,
326 parse_token token,
327 char *rest)
328{
329 char filename[MAX_BUFFER];
330 char e_state[MAX_STR_LEN];
331 u_int32_t load_addr;
332 u_int32_t entry_point;
333
334 assert(context != NULL);
335 assert(rest != NULL);
336
Peer Chen7557d9b2011-02-24 09:29:23 -0800337 if (context->generate_bct != 0)
338 return 0;
Peer Chen8d782ee2011-01-18 21:34:18 -0500339 /* Parse the file name. */
340 rest = parse_filename(rest, filename, MAX_BUFFER);
341 if (rest == NULL)
342 return 1;
343
344 PARSE_COMMA(1);
345
346 /* Parse the load address. */
347 rest = parse_u32(rest, &load_addr);
348 if (rest == NULL)
349 return 1;
350
351 PARSE_COMMA(1);
352
353 /* Parse the entry point. */
354 rest = parse_u32(rest, &entry_point);
355 if (rest == NULL)
356 return 1;
357
358 PARSE_COMMA(1);
359
360 /* Parse the end state. */
361 rest = parse_end_state(rest, e_state, MAX_STR_LEN);
362 if (rest == NULL)
363 return 1;
364 if (strncmp(e_state, "Complete", strlen("Complete")))
365 return 1;
366
367 /* Parsing has finished - set the bootloader */
368 return set_bootloader(context, filename, load_addr, entry_point);
369}
370
371/*
Peer Chen6f2cbc72012-03-13 11:12:39 +0800372 * Parse the given string and find the array items in config file.
373 *
374 * @param context The main context pointer
375 * @param token The parse token value
376 * @param rest String to parse
377 * @return 0 and 1 for success and failure
Peer Chen8d782ee2011-01-18 21:34:18 -0500378 */
379static int
380parse_array(build_image_context *context, parse_token token, char *rest)
381{
382 u_int32_t index;
383 u_int32_t value;
384
385 assert(context != NULL);
386 assert(rest != NULL);
387
388 /* Parse the index. */
389 rest = parse_u32(rest, &index);
390 if (rest == NULL)
391 return 1;
392
393 /* Parse the closing bracket. */
394 if (*rest != ']')
395 return 1;
396 rest++;
397
398 /* Parse the equals sign.*/
399 if (*rest != '=')
400 return 1;
401 rest++;
402
403 /* Parse the value based on the field table. */
Peer Chen6f2cbc72012-03-13 11:12:39 +0800404 switch (token) {
Peer Chen7557d9b2011-02-24 09:29:23 -0800405 case token_attribute:
406 rest = parse_u32(rest, &value);
407 break;
408 case token_dev_type:
Peer Chen6f2cbc72012-03-13 11:12:39 +0800409 rest = parse_enum(context,
410 rest,
411 s_devtype_table_t20,
412 &value);
Peer Chen7557d9b2011-02-24 09:29:23 -0800413 break;
Peer Chen8d782ee2011-01-18 21:34:18 -0500414
Peer Chen7557d9b2011-02-24 09:29:23 -0800415 default:
416 /* Unknown token */
417 return 1;
Peer Chen8d782ee2011-01-18 21:34:18 -0500418 }
419
420 if (rest == NULL)
421 return 1;
422
423 /* Store the result. */
Peer Chen6f2cbc72012-03-13 11:12:39 +0800424 return set_array(context, index, token, value);
Peer Chen8d782ee2011-01-18 21:34:18 -0500425}
426
427/*
Peer Chen6f2cbc72012-03-13 11:12:39 +0800428 * Call hw interface to set the value for array item in bct such as device
429 * type and bootloader attribute.
430 *
431 * @param context The main context pointer
432 * @param index The index for array
433 * @param token The parse token value
434 * @param value The value to set
435 * @return 0 and -ENODATA for success and failure
436 */
437
438static int
439set_array(build_image_context *context,
440 u_int32_t index,
441 parse_token token,
442 u_int32_t value)
443{
444 int err = 0;
445
446 assert(context != NULL);
447
448 switch (token) {
449 case token_attribute:
450 err = g_bct_parse_interf->setbl_param(index,
451 token_bl_attribute,
452 &value,
453 context->bct);
454 break;
455 case token_dev_type:
456 err = g_bct_parse_interf->set_dev_param(context,
457 index,
458 token_dev_type,
459 value);
460 break;
461 default:
462 break;
463 }
464 return err;
465}
466
467/*
468 * General handler for setting u_int32_t values in config files.
469 *
470 * @param context The main context pointer
471 * @param token The parse token value
472 * @param rest String to parse
473 * @return 0 and 1 for success and failure
Peer Chen8d782ee2011-01-18 21:34:18 -0500474 */
475static int parse_value_u32(build_image_context *context,
476 parse_token token,
477 char *rest)
478{
479 u_int32_t value;
480
481 assert(context != NULL);
482 assert(rest != NULL);
483
484 rest = parse_u32(rest, &value);
485 if (rest == NULL)
486 return 1;
487
488 return context_set_value(context, token, value);
489}
490
Peer Chen6f2cbc72012-03-13 11:12:39 +0800491/*
492 * Parse the given string and find the bct file name.
493 *
494 * @param context The main context pointer
495 * @param token The parse token value
496 * @param rest String to parse
497 * @return 0 and 1 for success and failure
498 */
Peer Chen8d782ee2011-01-18 21:34:18 -0500499static int
500parse_bct_file(build_image_context *context, parse_token token, char *rest)
501{
502 char filename[MAX_BUFFER];
503
504 assert(context != NULL);
505 assert(rest != NULL);
506
507 /* Parse the file name. */
508 rest = parse_filename(rest, filename, MAX_BUFFER);
509 if (rest == NULL)
510 return 1;
511
512 /* Parsing has finished - set the bctfile */
513 context->bct_filename = filename;
514 /* Read the bct file to buffer */
515 read_bct_file(context);
Peer Chen6f2cbc72012-03-13 11:12:39 +0800516 update_context(context);
Peer Chen8d782ee2011-01-18 21:34:18 -0500517 return 0;
518}
519
520static char *
Peer Chen6f2cbc72012-03-13 11:12:39 +0800521parse_end_state(char *str, char *uname, int chars_remaining)
Peer Chen8d782ee2011-01-18 21:34:18 -0500522{
Peer Chen6f2cbc72012-03-13 11:12:39 +0800523 while (isalpha(*str)) {
Peer Chen8d782ee2011-01-18 21:34:18 -0500524
Peer Chen6f2cbc72012-03-13 11:12:39 +0800525 *uname++ = *str++;
Peer Chen8d782ee2011-01-18 21:34:18 -0500526 if (--chars_remaining < 0)
527 return NULL;
528 }
529 *uname = '\0';
Peer Chen6f2cbc72012-03-13 11:12:39 +0800530 return str;
Peer Chen8d782ee2011-01-18 21:34:18 -0500531}
532
Peer Chen6f2cbc72012-03-13 11:12:39 +0800533/*
534 * Parse the given string and find device parameter listed in device table
535 * and value for this device parameter. If match, call the corresponding
536 * function in the table to set device parameter.
537 *
538 * @param context The main context pointer
539 * @param token The parse token value
540 * @param rest String to parse
541 * @return 0 and 1 for success and failure
542 */
Peer Chen7557d9b2011-02-24 09:29:23 -0800543static int
544parse_dev_param(build_image_context *context, parse_token token, char *rest)
545{
546 u_int32_t i;
547 u_int32_t value;
548 field_item *field;
549 u_int32_t index;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800550 parse_subfield_item *device_type_table;
Peer Chen7557d9b2011-02-24 09:29:23 -0800551 parse_subfield_item *device_item = NULL;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800552
Peer Chen7557d9b2011-02-24 09:29:23 -0800553 assert(context != NULL);
554 assert(rest != NULL);
555
Peer Chen6f2cbc72012-03-13 11:12:39 +0800556 if (context->boot_data_version == NVBOOT_BOOTDATA_VERSION(3, 1))
557 device_type_table = s_device_type_table_t30;
558 else
559 device_type_table = s_device_type_table_t20;
Peer Chen7557d9b2011-02-24 09:29:23 -0800560 /* Parse the index. */
561 rest = parse_u32(rest, &index);
562 if (rest == NULL)
563 return 1;
564
565 /* Parse the closing bracket. */
566 if (*rest != ']')
567 return 1;
568 rest++;
569
570 /* Parse the following '.' */
571 if (*rest != '.')
572 return 1;
573 rest++;
574
575 /* Parse the device name. */
Peer Chen6f2cbc72012-03-13 11:12:39 +0800576 for (i = 0; device_type_table[i].prefix != NULL; i++) {
577 if (!strncmp(device_type_table[i].prefix,
578 rest, strlen(device_type_table[i].prefix))) {
Peer Chen7557d9b2011-02-24 09:29:23 -0800579
Peer Chen6f2cbc72012-03-13 11:12:39 +0800580 device_item = &(device_type_table[i]);
581 rest = rest + strlen(device_type_table[i].prefix);
Peer Chen7557d9b2011-02-24 09:29:23 -0800582
583 /* Parse the field name. */
584 rest = parse_field_name(rest,
Peer Chen6f2cbc72012-03-13 11:12:39 +0800585 device_type_table[i].field_table,
Peer Chen7557d9b2011-02-24 09:29:23 -0800586 &field);
587 if (rest == NULL)
588 return 1;
589
590 /* Parse the equals sign.*/
591 if (*rest != '=')
592 return 1;
593 rest++;
594
595 /* Parse the value based on the field table. */
596 rest = parse_field_value(context, rest, field, &value);
597 if (rest == NULL)
598 return 1;
599 return device_item->process(context,
600 index, field->token, value);
601 }
602 }
Peer Chen6f2cbc72012-03-13 11:12:39 +0800603 return 1;
Peer Chen7557d9b2011-02-24 09:29:23 -0800604}
Peer Chen3a834ed2011-03-04 09:30:05 -0800605
Peer Chen6f2cbc72012-03-13 11:12:39 +0800606/*
607 * Parse the given string and find sdram parameter and value in config
608 * file. If match, call the corresponding function set the sdram parameter.
609 *
610 * @param context The main context pointer
611 * @param token The parse token value
612 * @param rest String to parse
613 * @return 0 and 1 for success and failure
614 */
Peer Chen3a834ed2011-03-04 09:30:05 -0800615static int
616parse_sdram_param(build_image_context *context, parse_token token, char *rest)
617{
618 u_int32_t value;
619 field_item *field;
620 u_int32_t index;
621
622 assert(context != NULL);
623 assert(rest != NULL);
624
625 /* Parse the index. */
626 rest = parse_u32(rest, &index);
627 if (rest == NULL)
628 return 1;
629
630 /* Parse the closing bracket. */
631 if (*rest != ']')
632 return 1;
633 rest++;
634
635 /* Parse the following '.' */
636 if (*rest != '.')
637 return 1;
638 rest++;
639
640 /* Parse the field name. */
Peer Chen6f2cbc72012-03-13 11:12:39 +0800641 if (context->boot_data_version == NVBOOT_BOOTDATA_VERSION(3, 1))
642 rest = parse_field_name(rest, s_sdram_field_table_t30, &field);
643 else
644 rest = parse_field_name(rest, s_sdram_field_table_t20, &field);
Peer Chen3a834ed2011-03-04 09:30:05 -0800645 if (rest == NULL)
646 return 1;
647
648 /* Parse the equals sign.*/
649 if (*rest != '=')
650 return 1;
651 rest++;
652
653 /* Parse the value based on the field table. */
654 rest = parse_field_value(context, rest, field, &value);
655 if (rest == NULL)
656 return 1;
657
658 /* Store the result. */
Peer Chen6f2cbc72012-03-13 11:12:39 +0800659 return g_bct_parse_interf->set_sdram_param(context,
660 index,
661 field->token,
662 value);
Peer Chen3a834ed2011-03-04 09:30:05 -0800663}
Peer Chen6f2cbc72012-03-13 11:12:39 +0800664
665/*
666 * Compare the given string with item listed in table.
667 * Execute the proper process function if match.
668 *
669 * @param context The main context pointer
670 * @param str String to parse
671 * @param simple_parse Simple parse flag
672 * @return 0 and 1 for success and failure
673 */
Peer Chen8d782ee2011-01-18 21:34:18 -0500674static int
Peer Chen6f2cbc72012-03-13 11:12:39 +0800675process_statement(build_image_context *context,
676 char *str,
677 u_int8_t simple_parse)
Peer Chen8d782ee2011-01-18 21:34:18 -0500678{
679 int i;
680 char *rest;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800681 parse_item *cfg_parse_item;
Peer Chen8d782ee2011-01-18 21:34:18 -0500682
Peer Chen6f2cbc72012-03-13 11:12:39 +0800683 if (simple_parse == 0)
684 cfg_parse_item = s_top_level_items;
685 else
686 cfg_parse_item = parse_simple_items;
Peer Chen8d782ee2011-01-18 21:34:18 -0500687
Peer Chen6f2cbc72012-03-13 11:12:39 +0800688 for (i = 0; cfg_parse_item[i].prefix != NULL; i++) {
689 if (!strncmp(cfg_parse_item[i].prefix, str,
690 strlen(cfg_parse_item[i].prefix))) {
691 rest = str + strlen(cfg_parse_item[i].prefix);
692
693 return cfg_parse_item[i].process(context,
694 cfg_parse_item[i].token,
Peer Chen8d782ee2011-01-18 21:34:18 -0500695 rest);
696 }
697 }
698
699 /* If this point was reached, there was a processing error. */
700 return 1;
701}
702
Peer Chen6f2cbc72012-03-13 11:12:39 +0800703/*
704 * The main function parse the config file.
705 *
706 * @param context The main context pointer
707 * @param simple_parse Simple parse flag
708 */
709void process_config_file(build_image_context *context, u_int8_t simple_parse)
Peer Chen8d782ee2011-01-18 21:34:18 -0500710{
711 char buffer[MAX_BUFFER];
712 int space = 0;
713 char current;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800714 u_int8_t c_eol_comment_start = 0; /* True after first slash */
Peer Chen8d782ee2011-01-18 21:34:18 -0500715 u_int8_t comment = 0;
716 u_int8_t string = 0;
717 u_int8_t equal_encounter = 0;
718
719 assert(context != NULL);
720 assert(context->config_file != NULL);
721
Peer Chen6f2cbc72012-03-13 11:12:39 +0800722 while ((current = fgetc(context->config_file)) != EOF) {
Peer Chen8d782ee2011-01-18 21:34:18 -0500723 if (space >= (MAX_BUFFER-1)) {
724 /* if we exceeded the max buffer size, it is likely
725 due to a missing semi-colon at the end of a line */
726 printf("Config file parsing error!");
727 exit(1);
728 }
729
730 /* Handle failure to complete "//" comment token.
731 Insert the '/' into the busffer and proceed with
732 processing the current character. */
733 if (c_eol_comment_start && current != '/') {
734 c_eol_comment_start = 0;
735 buffer[space++] = '/';
736 }
737
738 switch (current) {
739 case '\"': /* " indicates start or end of a string */
740 if (!comment) {
741 string ^= 1;
742 buffer[space++] = current;
743 }
744 break;
745 case ';':
746 if (!string && !comment) {
747 buffer[space++] = '\0';
748
Peer Chen6f2cbc72012-03-13 11:12:39 +0800749 if (process_statement(context,
750 buffer,
751 simple_parse))
752 goto error;
Peer Chen8d782ee2011-01-18 21:34:18 -0500753 space = 0;
754 equal_encounter = 0;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800755 } else if (string)
Peer Chen8d782ee2011-01-18 21:34:18 -0500756 buffer[space++] = current;
Peer Chen8d782ee2011-01-18 21:34:18 -0500757 break;
758
759 case '/':
760 if (!string && !comment) {
761 if (c_eol_comment_start) {
Peer Chen6f2cbc72012-03-13 11:12:39 +0800762 /* EOL comment started. */
Peer Chen8d782ee2011-01-18 21:34:18 -0500763 comment = 1;
764 c_eol_comment_start = 0;
765 } else {
766 /* Potential start of eol comment. */
767 c_eol_comment_start = 1;
768 }
Peer Chen6f2cbc72012-03-13 11:12:39 +0800769 } else if (!comment)
Peer Chen8d782ee2011-01-18 21:34:18 -0500770 buffer[space++] = current;
Peer Chen8d782ee2011-01-18 21:34:18 -0500771 break;
772
773 /* ignore whitespace. uses fallthrough */
774 case '\n':
775 case '\r': /* carriage returns end comments */
776 string = 0;
777 comment = 0;
778 c_eol_comment_start = 0;
779 case ' ':
780 case '\t':
Peer Chen6f2cbc72012-03-13 11:12:39 +0800781 if (string)
Peer Chen8d782ee2011-01-18 21:34:18 -0500782 buffer[space++] = current;
Peer Chen8d782ee2011-01-18 21:34:18 -0500783 break;
784
785 case '#':
Peer Chen6f2cbc72012-03-13 11:12:39 +0800786 if (!string)
Peer Chen8d782ee2011-01-18 21:34:18 -0500787 comment = 1;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800788 else
Peer Chen8d782ee2011-01-18 21:34:18 -0500789 buffer[space++] = current;
Peer Chen8d782ee2011-01-18 21:34:18 -0500790 break;
791
792 default:
793 if (!comment) {
794 buffer[space++] = current;
795 if (current == '=') {
Peer Chen6f2cbc72012-03-13 11:12:39 +0800796 if (!equal_encounter)
Peer Chen8d782ee2011-01-18 21:34:18 -0500797 equal_encounter = 1;
Peer Chen6f2cbc72012-03-13 11:12:39 +0800798 else
Peer Chen8d782ee2011-01-18 21:34:18 -0500799 goto error;
Peer Chen8d782ee2011-01-18 21:34:18 -0500800 }
801 }
802 break;
803 }
804 }
805
806 return;
807
808 error:
809 printf("Error parsing: %s\n", buffer);
810 exit(1);
811}