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