treewide: Move device_tree to commonlib
[coreboot2.git] / util / cbfstool / fmd_parser.y
bloba29c9d64ac3d21384f4707c639cfc2d9c64ae4d5
1 /* parser generator for flashmap descriptor language */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 %{
5 #include "fmd_scanner.h"
6 #include "common.h"
8 #include <stdlib.h>
10 struct flashmap_descriptor *res = NULL;
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;
22 %code requires {
23 #include "fmd.h"
24 #include "option.h"
26 #include <stdbool.h>
28 struct descriptor_node {
29 struct flashmap_descriptor *val;
30 struct descriptor_node *next;
33 struct descriptor_list {
34 size_t len;
35 struct descriptor_node *head;
36 struct descriptor_node *tail;
39 extern struct flashmap_descriptor *res;
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);
47 %token <intval> INTEGER
48 %token OCTAL
49 %token <strval> STRING
50 %token FLAG_CBFS
51 %token FLAG_PRESERVE
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
68 flash_chip: region_name region_offset_opt region_size region_list
70 union flashmap_flags flags = { .v=0 };
71 if (!(res = parse_descriptor($1, flags, $2, $3, $4)))
72 YYABORT;
74 flash_region: region_name region_flags_opt region_offset_opt region_size_opt
75 region_list_opt
77 struct flashmap_descriptor *node = parse_descriptor($1, $2, $3, $4, $5);
78 if (!node)
79 YYABORT;
81 if (node->flags.f.cbfs && !fmd_process_flag_cbfs(node)) {
82 ERROR("Section '%s' cannot have flag 'CBFS''\n", node->name);
83 YYABORT;
86 $$ = node;
88 region_name: STRING
90 if (!$1) {
91 perror("E: While allocating section name");
92 YYABORT;
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:
108 $$ = (struct descriptor_list)
109 {.len = 0, .head = NULL, .tail = NULL};
111 | region_list;
112 region_list: '{' region_list_entries '}' { $$ = $2; };
113 region_list_entries: flash_region
115 struct descriptor_node *node = malloc(sizeof(*node));
116 if (!node) {
117 perror("E: While allocating linked list node");
118 YYABORT;
120 node->val = $1;
121 node->next = NULL;
122 $$ = (struct descriptor_list){.len = 1, .head = node, .tail = node};
124 | region_list_entries flash_region
126 struct descriptor_node *node = malloc(sizeof(*node));
127 if (!node) {
128 perror("E: While allocating linked list node");
129 YYABORT;
131 node->val = $2;
132 node->next = NULL;
134 $1.tail->next = node;
135 $$ = (struct descriptor_list)
136 {.len = $1.len + 1, .head = $1.head, .tail = node};
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)
145 struct flashmap_descriptor *region = malloc(sizeof(*region));
146 if (!region) {
147 perror("E: While allocating descriptor section");
148 return NULL;
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;
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;
167 struct descriptor_node *next_node = cur_node->next;
168 free(cur_node);
169 cur_node = next_node;
171 } else {
172 region->list = NULL;
174 return region;
177 void yyerror(const char *s)
179 fprintf(stderr, "%s\n", s);