xref: /openbmc/phosphor-mboxd/test/erase_flash.c (revision c3144042b9f050c3d880f4ae5464a2a21617fe7d)
1 /*
2  * MBox Daemon Test File
3  *
4  * Copyright 2017 IBM
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26 
27 #include <linux/types.h>
28 
29 #include "mbox.h"
30 #include "mboxd_flash.h"
31 
32 #include "test/tmpf.h"
33 
34 static struct tmpf mtd;
35 
36 void cleanup_mtd(void)
37 {
38 	tmpf_destroy(&mtd);
39 }
40 
41 char *get_dev_mtd(void)
42 {
43 	int rc;
44 
45 	rc = tmpf_init(&mtd, "flash-store.XXXXXX");
46 	if (rc < 0)
47 		return NULL;
48 
49 	return strdup(mtd.path);
50 }
51 
52 struct erase_info_user *recorded;
53 int n_ioctls;
54 
55 #define MEM_SIZE 3
56 #define ERASE_SIZE 1
57 
58 int ioctl(int fd, unsigned long request, ...)
59 {
60 	va_list ap;
61 	struct erase_info_user *provided, *alloced;
62 
63 	if (!(request == MEMERASE || request == MEMGETINFO)) {
64 		printf("Uh-oh: ioctl() called with request 0x%08lx\n", request);
65 		return -1;
66 	}
67 
68 	switch (request) {
69 	case MEMGETINFO:
70 	{
71 		struct mtd_info_user *info;
72 
73 		va_start(ap, request);
74 		info = va_arg(ap, struct mtd_info_user *);
75 		info->size = MEM_SIZE;
76 		info->erasesize = ERASE_SIZE;
77 		va_end(ap);
78 		break;
79 	}
80 	case MEMERASE:
81 		va_start(ap, request);
82 		provided = va_arg(ap, struct erase_info_user *);
83 
84 		n_ioctls++;
85 
86 		alloced = realloc(recorded, n_ioctls * sizeof(*recorded));
87 		if (!alloced)
88 			return -1;
89 		recorded = alloced;
90 
91 		memcpy(&recorded[n_ioctls - 1], provided, sizeof(*provided));
92 
93 		va_end(ap);
94 		break;
95 	default:
96 		break;
97 	}
98 
99 	return 0;
100 }
101 
102 void dump_ioctls(void)
103 {
104 	int i;
105 
106 	printf("n_ioctls: %d\n", n_ioctls);
107 
108 	for (i = 0; i < n_ioctls; i++)
109 		printf("%d: start: %d, length %d\n",
110 				i, recorded[i].start, recorded[i].length);
111 }
112 
113 int main(void)
114 {
115 	struct mbox_context context;
116 	char data[MEM_SIZE];
117 	int rc;
118 
119 	rc = atexit(cleanup_mtd);
120 	if (rc)
121 		return rc;
122 
123 	mbox_vlog = &mbox_log_console;
124 
125 	n_ioctls = 0;
126 	recorded = NULL;
127 
128 	init_flash_dev(&context);
129 
130 	/* Erase from an unknown state */
131 	rc = erase_flash(&context, 0, sizeof(data));
132 
133 	assert(rc == 0);
134 	assert(n_ioctls == 1);
135 	assert(recorded[0].start == 0);
136 	assert(recorded[0].length == sizeof(data));
137 
138 	free(recorded);
139 	recorded = NULL;
140 	n_ioctls = 0;
141 
142 	/* Erase an erased flash */
143 	rc = erase_flash(&context, 0, sizeof(data));
144 
145 	assert(rc == 0);
146 	assert(n_ioctls == 0);
147 
148 	memset(data, 0xaa, sizeof(data));
149 
150 	/* Erase written flash */
151 	rc = write_flash(&context, 0, data, sizeof(data));
152 	assert(rc == 0);
153 	rc = erase_flash(&context, 0, sizeof(data));
154 
155 	assert(rc == 0);
156 	assert(n_ioctls == 1);
157 	assert(recorded[0].start == 0);
158 	assert(recorded[0].length == sizeof(data));
159 
160 	free(recorded);
161 	recorded = NULL;
162 	n_ioctls = 0;
163 
164 	/* Erase the start of flash */
165 	rc = write_flash(&context, 0, data, sizeof(data) - 1);
166 	assert(rc == 0);
167 	rc = erase_flash(&context, 0, sizeof(data));
168 
169 	assert(rc == 0);
170 	assert(n_ioctls == 1);
171 	assert(recorded[0].start == 0);
172 	assert(recorded[0].length == sizeof(data) - 1);
173 
174 	free(recorded);
175 	recorded = NULL;
176 	n_ioctls = 0;
177 
178 	/* Erase the end of flash */
179 	rc = write_flash(&context, 1, data, sizeof(data) - 1);
180 	assert(rc == 0);
181 	rc = erase_flash(&context, 0, sizeof(data));
182 
183 	assert(rc == 0);
184 	assert(n_ioctls == 1);
185 	assert(recorded[0].start == 1);
186 	assert(recorded[0].length == sizeof(data) - 1);
187 
188 	free(recorded);
189 	recorded = NULL;
190 	n_ioctls = 0;
191 
192 	/* Erase each end of flash */
193 	rc = write_flash(&context, 0, data, 1);
194 	rc = write_flash(&context, 2, data, 1);
195 	assert(rc == 0);
196 	rc = erase_flash(&context, 0, sizeof(data));
197 
198 	assert(rc == 0);
199 	assert(n_ioctls == 2);
200 	assert(recorded[0].start == 0);
201 	assert(recorded[0].length == 1);
202 	assert(recorded[1].start == 2);
203 	assert(recorded[1].length == 1);
204 
205 	free(recorded);
206 	recorded = NULL;
207 	n_ioctls = 0;
208 
209 	/* Erase the middle of flash */
210 	rc = write_flash(&context, 1, data, 1);
211 	assert(rc == 0);
212 	rc = erase_flash(&context, 0, sizeof(data));
213 
214 	assert(rc == 0);
215 	assert(n_ioctls == 1);
216 	assert(recorded[0].start == 1);
217 	assert(recorded[0].length == 1);
218 
219 	free(recorded);
220 	recorded = NULL;
221 	n_ioctls = 0;
222 
223 	free_flash_dev(&context);
224 
225 	return rc;
226 }
227