blob: 3ba710c28949871fdc47c8b0f0a26f423f6915a5 [file] [log] [blame]
Sol Boucher69b88bf2015-02-26 11:47:19 -08001/*
2 * fmd_parser.y, parser generator for flashmap descriptor language
3 *
4 * Copyright (C) 2015 Google, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
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
13 * GNU General Public License for more details.
Sol Boucher69b88bf2015-02-26 11:47:19 -080014 */
15
16%{
17#include "fmd_scanner.h"
Sol Boucherb9740812015-03-18 10:13:48 -070018#include "common.h"
Sol Boucher69b88bf2015-02-26 11:47:19 -080019
20#include <stdlib.h>
21
22struct flashmap_descriptor *res = NULL;
23%}
24
25%union {
26 unsigned intval;
27 char *strval;
28 struct unsigned_option maybe_intval;
29 struct flashmap_descriptor *region_ptr;
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080030 union flashmap_flags flags;
Sol Boucher69b88bf2015-02-26 11:47:19 -080031 struct descriptor_list region_listhdr;
32}
33
34%code requires {
35#include "fmd.h"
36#include "option.h"
37
38#include <stdbool.h>
39
40struct descriptor_node {
41 struct flashmap_descriptor *val;
42 struct descriptor_node *next;
43};
44
45struct descriptor_list {
46 size_t len;
47 struct descriptor_node *head;
48 struct descriptor_node *tail;
49};
50
51extern struct flashmap_descriptor *res;
52
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080053struct flashmap_descriptor *parse_descriptor(
54 char *name, union flashmap_flags flags, struct unsigned_option offset,
55 struct unsigned_option size, struct descriptor_list children);
Sol Boucher69b88bf2015-02-26 11:47:19 -080056void yyerror(const char *s);
57}
58
59%token <intval> INTEGER
60%token OCTAL
61%token <strval> STRING
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080062%token FLAG_CBFS
Hung-Te Lin49a44502019-03-04 15:41:09 +080063%token FLAG_PRESERVE
Sol Boucher69b88bf2015-02-26 11:47:19 -080064
65%type <region_ptr> flash_region
66%type <strval> region_name
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080067%type <flags> region_flags_opt
68%type <flags> region_flags
69%type <flags> region_flag
Sol Boucher69b88bf2015-02-26 11:47:19 -080070%type <maybe_intval> region_offset_opt
71%type <maybe_intval> region_offset
72%type <maybe_intval> region_size_opt
73%type <maybe_intval> region_size
74%type <region_listhdr> region_list_opt
75%type <region_listhdr> region_list
76%type <region_listhdr> region_list_entries
77
78%%
79
80flash_chip: region_name region_offset_opt region_size region_list
81{
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080082 union flashmap_flags flags = { .v=0 };
83 if (!(res = parse_descriptor($1, flags, $2, $3, $4)))
Sol Boucher69b88bf2015-02-26 11:47:19 -080084 YYABORT;
85};
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080086flash_region: region_name region_flags_opt region_offset_opt region_size_opt
87 region_list_opt
Sol Boucher69b88bf2015-02-26 11:47:19 -080088{
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080089 struct flashmap_descriptor *node = parse_descriptor($1, $2, $3, $4, $5);
Sol Boucher69b88bf2015-02-26 11:47:19 -080090 if (!node)
91 YYABORT;
92
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080093 if (node->flags.f.cbfs && !fmd_process_flag_cbfs(node)) {
94 ERROR("Section '%s' cannot have flag 'CBFS''\n", node->name);
Sol Boucher69b88bf2015-02-26 11:47:19 -080095 YYABORT;
96 }
Sol Boucher69b88bf2015-02-26 11:47:19 -080097
98 $$ = node;
99};
100region_name: STRING
101{
102 if (!$1) {
Sol Boucherb9740812015-03-18 10:13:48 -0700103 perror("E: While allocating section name");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800104 YYABORT;
105 }
106};
Hung-Te Lin9497fcb2019-03-04 14:28:37 +0800107region_flags_opt: { $$ = (union flashmap_flags){ .v=0 }; }
108 | '(' region_flags ')' { $$ = $2; };
109region_flags: region_flag | region_flag region_flags { $$.v = $1.v | $2.v; };
110region_flag: FLAG_CBFS { $$.v = 0; $$.f.cbfs = 1; };
Hung-Te Lin49a44502019-03-04 15:41:09 +0800111region_flag: FLAG_PRESERVE { $$.v = 0; $$.f.preserve = 1; };
Sol Boucher69b88bf2015-02-26 11:47:19 -0800112region_offset_opt: { $$ = (struct unsigned_option){false, 0}; }
113 | region_offset;
114region_offset: '@' INTEGER { $$ = (struct unsigned_option){true, $2}; };
115region_size_opt: { $$ = (struct unsigned_option){false, 0}; }
116 | region_size;
117region_size: INTEGER { $$ = (struct unsigned_option){true, $1}; };
118region_list_opt:
119{
120 $$ = (struct descriptor_list)
121 {.len = 0, .head = NULL, .tail = NULL};
122}
123 | region_list;
124region_list: '{' region_list_entries '}' { $$ = $2; };
125region_list_entries: flash_region
126{
127 struct descriptor_node *node = malloc(sizeof(*node));
128 if (!node) {
Sol Boucherb9740812015-03-18 10:13:48 -0700129 perror("E: While allocating linked list node");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800130 YYABORT;
131 }
132 node->val = $1;
133 node->next = NULL;
134 $$ = (struct descriptor_list){.len = 1, .head = node, .tail = node};
135}
136 | region_list_entries flash_region
137{
138 struct descriptor_node *node = malloc(sizeof(*node));
139 if (!node) {
Sol Boucherb9740812015-03-18 10:13:48 -0700140 perror("E: While allocating linked list node");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800141 YYABORT;
142 }
143 node->val = $2;
144 node->next = NULL;
145
146 $1.tail->next = node;
147 $$ = (struct descriptor_list)
148 {.len = $1.len + 1, .head = $1.head, .tail = node};
149};
150
151%%
152
Hung-Te Lin9497fcb2019-03-04 14:28:37 +0800153struct flashmap_descriptor *parse_descriptor(
154 char *name, union flashmap_flags flags, struct unsigned_option offset,
155 struct unsigned_option size, struct descriptor_list children)
Sol Boucher69b88bf2015-02-26 11:47:19 -0800156{
157 struct flashmap_descriptor *region = malloc(sizeof(*region));
158 if (!region) {
Sol Boucherb9740812015-03-18 10:13:48 -0700159 perror("E: While allocating descriptor section");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800160 return NULL;
161 }
162 region->name = name;
Hung-Te Lin9497fcb2019-03-04 14:28:37 +0800163 region->flags = flags;
Sol Boucher69b88bf2015-02-26 11:47:19 -0800164 region->offset_known = offset.val_known;
165 region->offset = offset.val;
166 region->size_known = size.val_known;
167 region->size = size.val;
168 region->list_len = children.len;
169 if (region->list_len) {
170 region->list = malloc(region->list_len * sizeof(*region->list));
171 if (!region->list) {
Sol Boucherb9740812015-03-18 10:13:48 -0700172 perror("E: While allocating node children array");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800173 return NULL;
174 }
175 struct descriptor_node *cur_node = children.head;
176 for (unsigned idx = 0; idx < region->list_len; ++idx) {
177 region->list[idx] = cur_node->val;
178
179 struct descriptor_node *next_node = cur_node->next;
180 free(cur_node);
181 cur_node = next_node;
182 }
183 } else {
184 region->list = NULL;
185 }
186 return region;
187}
188
189void yyerror(const char *s)
190{
191 fprintf(stderr, "%s\n", s);
192}