xref: /openbmc/phosphor-mboxd/test/erase_flash.c (revision faeb88c0)
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, "flashXXXXXX");
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 	n_ioctls = 0;
124 	recorded = NULL;
125 
126 	init_flash_dev(&context);
127 
128 	/* Erase from an unknown state */
129 	rc = erase_flash(&context, 0, sizeof(data));
130 
131 	assert(rc == 0);
132 	assert(n_ioctls == 1);
133 	assert(recorded[0].start == 0);
134 	assert(recorded[0].length == sizeof(data));
135 
136 	free(recorded);
137 	recorded = NULL;
138 	n_ioctls = 0;
139 
140 	/* Erase an erased flash */
141 	rc = erase_flash(&context, 0, sizeof(data));
142 
143 	assert(rc == 0);
144 	assert(n_ioctls == 0);
145 
146 	memset(data, 0xaa, sizeof(data));
147 
148 	/* Erase written flash */
149 	rc = write_flash(&context, 0, data, sizeof(data));
150 	assert(rc == 0);
151 	rc = erase_flash(&context, 0, sizeof(data));
152 
153 	assert(rc == 0);
154 	assert(n_ioctls == 1);
155 	assert(recorded[0].start == 0);
156 	assert(recorded[0].length == sizeof(data));
157 
158 	free(recorded);
159 	recorded = NULL;
160 	n_ioctls = 0;
161 
162 	/* Erase the start of flash */
163 	rc = write_flash(&context, 0, data, sizeof(data) - 1);
164 	assert(rc == 0);
165 	rc = erase_flash(&context, 0, sizeof(data));
166 
167 	assert(rc == 0);
168 	assert(n_ioctls == 1);
169 	assert(recorded[0].start == 0);
170 	assert(recorded[0].length == sizeof(data) - 1);
171 
172 	free(recorded);
173 	recorded = NULL;
174 	n_ioctls = 0;
175 
176 	/* Erase the end of flash */
177 	rc = write_flash(&context, 1, data, sizeof(data) - 1);
178 	assert(rc == 0);
179 	rc = erase_flash(&context, 0, sizeof(data));
180 
181 	assert(rc == 0);
182 	assert(n_ioctls == 1);
183 	assert(recorded[0].start == 1);
184 	assert(recorded[0].length == sizeof(data) - 1);
185 
186 	free(recorded);
187 	recorded = NULL;
188 	n_ioctls = 0;
189 
190 	/* Erase each end of flash */
191 	rc = write_flash(&context, 0, data, 1);
192 	rc = write_flash(&context, 2, data, 1);
193 	assert(rc == 0);
194 	rc = erase_flash(&context, 0, sizeof(data));
195 
196 	assert(rc == 0);
197 	assert(n_ioctls == 2);
198 	assert(recorded[0].start == 0);
199 	assert(recorded[0].length == 1);
200 	assert(recorded[1].start == 2);
201 	assert(recorded[1].length == 1);
202 
203 	free(recorded);
204 	recorded = NULL;
205 	n_ioctls = 0;
206 
207 	/* Erase the middle of flash */
208 	rc = write_flash(&context, 1, data, 1);
209 	assert(rc == 0);
210 	rc = erase_flash(&context, 0, sizeof(data));
211 
212 	assert(rc == 0);
213 	assert(n_ioctls == 1);
214 	assert(recorded[0].start == 1);
215 	assert(recorded[0].length == 1);
216 
217 	free(recorded);
218 	recorded = NULL;
219 	n_ioctls = 0;
220 
221 	free_flash_dev(&context);
222 
223 	return rc;
224 }
225