blob: a29c9d64ac3d21384f4707c639cfc2d9c64ae4d5 [file] [log] [blame]
Patrick Georgiea063cb2020-05-08 19:28:13 +02001/* parser generator for flashmap descriptor language */
Patrick Georgi7333a112020-05-08 20:48:04 +02002/* SPDX-License-Identifier: GPL-2.0-only */
Sol Boucher69b88bf2015-02-26 11:47:19 -08003
4%{
5#include "fmd_scanner.h"
Sol Boucherb9740812015-03-18 10:13:48 -07006#include "common.h"
Sol Boucher69b88bf2015-02-26 11:47:19 -08007
8#include <stdlib.h>
9
10struct flashmap_descriptor *res = NULL;
11%}
12
13%union {
14 unsigned intval;
15 char *strval;
16 struct unsigned_option maybe_intval;
17 struct flashmap_descriptor *region_ptr;
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080018 union flashmap_flags flags;
Sol Boucher69b88bf2015-02-26 11:47:19 -080019 struct descriptor_list region_listhdr;
20}
21
22%code requires {
23#include "fmd.h"
24#include "option.h"
25
26#include <stdbool.h>
27
28struct descriptor_node {
29 struct flashmap_descriptor *val;
30 struct descriptor_node *next;
31};
32
33struct descriptor_list {
34 size_t len;
35 struct descriptor_node *head;
36 struct descriptor_node *tail;
37};
38
39extern struct flashmap_descriptor *res;
40
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080041struct flashmap_descriptor *parse_descriptor(
42 char *name, union flashmap_flags flags, struct unsigned_option offset,
43 struct unsigned_option size, struct descriptor_list children);
Sol Boucher69b88bf2015-02-26 11:47:19 -080044void yyerror(const char *s);
45}
46
47%token <intval> INTEGER
48%token OCTAL
49%token <strval> STRING
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080050%token FLAG_CBFS
Hung-Te Lin49a44502019-03-04 15:41:09 +080051%token FLAG_PRESERVE
Sol Boucher69b88bf2015-02-26 11:47:19 -080052
53%type <region_ptr> flash_region
54%type <strval> region_name
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080055%type <flags> region_flags_opt
56%type <flags> region_flags
57%type <flags> region_flag
Sol Boucher69b88bf2015-02-26 11:47:19 -080058%type <maybe_intval> region_offset_opt
59%type <maybe_intval> region_offset
60%type <maybe_intval> region_size_opt
61%type <maybe_intval> region_size
62%type <region_listhdr> region_list_opt
63%type <region_listhdr> region_list
64%type <region_listhdr> region_list_entries
65
66%%
67
68flash_chip: region_name region_offset_opt region_size region_list
69{
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080070 union flashmap_flags flags = { .v=0 };
71 if (!(res = parse_descriptor($1, flags, $2, $3, $4)))
Sol Boucher69b88bf2015-02-26 11:47:19 -080072 YYABORT;
73};
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080074flash_region: region_name region_flags_opt region_offset_opt region_size_opt
75 region_list_opt
Sol Boucher69b88bf2015-02-26 11:47:19 -080076{
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080077 struct flashmap_descriptor *node = parse_descriptor($1, $2, $3, $4, $5);
Sol Boucher69b88bf2015-02-26 11:47:19 -080078 if (!node)
79 YYABORT;
80
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080081 if (node->flags.f.cbfs && !fmd_process_flag_cbfs(node)) {
82 ERROR("Section '%s' cannot have flag 'CBFS''\n", node->name);
Sol Boucher69b88bf2015-02-26 11:47:19 -080083 YYABORT;
84 }
Sol Boucher69b88bf2015-02-26 11:47:19 -080085
86 $$ = node;
87};
88region_name: STRING
89{
90 if (!$1) {
Sol Boucherb9740812015-03-18 10:13:48 -070091 perror("E: While allocating section name");
Sol Boucher69b88bf2015-02-26 11:47:19 -080092 YYABORT;
93 }
94};
Hung-Te Lin9497fcb2019-03-04 14:28:37 +080095region_flags_opt: { $$ = (union flashmap_flags){ .v=0 }; }
96 | '(' region_flags ')' { $$ = $2; };
97region_flags: region_flag | region_flag region_flags { $$.v = $1.v | $2.v; };
98region_flag: FLAG_CBFS { $$.v = 0; $$.f.cbfs = 1; };
Hung-Te Lin49a44502019-03-04 15:41:09 +080099region_flag: FLAG_PRESERVE { $$.v = 0; $$.f.preserve = 1; };
Sol Boucher69b88bf2015-02-26 11:47:19 -0800100region_offset_opt: { $$ = (struct unsigned_option){false, 0}; }
101 | region_offset;
102region_offset: '@' INTEGER { $$ = (struct unsigned_option){true, $2}; };
103region_size_opt: { $$ = (struct unsigned_option){false, 0}; }
104 | region_size;
105region_size: INTEGER { $$ = (struct unsigned_option){true, $1}; };
106region_list_opt:
107{
108 $$ = (struct descriptor_list)
109 {.len = 0, .head = NULL, .tail = NULL};
110}
111 | region_list;
112region_list: '{' region_list_entries '}' { $$ = $2; };
113region_list_entries: flash_region
114{
115 struct descriptor_node *node = malloc(sizeof(*node));
116 if (!node) {
Sol Boucherb9740812015-03-18 10:13:48 -0700117 perror("E: While allocating linked list node");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800118 YYABORT;
119 }
120 node->val = $1;
121 node->next = NULL;
122 $$ = (struct descriptor_list){.len = 1, .head = node, .tail = node};
123}
124 | region_list_entries flash_region
125{
126 struct descriptor_node *node = malloc(sizeof(*node));
127 if (!node) {
Sol Boucherb9740812015-03-18 10:13:48 -0700128 perror("E: While allocating linked list node");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800129 YYABORT;
130 }
131 node->val = $2;
132 node->next = NULL;
133
134 $1.tail->next = node;
135 $$ = (struct descriptor_list)
136 {.len = $1.len + 1, .head = $1.head, .tail = node};
137};
138
139%%
140
Hung-Te Lin9497fcb2019-03-04 14:28:37 +0800141struct flashmap_descriptor *parse_descriptor(
142 char *name, union flashmap_flags flags, struct unsigned_option offset,
143 struct unsigned_option size, struct descriptor_list children)
Sol Boucher69b88bf2015-02-26 11:47:19 -0800144{
145 struct flashmap_descriptor *region = malloc(sizeof(*region));
146 if (!region) {
Sol Boucherb9740812015-03-18 10:13:48 -0700147 perror("E: While allocating descriptor section");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800148 return NULL;
149 }
150 region->name = name;
Hung-Te Lin9497fcb2019-03-04 14:28:37 +0800151 region->flags = flags;
Sol Boucher69b88bf2015-02-26 11:47:19 -0800152 region->offset_known = offset.val_known;
153 region->offset = offset.val;
154 region->size_known = size.val_known;
155 region->size = size.val;
156 region->list_len = children.len;
157 if (region->list_len) {
158 region->list = malloc(region->list_len * sizeof(*region->list));
159 if (!region->list) {
Sol Boucherb9740812015-03-18 10:13:48 -0700160 perror("E: While allocating node children array");
Sol Boucher69b88bf2015-02-26 11:47:19 -0800161 return NULL;
162 }
163 struct descriptor_node *cur_node = children.head;
164 for (unsigned idx = 0; idx < region->list_len; ++idx) {
165 region->list[idx] = cur_node->val;
166
167 struct descriptor_node *next_node = cur_node->next;
168 free(cur_node);
169 cur_node = next_node;
170 }
171 } else {
172 region->list = NULL;
173 }
174 return region;
175}
176
177void yyerror(const char *s)
178{
179 fprintf(stderr, "%s\n", s);
180}