xref: /aosp_15_r20/external/gsc-utils/extra/usb_updater/desc_parser.c (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1*4f2df630SAndroid Build Coastguard Worker /*
2*4f2df630SAndroid Build Coastguard Worker  * Copyright 2018 The ChromiumOS Authors
3*4f2df630SAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
4*4f2df630SAndroid Build Coastguard Worker  * found in the LICENSE file.
5*4f2df630SAndroid Build Coastguard Worker  */
6*4f2df630SAndroid Build Coastguard Worker 
7*4f2df630SAndroid Build Coastguard Worker #include <ctype.h>
8*4f2df630SAndroid Build Coastguard Worker #include <errno.h>
9*4f2df630SAndroid Build Coastguard Worker #include <malloc.h>
10*4f2df630SAndroid Build Coastguard Worker #include <stdio.h>
11*4f2df630SAndroid Build Coastguard Worker #include <stdlib.h>
12*4f2df630SAndroid Build Coastguard Worker #include <string.h>
13*4f2df630SAndroid Build Coastguard Worker #include <sys/stat.h>
14*4f2df630SAndroid Build Coastguard Worker 
15*4f2df630SAndroid Build Coastguard Worker #include "desc_parser.h"
16*4f2df630SAndroid Build Coastguard Worker 
17*4f2df630SAndroid Build Coastguard Worker static FILE *hash_file_;
18*4f2df630SAndroid Build Coastguard Worker static int line_count_;
19*4f2df630SAndroid Build Coastguard Worker static int section_count_;
20*4f2df630SAndroid Build Coastguard Worker 
21*4f2df630SAndroid Build Coastguard Worker /*
22*4f2df630SAndroid Build Coastguard Worker  * This is used to verify consistency of the description database, namely that
23*4f2df630SAndroid Build Coastguard Worker  * all hash sections include the same number of hash variants.
24*4f2df630SAndroid Build Coastguard Worker  */
25*4f2df630SAndroid Build Coastguard Worker static size_t variant_count;
26*4f2df630SAndroid Build Coastguard Worker 
27*4f2df630SAndroid Build Coastguard Worker /* Size of the retrieved string or negative OS error value. */
get_next_line(char * next_line,size_t line_size)28*4f2df630SAndroid Build Coastguard Worker static ssize_t get_next_line(char *next_line, size_t line_size)
29*4f2df630SAndroid Build Coastguard Worker {
30*4f2df630SAndroid Build Coastguard Worker 	size_t index = 0;
31*4f2df630SAndroid Build Coastguard Worker 
32*4f2df630SAndroid Build Coastguard Worker 	while (fgets(next_line + index, line_size - index, hash_file_)) {
33*4f2df630SAndroid Build Coastguard Worker 		line_count_++;
34*4f2df630SAndroid Build Coastguard Worker 
35*4f2df630SAndroid Build Coastguard Worker 		if (next_line[index] == '#')
36*4f2df630SAndroid Build Coastguard Worker 			continue; /* Skip the comment */
37*4f2df630SAndroid Build Coastguard Worker 
38*4f2df630SAndroid Build Coastguard Worker 		if (next_line[index] == '\n') {
39*4f2df630SAndroid Build Coastguard Worker 			/*
40*4f2df630SAndroid Build Coastguard Worker 			 * This is an empty line, return all collected data,
41*4f2df630SAndroid Build Coastguard Worker 			 * pontintially an array of size zero if this is a
42*4f2df630SAndroid Build Coastguard Worker 			 * repeated empty line.
43*4f2df630SAndroid Build Coastguard Worker 			 */
44*4f2df630SAndroid Build Coastguard Worker 			next_line[index] = '\0';
45*4f2df630SAndroid Build Coastguard Worker 			return index;
46*4f2df630SAndroid Build Coastguard Worker 		}
47*4f2df630SAndroid Build Coastguard Worker 
48*4f2df630SAndroid Build Coastguard Worker 		/* Make sure next string overwrites this string's newline. */
49*4f2df630SAndroid Build Coastguard Worker 		index += strlen(next_line + index) - 1;
50*4f2df630SAndroid Build Coastguard Worker 
51*4f2df630SAndroid Build Coastguard Worker 		if (index >= (line_size - 1)) {
52*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: Input overflow in line %d\n",
53*4f2df630SAndroid Build Coastguard Worker 				__func__, line_count_);
54*4f2df630SAndroid Build Coastguard Worker 			return -EOVERFLOW;
55*4f2df630SAndroid Build Coastguard Worker 		}
56*4f2df630SAndroid Build Coastguard Worker 	}
57*4f2df630SAndroid Build Coastguard Worker 
58*4f2df630SAndroid Build Coastguard Worker 	if (index) {
59*4f2df630SAndroid Build Coastguard Worker 		/*
60*4f2df630SAndroid Build Coastguard Worker 		 * This must be the last line in the file with no empty line
61*4f2df630SAndroid Build Coastguard Worker 		 * after it. Drop the closing newline, if it is there.
62*4f2df630SAndroid Build Coastguard Worker 		 */
63*4f2df630SAndroid Build Coastguard Worker 		if (next_line[index] == '\n')
64*4f2df630SAndroid Build Coastguard Worker 			next_line[index--] = '\0';
65*4f2df630SAndroid Build Coastguard Worker 
66*4f2df630SAndroid Build Coastguard Worker 		return index;
67*4f2df630SAndroid Build Coastguard Worker 	}
68*4f2df630SAndroid Build Coastguard Worker 	return errno ? -errno : -ENODATA;
69*4f2df630SAndroid Build Coastguard Worker }
70*4f2df630SAndroid Build Coastguard Worker 
get_next_token(char * input,size_t expected_size,char ** output)71*4f2df630SAndroid Build Coastguard Worker static int get_next_token(char *input, size_t expected_size, char **output)
72*4f2df630SAndroid Build Coastguard Worker {
73*4f2df630SAndroid Build Coastguard Worker 	char *next_colon;
74*4f2df630SAndroid Build Coastguard Worker 
75*4f2df630SAndroid Build Coastguard Worker 	next_colon = strchr(input, ':');
76*4f2df630SAndroid Build Coastguard Worker 	if (next_colon)
77*4f2df630SAndroid Build Coastguard Worker 		*next_colon = '\0';
78*4f2df630SAndroid Build Coastguard Worker 	if (!next_colon || (expected_size && strlen(input) != expected_size)) {
79*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid entry in section %d\n",
80*4f2df630SAndroid Build Coastguard Worker 			section_count_);
81*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
82*4f2df630SAndroid Build Coastguard Worker 	}
83*4f2df630SAndroid Build Coastguard Worker 
84*4f2df630SAndroid Build Coastguard Worker 	*output = next_colon + 1;
85*4f2df630SAndroid Build Coastguard Worker 	return 0;
86*4f2df630SAndroid Build Coastguard Worker }
87*4f2df630SAndroid Build Coastguard Worker 
get_hex_value(char * input,char ** output)88*4f2df630SAndroid Build Coastguard Worker static int get_hex_value(char *input, char **output)
89*4f2df630SAndroid Build Coastguard Worker {
90*4f2df630SAndroid Build Coastguard Worker 	char *e;
91*4f2df630SAndroid Build Coastguard Worker 	long int value;
92*4f2df630SAndroid Build Coastguard Worker 
93*4f2df630SAndroid Build Coastguard Worker 	if (strchr(input, ':'))
94*4f2df630SAndroid Build Coastguard Worker 		get_next_token(input, 0, output);
95*4f2df630SAndroid Build Coastguard Worker 	else
96*4f2df630SAndroid Build Coastguard Worker 		*output = NULL;
97*4f2df630SAndroid Build Coastguard Worker 
98*4f2df630SAndroid Build Coastguard Worker 	value = strtol(input, &e, 16);
99*4f2df630SAndroid Build Coastguard Worker 	if ((e && *e) || (strlen(input) > 8)) {
100*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid hex value %s in section %d\n", input,
101*4f2df630SAndroid Build Coastguard Worker 			section_count_);
102*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
103*4f2df630SAndroid Build Coastguard Worker 	}
104*4f2df630SAndroid Build Coastguard Worker 
105*4f2df630SAndroid Build Coastguard Worker 	return value;
106*4f2df630SAndroid Build Coastguard Worker }
107*4f2df630SAndroid Build Coastguard Worker 
parse_range(char * next_line,size_t line_len,struct addr_range * parsed_range)108*4f2df630SAndroid Build Coastguard Worker static int parse_range(char *next_line, size_t line_len,
109*4f2df630SAndroid Build Coastguard Worker 		       struct addr_range *parsed_range)
110*4f2df630SAndroid Build Coastguard Worker {
111*4f2df630SAndroid Build Coastguard Worker 	char *line_cursor;
112*4f2df630SAndroid Build Coastguard Worker 	char *next_token;
113*4f2df630SAndroid Build Coastguard Worker 	int is_a_hash_range;
114*4f2df630SAndroid Build Coastguard Worker 	struct result_node *node;
115*4f2df630SAndroid Build Coastguard Worker 	int value;
116*4f2df630SAndroid Build Coastguard Worker 
117*4f2df630SAndroid Build Coastguard Worker 	section_count_++;
118*4f2df630SAndroid Build Coastguard Worker 	line_cursor = next_line;
119*4f2df630SAndroid Build Coastguard Worker 
120*4f2df630SAndroid Build Coastguard Worker 	/* Range type. */
121*4f2df630SAndroid Build Coastguard Worker 	if (get_next_token(line_cursor, 1, &next_token))
122*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
123*4f2df630SAndroid Build Coastguard Worker 
124*4f2df630SAndroid Build Coastguard Worker 	switch (*line_cursor) {
125*4f2df630SAndroid Build Coastguard Worker 	case 'a':
126*4f2df630SAndroid Build Coastguard Worker 		parsed_range->range_type = AP_RANGE;
127*4f2df630SAndroid Build Coastguard Worker 		break;
128*4f2df630SAndroid Build Coastguard Worker 	case 'e':
129*4f2df630SAndroid Build Coastguard Worker 		parsed_range->range_type = EC_RANGE;
130*4f2df630SAndroid Build Coastguard Worker 		break;
131*4f2df630SAndroid Build Coastguard Worker 	case 'g':
132*4f2df630SAndroid Build Coastguard Worker 		parsed_range->range_type = EC_GANG_RANGE;
133*4f2df630SAndroid Build Coastguard Worker 		break;
134*4f2df630SAndroid Build Coastguard Worker 	default:
135*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid range type %c in section %d\n",
136*4f2df630SAndroid Build Coastguard Worker 			*line_cursor, section_count_);
137*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
138*4f2df630SAndroid Build Coastguard Worker 	}
139*4f2df630SAndroid Build Coastguard Worker 	line_cursor = next_token;
140*4f2df630SAndroid Build Coastguard Worker 
141*4f2df630SAndroid Build Coastguard Worker 	/* Hash or dump? */
142*4f2df630SAndroid Build Coastguard Worker 	if (get_next_token(line_cursor, 1, &next_token))
143*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
144*4f2df630SAndroid Build Coastguard Worker 
145*4f2df630SAndroid Build Coastguard Worker 	switch (*line_cursor) {
146*4f2df630SAndroid Build Coastguard Worker 	case 'd':
147*4f2df630SAndroid Build Coastguard Worker 		is_a_hash_range = 0;
148*4f2df630SAndroid Build Coastguard Worker 		break;
149*4f2df630SAndroid Build Coastguard Worker 	case 'h':
150*4f2df630SAndroid Build Coastguard Worker 		is_a_hash_range = 1;
151*4f2df630SAndroid Build Coastguard Worker 		break;
152*4f2df630SAndroid Build Coastguard Worker 	default:
153*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid entry kind %c in section %d\n",
154*4f2df630SAndroid Build Coastguard Worker 			*line_cursor, section_count_);
155*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
156*4f2df630SAndroid Build Coastguard Worker 	}
157*4f2df630SAndroid Build Coastguard Worker 	line_cursor = next_token;
158*4f2df630SAndroid Build Coastguard Worker 
159*4f2df630SAndroid Build Coastguard Worker 	/* Range base address. */
160*4f2df630SAndroid Build Coastguard Worker 	value = get_hex_value(line_cursor, &next_token);
161*4f2df630SAndroid Build Coastguard Worker 	if (value < 0)
162*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
163*4f2df630SAndroid Build Coastguard Worker 	parsed_range->base_addr = value;
164*4f2df630SAndroid Build Coastguard Worker 
165*4f2df630SAndroid Build Coastguard Worker 	/* Range size. */
166*4f2df630SAndroid Build Coastguard Worker 	line_cursor = next_token;
167*4f2df630SAndroid Build Coastguard Worker 	value = get_hex_value(line_cursor, &next_token);
168*4f2df630SAndroid Build Coastguard Worker 	if (value < 0)
169*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
170*4f2df630SAndroid Build Coastguard Worker 	parsed_range->range_size = value;
171*4f2df630SAndroid Build Coastguard Worker 
172*4f2df630SAndroid Build Coastguard Worker 	if (!next_token && is_a_hash_range) {
173*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Missing hash in section %d\n", section_count_);
174*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
175*4f2df630SAndroid Build Coastguard Worker 	}
176*4f2df630SAndroid Build Coastguard Worker 
177*4f2df630SAndroid Build Coastguard Worker 	if (next_token && !is_a_hash_range) {
178*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected data in section %d\n",
179*4f2df630SAndroid Build Coastguard Worker 			section_count_);
180*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
181*4f2df630SAndroid Build Coastguard Worker 	}
182*4f2df630SAndroid Build Coastguard Worker 
183*4f2df630SAndroid Build Coastguard Worker 	parsed_range->variant_count = 0;
184*4f2df630SAndroid Build Coastguard Worker 	if (!is_a_hash_range)
185*4f2df630SAndroid Build Coastguard Worker 		return 0; /* No more input for dump ranges. */
186*4f2df630SAndroid Build Coastguard Worker 
187*4f2df630SAndroid Build Coastguard Worker 	node = parsed_range->variants;
188*4f2df630SAndroid Build Coastguard Worker 	do { /* While line is not over. */
189*4f2df630SAndroid Build Coastguard Worker 		char c;
190*4f2df630SAndroid Build Coastguard Worker 		int i = 0;
191*4f2df630SAndroid Build Coastguard Worker 
192*4f2df630SAndroid Build Coastguard Worker 		line_cursor = next_token;
193*4f2df630SAndroid Build Coastguard Worker 		next_token = strchr(line_cursor, ':');
194*4f2df630SAndroid Build Coastguard Worker 		if (next_token)
195*4f2df630SAndroid Build Coastguard Worker 			*next_token++ = '\0';
196*4f2df630SAndroid Build Coastguard Worker 		if (strlen(line_cursor) != (2 * sizeof(*node))) {
197*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
198*4f2df630SAndroid Build Coastguard Worker 				"Invalid hash %zd size %zd in section %d\n",
199*4f2df630SAndroid Build Coastguard Worker 				parsed_range->variant_count + 1,
200*4f2df630SAndroid Build Coastguard Worker 				strlen(line_cursor), section_count_);
201*4f2df630SAndroid Build Coastguard Worker 			return -EINVAL;
202*4f2df630SAndroid Build Coastguard Worker 		}
203*4f2df630SAndroid Build Coastguard Worker 
204*4f2df630SAndroid Build Coastguard Worker 		while ((c = *line_cursor++) != 0) {
205*4f2df630SAndroid Build Coastguard Worker 			uint8_t nibble;
206*4f2df630SAndroid Build Coastguard Worker 
207*4f2df630SAndroid Build Coastguard Worker 			if (!isxdigit(c)) {
208*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
209*4f2df630SAndroid Build Coastguard Worker 					"Invalid hash %zd value in section %d\n",
210*4f2df630SAndroid Build Coastguard Worker 					parsed_range->variant_count + 1,
211*4f2df630SAndroid Build Coastguard Worker 					section_count_);
212*4f2df630SAndroid Build Coastguard Worker 				return -EINVAL;
213*4f2df630SAndroid Build Coastguard Worker 			}
214*4f2df630SAndroid Build Coastguard Worker 
215*4f2df630SAndroid Build Coastguard Worker 			if (c <= '9')
216*4f2df630SAndroid Build Coastguard Worker 				nibble = c - '0';
217*4f2df630SAndroid Build Coastguard Worker 			else if (c >= 'a')
218*4f2df630SAndroid Build Coastguard Worker 				nibble = c - 'a' + 10;
219*4f2df630SAndroid Build Coastguard Worker 			else
220*4f2df630SAndroid Build Coastguard Worker 				nibble = c - 'A' + 10;
221*4f2df630SAndroid Build Coastguard Worker 
222*4f2df630SAndroid Build Coastguard Worker 			if (i & 1)
223*4f2df630SAndroid Build Coastguard Worker 				node->expected_result[i / 2] |= nibble;
224*4f2df630SAndroid Build Coastguard Worker 			else
225*4f2df630SAndroid Build Coastguard Worker 				node->expected_result[i / 2] = nibble << 4;
226*4f2df630SAndroid Build Coastguard Worker 
227*4f2df630SAndroid Build Coastguard Worker 			i++;
228*4f2df630SAndroid Build Coastguard Worker 		}
229*4f2df630SAndroid Build Coastguard Worker 
230*4f2df630SAndroid Build Coastguard Worker 		node++;
231*4f2df630SAndroid Build Coastguard Worker 		parsed_range->variant_count++;
232*4f2df630SAndroid Build Coastguard Worker 
233*4f2df630SAndroid Build Coastguard Worker 	} while (next_token);
234*4f2df630SAndroid Build Coastguard Worker 
235*4f2df630SAndroid Build Coastguard Worker 	return 0;
236*4f2df630SAndroid Build Coastguard Worker }
237*4f2df630SAndroid Build Coastguard Worker 
parser_get_next_range(struct addr_range ** range)238*4f2df630SAndroid Build Coastguard Worker int parser_get_next_range(struct addr_range **range)
239*4f2df630SAndroid Build Coastguard Worker {
240*4f2df630SAndroid Build Coastguard Worker 	char next_line[1000]; /* Should be enough for the largest descriptor. */
241*4f2df630SAndroid Build Coastguard Worker 	ssize_t entry_size;
242*4f2df630SAndroid Build Coastguard Worker 	struct addr_range *new_range;
243*4f2df630SAndroid Build Coastguard Worker 	int rv;
244*4f2df630SAndroid Build Coastguard Worker 
245*4f2df630SAndroid Build Coastguard Worker 	/*
246*4f2df630SAndroid Build Coastguard Worker 	 * We come here after hash descriptor database file was opened and the
247*4f2df630SAndroid Build Coastguard Worker 	 * current board's section has been found. Just in case check if the
248*4f2df630SAndroid Build Coastguard Worker 	 * file has been opened.
249*4f2df630SAndroid Build Coastguard Worker 	 */
250*4f2df630SAndroid Build Coastguard Worker 	if (!hash_file_ || !range)
251*4f2df630SAndroid Build Coastguard Worker 		return -EIO;
252*4f2df630SAndroid Build Coastguard Worker 
253*4f2df630SAndroid Build Coastguard Worker 	*range = NULL;
254*4f2df630SAndroid Build Coastguard Worker 	do {
255*4f2df630SAndroid Build Coastguard Worker 		entry_size = get_next_line(next_line, sizeof(next_line));
256*4f2df630SAndroid Build Coastguard Worker 		if (entry_size < 0)
257*4f2df630SAndroid Build Coastguard Worker 			return entry_size;
258*4f2df630SAndroid Build Coastguard Worker 	} while (!entry_size); /* Skip empty lines. */
259*4f2df630SAndroid Build Coastguard Worker 
260*4f2df630SAndroid Build Coastguard Worker 	if (entry_size == 4) /* Next board's entry must have been reached. */
261*4f2df630SAndroid Build Coastguard Worker 		return -ENODATA;
262*4f2df630SAndroid Build Coastguard Worker 
263*4f2df630SAndroid Build Coastguard Worker 	/* This sure will be enough to fit parsed structure contents. */
264*4f2df630SAndroid Build Coastguard Worker 	new_range = malloc(sizeof(*new_range) + entry_size);
265*4f2df630SAndroid Build Coastguard Worker 	if (!new_range) {
266*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Failed to allocate %zd bytes\n",
267*4f2df630SAndroid Build Coastguard Worker 			sizeof(*new_range) + entry_size);
268*4f2df630SAndroid Build Coastguard Worker 		return -ENOMEM;
269*4f2df630SAndroid Build Coastguard Worker 	}
270*4f2df630SAndroid Build Coastguard Worker 
271*4f2df630SAndroid Build Coastguard Worker 	/* This must be a new descriptor section, lets parse it. */
272*4f2df630SAndroid Build Coastguard Worker 	rv = parse_range(next_line, entry_size, new_range);
273*4f2df630SAndroid Build Coastguard Worker 
274*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
275*4f2df630SAndroid Build Coastguard Worker 		free(new_range);
276*4f2df630SAndroid Build Coastguard Worker 		return rv;
277*4f2df630SAndroid Build Coastguard Worker 	}
278*4f2df630SAndroid Build Coastguard Worker 
279*4f2df630SAndroid Build Coastguard Worker 	if (new_range->variant_count) {
280*4f2df630SAndroid Build Coastguard Worker 		/*
281*4f2df630SAndroid Build Coastguard Worker 		 * A new range was found, if this is the first hash range we
282*4f2df630SAndroid Build Coastguard Worker 		 * encountered, save its dimensions for future reference.
283*4f2df630SAndroid Build Coastguard Worker 		 *
284*4f2df630SAndroid Build Coastguard Worker 		 * If this is not the first one - verify that it has the same
285*4f2df630SAndroid Build Coastguard Worker 		 * number of hash variants as all previous hash blocks.
286*4f2df630SAndroid Build Coastguard Worker 		 */
287*4f2df630SAndroid Build Coastguard Worker 		if (!variant_count) {
288*4f2df630SAndroid Build Coastguard Worker 			variant_count = new_range->variant_count;
289*4f2df630SAndroid Build Coastguard Worker 		} else if (variant_count != new_range->variant_count) {
290*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
291*4f2df630SAndroid Build Coastguard Worker 				"Unexpected number of variants in section %d\n",
292*4f2df630SAndroid Build Coastguard Worker 				section_count_);
293*4f2df630SAndroid Build Coastguard Worker 			free(new_range);
294*4f2df630SAndroid Build Coastguard Worker 			return -EINVAL;
295*4f2df630SAndroid Build Coastguard Worker 		}
296*4f2df630SAndroid Build Coastguard Worker 	}
297*4f2df630SAndroid Build Coastguard Worker 
298*4f2df630SAndroid Build Coastguard Worker 	*range = new_range;
299*4f2df630SAndroid Build Coastguard Worker 	return 0;
300*4f2df630SAndroid Build Coastguard Worker }
301*4f2df630SAndroid Build Coastguard Worker 
parser_find_board(const char * hash_file_name,const char * board_id)302*4f2df630SAndroid Build Coastguard Worker int parser_find_board(const char *hash_file_name, const char *board_id)
303*4f2df630SAndroid Build Coastguard Worker {
304*4f2df630SAndroid Build Coastguard Worker 	char next_line[1000]; /* Should be enough for the largest descriptor. */
305*4f2df630SAndroid Build Coastguard Worker 	ssize_t id_len = strlen(board_id);
306*4f2df630SAndroid Build Coastguard Worker 
307*4f2df630SAndroid Build Coastguard Worker 	if (!hash_file_) {
308*4f2df630SAndroid Build Coastguard Worker 		hash_file_ = fopen(hash_file_name, "r");
309*4f2df630SAndroid Build Coastguard Worker 		if (!hash_file_) {
310*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error:%s can not open file '%s'\n",
311*4f2df630SAndroid Build Coastguard Worker 				strerror(errno), hash_file_name);
312*4f2df630SAndroid Build Coastguard Worker 			return errno;
313*4f2df630SAndroid Build Coastguard Worker 		}
314*4f2df630SAndroid Build Coastguard Worker 	}
315*4f2df630SAndroid Build Coastguard Worker 
316*4f2df630SAndroid Build Coastguard Worker 	while (1) {
317*4f2df630SAndroid Build Coastguard Worker 		ssize_t entry_size;
318*4f2df630SAndroid Build Coastguard Worker 
319*4f2df630SAndroid Build Coastguard Worker 		entry_size = get_next_line(next_line, sizeof(next_line));
320*4f2df630SAndroid Build Coastguard Worker 		if (entry_size < 0) {
321*4f2df630SAndroid Build Coastguard Worker 			return entry_size;
322*4f2df630SAndroid Build Coastguard Worker 		}
323*4f2df630SAndroid Build Coastguard Worker 
324*4f2df630SAndroid Build Coastguard Worker 		if ((entry_size == id_len) &&
325*4f2df630SAndroid Build Coastguard Worker 		    !memcmp(next_line, board_id, id_len)) {
326*4f2df630SAndroid Build Coastguard Worker 			variant_count = 0;
327*4f2df630SAndroid Build Coastguard Worker 			return 0;
328*4f2df630SAndroid Build Coastguard Worker 		}
329*4f2df630SAndroid Build Coastguard Worker 	}
330*4f2df630SAndroid Build Coastguard Worker 
331*4f2df630SAndroid Build Coastguard Worker 	return -ENODATA;
332*4f2df630SAndroid Build Coastguard Worker }
333*4f2df630SAndroid Build Coastguard Worker 
parser_done(void)334*4f2df630SAndroid Build Coastguard Worker void parser_done(void)
335*4f2df630SAndroid Build Coastguard Worker {
336*4f2df630SAndroid Build Coastguard Worker 	if (!hash_file_)
337*4f2df630SAndroid Build Coastguard Worker 		return;
338*4f2df630SAndroid Build Coastguard Worker 
339*4f2df630SAndroid Build Coastguard Worker 	fclose(hash_file_);
340*4f2df630SAndroid Build Coastguard Worker 	hash_file_ = NULL;
341*4f2df630SAndroid Build Coastguard Worker }
342*4f2df630SAndroid Build Coastguard Worker 
343*4f2df630SAndroid Build Coastguard Worker #ifdef TEST_PARSER
main(int argc,char ** argv)344*4f2df630SAndroid Build Coastguard Worker int main(int argc, char **argv)
345*4f2df630SAndroid Build Coastguard Worker {
346*4f2df630SAndroid Build Coastguard Worker 	const char *board_name = "QZUX";
347*4f2df630SAndroid Build Coastguard Worker 	int rv;
348*4f2df630SAndroid Build Coastguard Worker 	int count;
349*4f2df630SAndroid Build Coastguard Worker 
350*4f2df630SAndroid Build Coastguard Worker 	if (argc < 2) {
351*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Name of the file to parse is required.\n");
352*4f2df630SAndroid Build Coastguard Worker 		return -1;
353*4f2df630SAndroid Build Coastguard Worker 	}
354*4f2df630SAndroid Build Coastguard Worker 
355*4f2df630SAndroid Build Coastguard Worker 	if (parser_find_board(argv[1], board_name)) {
356*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Board %s NOT found\n", board_name);
357*4f2df630SAndroid Build Coastguard Worker 		return -1;
358*4f2df630SAndroid Build Coastguard Worker 	}
359*4f2df630SAndroid Build Coastguard Worker 
360*4f2df630SAndroid Build Coastguard Worker 	count = 0;
361*4f2df630SAndroid Build Coastguard Worker 	do {
362*4f2df630SAndroid Build Coastguard Worker 		struct addr_range *range;
363*4f2df630SAndroid Build Coastguard Worker 
364*4f2df630SAndroid Build Coastguard Worker 		rv = parser_get_next_range(&range);
365*4f2df630SAndroid Build Coastguard Worker 		count++;
366*4f2df630SAndroid Build Coastguard Worker 		printf("Section %d, rv %d\n", count, rv);
367*4f2df630SAndroid Build Coastguard Worker 		free(range); /* Freeing NULL is OK. */
368*4f2df630SAndroid Build Coastguard Worker 
369*4f2df630SAndroid Build Coastguard Worker 	} while (rv != -ENODATA);
370*4f2df630SAndroid Build Coastguard Worker 
371*4f2df630SAndroid Build Coastguard Worker 	return 0;
372*4f2df630SAndroid Build Coastguard Worker }
373*4f2df630SAndroid Build Coastguard Worker #endif
374