blob: 6e476c21ea38dadb56413f54c9c7e8e34ad58917 [file] [log] [blame]
Uwe Hermann75f51072008-03-04 16:29:54 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2005-2008 coresystems GmbH
5 * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
Stefan Tauner949ccc82013-09-15 14:01:06 +00006 * Copyright (C) 2011-2013 Stefan Tauner
Uwe Hermann75f51072008-03-04 16:29:54 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Uwe Hermann75f51072008-03-04 16:29:54 +000016 */
17
Nico Huber70461a92019-06-15 14:56:19 +020018#include <errno.h>
Carl-Daniel Hailfinger831e8f42010-05-30 22:24:40 +000019#include <stdio.h>
Ollie Lho184a4042005-11-26 21:55:36 +000020#include <stdlib.h>
21#include <string.h>
Carl-Daniel Hailfingercb6ad162010-11-02 03:12:51 +000022#include <limits.h>
Uwe Hermann0846f892007-08-23 13:34:59 +000023#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000024#include "programmer.h"
Nico Huber3a9939b2016-04-27 15:56:14 +020025#include "layout.h"
Ollie Lho184a4042005-11-26 21:55:36 +000026
Jacob Garberafc3ad62019-06-24 16:05:28 -060027static struct romentry entries[MAX_ROMLAYOUT];
Nico Huber2b94cdb2019-06-15 18:19:26 +020028static struct flashrom_layout global_layout = { entries, 0 };
Stefan Taunerc70bc8a2013-08-30 22:22:57 +000029
Nico Huber305f4172013-06-14 11:55:26 +020030struct flashrom_layout *get_global_layout(void)
Nico Huber3a9939b2016-04-27 15:56:14 +020031{
Nico Huber2b94cdb2019-06-15 18:19:26 +020032 return &global_layout;
Nico Huber3a9939b2016-04-27 15:56:14 +020033}
34
dhendrixbeaefe02017-09-03 18:06:53 -070035const struct flashrom_layout *get_layout(const struct flashrom_flashctx *const flashctx)
36{
37 if (flashctx->layout && flashctx->layout->num_entries)
38 return flashctx->layout;
39 else
40 return &flashctx->fallback_layout.base;
41}
42
Patrick Georgia9095a92010-09-30 17:03:32 +000043#ifndef __LIBPAYLOAD__
Mark Marshallf20b7be2014-05-09 21:16:21 +000044int read_romlayout(const char *name)
Ollie Lho184a4042005-11-26 21:55:36 +000045{
Nico Huber2b94cdb2019-06-15 18:19:26 +020046 struct flashrom_layout *const layout = get_global_layout();
Ollie Lho184a4042005-11-26 21:55:36 +000047 FILE *romlayout;
Nico Huber70461a92019-06-15 14:56:19 +020048 char tempstr[256], tempname[256];
49 int i, ret = 1;
Ollie Lho184a4042005-11-26 21:55:36 +000050
Uwe Hermanna7e05482007-05-09 10:17:44 +000051 romlayout = fopen(name, "r");
52
53 if (!romlayout) {
Carl-Daniel Hailfinger831e8f42010-05-30 22:24:40 +000054 msg_gerr("ERROR: Could not open ROM layout (%s).\n",
Uwe Hermanna7e05482007-05-09 10:17:44 +000055 name);
Ollie Lho184a4042005-11-26 21:55:36 +000056 return -1;
57 }
Uwe Hermanna7e05482007-05-09 10:17:44 +000058
59 while (!feof(romlayout)) {
Ollie Lho184a4042005-11-26 21:55:36 +000060 char *tstr1, *tstr2;
Carl-Daniel Hailfingerda53ada2010-12-04 11:56:52 +000061
Nico Huber2b94cdb2019-06-15 18:19:26 +020062 if (layout->num_entries >= MAX_ROMLAYOUT) {
Carl-Daniel Hailfingerda53ada2010-12-04 11:56:52 +000063 msg_gerr("Maximum number of ROM images (%i) in layout "
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +000064 "file reached.\n", MAX_ROMLAYOUT);
Nico Huber70461a92019-06-15 14:56:19 +020065 goto _close_ret;
Carl-Daniel Hailfingerda53ada2010-12-04 11:56:52 +000066 }
Nico Huber70461a92019-06-15 14:56:19 +020067 if (2 != fscanf(romlayout, "%255s %255s\n", tempstr, tempname))
Peter Stuge1fec0f32009-01-12 21:00:35 +000068 continue;
Ollie Lho184a4042005-11-26 21:55:36 +000069#if 0
70 // fscanf does not like arbitrary comments like that :( later
Uwe Hermanna7e05482007-05-09 10:17:44 +000071 if (tempstr[0] == '#') {
Ollie Lho184a4042005-11-26 21:55:36 +000072 continue;
73 }
74#endif
Uwe Hermanna7e05482007-05-09 10:17:44 +000075 tstr1 = strtok(tempstr, ":");
76 tstr2 = strtok(NULL, ":");
Uwe Hermann58783e32008-12-22 16:42:59 +000077 if (!tstr1 || !tstr2) {
Stefan Taunereb582572012-09-21 12:52:50 +000078 msg_gerr("Error parsing layout file. Offending string: \"%s\"\n", tempstr);
Nico Huber70461a92019-06-15 14:56:19 +020079 goto _close_ret;
Uwe Hermann58783e32008-12-22 16:42:59 +000080 }
Nico Huber2b94cdb2019-06-15 18:19:26 +020081 layout->entries[layout->num_entries].start = strtol(tstr1, (char **)NULL, 16);
82 layout->entries[layout->num_entries].end = strtol(tstr2, (char **)NULL, 16);
83 layout->entries[layout->num_entries].included = 0;
Nico Huber70461a92019-06-15 14:56:19 +020084 layout->entries[layout->num_entries].name = strdup(tempname);
85 if (!layout->entries[layout->num_entries].name) {
86 msg_gerr("Error adding layout entry: %s\n", strerror(errno));
87 goto _close_ret;
88 }
Nico Huber2b94cdb2019-06-15 18:19:26 +020089 layout->num_entries++;
Ollie Lho184a4042005-11-26 21:55:36 +000090 }
Uwe Hermanna7e05482007-05-09 10:17:44 +000091
Nico Huber2b94cdb2019-06-15 18:19:26 +020092 for (i = 0; i < layout->num_entries; i++) {
Carl-Daniel Hailfinger831e8f42010-05-30 22:24:40 +000093 msg_gdbg("romlayout %08x - %08x named %s\n",
Nico Huber2b94cdb2019-06-15 18:19:26 +020094 layout->entries[i].start,
95 layout->entries[i].end, layout->entries[i].name);
Ollie Lho184a4042005-11-26 21:55:36 +000096 }
97
Nico Huber70461a92019-06-15 14:56:19 +020098 ret = 0;
Uwe Hermannffec5f32007-08-23 16:08:21 +000099
Nico Huber70461a92019-06-15 14:56:19 +0200100_close_ret:
101 (void)fclose(romlayout);
102 return ret;
Ollie Lho184a4042005-11-26 21:55:36 +0000103}
Patrick Georgia9095a92010-09-30 17:03:32 +0000104#endif
Ollie Lho184a4042005-11-26 21:55:36 +0000105
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000106/* register an include argument (-i) for later processing */
Arthur Heymansb04fef92019-02-05 17:35:05 +0100107int register_include_arg(struct layout_include_args **args, char *name)
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000108{
Arthur Heymansb04fef92019-02-05 17:35:05 +0100109 struct layout_include_args *tmp;
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000110 if (name == NULL) {
111 msg_gerr("<NULL> is a bad region name.\n");
112 return 1;
113 }
114
Arthur Heymansb04fef92019-02-05 17:35:05 +0100115 tmp = *args;
116 while (tmp) {
117 if (!strcmp(tmp->name, name)) {
118 msg_gerr("Duplicate region name: \"%s\".\n", name);
119 return 1;
120 }
121 tmp = tmp->next;
122 }
123
124 tmp = malloc(sizeof(struct layout_include_args));
125 if (tmp == NULL) {
126 msg_gerr("Could not allocate memory");
Stefan Tauner23bb6d52012-04-15 14:09:16 +0000127 return 1;
128 }
129
Arthur Heymansb04fef92019-02-05 17:35:05 +0100130 tmp->name = name;
131 tmp->next = *args;
132 *args = tmp;
133
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000134 return 0;
135}
136
Arthur Heymans32b9f5c2019-02-05 16:14:55 +0100137/* returns -1 if an entry is not found, 0 if found. */
Nico Huber305f4172013-06-14 11:55:26 +0200138static int find_romentry(struct flashrom_layout *const l, char *name)
Ollie Lho184a4042005-11-26 21:55:36 +0000139{
Nico Huber305f4172013-06-14 11:55:26 +0200140 if (l->num_entries == 0)
Uwe Hermanna7e05482007-05-09 10:17:44 +0000141 return -1;
Ollie Lho184a4042005-11-26 21:55:36 +0000142
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000143 msg_gspew("Looking for region \"%s\"... ", name);
Arthur Heymans32b9f5c2019-02-05 16:14:55 +0100144 if (flashrom_layout_include_region(l, name)) {
145 msg_gspew("not found.\n");
146 return -1;
Ollie Lho184a4042005-11-26 21:55:36 +0000147 }
Arthur Heymans32b9f5c2019-02-05 16:14:55 +0100148 msg_gspew("found.\n");
149 return 0;
Ollie Lho184a4042005-11-26 21:55:36 +0000150}
151
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000152/* process -i arguments
153 * returns 0 to indicate success, >0 to indicate failure
154 */
Arthur Heymansb04fef92019-02-05 17:35:05 +0100155int process_include_args(struct flashrom_layout *l, const struct layout_include_args *const args)
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000156{
Arthur Heymansb04fef92019-02-05 17:35:05 +0100157 int found = 0;
158 const struct layout_include_args *tmp;
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000159
Arthur Heymansb04fef92019-02-05 17:35:05 +0100160 if (args == NULL)
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000161 return 0;
162
Stefan Tauner23bb6d52012-04-15 14:09:16 +0000163 /* User has specified an area, but no layout file is loaded. */
Nico Huber305f4172013-06-14 11:55:26 +0200164 if (l->num_entries == 0) {
Stefan Tauner23bb6d52012-04-15 14:09:16 +0000165 msg_gerr("Region requested (with -i \"%s\"), "
166 "but no layout data is available.\n",
Arthur Heymansb04fef92019-02-05 17:35:05 +0100167 args->name);
Stefan Tauner23bb6d52012-04-15 14:09:16 +0000168 return 1;
169 }
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000170
Arthur Heymansb04fef92019-02-05 17:35:05 +0100171 tmp = args;
172 while (tmp) {
173 if (find_romentry(l, tmp->name) < 0) {
Stefan Tauner23bb6d52012-04-15 14:09:16 +0000174 msg_gerr("Invalid region specified: \"%s\".\n",
Arthur Heymansb04fef92019-02-05 17:35:05 +0100175 tmp->name);
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000176 return 1;
177 }
Arthur Heymansb04fef92019-02-05 17:35:05 +0100178 tmp = tmp->next;
179 found++;
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000180 }
181
Arthur Heymansb04fef92019-02-05 17:35:05 +0100182 msg_ginfo("Using region%s:", found > 1 ? "s" : "");
183 tmp = args;
184 while (tmp) {
185 msg_ginfo(" \"%s\"%s", tmp->name, found > 1 ? "," : "");
186 found--;
187 tmp = tmp->next;
188 }
Louis Yung-Chieh Lo9bcf2682011-12-25 09:12:16 +0000189 msg_ginfo(".\n");
190 return 0;
191}
192
Arthur Heymansb04fef92019-02-05 17:35:05 +0100193void layout_cleanup(struct layout_include_args **args)
Stefan Tauner949ccc82013-09-15 14:01:06 +0000194{
Nico Huber2b94cdb2019-06-15 18:19:26 +0200195 struct flashrom_layout *const layout = get_global_layout();
Stefan Tauner949ccc82013-09-15 14:01:06 +0000196 int i;
Arthur Heymansb04fef92019-02-05 17:35:05 +0100197 struct layout_include_args *tmp;
198
199 while (*args) {
200 tmp = (*args)->next;
201 free(*args);
202 *args = tmp;
Stefan Tauner949ccc82013-09-15 14:01:06 +0000203 }
Stefan Tauner949ccc82013-09-15 14:01:06 +0000204
Nico Huber2b94cdb2019-06-15 18:19:26 +0200205 for (i = 0; i < layout->num_entries; i++) {
Nico Huber70461a92019-06-15 14:56:19 +0200206 free(layout->entries[i].name);
Nico Huber2b94cdb2019-06-15 18:19:26 +0200207 layout->entries[i].included = 0;
Stefan Tauner949ccc82013-09-15 14:01:06 +0000208 }
Nico Huber2b94cdb2019-06-15 18:19:26 +0200209 layout->num_entries = 0;
Stefan Tauner949ccc82013-09-15 14:01:06 +0000210}
211
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000212/* Validate and - if needed - normalize layout entries. */
213int normalize_romentries(const struct flashctx *flash)
214{
Nico Huber2b94cdb2019-06-15 18:19:26 +0200215 struct flashrom_layout *const layout = get_global_layout();
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000216 chipsize_t total_size = flash->chip->total_size * 1024;
217 int ret = 0;
218
219 int i;
Nico Huber2b94cdb2019-06-15 18:19:26 +0200220 for (i = 0; i < layout->num_entries; i++) {
221 if (layout->entries[i].start >= total_size || layout->entries[i].end >= total_size) {
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000222 msg_gwarn("Warning: Address range of region \"%s\" exceeds the current chip's "
Nico Huber2b94cdb2019-06-15 18:19:26 +0200223 "address space.\n", layout->entries[i].name);
224 if (layout->entries[i].included)
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000225 ret = 1;
226 }
Nico Huber2b94cdb2019-06-15 18:19:26 +0200227 if (layout->entries[i].start > layout->entries[i].end) {
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000228 msg_gerr("Error: Size of the address range of region \"%s\" is not positive.\n",
Nico Huber2b94cdb2019-06-15 18:19:26 +0200229 layout->entries[i].name);
Stefan Tauner8268fdb2013-09-23 14:21:06 +0000230 ret = 1;
231 }
232 }
233
234 return ret;
235}
Nico Huber3d7b1e32018-12-22 00:53:14 +0100236
237const struct romentry *layout_next_included_region(
238 const struct flashrom_layout *const l, const chipoff_t where)
239{
240 unsigned int i;
241 const struct romentry *lowest = NULL;
242
243 for (i = 0; i < l->num_entries; ++i) {
244 if (!l->entries[i].included)
245 continue;
246 if (l->entries[i].end < where)
247 continue;
248 if (!lowest || lowest->start > l->entries[i].start)
249 lowest = &l->entries[i];
250 }
251
252 return lowest;
253}
Nico Huber4f213282019-06-15 17:33:49 +0200254
Nico Huber5ca55232019-06-15 22:29:08 +0200255const struct romentry *layout_next_included(
256 const struct flashrom_layout *const layout, const struct romentry *iterator)
257{
258 const struct romentry *const end = layout->entries + layout->num_entries;
259
260 if (iterator)
261 ++iterator;
262 else
263 iterator = &layout->entries[0];
264
265 for (; iterator < end; ++iterator) {
266 if (!iterator->included)
267 continue;
268 return iterator;
269 }
270 return NULL;
271}
272
Nico Huber4f213282019-06-15 17:33:49 +0200273/**
274 * @addtogroup flashrom-layout
275 * @{
276 */
277
278/**
279 * @brief Mark given region as included.
280 *
281 * @param layout The layout to alter.
282 * @param name The name of the region to include.
283 *
284 * @return 0 on success,
285 * 1 if the given name can't be found.
286 */
287int flashrom_layout_include_region(struct flashrom_layout *const layout, const char *name)
288{
289 size_t i;
290 for (i = 0; i < layout->num_entries; ++i) {
291 if (!strcmp(layout->entries[i].name, name)) {
292 layout->entries[i].included = true;
293 return 0;
294 }
295 }
296 return 1;
297}
298
299/**
300 * @brief Free a layout.
301 *
302 * @param layout Layout to free.
303 */
304void flashrom_layout_release(struct flashrom_layout *const layout)
305{
Nico Huber70461a92019-06-15 14:56:19 +0200306 unsigned int i;
307
308 if (!layout || layout == get_global_layout())
Nico Huber4f213282019-06-15 17:33:49 +0200309 return;
310
Nico Huber70461a92019-06-15 14:56:19 +0200311 for (i = 0; i < layout->num_entries; ++i)
312 free(layout->entries[i].name);
Nico Huber4f213282019-06-15 17:33:49 +0200313 free(layout);
314}
315
316/** @} */ /* end flashrom-layout */