]> Git Repo - J-linux.git/blob - drivers/media/v4l2-core/v4l2-compat-ioctl32.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / media / v4l2-core / v4l2-compat-ioctl32.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4  *      Separated from fs stuff by Arnd Bergmann <[email protected]>
5  *
6  * Copyright (C) 1997-2000  Jakub Jelinek  ([email protected])
7  * Copyright (C) 1998  Eddie C. Dost  ([email protected])
8  * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
9  * Copyright (C) 2003       Pavel Machek ([email protected])
10  * Copyright (C) 2005       Philippe De Muyter ([email protected])
11  * Copyright (C) 2008       Hans Verkuil <[email protected]>
12  *
13  * These routines maintain argument size conversion between 32bit and 64bit
14  * ioctls.
15  */
16
17 #include <linux/compat.h>
18 #include <linux/module.h>
19 #include <linux/videodev2.h>
20 #include <linux/v4l2-subdev.h>
21 #include <media/v4l2-dev.h>
22 #include <media/v4l2-fh.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-ioctl.h>
25
26 /*
27  * Per-ioctl data copy handlers.
28  *
29  * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
30  * where "v4l2_foo" is the name of the V4L2 struct.
31  *
32  * They basically get two __user pointers, one with a 32-bits struct that
33  * came from the userspace call and a 64-bits struct, also allocated as
34  * userspace, but filled internally by do_video_ioctl().
35  *
36  * For ioctls that have pointers inside it, the functions will also
37  * receive an ancillary buffer with extra space, used to pass extra
38  * data to the routine.
39  */
40
41 struct v4l2_window32 {
42         struct v4l2_rect        w;
43         __u32                   field;  /* enum v4l2_field */
44         __u32                   chromakey;
45         compat_caddr_t          clips; /* always NULL */
46         __u32                   clipcount; /* always 0 */
47         compat_caddr_t          bitmap; /* always NULL */
48         __u8                    global_alpha;
49 };
50
51 static int get_v4l2_window32(struct v4l2_window *p64,
52                              struct v4l2_window32 __user *p32)
53 {
54         struct v4l2_window32 w32;
55
56         if (copy_from_user(&w32, p32, sizeof(w32)))
57                 return -EFAULT;
58
59         *p64 = (struct v4l2_window) {
60                 .w              = w32.w,
61                 .field          = w32.field,
62                 .chromakey      = w32.chromakey,
63                 .clips          = NULL,
64                 .clipcount      = 0,
65                 .bitmap         = NULL,
66                 .global_alpha   = w32.global_alpha,
67         };
68
69         return 0;
70 }
71
72 static int put_v4l2_window32(struct v4l2_window *p64,
73                              struct v4l2_window32 __user *p32)
74 {
75         struct v4l2_window32 w32;
76
77         memset(&w32, 0, sizeof(w32));
78         w32 = (struct v4l2_window32) {
79                 .w              = p64->w,
80                 .field          = p64->field,
81                 .chromakey      = p64->chromakey,
82                 .clips          = 0,
83                 .clipcount      = 0,
84                 .bitmap         = 0,
85                 .global_alpha   = p64->global_alpha,
86         };
87
88         if (copy_to_user(p32, &w32, sizeof(w32)))
89                 return -EFAULT;
90
91         return 0;
92 }
93
94 struct v4l2_format32 {
95         __u32   type;   /* enum v4l2_buf_type */
96         union {
97                 struct v4l2_pix_format  pix;
98                 struct v4l2_pix_format_mplane   pix_mp;
99                 struct v4l2_window32    win;
100                 struct v4l2_vbi_format  vbi;
101                 struct v4l2_sliced_vbi_format   sliced;
102                 struct v4l2_sdr_format  sdr;
103                 struct v4l2_meta_format meta;
104                 __u8    raw_data[200];        /* user-defined */
105         } fmt;
106 };
107
108 /**
109  * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
110  * @index:      on return, index of the first created buffer
111  * @count:      entry: number of requested buffers,
112  *              return: number of created buffers
113  * @memory:     buffer memory type
114  * @format:     frame format, for which buffers are requested
115  * @capabilities: capabilities of this buffer type.
116  * @flags:      additional buffer management attributes (ignored unless the
117  *              queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
118  *              configured for MMAP streaming I/O).
119  * @max_num_buffers: if V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set
120  *              this field indicate the maximum possible number of buffers
121  *              for this queue.
122  * @reserved:   future extensions
123  */
124 struct v4l2_create_buffers32 {
125         __u32                   index;
126         __u32                   count;
127         __u32                   memory; /* enum v4l2_memory */
128         struct v4l2_format32    format;
129         __u32                   capabilities;
130         __u32                   flags;
131         __u32                   max_num_buffers;
132         __u32                   reserved[5];
133 };
134
135 static int get_v4l2_format32(struct v4l2_format *p64,
136                              struct v4l2_format32 __user *p32)
137 {
138         if (get_user(p64->type, &p32->type))
139                 return -EFAULT;
140
141         switch (p64->type) {
142         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
143         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
144                 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
145                                       sizeof(p64->fmt.pix)) ? -EFAULT : 0;
146         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
147         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
148                 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
149                                       sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
150         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
151         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
152                 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
153         case V4L2_BUF_TYPE_VBI_CAPTURE:
154         case V4L2_BUF_TYPE_VBI_OUTPUT:
155                 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
156                                       sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
157         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
158         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
159                 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
160                                       sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
161         case V4L2_BUF_TYPE_SDR_CAPTURE:
162         case V4L2_BUF_TYPE_SDR_OUTPUT:
163                 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
164                                       sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
165         case V4L2_BUF_TYPE_META_CAPTURE:
166         case V4L2_BUF_TYPE_META_OUTPUT:
167                 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
168                                       sizeof(p64->fmt.meta)) ? -EFAULT : 0;
169         default:
170                 return -EINVAL;
171         }
172 }
173
174 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
175                              struct v4l2_create_buffers32 __user *p32)
176 {
177         if (copy_from_user(p64, p32,
178                            offsetof(struct v4l2_create_buffers32, format)))
179                 return -EFAULT;
180         if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
181                 return -EFAULT;
182         if (copy_from_user(&p64->max_num_buffers, &p32->max_num_buffers,
183                            sizeof(p32->max_num_buffers)))
184                 return -EFAULT;
185         return get_v4l2_format32(&p64->format, &p32->format);
186 }
187
188 static int put_v4l2_format32(struct v4l2_format *p64,
189                              struct v4l2_format32 __user *p32)
190 {
191         switch (p64->type) {
192         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
193         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
194                 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
195                                     sizeof(p64->fmt.pix)) ? -EFAULT : 0;
196         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
197         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
198                 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
199                                     sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
200         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
201         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
202                 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
203         case V4L2_BUF_TYPE_VBI_CAPTURE:
204         case V4L2_BUF_TYPE_VBI_OUTPUT:
205                 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
206                                     sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
207         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
208         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
209                 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
210                                     sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
211         case V4L2_BUF_TYPE_SDR_CAPTURE:
212         case V4L2_BUF_TYPE_SDR_OUTPUT:
213                 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
214                                     sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
215         case V4L2_BUF_TYPE_META_CAPTURE:
216         case V4L2_BUF_TYPE_META_OUTPUT:
217                 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
218                                     sizeof(p64->fmt.meta)) ? -EFAULT : 0;
219         default:
220                 return -EINVAL;
221         }
222 }
223
224 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
225                              struct v4l2_create_buffers32 __user *p32)
226 {
227         if (copy_to_user(p32, p64,
228                          offsetof(struct v4l2_create_buffers32, format)) ||
229             put_user(p64->capabilities, &p32->capabilities) ||
230             put_user(p64->flags, &p32->flags) ||
231             put_user(p64->max_num_buffers, &p32->max_num_buffers) ||
232             copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
233                 return -EFAULT;
234         return put_v4l2_format32(&p64->format, &p32->format);
235 }
236
237 struct v4l2_standard32 {
238         __u32                index;
239         compat_u64           id;
240         __u8                 name[24];
241         struct v4l2_fract    frameperiod; /* Frames, not fields */
242         __u32                framelines;
243         __u32                reserved[4];
244 };
245
246 static int get_v4l2_standard32(struct v4l2_standard *p64,
247                                struct v4l2_standard32 __user *p32)
248 {
249         /* other fields are not set by the user, nor used by the driver */
250         return get_user(p64->index, &p32->index);
251 }
252
253 static int put_v4l2_standard32(struct v4l2_standard *p64,
254                                struct v4l2_standard32 __user *p32)
255 {
256         if (put_user(p64->index, &p32->index) ||
257             put_user(p64->id, &p32->id) ||
258             copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
259             copy_to_user(&p32->frameperiod, &p64->frameperiod,
260                          sizeof(p32->frameperiod)) ||
261             put_user(p64->framelines, &p32->framelines) ||
262             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
263                 return -EFAULT;
264         return 0;
265 }
266
267 struct v4l2_plane32 {
268         __u32                   bytesused;
269         __u32                   length;
270         union {
271                 __u32           mem_offset;
272                 compat_long_t   userptr;
273                 __s32           fd;
274         } m;
275         __u32                   data_offset;
276         __u32                   reserved[11];
277 };
278
279 /*
280  * This is correct for all architectures including i386, but not x32,
281  * which has different alignment requirements for timestamp
282  */
283 struct v4l2_buffer32 {
284         __u32                   index;
285         __u32                   type;   /* enum v4l2_buf_type */
286         __u32                   bytesused;
287         __u32                   flags;
288         __u32                   field;  /* enum v4l2_field */
289         struct {
290                 compat_s64      tv_sec;
291                 compat_s64      tv_usec;
292         }                       timestamp;
293         struct v4l2_timecode    timecode;
294         __u32                   sequence;
295
296         /* memory location */
297         __u32                   memory; /* enum v4l2_memory */
298         union {
299                 __u32           offset;
300                 compat_long_t   userptr;
301                 compat_caddr_t  planes;
302                 __s32           fd;
303         } m;
304         __u32                   length;
305         __u32                   reserved2;
306         __s32                   request_fd;
307 };
308
309 #ifdef CONFIG_COMPAT_32BIT_TIME
310 struct v4l2_buffer32_time32 {
311         __u32                   index;
312         __u32                   type;   /* enum v4l2_buf_type */
313         __u32                   bytesused;
314         __u32                   flags;
315         __u32                   field;  /* enum v4l2_field */
316         struct old_timeval32    timestamp;
317         struct v4l2_timecode    timecode;
318         __u32                   sequence;
319
320         /* memory location */
321         __u32                   memory; /* enum v4l2_memory */
322         union {
323                 __u32           offset;
324                 compat_long_t   userptr;
325                 compat_caddr_t  planes;
326                 __s32           fd;
327         } m;
328         __u32                   length;
329         __u32                   reserved2;
330         __s32                   request_fd;
331 };
332 #endif
333
334 static int get_v4l2_plane32(struct v4l2_plane *p64,
335                             struct v4l2_plane32 __user *p32,
336                             enum v4l2_memory memory)
337 {
338         struct v4l2_plane32 plane32;
339         typeof(p64->m) m = {};
340
341         if (copy_from_user(&plane32, p32, sizeof(plane32)))
342                 return -EFAULT;
343
344         switch (memory) {
345         case V4L2_MEMORY_MMAP:
346         case V4L2_MEMORY_OVERLAY:
347                 m.mem_offset = plane32.m.mem_offset;
348                 break;
349         case V4L2_MEMORY_USERPTR:
350                 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
351                 break;
352         case V4L2_MEMORY_DMABUF:
353                 m.fd = plane32.m.fd;
354                 break;
355         }
356
357         memset(p64, 0, sizeof(*p64));
358         *p64 = (struct v4l2_plane) {
359                 .bytesused      = plane32.bytesused,
360                 .length         = plane32.length,
361                 .m              = m,
362                 .data_offset    = plane32.data_offset,
363         };
364
365         return 0;
366 }
367
368 static int put_v4l2_plane32(struct v4l2_plane *p64,
369                             struct v4l2_plane32 __user *p32,
370                             enum v4l2_memory memory)
371 {
372         struct v4l2_plane32 plane32;
373
374         memset(&plane32, 0, sizeof(plane32));
375         plane32 = (struct v4l2_plane32) {
376                 .bytesused      = p64->bytesused,
377                 .length         = p64->length,
378                 .data_offset    = p64->data_offset,
379         };
380
381         switch (memory) {
382         case V4L2_MEMORY_MMAP:
383         case V4L2_MEMORY_OVERLAY:
384                 plane32.m.mem_offset = p64->m.mem_offset;
385                 break;
386         case V4L2_MEMORY_USERPTR:
387                 plane32.m.userptr = (uintptr_t)(p64->m.userptr);
388                 break;
389         case V4L2_MEMORY_DMABUF:
390                 plane32.m.fd = p64->m.fd;
391                 break;
392         }
393
394         if (copy_to_user(p32, &plane32, sizeof(plane32)))
395                 return -EFAULT;
396
397         return 0;
398 }
399
400 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
401                              struct v4l2_buffer32 __user *arg)
402 {
403         struct v4l2_buffer32 vb32;
404
405         if (copy_from_user(&vb32, arg, sizeof(vb32)))
406                 return -EFAULT;
407
408         memset(vb, 0, sizeof(*vb));
409         *vb = (struct v4l2_buffer) {
410                 .index          = vb32.index,
411                 .type           = vb32.type,
412                 .bytesused      = vb32.bytesused,
413                 .flags          = vb32.flags,
414                 .field          = vb32.field,
415                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
416                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
417                 .timecode       = vb32.timecode,
418                 .sequence       = vb32.sequence,
419                 .memory         = vb32.memory,
420                 .m.offset       = vb32.m.offset,
421                 .length         = vb32.length,
422                 .request_fd     = vb32.request_fd,
423         };
424
425         switch (vb->memory) {
426         case V4L2_MEMORY_MMAP:
427         case V4L2_MEMORY_OVERLAY:
428                 vb->m.offset = vb32.m.offset;
429                 break;
430         case V4L2_MEMORY_USERPTR:
431                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
432                 break;
433         case V4L2_MEMORY_DMABUF:
434                 vb->m.fd = vb32.m.fd;
435                 break;
436         }
437
438         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
439                 vb->m.planes = (void __force *)
440                                 compat_ptr(vb32.m.planes);
441
442         return 0;
443 }
444
445 #ifdef CONFIG_COMPAT_32BIT_TIME
446 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
447                                     struct v4l2_buffer32_time32 __user *arg)
448 {
449         struct v4l2_buffer32_time32 vb32;
450
451         if (copy_from_user(&vb32, arg, sizeof(vb32)))
452                 return -EFAULT;
453
454         *vb = (struct v4l2_buffer) {
455                 .index          = vb32.index,
456                 .type           = vb32.type,
457                 .bytesused      = vb32.bytesused,
458                 .flags          = vb32.flags,
459                 .field          = vb32.field,
460                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
461                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
462                 .timecode       = vb32.timecode,
463                 .sequence       = vb32.sequence,
464                 .memory         = vb32.memory,
465                 .m.offset       = vb32.m.offset,
466                 .length         = vb32.length,
467                 .request_fd     = vb32.request_fd,
468         };
469         switch (vb->memory) {
470         case V4L2_MEMORY_MMAP:
471         case V4L2_MEMORY_OVERLAY:
472                 vb->m.offset = vb32.m.offset;
473                 break;
474         case V4L2_MEMORY_USERPTR:
475                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
476                 break;
477         case V4L2_MEMORY_DMABUF:
478                 vb->m.fd = vb32.m.fd;
479                 break;
480         }
481
482         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
483                 vb->m.planes = (void __force *)
484                                 compat_ptr(vb32.m.planes);
485
486         return 0;
487 }
488 #endif
489
490 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
491                              struct v4l2_buffer32 __user *arg)
492 {
493         struct v4l2_buffer32 vb32;
494
495         memset(&vb32, 0, sizeof(vb32));
496         vb32 = (struct v4l2_buffer32) {
497                 .index          = vb->index,
498                 .type           = vb->type,
499                 .bytesused      = vb->bytesused,
500                 .flags          = vb->flags,
501                 .field          = vb->field,
502                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
503                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
504                 .timecode       = vb->timecode,
505                 .sequence       = vb->sequence,
506                 .memory         = vb->memory,
507                 .m.offset       = vb->m.offset,
508                 .length         = vb->length,
509                 .request_fd     = vb->request_fd,
510         };
511
512         switch (vb->memory) {
513         case V4L2_MEMORY_MMAP:
514         case V4L2_MEMORY_OVERLAY:
515                 vb32.m.offset = vb->m.offset;
516                 break;
517         case V4L2_MEMORY_USERPTR:
518                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
519                 break;
520         case V4L2_MEMORY_DMABUF:
521                 vb32.m.fd = vb->m.fd;
522                 break;
523         }
524
525         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
526                 vb32.m.planes = (uintptr_t)vb->m.planes;
527
528         if (copy_to_user(arg, &vb32, sizeof(vb32)))
529                 return -EFAULT;
530
531         return 0;
532 }
533
534 #ifdef CONFIG_COMPAT_32BIT_TIME
535 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
536                                     struct v4l2_buffer32_time32 __user *arg)
537 {
538         struct v4l2_buffer32_time32 vb32;
539
540         memset(&vb32, 0, sizeof(vb32));
541         vb32 = (struct v4l2_buffer32_time32) {
542                 .index          = vb->index,
543                 .type           = vb->type,
544                 .bytesused      = vb->bytesused,
545                 .flags          = vb->flags,
546                 .field          = vb->field,
547                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
548                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
549                 .timecode       = vb->timecode,
550                 .sequence       = vb->sequence,
551                 .memory         = vb->memory,
552                 .m.offset       = vb->m.offset,
553                 .length         = vb->length,
554                 .request_fd     = vb->request_fd,
555         };
556         switch (vb->memory) {
557         case V4L2_MEMORY_MMAP:
558         case V4L2_MEMORY_OVERLAY:
559                 vb32.m.offset = vb->m.offset;
560                 break;
561         case V4L2_MEMORY_USERPTR:
562                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
563                 break;
564         case V4L2_MEMORY_DMABUF:
565                 vb32.m.fd = vb->m.fd;
566                 break;
567         }
568
569         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
570                 vb32.m.planes = (uintptr_t)vb->m.planes;
571
572         if (copy_to_user(arg, &vb32, sizeof(vb32)))
573                 return -EFAULT;
574
575         return 0;
576 }
577 #endif
578
579 struct v4l2_framebuffer32 {
580         __u32                   capability;
581         __u32                   flags;
582         compat_caddr_t          base;
583         struct {
584                 __u32           width;
585                 __u32           height;
586                 __u32           pixelformat;
587                 __u32           field;
588                 __u32           bytesperline;
589                 __u32           sizeimage;
590                 __u32           colorspace;
591                 __u32           priv;
592         } fmt;
593 };
594
595 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
596                                   struct v4l2_framebuffer32 __user *p32)
597 {
598         if (get_user(p64->capability, &p32->capability) ||
599             get_user(p64->flags, &p32->flags) ||
600             copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
601                 return -EFAULT;
602         p64->base = NULL;
603
604         return 0;
605 }
606
607 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
608                                   struct v4l2_framebuffer32 __user *p32)
609 {
610         if (put_user((uintptr_t)p64->base, &p32->base) ||
611             put_user(p64->capability, &p32->capability) ||
612             put_user(p64->flags, &p32->flags) ||
613             copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
614                 return -EFAULT;
615
616         return 0;
617 }
618
619 struct v4l2_input32 {
620         __u32        index;             /*  Which input */
621         __u8         name[32];          /*  Label */
622         __u32        type;              /*  Type of input */
623         __u32        audioset;          /*  Associated audios (bitfield) */
624         __u32        tuner;             /*  Associated tuner */
625         compat_u64   std;
626         __u32        status;
627         __u32        capabilities;
628         __u32        reserved[3];
629 };
630
631 /*
632  * The 64-bit v4l2_input struct has extra padding at the end of the struct.
633  * Otherwise it is identical to the 32-bit version.
634  */
635 static inline int get_v4l2_input32(struct v4l2_input *p64,
636                                    struct v4l2_input32 __user *p32)
637 {
638         if (copy_from_user(p64, p32, sizeof(*p32)))
639                 return -EFAULT;
640         return 0;
641 }
642
643 static inline int put_v4l2_input32(struct v4l2_input *p64,
644                                    struct v4l2_input32 __user *p32)
645 {
646         if (copy_to_user(p32, p64, sizeof(*p32)))
647                 return -EFAULT;
648         return 0;
649 }
650
651 struct v4l2_ext_controls32 {
652         __u32 which;
653         __u32 count;
654         __u32 error_idx;
655         __s32 request_fd;
656         __u32 reserved[1];
657         compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
658 };
659
660 struct v4l2_ext_control32 {
661         __u32 id;
662         __u32 size;
663         __u32 reserved2[1];
664         union {
665                 __s32 value;
666                 __s64 value64;
667                 compat_caddr_t string; /* actually char * */
668         };
669 } __attribute__ ((packed));
670
671 /* Return true if this control is a pointer type. */
672 static inline bool ctrl_is_pointer(struct file *file, u32 id)
673 {
674         struct video_device *vdev = video_devdata(file);
675         struct v4l2_fh *fh = NULL;
676         struct v4l2_ctrl_handler *hdl = NULL;
677         struct v4l2_query_ext_ctrl qec = { id };
678         const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
679
680         if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
681                 fh = file->private_data;
682
683         if (fh && fh->ctrl_handler)
684                 hdl = fh->ctrl_handler;
685         else if (vdev->ctrl_handler)
686                 hdl = vdev->ctrl_handler;
687
688         if (hdl) {
689                 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
690
691                 return ctrl && ctrl->is_ptr;
692         }
693
694         if (!ops || !ops->vidioc_query_ext_ctrl)
695                 return false;
696
697         return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
698                 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
699 }
700
701 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
702                                    struct v4l2_ext_controls32 __user *p32)
703 {
704         struct v4l2_ext_controls32 ec32;
705
706         if (copy_from_user(&ec32, p32, sizeof(ec32)))
707                 return -EFAULT;
708
709         *p64 = (struct v4l2_ext_controls) {
710                 .which          = ec32.which,
711                 .count          = ec32.count,
712                 .error_idx      = ec32.error_idx,
713                 .request_fd     = ec32.request_fd,
714                 .reserved[0]    = ec32.reserved[0],
715                 .controls       = (void __force *)compat_ptr(ec32.controls),
716         };
717
718         return 0;
719 }
720
721 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
722                                    struct v4l2_ext_controls32 __user *p32)
723 {
724         struct v4l2_ext_controls32 ec32;
725
726         memset(&ec32, 0, sizeof(ec32));
727         ec32 = (struct v4l2_ext_controls32) {
728                 .which          = p64->which,
729                 .count          = p64->count,
730                 .error_idx      = p64->error_idx,
731                 .request_fd     = p64->request_fd,
732                 .reserved[0]    = p64->reserved[0],
733                 .controls       = (uintptr_t)p64->controls,
734         };
735
736         if (copy_to_user(p32, &ec32, sizeof(ec32)))
737                 return -EFAULT;
738
739         return 0;
740 }
741
742 #ifdef CONFIG_X86_64
743 /*
744  * x86 is the only compat architecture with different struct alignment
745  * between 32-bit and 64-bit tasks.
746  */
747 struct v4l2_event32 {
748         __u32                           type;
749         union {
750                 compat_s64              value64;
751                 __u8                    data[64];
752         } u;
753         __u32                           pending;
754         __u32                           sequence;
755         struct {
756                 compat_s64              tv_sec;
757                 compat_s64              tv_nsec;
758         } timestamp;
759         __u32                           id;
760         __u32                           reserved[8];
761 };
762
763 static int put_v4l2_event32(struct v4l2_event *p64,
764                             struct v4l2_event32 __user *p32)
765 {
766         if (put_user(p64->type, &p32->type) ||
767             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
768             put_user(p64->pending, &p32->pending) ||
769             put_user(p64->sequence, &p32->sequence) ||
770             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
771             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
772             put_user(p64->id, &p32->id) ||
773             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
774                 return -EFAULT;
775         return 0;
776 }
777
778 #endif
779
780 #ifdef CONFIG_COMPAT_32BIT_TIME
781 struct v4l2_event32_time32 {
782         __u32                           type;
783         union {
784                 compat_s64              value64;
785                 __u8                    data[64];
786         } u;
787         __u32                           pending;
788         __u32                           sequence;
789         struct old_timespec32           timestamp;
790         __u32                           id;
791         __u32                           reserved[8];
792 };
793
794 static int put_v4l2_event32_time32(struct v4l2_event *p64,
795                                    struct v4l2_event32_time32 __user *p32)
796 {
797         if (put_user(p64->type, &p32->type) ||
798             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
799             put_user(p64->pending, &p32->pending) ||
800             put_user(p64->sequence, &p32->sequence) ||
801             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
802             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
803             put_user(p64->id, &p32->id) ||
804             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
805                 return -EFAULT;
806         return 0;
807 }
808 #endif
809
810 struct v4l2_edid32 {
811         __u32 pad;
812         __u32 start_block;
813         __u32 blocks;
814         __u32 reserved[5];
815         compat_caddr_t edid;
816 };
817
818 static int get_v4l2_edid32(struct v4l2_edid *p64,
819                            struct v4l2_edid32 __user *p32)
820 {
821         compat_uptr_t edid;
822
823         if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
824             get_user(edid, &p32->edid))
825                 return -EFAULT;
826
827         p64->edid = (void __force *)compat_ptr(edid);
828         return 0;
829 }
830
831 static int put_v4l2_edid32(struct v4l2_edid *p64,
832                            struct v4l2_edid32 __user *p32)
833 {
834         if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
835                 return -EFAULT;
836         return 0;
837 }
838
839 /*
840  * List of ioctls that require 32-bits/64-bits conversion
841  *
842  * The V4L2 ioctls that aren't listed there don't have pointer arguments
843  * and the struct size is identical for both 32 and 64 bits versions, so
844  * they don't need translations.
845  */
846
847 #define VIDIOC_G_FMT32          _IOWR('V',  4, struct v4l2_format32)
848 #define VIDIOC_S_FMT32          _IOWR('V',  5, struct v4l2_format32)
849 #define VIDIOC_QUERYBUF32       _IOWR('V',  9, struct v4l2_buffer32)
850 #define VIDIOC_G_FBUF32         _IOR ('V', 10, struct v4l2_framebuffer32)
851 #define VIDIOC_S_FBUF32         _IOW ('V', 11, struct v4l2_framebuffer32)
852 #define VIDIOC_QBUF32           _IOWR('V', 15, struct v4l2_buffer32)
853 #define VIDIOC_DQBUF32          _IOWR('V', 17, struct v4l2_buffer32)
854 #define VIDIOC_ENUMSTD32        _IOWR('V', 25, struct v4l2_standard32)
855 #define VIDIOC_ENUMINPUT32      _IOWR('V', 26, struct v4l2_input32)
856 #define VIDIOC_G_EDID32         _IOWR('V', 40, struct v4l2_edid32)
857 #define VIDIOC_S_EDID32         _IOWR('V', 41, struct v4l2_edid32)
858 #define VIDIOC_TRY_FMT32        _IOWR('V', 64, struct v4l2_format32)
859 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
860 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
861 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
862 #define VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
863 #define VIDIOC_CREATE_BUFS32    _IOWR('V', 92, struct v4l2_create_buffers32)
864 #define VIDIOC_PREPARE_BUF32    _IOWR('V', 93, struct v4l2_buffer32)
865
866 #ifdef CONFIG_COMPAT_32BIT_TIME
867 #define VIDIOC_QUERYBUF32_TIME32        _IOWR('V',  9, struct v4l2_buffer32_time32)
868 #define VIDIOC_QBUF32_TIME32            _IOWR('V', 15, struct v4l2_buffer32_time32)
869 #define VIDIOC_DQBUF32_TIME32           _IOWR('V', 17, struct v4l2_buffer32_time32)
870 #define VIDIOC_DQEVENT32_TIME32         _IOR ('V', 89, struct v4l2_event32_time32)
871 #define VIDIOC_PREPARE_BUF32_TIME32     _IOWR('V', 93, struct v4l2_buffer32_time32)
872 #endif
873
874 unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
875 {
876         switch (cmd) {
877         case VIDIOC_G_FMT32:
878                 return VIDIOC_G_FMT;
879         case VIDIOC_S_FMT32:
880                 return VIDIOC_S_FMT;
881         case VIDIOC_TRY_FMT32:
882                 return VIDIOC_TRY_FMT;
883         case VIDIOC_G_FBUF32:
884                 return VIDIOC_G_FBUF;
885         case VIDIOC_S_FBUF32:
886                 return VIDIOC_S_FBUF;
887 #ifdef CONFIG_COMPAT_32BIT_TIME
888         case VIDIOC_QUERYBUF32_TIME32:
889                 return VIDIOC_QUERYBUF;
890         case VIDIOC_QBUF32_TIME32:
891                 return VIDIOC_QBUF;
892         case VIDIOC_DQBUF32_TIME32:
893                 return VIDIOC_DQBUF;
894         case VIDIOC_PREPARE_BUF32_TIME32:
895                 return VIDIOC_PREPARE_BUF;
896 #endif
897         case VIDIOC_QUERYBUF32:
898                 return VIDIOC_QUERYBUF;
899         case VIDIOC_QBUF32:
900                 return VIDIOC_QBUF;
901         case VIDIOC_DQBUF32:
902                 return VIDIOC_DQBUF;
903         case VIDIOC_CREATE_BUFS32:
904                 return VIDIOC_CREATE_BUFS;
905         case VIDIOC_G_EXT_CTRLS32:
906                 return VIDIOC_G_EXT_CTRLS;
907         case VIDIOC_S_EXT_CTRLS32:
908                 return VIDIOC_S_EXT_CTRLS;
909         case VIDIOC_TRY_EXT_CTRLS32:
910                 return VIDIOC_TRY_EXT_CTRLS;
911         case VIDIOC_PREPARE_BUF32:
912                 return VIDIOC_PREPARE_BUF;
913         case VIDIOC_ENUMSTD32:
914                 return VIDIOC_ENUMSTD;
915         case VIDIOC_ENUMINPUT32:
916                 return VIDIOC_ENUMINPUT;
917         case VIDIOC_G_EDID32:
918                 return VIDIOC_G_EDID;
919         case VIDIOC_S_EDID32:
920                 return VIDIOC_S_EDID;
921 #ifdef CONFIG_X86_64
922         case VIDIOC_DQEVENT32:
923                 return VIDIOC_DQEVENT;
924 #endif
925 #ifdef CONFIG_COMPAT_32BIT_TIME
926         case VIDIOC_DQEVENT32_TIME32:
927                 return VIDIOC_DQEVENT;
928 #endif
929         }
930         return cmd;
931 }
932
933 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
934 {
935         switch (cmd) {
936         case VIDIOC_G_FMT32:
937         case VIDIOC_S_FMT32:
938         case VIDIOC_TRY_FMT32:
939                 return get_v4l2_format32(parg, arg);
940
941         case VIDIOC_S_FBUF32:
942                 return get_v4l2_framebuffer32(parg, arg);
943 #ifdef CONFIG_COMPAT_32BIT_TIME
944         case VIDIOC_QUERYBUF32_TIME32:
945         case VIDIOC_QBUF32_TIME32:
946         case VIDIOC_DQBUF32_TIME32:
947         case VIDIOC_PREPARE_BUF32_TIME32:
948                 return get_v4l2_buffer32_time32(parg, arg);
949 #endif
950         case VIDIOC_QUERYBUF32:
951         case VIDIOC_QBUF32:
952         case VIDIOC_DQBUF32:
953         case VIDIOC_PREPARE_BUF32:
954                 return get_v4l2_buffer32(parg, arg);
955
956         case VIDIOC_G_EXT_CTRLS32:
957         case VIDIOC_S_EXT_CTRLS32:
958         case VIDIOC_TRY_EXT_CTRLS32:
959                 return get_v4l2_ext_controls32(parg, arg);
960
961         case VIDIOC_CREATE_BUFS32:
962                 return get_v4l2_create32(parg, arg);
963
964         case VIDIOC_ENUMSTD32:
965                 return get_v4l2_standard32(parg, arg);
966
967         case VIDIOC_ENUMINPUT32:
968                 return get_v4l2_input32(parg, arg);
969
970         case VIDIOC_G_EDID32:
971         case VIDIOC_S_EDID32:
972                 return get_v4l2_edid32(parg, arg);
973         }
974         return 0;
975 }
976
977 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
978 {
979         switch (cmd) {
980         case VIDIOC_G_FMT32:
981         case VIDIOC_S_FMT32:
982         case VIDIOC_TRY_FMT32:
983                 return put_v4l2_format32(parg, arg);
984
985         case VIDIOC_G_FBUF32:
986                 return put_v4l2_framebuffer32(parg, arg);
987 #ifdef CONFIG_COMPAT_32BIT_TIME
988         case VIDIOC_QUERYBUF32_TIME32:
989         case VIDIOC_QBUF32_TIME32:
990         case VIDIOC_DQBUF32_TIME32:
991         case VIDIOC_PREPARE_BUF32_TIME32:
992                 return put_v4l2_buffer32_time32(parg, arg);
993 #endif
994         case VIDIOC_QUERYBUF32:
995         case VIDIOC_QBUF32:
996         case VIDIOC_DQBUF32:
997         case VIDIOC_PREPARE_BUF32:
998                 return put_v4l2_buffer32(parg, arg);
999
1000         case VIDIOC_G_EXT_CTRLS32:
1001         case VIDIOC_S_EXT_CTRLS32:
1002         case VIDIOC_TRY_EXT_CTRLS32:
1003                 return put_v4l2_ext_controls32(parg, arg);
1004
1005         case VIDIOC_CREATE_BUFS32:
1006                 return put_v4l2_create32(parg, arg);
1007
1008         case VIDIOC_ENUMSTD32:
1009                 return put_v4l2_standard32(parg, arg);
1010
1011         case VIDIOC_ENUMINPUT32:
1012                 return put_v4l2_input32(parg, arg);
1013
1014         case VIDIOC_G_EDID32:
1015         case VIDIOC_S_EDID32:
1016                 return put_v4l2_edid32(parg, arg);
1017 #ifdef CONFIG_X86_64
1018         case VIDIOC_DQEVENT32:
1019                 return put_v4l2_event32(parg, arg);
1020 #endif
1021 #ifdef CONFIG_COMPAT_32BIT_TIME
1022         case VIDIOC_DQEVENT32_TIME32:
1023                 return put_v4l2_event32_time32(parg, arg);
1024 #endif
1025         }
1026         return 0;
1027 }
1028
1029 int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1030                                void __user *user_ptr, size_t array_size,
1031                                unsigned int cmd, void *arg)
1032 {
1033         int err = 0;
1034
1035         memset(mbuf, 0, array_size);
1036
1037         switch (cmd) {
1038 #ifdef CONFIG_COMPAT_32BIT_TIME
1039         case VIDIOC_QUERYBUF32_TIME32:
1040         case VIDIOC_QBUF32_TIME32:
1041         case VIDIOC_DQBUF32_TIME32:
1042         case VIDIOC_PREPARE_BUF32_TIME32:
1043 #endif
1044         case VIDIOC_QUERYBUF32:
1045         case VIDIOC_QBUF32:
1046         case VIDIOC_DQBUF32:
1047         case VIDIOC_PREPARE_BUF32: {
1048                 struct v4l2_buffer *b64 = arg;
1049                 struct v4l2_plane *p64 = mbuf;
1050                 struct v4l2_plane32 __user *p32 = user_ptr;
1051
1052                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1053                         u32 num_planes = b64->length;
1054
1055                         if (num_planes == 0)
1056                                 return 0;
1057
1058                         while (num_planes--) {
1059                                 err = get_v4l2_plane32(p64, p32, b64->memory);
1060                                 if (err)
1061                                         return err;
1062                                 ++p64;
1063                                 ++p32;
1064                         }
1065                 }
1066                 break;
1067         }
1068         case VIDIOC_G_EXT_CTRLS32:
1069         case VIDIOC_S_EXT_CTRLS32:
1070         case VIDIOC_TRY_EXT_CTRLS32: {
1071                 struct v4l2_ext_controls *ecs64 = arg;
1072                 struct v4l2_ext_control *ec64 = mbuf;
1073                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1074                 int n;
1075
1076                 for (n = 0; n < ecs64->count; n++) {
1077                         if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1078                                 return -EFAULT;
1079
1080                         if (ctrl_is_pointer(file, ec64->id)) {
1081                                 compat_uptr_t p;
1082
1083                                 if (get_user(p, &ec32->string))
1084                                         return -EFAULT;
1085                                 ec64->string = compat_ptr(p);
1086                         }
1087                         ec32++;
1088                         ec64++;
1089                 }
1090                 break;
1091         }
1092         default:
1093                 if (copy_from_user(mbuf, user_ptr, array_size))
1094                         err = -EFAULT;
1095                 break;
1096         }
1097
1098         return err;
1099 }
1100
1101 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1102                                void *mbuf, size_t array_size,
1103                                unsigned int cmd, void *arg)
1104 {
1105         int err = 0;
1106
1107         switch (cmd) {
1108 #ifdef CONFIG_COMPAT_32BIT_TIME
1109         case VIDIOC_QUERYBUF32_TIME32:
1110         case VIDIOC_QBUF32_TIME32:
1111         case VIDIOC_DQBUF32_TIME32:
1112         case VIDIOC_PREPARE_BUF32_TIME32:
1113 #endif
1114         case VIDIOC_QUERYBUF32:
1115         case VIDIOC_QBUF32:
1116         case VIDIOC_DQBUF32:
1117         case VIDIOC_PREPARE_BUF32: {
1118                 struct v4l2_buffer *b64 = arg;
1119                 struct v4l2_plane *p64 = mbuf;
1120                 struct v4l2_plane32 __user *p32 = user_ptr;
1121
1122                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1123                         u32 num_planes = b64->length;
1124
1125                         if (num_planes == 0)
1126                                 return 0;
1127
1128                         while (num_planes--) {
1129                                 err = put_v4l2_plane32(p64, p32, b64->memory);
1130                                 if (err)
1131                                         return err;
1132                                 ++p64;
1133                                 ++p32;
1134                         }
1135                 }
1136                 break;
1137         }
1138         case VIDIOC_G_EXT_CTRLS32:
1139         case VIDIOC_S_EXT_CTRLS32:
1140         case VIDIOC_TRY_EXT_CTRLS32: {
1141                 struct v4l2_ext_controls *ecs64 = arg;
1142                 struct v4l2_ext_control *ec64 = mbuf;
1143                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1144                 int n;
1145
1146                 for (n = 0; n < ecs64->count; n++) {
1147                         unsigned int size = sizeof(*ec32);
1148                         /*
1149                          * Do not modify the pointer when copying a pointer
1150                          * control.  The contents of the pointer was changed,
1151                          * not the pointer itself.
1152                          * The structures are otherwise compatible.
1153                          */
1154                         if (ctrl_is_pointer(file, ec64->id))
1155                                 size -= sizeof(ec32->value64);
1156
1157                         if (copy_to_user(ec32, ec64, size))
1158                                 return -EFAULT;
1159
1160                         ec32++;
1161                         ec64++;
1162                 }
1163                 break;
1164         }
1165         default:
1166                 if (copy_to_user(user_ptr, mbuf, array_size))
1167                         err = -EFAULT;
1168                 break;
1169         }
1170
1171         return err;
1172 }
1173
1174 /**
1175  * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1176  *
1177  * @file: pointer to &struct file with the file handler
1178  * @cmd: ioctl to be called
1179  * @arg: arguments passed from/to the ioctl handler
1180  *
1181  * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1182  * in order to deal with 32-bit calls on a 64-bits Kernel.
1183  *
1184  * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1185  * If the function is a private one it calls vdev->fops->compat_ioctl32
1186  * instead.
1187  */
1188 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1189 {
1190         struct video_device *vdev = video_devdata(file);
1191         long ret = -ENOIOCTLCMD;
1192
1193         if (!file->f_op->unlocked_ioctl)
1194                 return ret;
1195
1196         if (!video_is_registered(vdev))
1197                 return -ENODEV;
1198
1199         if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1200                 ret = file->f_op->unlocked_ioctl(file, cmd,
1201                                         (unsigned long)compat_ptr(arg));
1202         else if (vdev->fops->compat_ioctl32)
1203                 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1204
1205         if (ret == -ENOIOCTLCMD)
1206                 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1207                          _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1208         return ret;
1209 }
1210 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
This page took 0.101664 seconds and 4 git commands to generate.