From 69b88bf1276d2cb0309e2fc96df9d33a893138e3 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Thu, 26 Feb 2015 11:47:19 -0800 Subject: fmaptool: Introduce the fmd ("flashmap descriptor") language and compiler This adds a compiler for a language whose textual representation of flashmap regions will be used to describe the layout of flash chips that contain more than just a single CBFS. Direct integration with cbfstool (via a new command-line switch for the create action) is forthcoming but will be added separately. BUG=chromium:461875 TEST=Use Chromium OS's cros_bundle_firmware script on the fmap.dts file for panther. Using the latter file as a reference, write a corresponding fmap.fmd file and feed it through fmaptool. Run both binary output files though the flashmap project's own flashmap_decode utility. Observe only the expected differences. BRANCH=None Change-Id: I06b32d138dbef0a4e5ed43c81bd31c796fd5d669 Signed-off-by: Sol Boucher Original-Commit-Id: 005ab67eb594e21489cf31036aedaea87e0c7142 Original-Change-Id: Ia08f28688efdbbfc70c255916b8eb7eb0eb07fb2 Original-Signed-off-by: Sol Boucher Original-Reviewed-on: https://chromium-review.googlesource.com/255031 Original-Reviewed-by: Julius Werner Original-Reviewed-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/9942 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- util/cbfstool/fmd_parser.y | 190 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 util/cbfstool/fmd_parser.y (limited to 'util/cbfstool/fmd_parser.y') diff --git a/util/cbfstool/fmd_parser.y b/util/cbfstool/fmd_parser.y new file mode 100644 index 0000000000..292fba3d8a --- /dev/null +++ b/util/cbfstool/fmd_parser.y @@ -0,0 +1,190 @@ +/* + * fmd_parser.y, parser generator for flashmap descriptor language + * + * Copyright (C) 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +%{ +#include "fmd_scanner.h" + +#include + +struct flashmap_descriptor *res = NULL; +%} + +%union { + unsigned intval; + char *strval; + struct unsigned_option maybe_intval; + struct flashmap_descriptor *region_ptr; + struct descriptor_list region_listhdr; +} + +%code requires { +#include "fmd.h" +#include "option.h" + +#include + +struct descriptor_node { + struct flashmap_descriptor *val; + struct descriptor_node *next; +}; + +struct descriptor_list { + size_t len; + struct descriptor_node *head; + struct descriptor_node *tail; +}; + +extern struct flashmap_descriptor *res; + +struct flashmap_descriptor *parse_descriptor(char *name, + struct unsigned_option offset, struct unsigned_option size, + struct descriptor_list children); +void yyerror(const char *s); +} + +%token INTEGER +%token OCTAL +%token STRING + +%type flash_region +%type region_name +%type region_annotation_opt +%type region_annotation +%type region_offset_opt +%type region_offset +%type region_size_opt +%type region_size +%type region_list_opt +%type region_list +%type region_list_entries + +%% + +flash_chip: region_name region_offset_opt region_size region_list +{ + if (!(res = parse_descriptor($1, $2, $3, $4))) + YYABORT; +}; +flash_region: region_name region_annotation_opt region_offset_opt + region_size_opt region_list_opt +{ + struct flashmap_descriptor *node = parse_descriptor($1, $3, $4, $5); + if (!node) + YYABORT; + + char *annotation = $2; + if (annotation && !fmd_process_annotation_impl(node, annotation)) { + fprintf(stderr, "ERROR: Section '%s' has unexpected annotation '(%s)'\n", + node->name, annotation); + YYABORT; + } + free(annotation); + + $$ = node; +}; +region_name: STRING +{ + if (!$1) { + perror("ERROR: While allocating section name"); + YYABORT; + } +}; +region_annotation_opt: { $$ = NULL; } + | region_annotation; +region_annotation: '(' STRING ')' { $$ = $2; }; +region_offset_opt: { $$ = (struct unsigned_option){false, 0}; } + | region_offset; +region_offset: '@' INTEGER { $$ = (struct unsigned_option){true, $2}; }; +region_size_opt: { $$ = (struct unsigned_option){false, 0}; } + | region_size; +region_size: INTEGER { $$ = (struct unsigned_option){true, $1}; }; +region_list_opt: +{ + $$ = (struct descriptor_list) + {.len = 0, .head = NULL, .tail = NULL}; +} + | region_list; +region_list: '{' region_list_entries '}' { $$ = $2; }; +region_list_entries: flash_region +{ + struct descriptor_node *node = malloc(sizeof(*node)); + if (!node) { + perror("ERROR: While allocating linked list node"); + YYABORT; + } + node->val = $1; + node->next = NULL; + $$ = (struct descriptor_list){.len = 1, .head = node, .tail = node}; +} + | region_list_entries flash_region +{ + struct descriptor_node *node = malloc(sizeof(*node)); + if (!node) { + perror("ERROR: While allocating linked list node"); + YYABORT; + } + node->val = $2; + node->next = NULL; + + $1.tail->next = node; + $$ = (struct descriptor_list) + {.len = $1.len + 1, .head = $1.head, .tail = node}; +}; + +%% + +struct flashmap_descriptor *parse_descriptor(char *name, + struct unsigned_option offset, struct unsigned_option size, + struct descriptor_list children) +{ + struct flashmap_descriptor *region = malloc(sizeof(*region)); + if (!region) { + perror("ERROR: While allocating descriptor section"); + return NULL; + } + region->name = name; + region->offset_known = offset.val_known; + region->offset = offset.val; + region->size_known = size.val_known; + region->size = size.val; + region->list_len = children.len; + if (region->list_len) { + region->list = malloc(region->list_len * sizeof(*region->list)); + if (!region->list) { + perror("ERROR: While allocating node children array"); + return NULL; + } + struct descriptor_node *cur_node = children.head; + for (unsigned idx = 0; idx < region->list_len; ++idx) { + region->list[idx] = cur_node->val; + + struct descriptor_node *next_node = cur_node->next; + free(cur_node); + cur_node = next_node; + } + } else { + region->list = NULL; + } + return region; +} + +void yyerror(const char *s) +{ + fprintf(stderr, "%s\n", s); +} -- cgit v1.2.3