xref: /openbmc/phosphor-mboxd/test/erase_flash.c (revision 30bcf84c932a579532e5f8417af549494e11b6e9)
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  
20  void cleanup_mtd(void)
21  {
22  	tmpf_destroy(&mtd);
23  }
24  
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  
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  
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  
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