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 }