1 /*
2 * Copyright (c) 2012 Mike Frysinger <vapier@gentoo.org>
3 * Copyright (c) 2012-2021 The strace developers.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #include "defs.h"
9
10 #include <linux/ioctl.h>
11 #include <mtd/ubi-user.h>
12
13 #include "xlat/ubi_volume_types.h"
14 #include "xlat/ubi_volume_flags.h"
15 #include "xlat/ubi_volume_props.h"
16 #include "xlat/ubi_data_types.h"
17
18 static int
19 decode_UBI_IOCMKVOL(struct tcb *const tcp, const kernel_ulong_t arg)
20 {
21 struct ubi_mkvol_req mkvol;
22
23 if (entering(tcp)) {
24 tprint_arg_next();
25 if (umove_or_printaddr(tcp, arg, &mkvol))
26 return RVAL_IOCTL_DECODED;
27
28 tprint_struct_begin();
29 PRINT_FIELD_D(mkvol, vol_id);
30 tprint_struct_next();
31 PRINT_FIELD_D(mkvol, alignment);
32 tprint_struct_next();
33 PRINT_FIELD_D(mkvol, bytes);
34 tprint_struct_next();
35 PRINT_FIELD_XVAL(mkvol, vol_type,
36 ubi_volume_types, "UBI_???_VOLUME");
37 tprint_struct_next();
38 PRINT_FIELD_FLAGS(mkvol, flags,
39 ubi_volume_flags, "UBI_VOL_???");
40 tprint_struct_next();
41 PRINT_FIELD_D(mkvol, name_len);
42 tprint_struct_next();
43 PRINT_FIELD_CSTRING_SZ(mkvol, name,
44 1 + CLAMP(mkvol.name_len, 0,
45 (int) sizeof(mkvol.name) - 1));
46 tprint_struct_end();
47 return 0;
48 }
49
50 if (!syserror(tcp)) {
51 tprint_value_changed();
52 printnum_int(tcp, arg, "%d");
53 }
54
55 return RVAL_IOCTL_DECODED;
56 }
57
58 static int
59 decode_UBI_IOCRSVOL(struct tcb *const tcp, const kernel_ulong_t arg)
60 {
61 struct ubi_rsvol_req rsvol;
62
63 tprint_arg_next();
64 if (!umove_or_printaddr(tcp, arg, &rsvol)) {
65 tprint_struct_begin();
66 PRINT_FIELD_D(rsvol, bytes);
67 tprint_struct_next();
68 PRINT_FIELD_D(rsvol, vol_id);
69 tprint_struct_end();
70 }
71
72 return RVAL_IOCTL_DECODED;
73 }
74
75 static bool
76 print_ubi_rnvol_req_ent_array_member(struct tcb *tcp, void *elem_buf,
77 size_t elem_size, void *data)
78 {
79 typeof(&((struct ubi_rnvol_req *) NULL)->ents[0]) p = elem_buf;
80
81 tprint_struct_begin();
82 PRINT_FIELD_D(*p, vol_id);
83 tprint_struct_next();
84 PRINT_FIELD_D(*p, name_len);
85 tprint_struct_next();
86 PRINT_FIELD_CSTRING_SZ(*p, name,
87 1 + CLAMP(p->name_len, 0,
88 (int) sizeof(p->name) - 1));
89 tprint_struct_end();
90
91 return true;
92 }
93
94 static int
95 decode_UBI_IOCRNVOL(struct tcb *const tcp, const kernel_ulong_t arg)
96 {
97 struct ubi_rnvol_req rnvol;
98
99 tprint_arg_next();
100 if (!umove_or_printaddr(tcp, arg, &rnvol)) {
101 tprint_struct_begin();
102 PRINT_FIELD_D(rnvol, count);
103 tprint_struct_next();
104 PRINT_FIELD_ARRAY_UPTO(rnvol, ents, rnvol.count, tcp,
105 print_ubi_rnvol_req_ent_array_member);
106 tprint_struct_end();
107 }
108
109 return RVAL_IOCTL_DECODED;
110 }
111
112 static int
113 decode_UBI_IOCEBCH(struct tcb *const tcp, const kernel_ulong_t arg)
114 {
115 struct ubi_leb_change_req leb;
116
117 tprint_arg_next();
118 if (!umove_or_printaddr(tcp, arg, &leb)) {
119 tprint_struct_begin();
120 PRINT_FIELD_D(leb, lnum);
121 tprint_struct_next();
122 PRINT_FIELD_D(leb, bytes);
123 tprint_struct_next();
124 PRINT_FIELD_XVAL(leb, dtype, ubi_data_types, "UBI_???");
125 tprint_struct_end();
126 }
127
128 return RVAL_IOCTL_DECODED;
129 }
130
131 static int
132 decode_UBI_IOCATT(struct tcb *const tcp, const kernel_ulong_t arg)
133 {
134 if (entering(tcp)) {
135 struct ubi_attach_req attach;
136
137 tprint_arg_next();
138 if (umove_or_printaddr(tcp, arg, &attach))
139 return RVAL_IOCTL_DECODED;
140
141 tprint_struct_begin();
142 PRINT_FIELD_D(attach, ubi_num);
143 tprint_struct_next();
144 PRINT_FIELD_D(attach, mtd_num);
145 tprint_struct_next();
146 PRINT_FIELD_D(attach, vid_hdr_offset);
147 tprint_struct_next();
148 PRINT_FIELD_D(attach, max_beb_per1024);
149 tprint_struct_end();
150 return 0;
151 }
152
153 if (!syserror(tcp)) {
154 tprint_value_changed();
155 printnum_int(tcp, arg, "%d");
156 }
157
158 return RVAL_IOCTL_DECODED;
159 }
160
161 static int
162 decode_UBI_IOCEBMAP(struct tcb *const tcp, const kernel_ulong_t arg)
163 {
164 struct ubi_map_req map;
165
166 tprint_arg_next();
167 if (!umove_or_printaddr(tcp, arg, &map)) {
168 tprint_struct_begin();
169 PRINT_FIELD_D(map, lnum);
170 tprint_struct_next();
171 PRINT_FIELD_XVAL(map, dtype, ubi_data_types, "UBI_???");
172 tprint_struct_end();
173 }
174
175 return RVAL_IOCTL_DECODED;
176 }
177
178 static int
179 decode_UBI_IOCSETVOLPROP(struct tcb *const tcp, const kernel_ulong_t arg)
180 {
181 struct ubi_set_vol_prop_req prop;
182
183 tprint_arg_next();
184 if (!umove_or_printaddr(tcp, arg, &prop)) {
185 tprint_struct_begin();
186 PRINT_FIELD_XVAL(prop, property,
187 ubi_volume_props, "UBI_VOL_PROP_???");
188 tprint_struct_next();
189 PRINT_FIELD_X(prop, value);
190 tprint_struct_end();
191 }
192
193 return RVAL_IOCTL_DECODED;
194 }
195
196 int
197 ubi_ioctl(struct tcb *const tcp, const unsigned int code,
198 const kernel_ulong_t arg)
199 {
200 switch (code) {
201 #define case_UBI(name) case UBI_ ## name: return decode_UBI_ ## name(tcp, arg)
202 case_UBI(IOCATT);
203 case_UBI(IOCEBCH);
204 case_UBI(IOCEBMAP);
205 case_UBI(IOCMKVOL);
206 case_UBI(IOCRNVOL);
207 case_UBI(IOCRSVOL);
208 case_UBI(IOCSETVOLPROP);
209 #undef case_UBI
210
211 case UBI_IOCVOLUP:
212 tprint_arg_next();
213 printnum_int64(tcp, arg, "%" PRIi64);
214 break;
215
216 case UBI_IOCDET:
217 case UBI_IOCEBER:
218 case UBI_IOCEBISMAP:
219 case UBI_IOCEBUNMAP:
220 case UBI_IOCRMVOL:
221 case UBI_IOCRPEB:
222 case UBI_IOCSPEB:
223 tprint_arg_next();
224 printnum_int(tcp, arg, "%d");
225 break;
226
227 case UBI_IOCVOLCRBLK:
228 case UBI_IOCVOLRMBLK:
229 /* no arguments */
230 break;
231
232 default:
233 return RVAL_DECODED;
234 }
235
236 return RVAL_IOCTL_DECODED;
237 }