/ util / cbfstool / fmd_parser.y
fmd_parser.y
  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  
177  void yyerror(const char *s)
178  {
179  	fprintf(stderr, "%s\n", s);
180  }