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 2022 Google LLC
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; version 2 of the License.
9*0d6140beSAndroid Build Coastguard Worker *
10*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
14*0d6140beSAndroid Build Coastguard Worker */
15*0d6140beSAndroid Build Coastguard Worker
16*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
17*0d6140beSAndroid Build Coastguard Worker #include "string.h"
18*0d6140beSAndroid Build Coastguard Worker
19*0d6140beSAndroid Build Coastguard Worker #include "include/test.h"
20*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
21*0d6140beSAndroid Build Coastguard Worker #include "tests.h"
22*0d6140beSAndroid Build Coastguard Worker #include <cmocka.h>
23*0d6140beSAndroid Build Coastguard Worker
24*0d6140beSAndroid Build Coastguard Worker
25*0d6140beSAndroid Build Coastguard Worker #define assert_table(assertion, message, index, name) \
26*0d6140beSAndroid Build Coastguard Worker do { \
27*0d6140beSAndroid Build Coastguard Worker if (!(assertion)) \
28*0d6140beSAndroid Build Coastguard Worker fail_msg(message " for index:%zu name:%s", (index), (name) ? (name) : "unknown"); \
29*0d6140beSAndroid Build Coastguard Worker } while (0)
30*0d6140beSAndroid Build Coastguard Worker
31*0d6140beSAndroid Build Coastguard Worker
selfcheck_programmer_table(void ** state)32*0d6140beSAndroid Build Coastguard Worker void selfcheck_programmer_table(void **state)
33*0d6140beSAndroid Build Coastguard Worker {
34*0d6140beSAndroid Build Coastguard Worker (void)state; /* unused */
35*0d6140beSAndroid Build Coastguard Worker
36*0d6140beSAndroid Build Coastguard Worker size_t i;
37*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < programmer_table_size; i++) {
38*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry *const p = programmer_table[i];
39*0d6140beSAndroid Build Coastguard Worker assert_table(p, "programmer entry is null", i, "unknown");
40*0d6140beSAndroid Build Coastguard Worker assert_table(p->name, "programmer name is null", i, p->name);
41*0d6140beSAndroid Build Coastguard Worker bool type_good = false;
42*0d6140beSAndroid Build Coastguard Worker switch (p->type) {
43*0d6140beSAndroid Build Coastguard Worker case PCI:
44*0d6140beSAndroid Build Coastguard Worker case USB:
45*0d6140beSAndroid Build Coastguard Worker case OTHER:
46*0d6140beSAndroid Build Coastguard Worker type_good = true;
47*0d6140beSAndroid Build Coastguard Worker }
48*0d6140beSAndroid Build Coastguard Worker assert_table(type_good, "programmer type is invalid", i, p->name);
49*0d6140beSAndroid Build Coastguard Worker /* internal has its device list stored separately. */
50*0d6140beSAndroid Build Coastguard Worker if (strcmp("internal", p->name) != 0)
51*0d6140beSAndroid Build Coastguard Worker assert_table(p->devs.note, "programmer devs.note is null", i, p->name);
52*0d6140beSAndroid Build Coastguard Worker assert_table(p->init, "programmer init is null", i, p->name);
53*0d6140beSAndroid Build Coastguard Worker }
54*0d6140beSAndroid Build Coastguard Worker }
55*0d6140beSAndroid Build Coastguard Worker
selfcheck_flashchips_table(void ** state)56*0d6140beSAndroid Build Coastguard Worker void selfcheck_flashchips_table(void **state)
57*0d6140beSAndroid Build Coastguard Worker {
58*0d6140beSAndroid Build Coastguard Worker (void)state; /* unused */
59*0d6140beSAndroid Build Coastguard Worker
60*0d6140beSAndroid Build Coastguard Worker size_t i;
61*0d6140beSAndroid Build Coastguard Worker assert_true(flashchips_size > 1);
62*0d6140beSAndroid Build Coastguard Worker assert_true(flashchips[flashchips_size - 1].name == NULL);
63*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < flashchips_size - 1; i++) {
64*0d6140beSAndroid Build Coastguard Worker const struct flashchip *chip = &flashchips[i];
65*0d6140beSAndroid Build Coastguard Worker assert_table(chip->vendor, "chip vendor is null", i, chip->name);
66*0d6140beSAndroid Build Coastguard Worker assert_table(chip->name, "chip name is null", i, chip->name);
67*0d6140beSAndroid Build Coastguard Worker assert_table(chip->bustype != BUS_NONE, "chip bustype is BUS_NONE", i, chip->name);
68*0d6140beSAndroid Build Coastguard Worker }
69*0d6140beSAndroid Build Coastguard Worker }
70*0d6140beSAndroid Build Coastguard Worker
selfcheck_eraseblocks(void ** state)71*0d6140beSAndroid Build Coastguard Worker void selfcheck_eraseblocks(void **state)
72*0d6140beSAndroid Build Coastguard Worker {
73*0d6140beSAndroid Build Coastguard Worker (void)state; /* unused */
74*0d6140beSAndroid Build Coastguard Worker
75*0d6140beSAndroid Build Coastguard Worker size_t chip_index;
76*0d6140beSAndroid Build Coastguard Worker for (chip_index = 0; chip_index < flashchips_size - 1; chip_index++) {
77*0d6140beSAndroid Build Coastguard Worker size_t i, j, k;
78*0d6140beSAndroid Build Coastguard Worker const struct flashchip *chip = &flashchips[chip_index];
79*0d6140beSAndroid Build Coastguard Worker unsigned int prev_eraseblock_count = chip->total_size * 1024;
80*0d6140beSAndroid Build Coastguard Worker
81*0d6140beSAndroid Build Coastguard Worker for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
82*0d6140beSAndroid Build Coastguard Worker unsigned int done = 0;
83*0d6140beSAndroid Build Coastguard Worker struct block_eraser eraser = chip->block_erasers[k];
84*0d6140beSAndroid Build Coastguard Worker unsigned int curr_eraseblock_count = 0;
85*0d6140beSAndroid Build Coastguard Worker
86*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < NUM_ERASEREGIONS; i++) {
87*0d6140beSAndroid Build Coastguard Worker /* Blocks with zero size are bugs in flashchips.c. */
88*0d6140beSAndroid Build Coastguard Worker if (eraser.eraseblocks[i].count && !eraser.eraseblocks[i].size) {
89*0d6140beSAndroid Build Coastguard Worker fail_msg("Flash chip %s erase function %zu region %zu has size 0",
90*0d6140beSAndroid Build Coastguard Worker chip->name, k, i);
91*0d6140beSAndroid Build Coastguard Worker }
92*0d6140beSAndroid Build Coastguard Worker /* Blocks with zero count are bugs in flashchips.c. */
93*0d6140beSAndroid Build Coastguard Worker if (!eraser.eraseblocks[i].count && eraser.eraseblocks[i].size) {
94*0d6140beSAndroid Build Coastguard Worker fail_msg("Flash chip %s erase function %zu region %zu has count 0",
95*0d6140beSAndroid Build Coastguard Worker chip->name, k, i);
96*0d6140beSAndroid Build Coastguard Worker }
97*0d6140beSAndroid Build Coastguard Worker done += eraser.eraseblocks[i].count * eraser.eraseblocks[i].size;
98*0d6140beSAndroid Build Coastguard Worker curr_eraseblock_count += eraser.eraseblocks[i].count;
99*0d6140beSAndroid Build Coastguard Worker }
100*0d6140beSAndroid Build Coastguard Worker /* Empty eraseblock definition with erase function. */
101*0d6140beSAndroid Build Coastguard Worker if (!done && eraser.block_erase) {
102*0d6140beSAndroid Build Coastguard Worker printf("Strange: Empty eraseblock definition with non-empty erase function chip %s function %zu. Not an error.\n",
103*0d6140beSAndroid Build Coastguard Worker chip->name, k);
104*0d6140beSAndroid Build Coastguard Worker }
105*0d6140beSAndroid Build Coastguard Worker
106*0d6140beSAndroid Build Coastguard Worker if (!done)
107*0d6140beSAndroid Build Coastguard Worker continue;
108*0d6140beSAndroid Build Coastguard Worker if (done != chip->total_size * 1024) {
109*0d6140beSAndroid Build Coastguard Worker fail_msg(
110*0d6140beSAndroid Build Coastguard Worker "Flash chip %s erase function %zu region walking resulted in 0x%06x bytes total, expected 0x%06x bytes.",
111*0d6140beSAndroid Build Coastguard Worker chip->name, k, done, chip->total_size * 1024);
112*0d6140beSAndroid Build Coastguard Worker assert_true(false);
113*0d6140beSAndroid Build Coastguard Worker }
114*0d6140beSAndroid Build Coastguard Worker
115*0d6140beSAndroid Build Coastguard Worker if (!eraser.block_erase)
116*0d6140beSAndroid Build Coastguard Worker continue;
117*0d6140beSAndroid Build Coastguard Worker /* Check if there are identical erase functions for different
118*0d6140beSAndroid Build Coastguard Worker * layouts. That would imply "magic" erase functions. The
119*0d6140beSAndroid Build Coastguard Worker * easiest way to check this is with function pointers.
120*0d6140beSAndroid Build Coastguard Worker */
121*0d6140beSAndroid Build Coastguard Worker for (j = k + 1; j < NUM_ERASEFUNCTIONS; j++) {
122*0d6140beSAndroid Build Coastguard Worker if (eraser.block_erase == chip->block_erasers[j].block_erase) {
123*0d6140beSAndroid Build Coastguard Worker fail_msg("Flash chip %s erase function %zu and %zu are identical.",
124*0d6140beSAndroid Build Coastguard Worker chip->name, k, j);
125*0d6140beSAndroid Build Coastguard Worker }
126*0d6140beSAndroid Build Coastguard Worker }
127*0d6140beSAndroid Build Coastguard Worker if (curr_eraseblock_count > prev_eraseblock_count) {
128*0d6140beSAndroid Build Coastguard Worker fail_msg("Flash chip %s erase function %zu is not in order", chip->name, k);
129*0d6140beSAndroid Build Coastguard Worker }
130*0d6140beSAndroid Build Coastguard Worker prev_eraseblock_count = curr_eraseblock_count;
131*0d6140beSAndroid Build Coastguard Worker }
132*0d6140beSAndroid Build Coastguard Worker }
133*0d6140beSAndroid Build Coastguard Worker }
134*0d6140beSAndroid Build Coastguard Worker
135*0d6140beSAndroid Build Coastguard Worker #if CONFIG_INTERNAL == 1
selfcheck_board_matches_table(void ** state)136*0d6140beSAndroid Build Coastguard Worker void selfcheck_board_matches_table(void **state)
137*0d6140beSAndroid Build Coastguard Worker {
138*0d6140beSAndroid Build Coastguard Worker (void)state; /* unused */
139*0d6140beSAndroid Build Coastguard Worker
140*0d6140beSAndroid Build Coastguard Worker size_t i;
141*0d6140beSAndroid Build Coastguard Worker
142*0d6140beSAndroid Build Coastguard Worker assert_true(board_matches_size > 0);
143*0d6140beSAndroid Build Coastguard Worker assert_true(board_matches[board_matches_size - 1].vendor_name == NULL);
144*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < board_matches_size - 1; i++) {
145*0d6140beSAndroid Build Coastguard Worker const struct board_match *b = &board_matches[i];
146*0d6140beSAndroid Build Coastguard Worker assert_table(b->vendor_name, "board vendor_name is null", i, b->board_name);
147*0d6140beSAndroid Build Coastguard Worker assert_table(b->board_name, "board boad_name is null", i, b->board_name);
148*0d6140beSAndroid Build Coastguard Worker if ((!b->first_vendor || !b->first_device || !b->second_vendor || !b->second_device)
149*0d6140beSAndroid Build Coastguard Worker || ((!b->lb_vendor) ^ (!b->lb_part)) || (!b->max_rom_decode_parallel && !b->enable))
150*0d6140beSAndroid Build Coastguard Worker fail_msg("Board enable for %s %s is misdefined.\n", b->vendor_name, b->board_name);
151*0d6140beSAndroid Build Coastguard Worker }
152*0d6140beSAndroid Build Coastguard Worker }
153*0d6140beSAndroid Build Coastguard Worker
154*0d6140beSAndroid Build Coastguard Worker #else
155*0d6140beSAndroid Build Coastguard Worker SKIP_TEST(selfcheck_board_matches_table)
156*0d6140beSAndroid Build Coastguard Worker #endif /* CONFIG_INTERNAL */
157