diff options
author | ming_qian <ming.qian@nxp.com> | 2019-06-19 10:39:56 +0800 |
---|---|---|
committer | ming_qian <ming.qian@nxp.com> | 2019-06-20 09:07:11 +0800 |
commit | ec7984b92d9ddf541e4e3abba62d6569a46c14a5 (patch) | |
tree | 76f4248f1cdad5055d11bdf9f8cd8d42392012be /drivers | |
parent | 641dde76ea39268e3f870e407aa7f79386e656b6 (diff) |
MLK-22037: VPU Decoder: the resolution of g_fmt may be incorrect
sometime firmware may report wrong sequence info, invalid resolution.
getting and setting seqinfo may in the same time, it's a risk
Signed-off-by: ming_qian <ming.qian@nxp.com>
Reviewed-by: Shijie Qin <shijie.qin@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/vpu_malone/vpu_b0.c | 58 | ||||
-rw-r--r-- | drivers/mxc/vpu_malone/vpu_b0.h | 2 |
2 files changed, 52 insertions, 8 deletions
diff --git a/drivers/mxc/vpu_malone/vpu_b0.c b/drivers/mxc/vpu_malone/vpu_b0.c index 781211a95e4f..71d0777ede25 100644 --- a/drivers/mxc/vpu_malone/vpu_b0.c +++ b/drivers/mxc/vpu_malone/vpu_b0.c @@ -717,7 +717,7 @@ static bool is_10bit_format(struct vpu_ctx *ctx) return false; } -static void caculate_frame_size(struct vpu_ctx *ctx) +static void calculate_frame_size(struct vpu_ctx *ctx) { u_int32 width = ctx->pSeqinfo->uHorDecodeRes; u_int32 height = ctx->pSeqinfo->uVerDecodeRes; @@ -759,17 +759,25 @@ static int v4l2_ioctl_g_fmt(struct file *file, vpu_dbg(LVL_BIT_FUNC, "%s()\n", __func__); if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + MediaIPFW_Video_SeqInfo *info = ctx->pSeqinfo; + q_data = &ctx->q_data[V4L2_DST]; if (is_10bit_format(ctx)) pix_mp->pixelformat = V4L2_PIX_FMT_NV12_10BIT; else pix_mp->pixelformat = V4L2_PIX_FMT_NV12; - pix_mp->width = ctx->pSeqinfo->uHorRes > 0?ctx->pSeqinfo->uHorRes:q_data->width; - pix_mp->height = ctx->pSeqinfo->uVerRes > 0?ctx->pSeqinfo->uVerRes:q_data->height; - if (ctx->pSeqinfo->uProgressive == 1) + pix_mp->width = q_data->width; + pix_mp->height = q_data->height; + down(&q_data->drv_q_lock); + if (!ctx->b_firstseq && info->uHorRes && info->uVerRes) { + pix_mp->width = ctx->pSeqinfo->uHorRes; + pix_mp->height = ctx->pSeqinfo->uVerRes; + } + if (info->uProgressive == 1) pix_mp->field = V4L2_FIELD_NONE; else pix_mp->field = V4L2_FIELD_INTERLACED; + up(&q_data->drv_q_lock); pix_mp->num_planes = 2; pix_mp->colorspace = V4L2_COLORSPACE_REC709; @@ -1206,6 +1214,10 @@ static int alloc_mbi_buffer(struct vpu_ctx *ctx, u32 index) vpu_dbg(LVL_ERR, "request mbi buffer number out of range\n"); return -EINVAL; } + if (!ctx->mbi_size) { + vpu_dbg(LVL_ERR, "mbi buffer size is not initialized\n"); + return -EINVAL; + } mbi_buffer = &ctx->mbi_buffer[index]; if (mbi_buffer->dma_virt && mbi_buffer->dma_size >= ctx->mbi_size) @@ -1215,7 +1227,7 @@ static int alloc_mbi_buffer(struct vpu_ctx *ctx, u32 index) mbi_buffer->dma_size = ctx->mbi_size; ret = alloc_dma_buffer(ctx, mbi_buffer); if (ret) { - vpu_dbg(LVL_ERR, "error: alloc dcp buffer[%d] fail\n", index); + vpu_dbg(LVL_ERR, "error: alloc mbi buffer[%d] fail\n", index); return ret; } @@ -1308,6 +1320,11 @@ static int v4l2_ioctl_reqbufs(struct file *file, return -EINVAL; } + if (!q_data->sizeimage[0]) { + vpu_dbg(LVL_ERR, "sizeimage isn't initialized, reqbufs fail\n"); + return -EINVAL; + } + ret = vpu_dec_queue_reqbufs(q_data, reqbuf); if (ret) { vpu_dbg(LVL_WARN, "warning: %s() can't request (%d) buffer : %d\n", @@ -3594,6 +3611,26 @@ static void release_frame_buffer(struct vpu_ctx *ctx, set_data_req_status(p_data_req, FRAME_ALLOC); } +static bool check_seq_info_is_valid(u32 ctx_id, MediaIPFW_Video_SeqInfo *info) +{ + if (!info) + return false; + + if (!info->uHorRes || !info->uVerRes) { + vpu_dbg(LVL_ERR, "ctx[%d] invalid seq info : %d x %d\n", + ctx_id, info->uHorRes, info->uVerRes); + return false; + } + if (info->uHorRes > VPU_DEC_MAX_WIDTH || + info->uVerRes > VPU_DEC_MAX_HEIGTH) { + vpu_dbg(LVL_ERR, "ctx[%d] invalid seq info : %d x %d\n", + ctx_id, info->uHorRes, info->uVerRes); + return false; + } + + return true; +} + static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 uEvent, u_int32 *event_data) { struct vpu_dev *dev; @@ -3640,8 +3677,10 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 down(&ctx->q_data[V4L2_DST].drv_q_lock); respond_req_frame(ctx, &ctx->q_data[V4L2_DST], true); reset_mbi_dcp_count(ctx); - up(&ctx->q_data[V4L2_DST].drv_q_lock); memset(ctx->pSeqinfo, 0, sizeof(MediaIPFW_Video_SeqInfo)); + ctx->q_data[V4L2_DST].sizeimage[0] = 0; + ctx->q_data[V4L2_DST].sizeimage[1] = 0; + up(&ctx->q_data[V4L2_DST].drv_q_lock); complete(&ctx->completion);//reduce possibility of abort hang if decoder enter stop automatically complete(&ctx->stop_cmp); } @@ -3729,6 +3768,9 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 // MediaIPFW_Video_FrameBuffer *pStreamDCPBuffer = &pSharedInterface->StreamDCPBuffer[uStrIdx]; MediaIPFW_Video_PitchInfo *pStreamPitchInfo = &pSharedInterface->StreamPitchInfo[uStrIdx]; unsigned int num = pSharedInterface->SeqInfoTabDesc.uNumSizeDescriptors; + + if (!check_seq_info_is_valid(ctx->str_index, pSeqInfo)) + break; if (ctx->pSeqinfo == NULL) { ctx->pSeqinfo = kzalloc(sizeof(MediaIPFW_Video_SeqInfo), GFP_KERNEL); atomic64_add(sizeof(MediaIPFW_Video_SeqInfo), &ctx->statistic.total_alloc_size); @@ -3737,10 +3779,10 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 vpu_dbg(LVL_INFO, "pSeqinfo is not NULL, need not to realloc\n"); down(&ctx->q_data[V4L2_DST].drv_q_lock); respond_req_frame(ctx, &ctx->q_data[V4L2_DST], true); - up(&ctx->q_data[V4L2_DST].drv_q_lock); memcpy(ctx->pSeqinfo, &pSeqInfo[ctx->str_index], sizeof(MediaIPFW_Video_SeqInfo)); + up(&ctx->q_data[V4L2_DST].drv_q_lock); - caculate_frame_size(ctx); + calculate_frame_size(ctx); parse_frame_interval_from_seqinfo(ctx, ctx->pSeqinfo); vpu_dbg(LVL_BIT_FLOW, "ctx[%d] SEQINFO GET: uHorRes:%d uVerRes:%d uHorDecodeRes:%d uVerDecodeRes:%d uNumDPBFrms:%d, num:%d, uNumRefFrms:%d, uNumDFEAreas:%d\n", ctx->str_index, diff --git a/drivers/mxc/vpu_malone/vpu_b0.h b/drivers/mxc/vpu_malone/vpu_b0.h index e3eda75ae5a4..089d821c9e5a 100644 --- a/drivers/mxc/vpu_malone/vpu_b0.h +++ b/drivers/mxc/vpu_malone/vpu_b0.h @@ -65,6 +65,8 @@ extern unsigned int vpu_dbg_level_decoder; #define DEFAULT_FRMDBG_ENABLE 0 #define DEFAULT_FRMDBG_LEVEL 0 #define VPU_DEC_CMD_DATA_MAX_NUM 16 +#define VPU_DEC_MAX_WIDTH 4096 +#define VPU_DEC_MAX_HEIGTH 4096 #define V4L2_EVENT_DECODE_ERROR (V4L2_EVENT_PRIVATE_START + 1) #define V4L2_EVENT_SKIP (V4L2_EVENT_PRIVATE_START + 2) |