1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2005-2008 coresystems GmbH
5*0d6140beSAndroid Build Coastguard Worker * (Written by Stefan Reinauer <[email protected]> for coresystems GmbH)
6*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2011-2013 Stefan Tauner
7*0d6140beSAndroid Build Coastguard Worker *
8*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
9*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
10*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; version 2 of the License.
11*0d6140beSAndroid Build Coastguard Worker *
12*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
13*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
16*0d6140beSAndroid Build Coastguard Worker */
17*0d6140beSAndroid Build Coastguard Worker
18*0d6140beSAndroid Build Coastguard Worker #include <ctype.h>
19*0d6140beSAndroid Build Coastguard Worker #include <errno.h>
20*0d6140beSAndroid Build Coastguard Worker #include <stdio.h>
21*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
22*0d6140beSAndroid Build Coastguard Worker #include <string.h>
23*0d6140beSAndroid Build Coastguard Worker #include <limits.h>
24*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
25*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
26*0d6140beSAndroid Build Coastguard Worker #include "layout.h"
27*0d6140beSAndroid Build Coastguard Worker
28*0d6140beSAndroid Build Coastguard Worker struct flashrom_layout {
29*0d6140beSAndroid Build Coastguard Worker struct romentry *head;
30*0d6140beSAndroid Build Coastguard Worker };
31*0d6140beSAndroid Build Coastguard Worker
32*0d6140beSAndroid Build Coastguard Worker struct layout_include_args {
33*0d6140beSAndroid Build Coastguard Worker char *name;
34*0d6140beSAndroid Build Coastguard Worker char *file;
35*0d6140beSAndroid Build Coastguard Worker struct layout_include_args *next;
36*0d6140beSAndroid Build Coastguard Worker };
37*0d6140beSAndroid Build Coastguard Worker
get_default_layout(const struct flashrom_flashctx * const flashctx)38*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *get_default_layout(const struct flashrom_flashctx *const flashctx)
39*0d6140beSAndroid Build Coastguard Worker {
40*0d6140beSAndroid Build Coastguard Worker return flashctx->default_layout;
41*0d6140beSAndroid Build Coastguard Worker }
42*0d6140beSAndroid Build Coastguard Worker
get_layout(const struct flashrom_flashctx * const flashctx)43*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *get_layout(const struct flashrom_flashctx *const flashctx)
44*0d6140beSAndroid Build Coastguard Worker {
45*0d6140beSAndroid Build Coastguard Worker if (flashctx->layout)
46*0d6140beSAndroid Build Coastguard Worker return flashctx->layout;
47*0d6140beSAndroid Build Coastguard Worker else
48*0d6140beSAndroid Build Coastguard Worker return get_default_layout(flashctx);
49*0d6140beSAndroid Build Coastguard Worker }
50*0d6140beSAndroid Build Coastguard Worker
mutable_layout_next(const struct flashrom_layout * const layout,struct romentry * iterator)51*0d6140beSAndroid Build Coastguard Worker static struct romentry *mutable_layout_next(
52*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const layout, struct romentry *iterator)
53*0d6140beSAndroid Build Coastguard Worker {
54*0d6140beSAndroid Build Coastguard Worker return iterator ? iterator->next : layout->head;
55*0d6140beSAndroid Build Coastguard Worker }
56*0d6140beSAndroid Build Coastguard Worker
_layout_entry_by_name(const struct flashrom_layout * const layout,const char * name)57*0d6140beSAndroid Build Coastguard Worker static struct romentry *_layout_entry_by_name(
58*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const layout, const char *name)
59*0d6140beSAndroid Build Coastguard Worker {
60*0d6140beSAndroid Build Coastguard Worker struct romentry *entry = NULL;
61*0d6140beSAndroid Build Coastguard Worker if (!layout || !name)
62*0d6140beSAndroid Build Coastguard Worker return NULL;
63*0d6140beSAndroid Build Coastguard Worker while ((entry = mutable_layout_next(layout, entry))) {
64*0d6140beSAndroid Build Coastguard Worker if (!strcmp(entry->region.name, name))
65*0d6140beSAndroid Build Coastguard Worker return entry;
66*0d6140beSAndroid Build Coastguard Worker }
67*0d6140beSAndroid Build Coastguard Worker return NULL;
68*0d6140beSAndroid Build Coastguard Worker }
69*0d6140beSAndroid Build Coastguard Worker
70*0d6140beSAndroid Build Coastguard Worker #ifndef __LIBPAYLOAD__
layout_from_file(struct flashrom_layout ** layout,const char * name)71*0d6140beSAndroid Build Coastguard Worker int layout_from_file(struct flashrom_layout **layout, const char *name)
72*0d6140beSAndroid Build Coastguard Worker {
73*0d6140beSAndroid Build Coastguard Worker FILE *romlayout;
74*0d6140beSAndroid Build Coastguard Worker char tempstr[256], tempname[256];
75*0d6140beSAndroid Build Coastguard Worker int ret = 1;
76*0d6140beSAndroid Build Coastguard Worker
77*0d6140beSAndroid Build Coastguard Worker if (flashrom_layout_new(layout))
78*0d6140beSAndroid Build Coastguard Worker return 1;
79*0d6140beSAndroid Build Coastguard Worker
80*0d6140beSAndroid Build Coastguard Worker romlayout = fopen(name, "r");
81*0d6140beSAndroid Build Coastguard Worker
82*0d6140beSAndroid Build Coastguard Worker if (!romlayout) {
83*0d6140beSAndroid Build Coastguard Worker msg_gerr("ERROR: Could not open layout file (%s).\n",
84*0d6140beSAndroid Build Coastguard Worker name);
85*0d6140beSAndroid Build Coastguard Worker return -1;
86*0d6140beSAndroid Build Coastguard Worker }
87*0d6140beSAndroid Build Coastguard Worker
88*0d6140beSAndroid Build Coastguard Worker while (!feof(romlayout)) {
89*0d6140beSAndroid Build Coastguard Worker char *tstr1, *tstr2;
90*0d6140beSAndroid Build Coastguard Worker
91*0d6140beSAndroid Build Coastguard Worker if (2 != fscanf(romlayout, "%255s %255s\n", tempstr, tempname))
92*0d6140beSAndroid Build Coastguard Worker continue;
93*0d6140beSAndroid Build Coastguard Worker #if 0
94*0d6140beSAndroid Build Coastguard Worker // fscanf does not like arbitrary comments like that :( later
95*0d6140beSAndroid Build Coastguard Worker if (tempstr[0] == '#') {
96*0d6140beSAndroid Build Coastguard Worker continue;
97*0d6140beSAndroid Build Coastguard Worker }
98*0d6140beSAndroid Build Coastguard Worker #endif
99*0d6140beSAndroid Build Coastguard Worker tstr1 = strtok(tempstr, ":");
100*0d6140beSAndroid Build Coastguard Worker tstr2 = strtok(NULL, ":");
101*0d6140beSAndroid Build Coastguard Worker if (!tstr1 || !tstr2) {
102*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error parsing layout file. Offending string: \"%s\"\n", tempstr);
103*0d6140beSAndroid Build Coastguard Worker goto _close_ret;
104*0d6140beSAndroid Build Coastguard Worker }
105*0d6140beSAndroid Build Coastguard Worker if (flashrom_layout_add_region(*layout,
106*0d6140beSAndroid Build Coastguard Worker strtol(tstr1, NULL, 16), strtol(tstr2, NULL, 16), tempname))
107*0d6140beSAndroid Build Coastguard Worker goto _close_ret;
108*0d6140beSAndroid Build Coastguard Worker }
109*0d6140beSAndroid Build Coastguard Worker ret = 0;
110*0d6140beSAndroid Build Coastguard Worker
111*0d6140beSAndroid Build Coastguard Worker _close_ret:
112*0d6140beSAndroid Build Coastguard Worker (void)fclose(romlayout);
113*0d6140beSAndroid Build Coastguard Worker return ret;
114*0d6140beSAndroid Build Coastguard Worker }
115*0d6140beSAndroid Build Coastguard Worker #endif
116*0d6140beSAndroid Build Coastguard Worker
parse_include_args(const char * arg,char ** name,char ** file)117*0d6140beSAndroid Build Coastguard Worker static bool parse_include_args(const char *arg, char **name, char **file)
118*0d6140beSAndroid Build Coastguard Worker {
119*0d6140beSAndroid Build Coastguard Worker char *colon;
120*0d6140beSAndroid Build Coastguard Worker char *tmp_name;
121*0d6140beSAndroid Build Coastguard Worker char *tmp_file = NULL; /* file is optional, so defaults to NULL */
122*0d6140beSAndroid Build Coastguard Worker
123*0d6140beSAndroid Build Coastguard Worker if (arg == NULL) {
124*0d6140beSAndroid Build Coastguard Worker msg_gerr("<NULL> is a bad region name.\n");
125*0d6140beSAndroid Build Coastguard Worker return false;
126*0d6140beSAndroid Build Coastguard Worker }
127*0d6140beSAndroid Build Coastguard Worker
128*0d6140beSAndroid Build Coastguard Worker /* -i <image>[:<file>] */
129*0d6140beSAndroid Build Coastguard Worker colon = strchr(arg, ':');
130*0d6140beSAndroid Build Coastguard Worker if (colon && !colon[1]) {
131*0d6140beSAndroid Build Coastguard Worker msg_gerr("Missing filename parameter in %s\n", arg);
132*0d6140beSAndroid Build Coastguard Worker return false;
133*0d6140beSAndroid Build Coastguard Worker }
134*0d6140beSAndroid Build Coastguard Worker
135*0d6140beSAndroid Build Coastguard Worker if (colon) {
136*0d6140beSAndroid Build Coastguard Worker tmp_name = strndup(arg, colon - arg);
137*0d6140beSAndroid Build Coastguard Worker if (!tmp_name) {
138*0d6140beSAndroid Build Coastguard Worker msg_gerr("Out of memory\n");
139*0d6140beSAndroid Build Coastguard Worker goto error;
140*0d6140beSAndroid Build Coastguard Worker }
141*0d6140beSAndroid Build Coastguard Worker
142*0d6140beSAndroid Build Coastguard Worker tmp_file = strdup(colon + 1);
143*0d6140beSAndroid Build Coastguard Worker if (!tmp_file) {
144*0d6140beSAndroid Build Coastguard Worker msg_gerr("Out of memory\n");
145*0d6140beSAndroid Build Coastguard Worker goto error;
146*0d6140beSAndroid Build Coastguard Worker }
147*0d6140beSAndroid Build Coastguard Worker } else {
148*0d6140beSAndroid Build Coastguard Worker tmp_name = strdup(arg);
149*0d6140beSAndroid Build Coastguard Worker }
150*0d6140beSAndroid Build Coastguard Worker
151*0d6140beSAndroid Build Coastguard Worker *name = tmp_name;
152*0d6140beSAndroid Build Coastguard Worker *file = tmp_file;
153*0d6140beSAndroid Build Coastguard Worker
154*0d6140beSAndroid Build Coastguard Worker return true;
155*0d6140beSAndroid Build Coastguard Worker
156*0d6140beSAndroid Build Coastguard Worker error:
157*0d6140beSAndroid Build Coastguard Worker free(tmp_name);
158*0d6140beSAndroid Build Coastguard Worker free(tmp_file);
159*0d6140beSAndroid Build Coastguard Worker return false;
160*0d6140beSAndroid Build Coastguard Worker }
161*0d6140beSAndroid Build Coastguard Worker
162*0d6140beSAndroid Build Coastguard Worker /* register an include argument (-i) for later processing */
register_include_arg(struct layout_include_args ** args,const char * arg)163*0d6140beSAndroid Build Coastguard Worker int register_include_arg(struct layout_include_args **args, const char *arg)
164*0d6140beSAndroid Build Coastguard Worker {
165*0d6140beSAndroid Build Coastguard Worker struct layout_include_args *tmp;
166*0d6140beSAndroid Build Coastguard Worker char *name;
167*0d6140beSAndroid Build Coastguard Worker char *file;
168*0d6140beSAndroid Build Coastguard Worker
169*0d6140beSAndroid Build Coastguard Worker if (!parse_include_args(arg, &name, &file))
170*0d6140beSAndroid Build Coastguard Worker return 1;
171*0d6140beSAndroid Build Coastguard Worker
172*0d6140beSAndroid Build Coastguard Worker for (tmp = *args; tmp; tmp = tmp->next) {
173*0d6140beSAndroid Build Coastguard Worker if (!strcmp(tmp->name, name)) {
174*0d6140beSAndroid Build Coastguard Worker msg_gerr("Duplicate region name: \"%s\".\n", name);
175*0d6140beSAndroid Build Coastguard Worker goto error;
176*0d6140beSAndroid Build Coastguard Worker }
177*0d6140beSAndroid Build Coastguard Worker }
178*0d6140beSAndroid Build Coastguard Worker
179*0d6140beSAndroid Build Coastguard Worker tmp = malloc(sizeof(*tmp));
180*0d6140beSAndroid Build Coastguard Worker if (tmp == NULL) {
181*0d6140beSAndroid Build Coastguard Worker msg_gerr("Out of memory\n");
182*0d6140beSAndroid Build Coastguard Worker goto error;
183*0d6140beSAndroid Build Coastguard Worker }
184*0d6140beSAndroid Build Coastguard Worker
185*0d6140beSAndroid Build Coastguard Worker tmp->name = name;
186*0d6140beSAndroid Build Coastguard Worker tmp->file = file;
187*0d6140beSAndroid Build Coastguard Worker tmp->next = *args;
188*0d6140beSAndroid Build Coastguard Worker *args = tmp;
189*0d6140beSAndroid Build Coastguard Worker return 0;
190*0d6140beSAndroid Build Coastguard Worker
191*0d6140beSAndroid Build Coastguard Worker error:
192*0d6140beSAndroid Build Coastguard Worker free(name);
193*0d6140beSAndroid Build Coastguard Worker free(file);
194*0d6140beSAndroid Build Coastguard Worker return 1;
195*0d6140beSAndroid Build Coastguard Worker }
196*0d6140beSAndroid Build Coastguard Worker
sanitise_filename(char * filename)197*0d6140beSAndroid Build Coastguard Worker static char *sanitise_filename(char *filename)
198*0d6140beSAndroid Build Coastguard Worker {
199*0d6140beSAndroid Build Coastguard Worker for (unsigned i = 0; filename[i]; i++) {
200*0d6140beSAndroid Build Coastguard Worker if (isspace((unsigned char)filename[i]))
201*0d6140beSAndroid Build Coastguard Worker filename[i] = '_';
202*0d6140beSAndroid Build Coastguard Worker }
203*0d6140beSAndroid Build Coastguard Worker return filename;
204*0d6140beSAndroid Build Coastguard Worker }
205*0d6140beSAndroid Build Coastguard Worker
206*0d6140beSAndroid Build Coastguard Worker /* returns 0 to indicate success, 1 to indicate failure */
include_region(struct flashrom_layout * const l,const char * name,const char * file)207*0d6140beSAndroid Build Coastguard Worker static int include_region(struct flashrom_layout *const l, const char *name,
208*0d6140beSAndroid Build Coastguard Worker const char *file)
209*0d6140beSAndroid Build Coastguard Worker {
210*0d6140beSAndroid Build Coastguard Worker struct romentry *const entry = _layout_entry_by_name(l, name);
211*0d6140beSAndroid Build Coastguard Worker if (entry) {
212*0d6140beSAndroid Build Coastguard Worker entry->included = true;
213*0d6140beSAndroid Build Coastguard Worker if (file)
214*0d6140beSAndroid Build Coastguard Worker entry->file = sanitise_filename(strdup(file));
215*0d6140beSAndroid Build Coastguard Worker return 0;
216*0d6140beSAndroid Build Coastguard Worker }
217*0d6140beSAndroid Build Coastguard Worker return 1;
218*0d6140beSAndroid Build Coastguard Worker }
219*0d6140beSAndroid Build Coastguard Worker
220*0d6140beSAndroid Build Coastguard Worker /* returns 0 to indicate success, 1 to indicate failure */
exclude_region(struct flashrom_layout * const l,const char * name)221*0d6140beSAndroid Build Coastguard Worker static int exclude_region(struct flashrom_layout *const l, const char *name)
222*0d6140beSAndroid Build Coastguard Worker {
223*0d6140beSAndroid Build Coastguard Worker struct romentry *const entry = _layout_entry_by_name(l, name);
224*0d6140beSAndroid Build Coastguard Worker if (entry) {
225*0d6140beSAndroid Build Coastguard Worker entry->included = false;
226*0d6140beSAndroid Build Coastguard Worker return 0;
227*0d6140beSAndroid Build Coastguard Worker }
228*0d6140beSAndroid Build Coastguard Worker return 1;
229*0d6140beSAndroid Build Coastguard Worker }
230*0d6140beSAndroid Build Coastguard Worker
231*0d6140beSAndroid Build Coastguard Worker /* returns -1 if an entry is not found, 0 if found. */
romentry_exists(struct flashrom_layout * const l,char * name,char * file)232*0d6140beSAndroid Build Coastguard Worker static int romentry_exists(struct flashrom_layout *const l, char *name, char *file)
233*0d6140beSAndroid Build Coastguard Worker {
234*0d6140beSAndroid Build Coastguard Worker if (!l->head)
235*0d6140beSAndroid Build Coastguard Worker return -1;
236*0d6140beSAndroid Build Coastguard Worker
237*0d6140beSAndroid Build Coastguard Worker msg_gspew("Looking for region \"%s\"... ", name);
238*0d6140beSAndroid Build Coastguard Worker if (include_region(l, name, file)) {
239*0d6140beSAndroid Build Coastguard Worker msg_gspew("not found.\n");
240*0d6140beSAndroid Build Coastguard Worker return -1;
241*0d6140beSAndroid Build Coastguard Worker }
242*0d6140beSAndroid Build Coastguard Worker msg_gspew("found.\n");
243*0d6140beSAndroid Build Coastguard Worker return 0;
244*0d6140beSAndroid Build Coastguard Worker }
245*0d6140beSAndroid Build Coastguard Worker
246*0d6140beSAndroid Build Coastguard Worker /* process -i arguments
247*0d6140beSAndroid Build Coastguard Worker * returns 0 to indicate success, >0 to indicate failure
248*0d6140beSAndroid Build Coastguard Worker */
process_include_args(struct flashrom_layout * l,const struct layout_include_args * const args)249*0d6140beSAndroid Build Coastguard Worker int process_include_args(struct flashrom_layout *l, const struct layout_include_args *const args)
250*0d6140beSAndroid Build Coastguard Worker {
251*0d6140beSAndroid Build Coastguard Worker unsigned int found = 0;
252*0d6140beSAndroid Build Coastguard Worker const struct layout_include_args *tmp;
253*0d6140beSAndroid Build Coastguard Worker
254*0d6140beSAndroid Build Coastguard Worker if (args == NULL)
255*0d6140beSAndroid Build Coastguard Worker return 0;
256*0d6140beSAndroid Build Coastguard Worker
257*0d6140beSAndroid Build Coastguard Worker /* User has specified an include argument, but no layout is loaded. */
258*0d6140beSAndroid Build Coastguard Worker if (!l || !l->head) {
259*0d6140beSAndroid Build Coastguard Worker msg_gerr("Region requested (with -i \"%s\"), "
260*0d6140beSAndroid Build Coastguard Worker "but no layout data is available.\n",
261*0d6140beSAndroid Build Coastguard Worker args->name);
262*0d6140beSAndroid Build Coastguard Worker return 1;
263*0d6140beSAndroid Build Coastguard Worker }
264*0d6140beSAndroid Build Coastguard Worker
265*0d6140beSAndroid Build Coastguard Worker tmp = args;
266*0d6140beSAndroid Build Coastguard Worker while (tmp) {
267*0d6140beSAndroid Build Coastguard Worker if (romentry_exists(l, tmp->name, tmp->file) < 0) {
268*0d6140beSAndroid Build Coastguard Worker msg_gerr("Invalid region specified: \"%s\".\n",
269*0d6140beSAndroid Build Coastguard Worker tmp->name);
270*0d6140beSAndroid Build Coastguard Worker return 1;
271*0d6140beSAndroid Build Coastguard Worker }
272*0d6140beSAndroid Build Coastguard Worker tmp = tmp->next;
273*0d6140beSAndroid Build Coastguard Worker found++;
274*0d6140beSAndroid Build Coastguard Worker }
275*0d6140beSAndroid Build Coastguard Worker
276*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Using region%s: ", found > 1 ? "s" : "");
277*0d6140beSAndroid Build Coastguard Worker tmp = args;
278*0d6140beSAndroid Build Coastguard Worker while (tmp) {
279*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\"%s\"", tmp->name);
280*0d6140beSAndroid Build Coastguard Worker if (tmp->file)
281*0d6140beSAndroid Build Coastguard Worker msg_ginfo(":\"%s\"", tmp->file);
282*0d6140beSAndroid Build Coastguard Worker if (found > 1)
283*0d6140beSAndroid Build Coastguard Worker msg_ginfo(", ");
284*0d6140beSAndroid Build Coastguard Worker found--;
285*0d6140beSAndroid Build Coastguard Worker tmp = tmp->next;
286*0d6140beSAndroid Build Coastguard Worker }
287*0d6140beSAndroid Build Coastguard Worker msg_ginfo(".\n");
288*0d6140beSAndroid Build Coastguard Worker return 0;
289*0d6140beSAndroid Build Coastguard Worker }
290*0d6140beSAndroid Build Coastguard Worker
check_include_args_filename(const struct layout_include_args * include_args)291*0d6140beSAndroid Build Coastguard Worker int check_include_args_filename(const struct layout_include_args *include_args)
292*0d6140beSAndroid Build Coastguard Worker {
293*0d6140beSAndroid Build Coastguard Worker const struct layout_include_args *arg;
294*0d6140beSAndroid Build Coastguard Worker for (arg = include_args; arg; arg = arg->next) {
295*0d6140beSAndroid Build Coastguard Worker if (!arg->file || (arg->file[0] == '\0')) {
296*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "Error: No region file specified.\n");
297*0d6140beSAndroid Build Coastguard Worker return 1;
298*0d6140beSAndroid Build Coastguard Worker }
299*0d6140beSAndroid Build Coastguard Worker }
300*0d6140beSAndroid Build Coastguard Worker
301*0d6140beSAndroid Build Coastguard Worker return 0;
302*0d6140beSAndroid Build Coastguard Worker }
303*0d6140beSAndroid Build Coastguard Worker
304*0d6140beSAndroid Build Coastguard Worker /* returns boolean 1 if any regions overlap, 0 otherwise */
included_regions_overlap(const struct flashrom_layout * const l)305*0d6140beSAndroid Build Coastguard Worker int included_regions_overlap(const struct flashrom_layout *const l)
306*0d6140beSAndroid Build Coastguard Worker {
307*0d6140beSAndroid Build Coastguard Worker const struct romentry *lhs = NULL;
308*0d6140beSAndroid Build Coastguard Worker int overlap_detected = 0;
309*0d6140beSAndroid Build Coastguard Worker
310*0d6140beSAndroid Build Coastguard Worker while ((lhs = layout_next(l, lhs))) {
311*0d6140beSAndroid Build Coastguard Worker if (!lhs->included)
312*0d6140beSAndroid Build Coastguard Worker continue;
313*0d6140beSAndroid Build Coastguard Worker
314*0d6140beSAndroid Build Coastguard Worker const struct romentry *rhs = lhs;
315*0d6140beSAndroid Build Coastguard Worker while ((rhs = layout_next(l, rhs))) {
316*0d6140beSAndroid Build Coastguard Worker if (!rhs->included)
317*0d6140beSAndroid Build Coastguard Worker continue;
318*0d6140beSAndroid Build Coastguard Worker
319*0d6140beSAndroid Build Coastguard Worker const struct flash_region *rhsr = &rhs->region;
320*0d6140beSAndroid Build Coastguard Worker const struct flash_region *lhsr = &lhs->region;
321*0d6140beSAndroid Build Coastguard Worker
322*0d6140beSAndroid Build Coastguard Worker if (lhsr->start > rhsr->end)
323*0d6140beSAndroid Build Coastguard Worker continue;
324*0d6140beSAndroid Build Coastguard Worker
325*0d6140beSAndroid Build Coastguard Worker if (lhsr->end < rhsr->start)
326*0d6140beSAndroid Build Coastguard Worker continue;
327*0d6140beSAndroid Build Coastguard Worker
328*0d6140beSAndroid Build Coastguard Worker msg_gwarn("Regions %s [0x%08"PRIx32"-0x%08"PRIx32"] and %s [0x%08"PRIx32"-0x%08"PRIx32"] overlap\n",
329*0d6140beSAndroid Build Coastguard Worker lhsr->name, lhsr->start, lhsr->end, rhsr->name, rhsr->start, rhsr->end);
330*0d6140beSAndroid Build Coastguard Worker overlap_detected = 1;
331*0d6140beSAndroid Build Coastguard Worker }
332*0d6140beSAndroid Build Coastguard Worker }
333*0d6140beSAndroid Build Coastguard Worker return overlap_detected;
334*0d6140beSAndroid Build Coastguard Worker }
335*0d6140beSAndroid Build Coastguard Worker
cleanup_include_args(struct layout_include_args ** args)336*0d6140beSAndroid Build Coastguard Worker void cleanup_include_args(struct layout_include_args **args)
337*0d6140beSAndroid Build Coastguard Worker {
338*0d6140beSAndroid Build Coastguard Worker struct layout_include_args *tmp;
339*0d6140beSAndroid Build Coastguard Worker
340*0d6140beSAndroid Build Coastguard Worker while (*args) {
341*0d6140beSAndroid Build Coastguard Worker tmp = (*args)->next;
342*0d6140beSAndroid Build Coastguard Worker free((*args)->name);
343*0d6140beSAndroid Build Coastguard Worker free((*args)->file);
344*0d6140beSAndroid Build Coastguard Worker free(*args);
345*0d6140beSAndroid Build Coastguard Worker *args = tmp;
346*0d6140beSAndroid Build Coastguard Worker }
347*0d6140beSAndroid Build Coastguard Worker }
348*0d6140beSAndroid Build Coastguard Worker
layout_sanity_checks(const struct flashrom_flashctx * const flash)349*0d6140beSAndroid Build Coastguard Worker int layout_sanity_checks(const struct flashrom_flashctx *const flash)
350*0d6140beSAndroid Build Coastguard Worker {
351*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const layout = get_layout(flash);
352*0d6140beSAndroid Build Coastguard Worker const chipsize_t total_size = flash->chip->total_size * 1024;
353*0d6140beSAndroid Build Coastguard Worker int ret = 0;
354*0d6140beSAndroid Build Coastguard Worker
355*0d6140beSAndroid Build Coastguard Worker const struct romentry *entry = NULL;
356*0d6140beSAndroid Build Coastguard Worker while ((entry = layout_next(layout, entry))) {
357*0d6140beSAndroid Build Coastguard Worker const struct flash_region *region = &entry->region;
358*0d6140beSAndroid Build Coastguard Worker if (region->start >= total_size || region->end >= total_size) {
359*0d6140beSAndroid Build Coastguard Worker msg_gwarn("Warning: Address range of region \"%s\" "
360*0d6140beSAndroid Build Coastguard Worker "exceeds the current chip's address space.\n", region->name);
361*0d6140beSAndroid Build Coastguard Worker if (entry->included)
362*0d6140beSAndroid Build Coastguard Worker ret = 1;
363*0d6140beSAndroid Build Coastguard Worker }
364*0d6140beSAndroid Build Coastguard Worker if (region->start > region->end) {
365*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Size of the address range of region \"%s\" is not positive.\n",
366*0d6140beSAndroid Build Coastguard Worker region->name);
367*0d6140beSAndroid Build Coastguard Worker ret = 1;
368*0d6140beSAndroid Build Coastguard Worker }
369*0d6140beSAndroid Build Coastguard Worker }
370*0d6140beSAndroid Build Coastguard Worker
371*0d6140beSAndroid Build Coastguard Worker return ret;
372*0d6140beSAndroid Build Coastguard Worker }
373*0d6140beSAndroid Build Coastguard Worker
prepare_layout_for_extraction(struct flashctx * flash)374*0d6140beSAndroid Build Coastguard Worker void prepare_layout_for_extraction(struct flashctx *flash)
375*0d6140beSAndroid Build Coastguard Worker {
376*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const l = get_layout(flash);
377*0d6140beSAndroid Build Coastguard Worker struct romentry *entry = NULL;
378*0d6140beSAndroid Build Coastguard Worker
379*0d6140beSAndroid Build Coastguard Worker while ((entry = mutable_layout_next(l, entry))) {
380*0d6140beSAndroid Build Coastguard Worker entry->included = true;
381*0d6140beSAndroid Build Coastguard Worker
382*0d6140beSAndroid Build Coastguard Worker if (!entry->file)
383*0d6140beSAndroid Build Coastguard Worker entry->file = sanitise_filename(strdup(entry->region.name));
384*0d6140beSAndroid Build Coastguard Worker }
385*0d6140beSAndroid Build Coastguard Worker }
386*0d6140beSAndroid Build Coastguard Worker
layout_next_included_region(const struct flashrom_layout * const l,const chipoff_t where)387*0d6140beSAndroid Build Coastguard Worker const struct romentry *layout_next_included_region(
388*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const l, const chipoff_t where)
389*0d6140beSAndroid Build Coastguard Worker {
390*0d6140beSAndroid Build Coastguard Worker const struct romentry *entry = NULL, *lowest = NULL;
391*0d6140beSAndroid Build Coastguard Worker
392*0d6140beSAndroid Build Coastguard Worker while ((entry = layout_next(l, entry))) {
393*0d6140beSAndroid Build Coastguard Worker if (!entry->included)
394*0d6140beSAndroid Build Coastguard Worker continue;
395*0d6140beSAndroid Build Coastguard Worker if (entry->region.end < where)
396*0d6140beSAndroid Build Coastguard Worker continue;
397*0d6140beSAndroid Build Coastguard Worker if (!lowest || lowest->region.start > entry->region.start)
398*0d6140beSAndroid Build Coastguard Worker lowest = entry;
399*0d6140beSAndroid Build Coastguard Worker }
400*0d6140beSAndroid Build Coastguard Worker
401*0d6140beSAndroid Build Coastguard Worker return lowest;
402*0d6140beSAndroid Build Coastguard Worker }
403*0d6140beSAndroid Build Coastguard Worker
layout_next_included(const struct flashrom_layout * const layout,const struct romentry * iterator)404*0d6140beSAndroid Build Coastguard Worker const struct romentry *layout_next_included(
405*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const layout, const struct romentry *iterator)
406*0d6140beSAndroid Build Coastguard Worker {
407*0d6140beSAndroid Build Coastguard Worker while ((iterator = layout_next(layout, iterator))) {
408*0d6140beSAndroid Build Coastguard Worker if (iterator->included)
409*0d6140beSAndroid Build Coastguard Worker break;
410*0d6140beSAndroid Build Coastguard Worker }
411*0d6140beSAndroid Build Coastguard Worker return iterator;
412*0d6140beSAndroid Build Coastguard Worker }
413*0d6140beSAndroid Build Coastguard Worker
layout_next(const struct flashrom_layout * const layout,const struct romentry * iterator)414*0d6140beSAndroid Build Coastguard Worker const struct romentry *layout_next(
415*0d6140beSAndroid Build Coastguard Worker const struct flashrom_layout *const layout, const struct romentry *iterator)
416*0d6140beSAndroid Build Coastguard Worker {
417*0d6140beSAndroid Build Coastguard Worker return iterator ? iterator->next : layout->head;
418*0d6140beSAndroid Build Coastguard Worker }
419*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_new(struct flashrom_layout ** const layout)420*0d6140beSAndroid Build Coastguard Worker int flashrom_layout_new(struct flashrom_layout **const layout)
421*0d6140beSAndroid Build Coastguard Worker {
422*0d6140beSAndroid Build Coastguard Worker *layout = calloc(1, sizeof(**layout));
423*0d6140beSAndroid Build Coastguard Worker if (!*layout) {
424*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error creating layout: %s\n", strerror(errno));
425*0d6140beSAndroid Build Coastguard Worker return 1;
426*0d6140beSAndroid Build Coastguard Worker }
427*0d6140beSAndroid Build Coastguard Worker
428*0d6140beSAndroid Build Coastguard Worker return 0;
429*0d6140beSAndroid Build Coastguard Worker }
430*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_add_region(struct flashrom_layout * const layout,const size_t start,const size_t end,const char * const name)431*0d6140beSAndroid Build Coastguard Worker int flashrom_layout_add_region(
432*0d6140beSAndroid Build Coastguard Worker struct flashrom_layout *const layout,
433*0d6140beSAndroid Build Coastguard Worker const size_t start, const size_t end, const char *const name)
434*0d6140beSAndroid Build Coastguard Worker {
435*0d6140beSAndroid Build Coastguard Worker struct romentry *const entry = malloc(sizeof(*entry));
436*0d6140beSAndroid Build Coastguard Worker if (!entry)
437*0d6140beSAndroid Build Coastguard Worker goto _err_ret;
438*0d6140beSAndroid Build Coastguard Worker
439*0d6140beSAndroid Build Coastguard Worker const struct romentry tmp = {
440*0d6140beSAndroid Build Coastguard Worker .next = layout->head,
441*0d6140beSAndroid Build Coastguard Worker .included = false,
442*0d6140beSAndroid Build Coastguard Worker .file = NULL,
443*0d6140beSAndroid Build Coastguard Worker .region = {
444*0d6140beSAndroid Build Coastguard Worker .start = start,
445*0d6140beSAndroid Build Coastguard Worker .end = end,
446*0d6140beSAndroid Build Coastguard Worker .name = strdup(name),
447*0d6140beSAndroid Build Coastguard Worker },
448*0d6140beSAndroid Build Coastguard Worker };
449*0d6140beSAndroid Build Coastguard Worker *entry = tmp;
450*0d6140beSAndroid Build Coastguard Worker if (!entry->region.name)
451*0d6140beSAndroid Build Coastguard Worker goto _err_ret;
452*0d6140beSAndroid Build Coastguard Worker
453*0d6140beSAndroid Build Coastguard Worker msg_gdbg("Added layout entry %08zx - %08zx named %s\n", start, end, name);
454*0d6140beSAndroid Build Coastguard Worker layout->head = entry;
455*0d6140beSAndroid Build Coastguard Worker return 0;
456*0d6140beSAndroid Build Coastguard Worker
457*0d6140beSAndroid Build Coastguard Worker _err_ret:
458*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error adding layout entry: %s\n", strerror(errno));
459*0d6140beSAndroid Build Coastguard Worker free(entry);
460*0d6140beSAndroid Build Coastguard Worker return 1;
461*0d6140beSAndroid Build Coastguard Worker }
462*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_include_region(struct flashrom_layout * const layout,const char * name)463*0d6140beSAndroid Build Coastguard Worker int flashrom_layout_include_region(struct flashrom_layout *const layout, const char *name)
464*0d6140beSAndroid Build Coastguard Worker {
465*0d6140beSAndroid Build Coastguard Worker return include_region(layout, name, NULL);
466*0d6140beSAndroid Build Coastguard Worker }
467*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_exclude_region(struct flashrom_layout * const layout,const char * name)468*0d6140beSAndroid Build Coastguard Worker int flashrom_layout_exclude_region(struct flashrom_layout *const layout, const char *name)
469*0d6140beSAndroid Build Coastguard Worker {
470*0d6140beSAndroid Build Coastguard Worker return exclude_region(layout, name);
471*0d6140beSAndroid Build Coastguard Worker }
472*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_get_region_range(struct flashrom_layout * const l,const char * name,unsigned int * start,unsigned int * len)473*0d6140beSAndroid Build Coastguard Worker int flashrom_layout_get_region_range(struct flashrom_layout *const l, const char *name,
474*0d6140beSAndroid Build Coastguard Worker unsigned int *start, unsigned int *len)
475*0d6140beSAndroid Build Coastguard Worker {
476*0d6140beSAndroid Build Coastguard Worker const struct romentry *const entry = _layout_entry_by_name(l, name);
477*0d6140beSAndroid Build Coastguard Worker if (entry) {
478*0d6140beSAndroid Build Coastguard Worker const struct flash_region *region = &entry->region;
479*0d6140beSAndroid Build Coastguard Worker *start = region->start;
480*0d6140beSAndroid Build Coastguard Worker *len = region->end - region->start + 1;
481*0d6140beSAndroid Build Coastguard Worker return 0;
482*0d6140beSAndroid Build Coastguard Worker }
483*0d6140beSAndroid Build Coastguard Worker return 1;
484*0d6140beSAndroid Build Coastguard Worker }
485*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_release(struct flashrom_layout * const layout)486*0d6140beSAndroid Build Coastguard Worker void flashrom_layout_release(struct flashrom_layout *const layout)
487*0d6140beSAndroid Build Coastguard Worker {
488*0d6140beSAndroid Build Coastguard Worker if (!layout)
489*0d6140beSAndroid Build Coastguard Worker return;
490*0d6140beSAndroid Build Coastguard Worker
491*0d6140beSAndroid Build Coastguard Worker while (layout->head) {
492*0d6140beSAndroid Build Coastguard Worker struct romentry *const entry = layout->head;
493*0d6140beSAndroid Build Coastguard Worker layout->head = entry->next;
494*0d6140beSAndroid Build Coastguard Worker free(entry->file);
495*0d6140beSAndroid Build Coastguard Worker free(entry->region.name);
496*0d6140beSAndroid Build Coastguard Worker free(entry);
497*0d6140beSAndroid Build Coastguard Worker }
498*0d6140beSAndroid Build Coastguard Worker free(layout);
499*0d6140beSAndroid Build Coastguard Worker }
500