Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: amlogic-c3: Use v4l2-isp for validation

Convert c3-isp-params.c to use the helpers defined in v4l2-isp.h
to perform validation of a ISP parameters buffer.

Reviewed-by: Keke Li <keke.li@amlogic.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Jacopo Mondi and committed by
Hans Verkuil
9f7d23d5 3a2730a4

+44 -122
+1
drivers/media/platform/amlogic/c3/isp/Kconfig
··· 10 10 select VIDEO_V4L2_SUBDEV_API 11 11 select VIDEOBUF2_DMA_CONTIG 12 12 select VIDEOBUF2_VMALLOC 13 + select V4L2_ISP 13 14 help 14 15 Video4Linux2 driver for Amlogic C3 ISP pipeline. 15 16 The C3 ISP is used for processing raw images and
+43 -122
drivers/media/platform/amlogic/c3/isp/c3-isp-params.c
··· 3 3 * Copyright (C) 2024 Amlogic, Inc. All rights reserved 4 4 */ 5 5 6 + #include <linux/build_bug.h> 6 7 #include <linux/cleanup.h> 7 8 #include <linux/media/amlogic/c3-isp-config.h> 8 9 #include <linux/pm_runtime.h> 9 10 10 11 #include <media/v4l2-ioctl.h> 12 + #include <media/v4l2-isp.h> 11 13 #include <media/v4l2-mc.h> 12 14 #include <media/videobuf2-vmalloc.h> 13 15 ··· 52 50 53 51 typedef void (*c3_isp_block_handler)(struct c3_isp_device *isp, 54 52 const union c3_isp_params_block *block); 55 - 56 - struct c3_isp_params_handler { 57 - size_t size; 58 - c3_isp_block_handler handler; 59 - }; 60 53 61 54 #define to_c3_isp_params_buffer(vbuf) \ 62 55 container_of(vbuf, struct c3_isp_params_buffer, vb) ··· 520 523 ISP_TOP_BEO_CTRL_BLC_EN); 521 524 } 522 525 523 - static const struct c3_isp_params_handler c3_isp_params_handlers[] = { 524 - [C3_ISP_PARAMS_BLOCK_AWB_GAINS] = { 525 - .size = sizeof(struct c3_isp_params_awb_gains), 526 - .handler = c3_isp_params_cfg_awb_gains, 527 - }, 528 - [C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = { 529 - .size = sizeof(struct c3_isp_params_awb_config), 530 - .handler = c3_isp_params_cfg_awb_config, 531 - }, 532 - [C3_ISP_PARAMS_BLOCK_AE_CONFIG] = { 533 - .size = sizeof(struct c3_isp_params_ae_config), 534 - .handler = c3_isp_params_cfg_ae_config, 535 - }, 536 - [C3_ISP_PARAMS_BLOCK_AF_CONFIG] = { 537 - .size = sizeof(struct c3_isp_params_af_config), 538 - .handler = c3_isp_params_cfg_af_config, 539 - }, 540 - [C3_ISP_PARAMS_BLOCK_PST_GAMMA] = { 541 - .size = sizeof(struct c3_isp_params_pst_gamma), 542 - .handler = c3_isp_params_cfg_pst_gamma, 543 - }, 544 - [C3_ISP_PARAMS_BLOCK_CCM] = { 545 - .size = sizeof(struct c3_isp_params_ccm), 546 - .handler = c3_isp_params_cfg_ccm, 547 - }, 548 - [C3_ISP_PARAMS_BLOCK_CSC] = { 549 - .size = sizeof(struct c3_isp_params_csc), 550 - .handler = c3_isp_params_cfg_csc, 551 - }, 552 - [C3_ISP_PARAMS_BLOCK_BLC] = { 553 - .size = sizeof(struct c3_isp_params_blc), 554 - .handler = c3_isp_params_cfg_blc, 555 - }, 526 + static const c3_isp_block_handler c3_isp_params_handlers[] = { 527 + [C3_ISP_PARAMS_BLOCK_AWB_GAINS] = c3_isp_params_cfg_awb_gains, 528 + [C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = c3_isp_params_cfg_awb_config, 529 + [C3_ISP_PARAMS_BLOCK_AE_CONFIG] = c3_isp_params_cfg_ae_config, 530 + [C3_ISP_PARAMS_BLOCK_AF_CONFIG] = c3_isp_params_cfg_af_config, 531 + [C3_ISP_PARAMS_BLOCK_PST_GAMMA] = c3_isp_params_cfg_pst_gamma, 532 + [C3_ISP_PARAMS_BLOCK_CCM] = c3_isp_params_cfg_ccm, 533 + [C3_ISP_PARAMS_BLOCK_CSC] = c3_isp_params_cfg_csc, 534 + [C3_ISP_PARAMS_BLOCK_BLC] = c3_isp_params_cfg_blc, 556 535 }; 536 + 537 + #define C3_ISP_PARAMS_BLOCK_INFO(block, data) \ 538 + [C3_ISP_PARAMS_BLOCK_ ## block] = { \ 539 + .size = sizeof(struct c3_isp_params_ ## data), \ 540 + } 541 + 542 + static const struct v4l2_isp_params_block_info c3_isp_params_blocks_info[] = { 543 + C3_ISP_PARAMS_BLOCK_INFO(AWB_GAINS, awb_gains), 544 + C3_ISP_PARAMS_BLOCK_INFO(AWB_CONFIG, awb_config), 545 + C3_ISP_PARAMS_BLOCK_INFO(AE_CONFIG, ae_config), 546 + C3_ISP_PARAMS_BLOCK_INFO(AF_CONFIG, af_config), 547 + C3_ISP_PARAMS_BLOCK_INFO(PST_GAMMA, pst_gamma), 548 + C3_ISP_PARAMS_BLOCK_INFO(CCM, ccm), 549 + C3_ISP_PARAMS_BLOCK_INFO(CSC, csc), 550 + C3_ISP_PARAMS_BLOCK_INFO(BLC, blc), 551 + }; 552 + 553 + static_assert(ARRAY_SIZE(c3_isp_params_handlers) == 554 + ARRAY_SIZE(c3_isp_params_blocks_info)); 557 555 558 556 static void c3_isp_params_cfg_blocks(struct c3_isp_params *params) 559 557 { ··· 560 568 561 569 /* Walk the list of parameter blocks and process them */ 562 570 while (block_offset < config->data_size) { 563 - const struct c3_isp_params_handler *block_handler; 564 571 const union c3_isp_params_block *block; 572 + c3_isp_block_handler block_handler; 565 573 566 574 block = (const union c3_isp_params_block *) 567 575 &config->data[block_offset]; 568 576 569 - block_handler = &c3_isp_params_handlers[block->header.type]; 570 - block_handler->handler(params->isp, block); 577 + block_handler = c3_isp_params_handlers[block->header.type]; 578 + block_handler(params->isp, block); 571 579 572 580 block_offset += block->header.size; 573 581 } ··· 763 771 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 764 772 struct c3_isp_params_buffer *buf = to_c3_isp_params_buffer(vbuf); 765 773 struct c3_isp_params *params = vb2_get_drv_priv(vb->vb2_queue); 766 - struct c3_isp_params_cfg *cfg = buf->cfg; 767 774 struct c3_isp_params_cfg *usr_cfg = vb2_plane_vaddr(vb, 0); 768 775 size_t payload_size = vb2_get_plane_payload(vb, 0); 769 - size_t header_size = offsetof(struct c3_isp_params_cfg, data); 770 - size_t block_offset = 0; 771 - size_t cfg_size; 776 + struct c3_isp_params_cfg *cfg = buf->cfg; 777 + int ret; 772 778 773 - /* Payload size can't be greater than the destination buffer size */ 774 - if (payload_size > params->vfmt.fmt.meta.buffersize) { 775 - dev_dbg(params->isp->dev, 776 - "Payload size is too large: %zu\n", payload_size); 777 - return -EINVAL; 778 - } 779 - 780 - /* Payload size can't be smaller than the header size */ 781 - if (payload_size < header_size) { 782 - dev_dbg(params->isp->dev, 783 - "Payload size is too small: %zu\n", payload_size); 784 - return -EINVAL; 785 - } 779 + ret = v4l2_isp_params_validate_buffer_size(params->isp->dev, vb, 780 + params->vfmt.fmt.meta.buffersize); 781 + if (ret) 782 + return ret; 786 783 787 784 /* 788 785 * Use the internal scratch buffer to avoid userspace modifying ··· 779 798 */ 780 799 memcpy(cfg, usr_cfg, payload_size); 781 800 782 - /* Only v0 is supported at the moment */ 783 - if (cfg->version != C3_ISP_PARAMS_BUFFER_V0) { 784 - dev_dbg(params->isp->dev, 785 - "Invalid params buffer version: %u\n", cfg->version); 786 - return -EINVAL; 787 - } 788 - 789 - /* Validate the size reported in the parameter buffer header */ 790 - cfg_size = header_size + cfg->data_size; 791 - if (cfg_size != payload_size) { 792 - dev_dbg(params->isp->dev, 793 - "Data size %zu and payload size %zu are different\n", 794 - cfg_size, payload_size); 795 - return -EINVAL; 796 - } 797 - 798 - /* Walk the list of parameter blocks and validate them */ 799 - cfg_size = cfg->data_size; 800 - while (cfg_size >= sizeof(struct c3_isp_params_block_header)) { 801 - const struct c3_isp_params_block_header *block; 802 - const struct c3_isp_params_handler *handler; 803 - 804 - block = (struct c3_isp_params_block_header *) 805 - &cfg->data[block_offset]; 806 - 807 - if (block->type >= ARRAY_SIZE(c3_isp_params_handlers)) { 808 - dev_dbg(params->isp->dev, 809 - "Invalid params block type\n"); 810 - return -EINVAL; 811 - } 812 - 813 - if (block->size > cfg_size) { 814 - dev_dbg(params->isp->dev, 815 - "Block size is greater than cfg size\n"); 816 - return -EINVAL; 817 - } 818 - 819 - if ((block->flags & (C3_ISP_PARAMS_BLOCK_FL_ENABLE | 820 - C3_ISP_PARAMS_BLOCK_FL_DISABLE)) == 821 - (C3_ISP_PARAMS_BLOCK_FL_ENABLE | 822 - C3_ISP_PARAMS_BLOCK_FL_DISABLE)) { 823 - dev_dbg(params->isp->dev, 824 - "Invalid parameters block flags\n"); 825 - return -EINVAL; 826 - } 827 - 828 - handler = &c3_isp_params_handlers[block->type]; 829 - if (block->size != handler->size) { 830 - dev_dbg(params->isp->dev, 831 - "Invalid params block size\n"); 832 - return -EINVAL; 833 - } 834 - 835 - block_offset += block->size; 836 - cfg_size -= block->size; 837 - } 838 - 839 - if (cfg_size) { 840 - dev_dbg(params->isp->dev, 841 - "Unexpected data after the params buffer end\n"); 842 - return -EINVAL; 843 - } 844 - 845 - return 0; 801 + return v4l2_isp_params_validate_buffer(params->isp->dev, vb, 802 + (struct v4l2_isp_params_buffer *)cfg, 803 + c3_isp_params_blocks_info, 804 + ARRAY_SIZE(c3_isp_params_blocks_info)); 846 805 } 847 806 848 807 static int c3_isp_params_vb2_buf_init(struct vb2_buffer *vb)