drm/panel: panel-himax-hx83102: support for csot-pna957qt1-1 MIPI-DSI panel
[drm/drm-misc.git] / tools / testing / selftests / powerpc / papr_vpd / papr_vpd.c
blobd6f99eb9be659d3c9bb60b922e4f81102ac7f918
1 // SPDX-License-Identifier: GPL-2.0-only
2 #define _GNU_SOURCE
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/ioctl.h>
8 #include <unistd.h>
10 #include <asm/papr-vpd.h>
12 #include "utils.h"
14 #define DEVPATH "/dev/papr-vpd"
16 static int dev_papr_vpd_open_close(void)
18 const int devfd = open(DEVPATH, O_RDONLY);
20 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
21 DEVPATH " not present");
23 FAIL_IF(devfd < 0);
24 FAIL_IF(close(devfd) != 0);
26 return 0;
29 static int dev_papr_vpd_get_handle_all(void)
31 const int devfd = open(DEVPATH, O_RDONLY);
32 struct papr_location_code lc = { .str = "", };
33 off_t size;
34 int fd;
36 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
37 DEVPATH " not present");
39 FAIL_IF(devfd < 0);
41 errno = 0;
42 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
43 FAIL_IF(errno != 0);
44 FAIL_IF(fd < 0);
46 FAIL_IF(close(devfd) != 0);
48 size = lseek(fd, 0, SEEK_END);
49 FAIL_IF(size <= 0);
51 void *buf = malloc((size_t)size);
52 FAIL_IF(!buf);
54 ssize_t consumed = pread(fd, buf, size, 0);
55 FAIL_IF(consumed != size);
57 /* Ensure EOF */
58 FAIL_IF(read(fd, buf, size) != 0);
59 FAIL_IF(close(fd));
61 /* Verify that the buffer looks like VPD */
62 static const char needle[] = "System VPD";
63 FAIL_IF(!memmem(buf, size, needle, strlen(needle)));
65 return 0;
68 static int dev_papr_vpd_get_handle_byte_at_a_time(void)
70 const int devfd = open(DEVPATH, O_RDONLY);
71 struct papr_location_code lc = { .str = "", };
72 int fd;
74 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
75 DEVPATH " not present");
77 FAIL_IF(devfd < 0);
79 errno = 0;
80 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
81 FAIL_IF(errno != 0);
82 FAIL_IF(fd < 0);
84 FAIL_IF(close(devfd) != 0);
86 size_t consumed = 0;
87 while (1) {
88 ssize_t res;
89 char c;
91 errno = 0;
92 res = read(fd, &c, sizeof(c));
93 FAIL_IF(res > sizeof(c));
94 FAIL_IF(res < 0);
95 FAIL_IF(errno != 0);
96 consumed += res;
97 if (res == 0)
98 break;
101 FAIL_IF(consumed != lseek(fd, 0, SEEK_END));
103 FAIL_IF(close(fd));
105 return 0;
109 static int dev_papr_vpd_unterm_loc_code(void)
111 const int devfd = open(DEVPATH, O_RDONLY);
112 struct papr_location_code lc = {};
113 int fd;
115 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
116 DEVPATH " not present");
118 FAIL_IF(devfd < 0);
121 * Place a non-null byte in every element of loc_code; the
122 * driver should reject this input.
124 memset(lc.str, 'x', ARRAY_SIZE(lc.str));
126 errno = 0;
127 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
128 FAIL_IF(fd != -1);
129 FAIL_IF(errno != EINVAL);
131 FAIL_IF(close(devfd) != 0);
132 return 0;
135 static int dev_papr_vpd_null_handle(void)
137 const int devfd = open(DEVPATH, O_RDONLY);
138 int rc;
140 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
141 DEVPATH " not present");
143 FAIL_IF(devfd < 0);
145 errno = 0;
146 rc = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, NULL);
147 FAIL_IF(rc != -1);
148 FAIL_IF(errno != EFAULT);
150 FAIL_IF(close(devfd) != 0);
151 return 0;
154 static int papr_vpd_close_handle_without_reading(void)
156 const int devfd = open(DEVPATH, O_RDONLY);
157 struct papr_location_code lc = { .str = "", };
158 int fd;
160 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
161 DEVPATH " not present");
163 FAIL_IF(devfd < 0);
165 errno = 0;
166 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
167 FAIL_IF(errno != 0);
168 FAIL_IF(fd < 0);
170 /* close the handle without reading it */
171 FAIL_IF(close(fd) != 0);
173 FAIL_IF(close(devfd) != 0);
174 return 0;
177 static int papr_vpd_reread(void)
179 const int devfd = open(DEVPATH, O_RDONLY);
180 struct papr_location_code lc = { .str = "", };
181 int fd;
183 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
184 DEVPATH " not present");
186 FAIL_IF(devfd < 0);
188 errno = 0;
189 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
190 FAIL_IF(errno != 0);
191 FAIL_IF(fd < 0);
193 FAIL_IF(close(devfd) != 0);
195 const off_t size = lseek(fd, 0, SEEK_END);
196 FAIL_IF(size <= 0);
198 char *bufs[2];
200 for (size_t i = 0; i < ARRAY_SIZE(bufs); ++i) {
201 bufs[i] = malloc(size);
202 FAIL_IF(!bufs[i]);
203 ssize_t consumed = pread(fd, bufs[i], size, 0);
204 FAIL_IF(consumed != size);
207 FAIL_IF(memcmp(bufs[0], bufs[1], size));
209 FAIL_IF(close(fd) != 0);
211 return 0;
214 static int get_system_loc_code(struct papr_location_code *lc)
216 static const char system_id_path[] = "/sys/firmware/devicetree/base/system-id";
217 static const char model_path[] = "/sys/firmware/devicetree/base/model";
218 char *system_id;
219 char *model;
220 int err = -1;
222 if (read_file_alloc(model_path, &model, NULL))
223 return err;
225 if (read_file_alloc(system_id_path, &system_id, NULL))
226 goto free_model;
228 char *mtm;
229 int sscanf_ret = sscanf(model, "IBM,%ms", &mtm);
230 if (sscanf_ret != 1)
231 goto free_system_id;
233 char *plant_and_seq;
234 if (sscanf(system_id, "IBM,%*c%*c%ms", &plant_and_seq) != 1)
235 goto free_mtm;
237 * Replace - with . to build location code.
239 char *sep = strchr(mtm, '-');
240 if (!sep)
241 goto free_mtm;
242 else
243 *sep = '.';
245 snprintf(lc->str, sizeof(lc->str),
246 "U%s.%s", mtm, plant_and_seq);
247 err = 0;
249 free(plant_and_seq);
250 free_mtm:
251 free(mtm);
252 free_system_id:
253 free(system_id);
254 free_model:
255 free(model);
256 return err;
259 static int papr_vpd_system_loc_code(void)
261 struct papr_location_code lc;
262 const int devfd = open(DEVPATH, O_RDONLY);
263 off_t size;
264 int fd;
266 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
267 DEVPATH " not present");
268 SKIP_IF_MSG(get_system_loc_code(&lc),
269 "Cannot determine system location code");
271 FAIL_IF(devfd < 0);
273 errno = 0;
274 fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc);
275 FAIL_IF(errno != 0);
276 FAIL_IF(fd < 0);
278 FAIL_IF(close(devfd) != 0);
280 size = lseek(fd, 0, SEEK_END);
281 FAIL_IF(size <= 0);
283 void *buf = malloc((size_t)size);
284 FAIL_IF(!buf);
286 ssize_t consumed = pread(fd, buf, size, 0);
287 FAIL_IF(consumed != size);
289 /* Ensure EOF */
290 FAIL_IF(read(fd, buf, size) != 0);
291 FAIL_IF(close(fd));
293 /* Verify that the buffer looks like VPD */
294 static const char needle[] = "System VPD";
295 FAIL_IF(!memmem(buf, size, needle, strlen(needle)));
297 return 0;
300 struct vpd_test {
301 int (*function)(void);
302 const char *description;
305 static const struct vpd_test vpd_tests[] = {
307 .function = dev_papr_vpd_open_close,
308 .description = "open/close " DEVPATH,
311 .function = dev_papr_vpd_unterm_loc_code,
312 .description = "ensure EINVAL on unterminated location code",
315 .function = dev_papr_vpd_null_handle,
316 .description = "ensure EFAULT on bad handle addr",
319 .function = dev_papr_vpd_get_handle_all,
320 .description = "get handle for all VPD"
323 .function = papr_vpd_close_handle_without_reading,
324 .description = "close handle without consuming VPD"
327 .function = dev_papr_vpd_get_handle_byte_at_a_time,
328 .description = "read all VPD one byte at a time"
331 .function = papr_vpd_reread,
332 .description = "ensure re-read yields same results"
335 .function = papr_vpd_system_loc_code,
336 .description = "get handle for system VPD"
340 int main(void)
342 size_t fails = 0;
344 for (size_t i = 0; i < ARRAY_SIZE(vpd_tests); ++i) {
345 const struct vpd_test *t = &vpd_tests[i];
347 if (test_harness(t->function, t->description))
348 ++fails;
351 return fails == 0 ? EXIT_SUCCESS : EXIT_FAILURE;