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(®istered_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(®istered_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