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