xref: /aosp_15_r20/external/flashrom/tests/selfcheck.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
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