xref: /aosp_15_r20/external/coreboot/util/cbfstool/fmd_parser.y (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* parser generator for flashmap descriptor language */
2 /* SPDX-License-Identifier: GPL-2.0-only */
3 
4 %{
5 #include "fmd_scanner.h"
6 #include "common.h"
7 
8 #include <stdlib.h>
9 
10 struct 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;
18 	union flashmap_flags flags;
19 	struct descriptor_list region_listhdr;
20 }
21 
22 %code requires {
23 #include "fmd.h"
24 #include "option.h"
25 
26 #include <stdbool.h>
27 
28 struct descriptor_node {
29 	struct flashmap_descriptor *val;
30 	struct descriptor_node *next;
31 };
32 
33 struct descriptor_list {
34 	size_t len;
35 	struct descriptor_node *head;
36 	struct descriptor_node *tail;
37 };
38 
39 extern struct flashmap_descriptor *res;
40 
41 struct flashmap_descriptor *parse_descriptor(
42 	char *name, union flashmap_flags flags, struct unsigned_option offset,
43 	struct unsigned_option size, struct descriptor_list children);
44 void yyerror(const char *s);
45 }
46 
47 %token <intval> INTEGER
48 %token OCTAL
49 %token <strval> STRING
50 %token FLAG_CBFS
51 %token FLAG_PRESERVE
52 
53 %type <region_ptr> flash_region
54 %type <strval> region_name
55 %type <flags> region_flags_opt
56 %type <flags> region_flags
57 %type <flags> region_flag
58 %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 
68 flash_chip: region_name region_offset_opt region_size region_list
69 {
70 	union flashmap_flags flags = { .v=0 };
71 	if (!(res = parse_descriptor($1, flags, $2, $3, $4)))
72 		YYABORT;
73 };
74 flash_region: region_name region_flags_opt region_offset_opt region_size_opt
75 	      region_list_opt
76 {
77 	struct flashmap_descriptor *node = parse_descriptor($1, $2, $3, $4, $5);
78 	if (!node)
79 		YYABORT;
80 
81 	if (node->flags.f.cbfs && !fmd_process_flag_cbfs(node)) {
82 		ERROR("Section '%s' cannot have flag 'CBFS''\n", node->name);
83 		YYABORT;
84 	}
85 
86 	$$ = node;
87 };
88 region_name: STRING
89 {
90 	if (!$1) {
91 		perror("E: While allocating section name");
92 		YYABORT;
93 	}
94 };
95 region_flags_opt: { $$ = (union flashmap_flags){ .v=0 }; }
96 	| '(' region_flags ')' { $$ = $2; };
97 region_flags: region_flag | region_flag region_flags { $$.v = $1.v | $2.v; };
98 region_flag: FLAG_CBFS { $$.v = 0; $$.f.cbfs = 1; };
99 region_flag: FLAG_PRESERVE { $$.v = 0; $$.f.preserve = 1; };
100 region_offset_opt: { $$ = (struct unsigned_option){false, 0}; }
101 	| region_offset;
102 region_offset: '@' INTEGER { $$ = (struct unsigned_option){true, $2}; };
103 region_size_opt: { $$ = (struct unsigned_option){false, 0}; }
104 	| region_size;
105 region_size: INTEGER { $$ = (struct unsigned_option){true, $1}; };
106 region_list_opt:
107 {
108 	$$ = (struct descriptor_list)
109 					{.len = 0, .head = NULL, .tail = NULL};
110 }
111 	| region_list;
112 region_list: '{' region_list_entries '}' { $$ = $2; };
113 region_list_entries: flash_region
114 {
115 	struct descriptor_node *node = malloc(sizeof(*node));
116 	if (!node) {
117 		perror("E: While allocating linked list node");
118 		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) {
128 		perror("E: While allocating linked list node");
129 		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 
141 struct flashmap_descriptor *parse_descriptor(
142 	char *name, union flashmap_flags flags, struct unsigned_option offset,
143 	struct unsigned_option size, struct descriptor_list children)
144 {
145 	struct flashmap_descriptor *region = malloc(sizeof(*region));
146 	if (!region) {
147 		perror("E: While allocating descriptor section");
148 		return NULL;
149 	}
150 	region->name = name;
151 	region->flags = flags;
152 	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) {
160 			perror("E: While allocating node children array");
161 			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 
yyerror(const char * s)177 void yyerror(const char *s)
178 {
179 	fprintf(stderr, "%s\n", s);
180 }
181