xref: /aosp_15_r20/external/flashrom/libflashrom.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2012, 2016 secunet Security Networks AG
5  * (Written by Nico Huber <[email protected]> for secunet)
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
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.
16  */
17 
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdarg.h>
22 
23 #include "flash.h"
24 #include "fmap.h"
25 #include "programmer.h"
26 #include "layout.h"
27 #include "ich_descriptors.h"
28 #include "libflashrom.h"
29 #include "writeprotect.h"
30 
31 
32 /** Pointer to log callback function. */
33 static flashrom_log_callback *global_log_callback = NULL;
34 
flashrom_init(const int perform_selfcheck)35 int flashrom_init(const int perform_selfcheck)
36 {
37 	if (perform_selfcheck && selfcheck())
38 		return 1;
39 	return 0;
40 }
41 
flashrom_shutdown(void)42 int flashrom_shutdown(void)
43 {
44 	return 0; /* TODO: nothing to do? */
45 }
46 
47 /* TODO: flashrom_set_loglevel()? do we need it?
48          For now, let the user decide in their callback. */
flashrom_set_log_callback(flashrom_log_callback * const log_callback)49 void flashrom_set_log_callback(flashrom_log_callback *const log_callback)
50 {
51 	global_log_callback = log_callback;
52 }
53 /** @private */
print(const enum flashrom_log_level level,const char * const fmt,...)54 int print(const enum flashrom_log_level level, const char *const fmt, ...)
55 {
56 	if (global_log_callback) {
57 		int ret;
58 		va_list args;
59 		va_start(args, fmt);
60 		ret = global_log_callback(level, fmt, args);
61 		va_end(args);
62 		return ret;
63 	}
64 	return 0;
65 }
66 
flashrom_set_progress_callback(struct flashrom_flashctx * flashctx,flashrom_progress_callback * progress_callback,struct flashrom_progress * progress_state)67 void flashrom_set_progress_callback(struct flashrom_flashctx *flashctx, flashrom_progress_callback *progress_callback, struct flashrom_progress *progress_state)
68 {
69 	flashctx->progress_callback = progress_callback;
70 	flashctx->progress_state = progress_state;
71 }
72 /** @private */
update_progress(struct flashrom_flashctx * flashctx,enum flashrom_progress_stage stage,size_t current,size_t total)73 void update_progress(struct flashrom_flashctx *flashctx, enum flashrom_progress_stage stage, size_t current, size_t total)
74 {
75 	if (flashctx->progress_callback == NULL)
76 		return;
77 	if (current > total)
78 		current = total;
79 
80 	flashctx->progress_state->stage = stage;
81 	flashctx->progress_state->current = current;
82 	flashctx->progress_state->total = total;
83 	flashctx->progress_callback(flashctx);
84 }
85 
flashrom_version_info(void)86 const char *flashrom_version_info(void)
87 {
88 	return flashrom_version;
89 }
90 
flashrom_supported_flash_chips(void)91 struct flashrom_flashchip_info *flashrom_supported_flash_chips(void)
92 {
93 	struct flashrom_flashchip_info *supported_flashchips =
94 		malloc(flashchips_size * sizeof(*supported_flashchips));
95 
96 	if (!supported_flashchips) {
97 		msg_gerr("Memory allocation error!\n");
98 		return NULL;
99 	}
100 
101 	for (unsigned int i = 0; i < flashchips_size; ++i) {
102 		supported_flashchips[i].vendor = flashchips[i].vendor;
103 		supported_flashchips[i].name = flashchips[i].name;
104 		supported_flashchips[i].manufacture_id = flashchips[i].manufacture_id;
105 		supported_flashchips[i].model_id = flashchips[i].model_id;
106 		supported_flashchips[i].tested.erase =
107 			(enum flashrom_test_state)flashchips[i].tested.erase;
108 		supported_flashchips[i].tested.probe =
109 			(enum flashrom_test_state)flashchips[i].tested.probe;
110 		supported_flashchips[i].tested.read =
111 			(enum flashrom_test_state)flashchips[i].tested.read;
112 		supported_flashchips[i].tested.write =
113 			(enum flashrom_test_state)flashchips[i].tested.write;
114 		supported_flashchips[i].total_size = flashchips[i].total_size;
115 	}
116 
117 	return supported_flashchips;
118 }
119 
flashrom_supported_boards(void)120 struct flashrom_board_info *flashrom_supported_boards(void)
121 {
122 #if CONFIG_INTERNAL == 1
123 	int boards_known_size = 0;
124 	const struct board_info *binfo = boards_known;
125 
126 	while ((binfo++)->vendor)
127 		++boards_known_size;
128 	binfo = boards_known;
129 	/* add place for {0} */
130 	++boards_known_size;
131 
132 	struct flashrom_board_info *supported_boards =
133 		malloc(boards_known_size * sizeof(*supported_boards));
134 
135 	if (!supported_boards) {
136 		msg_gerr("Memory allocation error!\n");
137 		return NULL;
138 	}
139 
140 	for (int i = 0; i < boards_known_size; ++i) {
141 		supported_boards[i].vendor = binfo[i].vendor;
142 		supported_boards[i].name = binfo[i].name;
143 		supported_boards[i].working =
144 			(enum flashrom_test_state) binfo[i].working;
145 	}
146 
147 	return supported_boards;
148 #else
149 	return NULL;
150 #endif
151 }
152 
flashrom_supported_chipsets(void)153 struct flashrom_chipset_info *flashrom_supported_chipsets(void)
154 {
155 #if CONFIG_INTERNAL == 1
156 	int chipset_enables_size = 0;
157 	const struct penable *chipset = chipset_enables;
158 
159 	while ((chipset++)->vendor_name)
160 		++chipset_enables_size;
161 	chipset = chipset_enables;
162 	/* add place for {0}*/
163 	++chipset_enables_size;
164 
165 	struct flashrom_chipset_info *supported_chipsets =
166 		malloc(chipset_enables_size * sizeof(*supported_chipsets));
167 
168 	if (!supported_chipsets) {
169 		msg_gerr("Memory allocation error!\n");
170 		return NULL;
171 	}
172 
173 	for (int i = 0; i < chipset_enables_size; ++i) {
174 		supported_chipsets[i].vendor = chipset[i].vendor_name;
175 		supported_chipsets[i].chipset = chipset[i].device_name;
176 		supported_chipsets[i].vendor_id = chipset[i].vendor_id;
177 		supported_chipsets[i].chipset_id = chipset[i].device_id;
178 		supported_chipsets[i].status =
179 			(enum flashrom_test_state) chipset[i].status;
180 	}
181 
182 	return supported_chipsets;
183 #else
184 	return NULL;
185 #endif
186 }
187 
flashrom_data_free(void * const p)188 int flashrom_data_free(void *const p)
189 {
190 	free(p);
191 	return 0;
192 }
193 
flashrom_programmer_init(struct flashrom_programmer ** const flashprog,const char * const prog_name,const char * const prog_param)194 int flashrom_programmer_init(struct flashrom_programmer **const flashprog,
195 			     const char *const prog_name, const char *const prog_param)
196 {
197 	unsigned prog;
198 
199 	for (prog = 0; prog < programmer_table_size; prog++) {
200 		if (strcmp(prog_name, programmer_table[prog]->name) == 0)
201 			break;
202 	}
203 	if (prog >= programmer_table_size) {
204 		msg_ginfo("Error: Unknown programmer \"%s\". Valid choices are:\n", prog_name);
205 		list_programmers_linebreak(0, 80, 0);
206 		return 1;
207 	}
208 	return programmer_init(programmer_table[prog], prog_param);
209 }
210 
flashrom_programmer_shutdown(struct flashrom_programmer * const flashprog)211 int flashrom_programmer_shutdown(struct flashrom_programmer *const flashprog)
212 {
213 	return programmer_shutdown();
214 }
215 
216 /* TODO: flashrom_programmer_capabilities()? */
217 
flashrom_flash_probe(struct flashrom_flashctx ** const flashctx,const struct flashrom_programmer * const flashprog,const char * const chip_name)218 int flashrom_flash_probe(struct flashrom_flashctx **const flashctx,
219 			 const struct flashrom_programmer *const flashprog,
220 			 const char *const chip_name)
221 {
222 	int i, ret = 2;
223 	struct flashrom_flashctx second_flashctx = { 0, };
224 
225 	*flashctx = malloc(sizeof(**flashctx));
226 	if (!*flashctx)
227 		return 1;
228 	memset(*flashctx, 0, sizeof(**flashctx));
229 
230 	for (i = 0; i < registered_master_count; ++i) {
231 		int flash_idx = -1;
232 		if (!ret || (flash_idx = probe_flash(&registered_masters[i], 0, *flashctx, 0, chip_name)) != -1) {
233 			ret = 0;
234 			/* We found one chip, now check that there is no second match. */
235 			if (probe_flash(&registered_masters[i], flash_idx + 1, &second_flashctx, 0, chip_name) != -1) {
236 				flashrom_layout_release(second_flashctx.default_layout);
237 				free(second_flashctx.chip);
238 				ret = 3;
239 				break;
240 			}
241 		}
242 	}
243 	if (ret) {
244 		flashrom_flash_release(*flashctx);
245 		*flashctx = NULL;
246 	}
247 	return ret;
248 }
249 
flashrom_flash_getsize(const struct flashrom_flashctx * const flashctx)250 size_t flashrom_flash_getsize(const struct flashrom_flashctx *const flashctx)
251 {
252 	return flashctx->chip->total_size * 1024;
253 }
254 
flashrom_flash_getinfo(const struct flashrom_flashctx * const flashctx,struct flashrom_flashchip_info * info)255 void flashrom_flash_getinfo(const struct flashrom_flashctx *const flashctx, struct flashrom_flashchip_info *info)
256 {
257 	if (!info) return;
258 
259 	info->vendor = flashctx->chip->vendor;
260 	info->name = flashctx->chip->name;
261 	info->manufacture_id = flashctx->chip->manufacture_id;
262 	info->model_id = flashctx->chip->model_id;
263 
264 	info->total_size = flashctx->chip->total_size;
265 
266 	info->tested.erase = (enum flashrom_test_state) flashctx->chip->tested.erase;
267 	info->tested.probe = (enum flashrom_test_state) flashctx->chip->tested.probe;
268 	info->tested.read  = (enum flashrom_test_state) flashctx->chip->tested.read;
269 	info->tested.write = (enum flashrom_test_state) flashctx->chip->tested.write;
270 }
271 
flashrom_flash_release(struct flashrom_flashctx * const flashctx)272 void flashrom_flash_release(struct flashrom_flashctx *const flashctx)
273 {
274 	if (!flashctx)
275 		return;
276 
277 	flashrom_layout_release(flashctx->default_layout);
278 	free(flashctx->chip);
279 	free(flashctx);
280 }
281 
flashrom_flag_set(struct flashrom_flashctx * const flashctx,const enum flashrom_flag flag,const bool value)282 void flashrom_flag_set(struct flashrom_flashctx *const flashctx,
283 		       const enum flashrom_flag flag, const bool value)
284 {
285 	switch (flag) {
286 		case FLASHROM_FLAG_FORCE:			flashctx->flags.force = value; break;
287 		case FLASHROM_FLAG_FORCE_BOARDMISMATCH:		flashctx->flags.force_boardmismatch = value; break;
288 		case FLASHROM_FLAG_VERIFY_AFTER_WRITE:		flashctx->flags.verify_after_write = value; break;
289 		case FLASHROM_FLAG_VERIFY_WHOLE_CHIP:		flashctx->flags.verify_whole_chip = value; break;
290 		case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS:	flashctx->flags.skip_unreadable_regions = value; break;
291 		case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS:	flashctx->flags.skip_unwritable_regions = value; break;
292 	}
293 }
294 
flashrom_flag_get(const struct flashrom_flashctx * const flashctx,const enum flashrom_flag flag)295 bool flashrom_flag_get(const struct flashrom_flashctx *const flashctx, const enum flashrom_flag flag)
296 {
297 	switch (flag) {
298 		case FLASHROM_FLAG_FORCE:			return flashctx->flags.force;
299 		case FLASHROM_FLAG_FORCE_BOARDMISMATCH:		return flashctx->flags.force_boardmismatch;
300 		case FLASHROM_FLAG_VERIFY_AFTER_WRITE:		return flashctx->flags.verify_after_write;
301 		case FLASHROM_FLAG_VERIFY_WHOLE_CHIP:		return flashctx->flags.verify_whole_chip;
302 		case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS:	return flashctx->flags.skip_unreadable_regions;
303 		case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS:	return flashctx->flags.skip_unwritable_regions;
304 		default:					return false;
305 	}
306 }
307 
flashrom_layout_read_from_ifd(struct flashrom_layout ** const layout,struct flashctx * const flashctx,const void * const dump,const size_t len)308 int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct flashctx *const flashctx,
309 				  const void *const dump, const size_t len)
310 {
311 #ifndef __FLASHROM_LITTLE_ENDIAN__
312 	return 6;
313 #else
314 	struct flashrom_layout *dump_layout = NULL, *chip_layout = NULL;
315 	int ret = 1;
316 
317 	void *const desc = malloc(0x1000);
318 	if (prepare_flash_access(flashctx, true, false, false, false))
319 		goto _free_ret;
320 
321 	msg_cinfo("Reading ich descriptor... ");
322 	if (read_flash(flashctx, desc, 0, 0x1000)) {
323 		msg_cerr("Read operation failed!\n");
324 		msg_cinfo("FAILED.\n");
325 		ret = 2;
326 		goto _finalize_ret;
327 	}
328 	msg_cinfo("done.\n");
329 
330 	if (layout_from_ich_descriptors(&chip_layout, desc, 0x1000)) {
331 		msg_cerr("Couldn't parse the descriptor!\n");
332 		ret = 3;
333 		goto _finalize_ret;
334 	}
335 
336 	if (dump) {
337 		if (layout_from_ich_descriptors(&dump_layout, dump, len)) {
338 			msg_cerr("Couldn't parse the descriptor!\n");
339 			ret = 4;
340 			goto _finalize_ret;
341 		}
342 
343 		const struct romentry *chip_entry = layout_next(chip_layout, NULL);
344 		const struct romentry *dump_entry = layout_next(dump_layout, NULL);
345 		while (chip_entry && dump_entry && !memcmp(chip_entry, dump_entry, sizeof(*chip_entry))) {
346 			chip_entry = layout_next(chip_layout, chip_entry);
347 			dump_entry = layout_next(dump_layout, dump_entry);
348 		}
349 		flashrom_layout_release(dump_layout);
350 		if (chip_entry || dump_entry) {
351 			msg_cerr("Descriptors don't match!\n");
352 			ret = 5;
353 			goto _finalize_ret;
354 		}
355 	}
356 
357 	*layout = (struct flashrom_layout *)chip_layout;
358 	ret = 0;
359 
360 _finalize_ret:
361 	finalize_flash_access(flashctx);
362 _free_ret:
363 	if (ret)
364 		flashrom_layout_release(chip_layout);
365 	free(desc);
366 	return ret;
367 #endif
368 }
369 
370 #ifdef __FLASHROM_LITTLE_ENDIAN__
flashrom_layout_parse_fmap(struct flashrom_layout ** layout,struct flashctx * const flashctx,const struct fmap * const fmap)371 static int flashrom_layout_parse_fmap(struct flashrom_layout **layout,
372 		struct flashctx *const flashctx, const struct fmap *const fmap)
373 {
374 	int i;
375 	char name[FMAP_STRLEN + 1];
376 	const struct fmap_area *area;
377 	struct flashrom_layout *l;
378 
379 	if (!fmap || flashrom_layout_new(&l))
380 		return 1;
381 
382 	for (i = 0, area = fmap->areas; i < fmap->nareas; i++, area++) {
383 		if (area->size == 0) {
384 			/* Layout regions use inclusive upper and lower bounds,
385 			 * so it's impossible to represent a region with zero
386 			 * size although it's allowed in fmap. */
387 			msg_gwarn("Ignoring zero-size fmap region \"%s\";"
388 				  " empty regions are unsupported.\n",
389 				  area->name);
390 			continue;
391 		}
392 
393 		snprintf(name, sizeof(name), "%s", area->name);
394 		if (flashrom_layout_add_region(l, area->offset, area->offset + area->size - 1, name)) {
395 			flashrom_layout_release(l);
396 			return 1;
397 		}
398 	}
399 
400 	*layout = l;
401 	return 0;
402 }
403 #endif /* __FLASHROM_LITTLE_ENDIAN__ */
404 
flashrom_layout_read_fmap_from_rom(struct flashrom_layout ** const layout,struct flashctx * const flashctx,size_t offset,size_t len)405 int flashrom_layout_read_fmap_from_rom(struct flashrom_layout **const layout,
406 		struct flashctx *const flashctx, size_t offset, size_t len)
407 {
408 #ifndef __FLASHROM_LITTLE_ENDIAN__
409 	return 3;
410 #else
411 	struct fmap *fmap = NULL;
412 	int ret = 0;
413 
414 	msg_gdbg("Attempting to read fmap from ROM content.\n");
415 	if (fmap_read_from_rom(&fmap, flashctx, offset, len)) {
416 		msg_gerr("Failed to read fmap from ROM.\n");
417 		return 1;
418 	}
419 
420 	msg_gdbg("Adding fmap layout to global layout.\n");
421 	if (flashrom_layout_parse_fmap(layout, flashctx, fmap)) {
422 		msg_gerr("Failed to add fmap regions to layout.\n");
423 		ret = 1;
424 	}
425 
426 	free(fmap);
427 	return ret;
428 #endif
429 }
430 
flashrom_layout_read_fmap_from_buffer(struct flashrom_layout ** const layout,struct flashctx * const flashctx,const uint8_t * const buf,size_t size)431 int flashrom_layout_read_fmap_from_buffer(struct flashrom_layout **const layout,
432 		struct flashctx *const flashctx, const uint8_t *const buf, size_t size)
433 {
434 #ifndef __FLASHROM_LITTLE_ENDIAN__
435 	return 3;
436 #else
437 	struct fmap *fmap = NULL;
438 	int ret = 1;
439 
440 	if (!buf || !size)
441 		goto _ret;
442 
443 	msg_gdbg("Attempting to read fmap from buffer.\n");
444 	if (fmap_read_from_buffer(&fmap, buf, size)) {
445 		msg_gerr("Failed to read fmap from buffer.\n");
446 		goto _ret;
447 	}
448 
449 	msg_gdbg("Adding fmap layout to global layout.\n");
450 	if (flashrom_layout_parse_fmap(layout, flashctx, fmap)) {
451 		msg_gerr("Failed to add fmap regions to layout.\n");
452 		goto _free_ret;
453 	}
454 
455 	ret = 0;
456 _free_ret:
457 	free(fmap);
458 _ret:
459 	return ret;
460 #endif
461 }
462 
flashrom_layout_set(struct flashrom_flashctx * const flashctx,const struct flashrom_layout * const layout)463 void flashrom_layout_set(struct flashrom_flashctx *const flashctx, const struct flashrom_layout *const layout)
464 {
465 	flashctx->layout = layout;
466 }
467 
flashrom_wp_cfg_new(struct flashrom_wp_cfg ** cfg)468 enum flashrom_wp_result flashrom_wp_cfg_new(struct flashrom_wp_cfg **cfg)
469 {
470 	*cfg = calloc(1, sizeof(**cfg));
471 	return *cfg ? 0 : FLASHROM_WP_ERR_OTHER;
472 }
473 
flashrom_wp_cfg_release(struct flashrom_wp_cfg * cfg)474 void flashrom_wp_cfg_release(struct flashrom_wp_cfg *cfg)
475 {
476 	free(cfg);
477 }
478 
flashrom_wp_set_mode(struct flashrom_wp_cfg * cfg,enum flashrom_wp_mode mode)479 void flashrom_wp_set_mode(struct flashrom_wp_cfg *cfg, enum flashrom_wp_mode mode)
480 {
481 	cfg->mode = mode;
482 }
483 
flashrom_wp_get_mode(const struct flashrom_wp_cfg * cfg)484 enum flashrom_wp_mode flashrom_wp_get_mode(const struct flashrom_wp_cfg *cfg)
485 {
486 	return cfg->mode;
487 }
488 
flashrom_wp_set_range(struct flashrom_wp_cfg * cfg,size_t start,size_t len)489 void flashrom_wp_set_range(struct flashrom_wp_cfg *cfg, size_t start, size_t len)
490 {
491 	cfg->range.start = start;
492 	cfg->range.len = len;
493 }
494 
flashrom_wp_get_range(size_t * start,size_t * len,const struct flashrom_wp_cfg * cfg)495 void flashrom_wp_get_range(size_t *start, size_t *len, const struct flashrom_wp_cfg *cfg)
496 {
497 	*start = cfg->range.start;
498 	*len = cfg->range.len;
499 }
500 
flashrom_wp_write_cfg(struct flashctx * flash,const struct flashrom_wp_cfg * cfg)501 enum flashrom_wp_result flashrom_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg)
502 {
503 	if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_write_cfg)
504 		return flash->mst->opaque.wp_write_cfg(flash, cfg);
505 
506 	if (wp_operations_available(flash))
507 		return wp_write_cfg(flash, cfg);
508 
509 	return FLASHROM_WP_ERR_OTHER;
510 }
511 
flashrom_wp_read_cfg(struct flashrom_wp_cfg * cfg,struct flashctx * flash)512 enum flashrom_wp_result flashrom_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash)
513 {
514 	if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_read_cfg)
515 		return flash->mst->opaque.wp_read_cfg(cfg, flash);
516 
517 	if (wp_operations_available(flash))
518 		return wp_read_cfg(cfg, flash);
519 
520 	return FLASHROM_WP_ERR_OTHER;
521 }
522 
flashrom_wp_get_available_ranges(struct flashrom_wp_ranges ** list,struct flashrom_flashctx * flash)523 enum flashrom_wp_result flashrom_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashrom_flashctx *flash)
524 {
525 	if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_get_ranges)
526 		return flash->mst->opaque.wp_get_ranges(list, flash);
527 
528 	if (wp_operations_available(flash))
529 		return wp_get_available_ranges(list, flash);
530 
531 	return FLASHROM_WP_ERR_OTHER;
532 }
533 
flashrom_wp_ranges_get_count(const struct flashrom_wp_ranges * list)534 size_t flashrom_wp_ranges_get_count(const struct flashrom_wp_ranges *list)
535 {
536 	return list->count;
537 }
538 
flashrom_wp_ranges_get_range(size_t * start,size_t * len,const struct flashrom_wp_ranges * list,unsigned int index)539 enum flashrom_wp_result flashrom_wp_ranges_get_range(size_t *start, size_t *len, const struct flashrom_wp_ranges *list, unsigned int index)
540 {
541 	if (index >= list->count)
542 		return FLASHROM_WP_ERR_OTHER;
543 
544 	*start = list->ranges[index].start;
545 	*len = list->ranges[index].len;
546 
547 	return 0;
548 }
549 
flashrom_wp_ranges_release(struct flashrom_wp_ranges * list)550 void flashrom_wp_ranges_release(struct flashrom_wp_ranges *list)
551 {
552 	if (!list)
553 		return;
554 
555 	free(list->ranges);
556 	free(list);
557 }
558