1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright (C) 2018 IBM Corp.
3
4 #include <assert.h>
5 #include <stdarg.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/ioctl.h>
10 #include <unistd.h>
11
12 #include <linux/types.h>
13
14 #include "common.h"
15 #include "mboxd.h"
16 #include "backend.h"
17
18 #include "test/tmpf.h"
19
20 static struct tmpf mtd;
21
cleanup_mtd(void)22 void cleanup_mtd(void)
23 {
24 tmpf_destroy(&mtd);
25 }
26
get_dev_mtd(void)27 char *get_dev_mtd(void)
28 {
29 int rc;
30
31 rc = tmpf_init(&mtd, "flash-store.XXXXXX");
32 if (rc < 0)
33 return NULL;
34
35 return mtd.path;
36 }
37
38 struct erase_info_user *recorded;
39 int n_ioctls;
40
41 #define MEM_SIZE 3
42 #define ERASE_SIZE 1
43
ioctl(int fd,unsigned long request,...)44 int ioctl(int fd __attribute__((unused)), unsigned long request, ...)
45 {
46 va_list ap;
47 struct erase_info_user *provided, *alloced;
48
49 if (!(request == MEMERASE || request == MEMGETINFO)) {
50 printf("Uh-oh: ioctl() called with request 0x%08lx\n", request);
51 return -1;
52 }
53
54 switch (request) {
55 case MEMGETINFO:
56 {
57 struct mtd_info_user *info;
58
59 va_start(ap, request);
60 info = va_arg(ap, struct mtd_info_user *);
61 info->size = MEM_SIZE;
62 info->erasesize = ERASE_SIZE;
63 va_end(ap);
64 break;
65 }
66 case MEMERASE:
67 va_start(ap, request);
68 provided = va_arg(ap, struct erase_info_user *);
69
70 n_ioctls++;
71
72 alloced = realloc(recorded, n_ioctls * sizeof(*recorded));
73 if (!alloced)
74 return -1;
75 recorded = alloced;
76
77 memcpy(&recorded[n_ioctls - 1], provided, sizeof(*provided));
78
79 va_end(ap);
80 break;
81 default:
82 break;
83 }
84
85 return 0;
86 }
87
dump_ioctls(void)88 void dump_ioctls(void)
89 {
90 int i;
91
92 printf("n_ioctls: %d\n", n_ioctls);
93
94 for (i = 0; i < n_ioctls; i++)
95 printf("%d: start: %d, length %d\n",
96 i, recorded[i].start, recorded[i].length);
97 }
98
main(void)99 int main(void)
100 {
101 struct mbox_context context = {0};
102 struct backend *backend;
103 char data[MEM_SIZE];
104 int rc;
105
106 backend = &context.backend;
107
108 rc = atexit(cleanup_mtd);
109 if (rc)
110 return rc;
111
112 mbox_vlog = &mbox_log_console;
113
114 n_ioctls = 0;
115 recorded = NULL;
116
117 assert(!backend_probe_mtd(backend, get_dev_mtd()));
118
119 /* Erase from an unknown state */
120 rc = backend_erase(backend, 0, sizeof(data));
121
122 assert(rc == 0);
123 assert(n_ioctls == 1);
124 assert(recorded[0].start == 0);
125 assert(recorded[0].length == sizeof(data));
126
127 free(recorded);
128 recorded = NULL;
129 n_ioctls = 0;
130
131 /* Erase an erased flash */
132 rc = backend_erase(backend, 0, sizeof(data));
133
134 assert(rc == 0);
135 assert(n_ioctls == 0);
136
137 memset(data, 0xaa, sizeof(data));
138
139 /* Erase written flash */
140 rc = backend_write(backend, 0, data, sizeof(data));
141 assert(rc == 0);
142 rc = backend_erase(backend, 0, sizeof(data));
143
144 assert(rc == 0);
145 assert(n_ioctls == 1);
146 assert(recorded[0].start == 0);
147 assert(recorded[0].length == sizeof(data));
148
149 free(recorded);
150 recorded = NULL;
151 n_ioctls = 0;
152
153 /* Erase the start of flash */
154 rc = backend_write(backend, 0, data, sizeof(data) - 1);
155 assert(rc == 0);
156 rc = backend_erase(backend, 0, sizeof(data));
157
158 assert(rc == 0);
159 assert(n_ioctls == 1);
160 assert(recorded[0].start == 0);
161 assert(recorded[0].length == sizeof(data) - 1);
162
163 free(recorded);
164 recorded = NULL;
165 n_ioctls = 0;
166
167 /* Erase the end of flash */
168 rc = backend_write(backend, 1, data, sizeof(data) - 1);
169 assert(rc == 0);
170 rc = backend_erase(backend, 0, sizeof(data));
171
172 assert(rc == 0);
173 assert(n_ioctls == 1);
174 assert(recorded[0].start == 1);
175 assert(recorded[0].length == sizeof(data) - 1);
176
177 free(recorded);
178 recorded = NULL;
179 n_ioctls = 0;
180
181 /* Erase each end of flash */
182 rc = backend_write(backend, 0, data, 1);
183 rc = backend_write(backend, 2, data, 1);
184 assert(rc == 0);
185 rc = backend_erase(backend, 0, sizeof(data));
186
187 assert(rc == 0);
188 assert(n_ioctls == 2);
189 assert(recorded[0].start == 0);
190 assert(recorded[0].length == 1);
191 assert(recorded[1].start == 2);
192 assert(recorded[1].length == 1);
193
194 free(recorded);
195 recorded = NULL;
196 n_ioctls = 0;
197
198 /* Erase the middle of flash */
199 rc = backend_write(backend, 1, data, 1);
200 assert(rc == 0);
201 rc = backend_erase(backend, 0, sizeof(data));
202
203 assert(rc == 0);
204 assert(n_ioctls == 1);
205 assert(recorded[0].start == 1);
206 assert(recorded[0].length == 1);
207
208 free(recorded);
209 recorded = NULL;
210 n_ioctls = 0;
211
212 backend_free(backend);
213
214 return rc;
215 }
216