From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D24E7C433F5 for ; Thu, 23 Sep 2021 14:39:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B202D611C6 for ; Thu, 23 Sep 2021 14:39:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241844AbhIWOlV (ORCPT ); Thu, 23 Sep 2021 10:41:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241766AbhIWOlJ (ORCPT ); Thu, 23 Sep 2021 10:41:09 -0400 Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [IPv6:2607:f8b0:4864:20::730]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A6421C061574 for ; Thu, 23 Sep 2021 07:39:37 -0700 (PDT) Received: by mail-qk1-x730.google.com with SMTP id 138so22445211qko.10 for ; Thu, 23 Sep 2021 07:39:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ndufresne-ca.20210112.gappssmtp.com; s=20210112; h=message-id:subject:from:to:cc:date:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=Fa6LZKz84Q6MojmcZUqxb0ZP/qUzgyt0GHuc22T9vXw=; b=FIJHJk8gobCXHWekmYCqLOQ+2FA1x+adCXlrmV0gmswS/qcZc8ix9NFqg0TfDpngiX BwTGlGn0mAsPGTrQ61p3fKsIc9tISK+u1XdLPEWy7fCdvRJO+nR0fLg9jGfO13Mk2bWl uKAzrDoG4plYkUFjc1gRBioV8Mn2KIO8/hs6yWinz5+sxlw5Dov6BeROgg8N7JX78NLq 2f+uwHYH0rb7wZiITjimMPFq9fXYNq3BlzyY+Mw4IJ2MK6nXc2UOeSlyZC+6GyPryLOp Cu6kjPjmaFsvXhs0GzMrG51f9ZpTM21O3rMW5hfbxHOOPZQilEYAIRkBm6rqj0xliMVw QXzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=Fa6LZKz84Q6MojmcZUqxb0ZP/qUzgyt0GHuc22T9vXw=; b=qGhCJOb2oEidT5WEd3F92rePX7MHjZmDJkfxG13vuE/4WvxoUDAdwKfS4auXkm3pmJ SyEsnKsjJRhLV3RMB8Q6XpeKXwbH7injY2WSfgWxtD4FV9tEdsA7aE8yBHutx3L6OpzH qOME7g4kNuS7Xhwj0E3sNRvPBtByQQAeUjxOV9DtqCuuBDEO0UdlMilaYqRgA9tq8rxI kL7tngiy0Xao2ze8q/fshfRI5NmiZWE9V33DQdhLyLSTWwwjqjPdjiTENQHyPfgHD3b+ YVqfA4cMf6fr8c8E1TlwvB/jgYzvzx8ZPc7uH0r7W8o8MxjDkeaQsXSbhePhzRgAdJBQ JEAw== X-Gm-Message-State: AOAM5316MYVhFjAyhvtiCawHNB3BA9ss2PIyyoQNItCkr17jtqilvhLr goB/JLuYP0F0VnxvnOWKYNN0MQ== X-Google-Smtp-Source: ABdhPJxkuXpHKO2NQEkf/f4kuWYm4bFeTNSFdx1N+XiMJuvH30YJ2wQlMKjfhw+QzXkSzuebqEEtTg== X-Received: by 2002:a37:9fc1:: with SMTP id i184mr5294532qke.247.1632407974323; Thu, 23 Sep 2021 07:39:34 -0700 (PDT) Received: from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net. [173.246.12.168]) by smtp.gmail.com with ESMTPSA id l195sm4431074qke.98.2021.09.23.07.39.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Sep 2021 07:39:33 -0700 (PDT) Message-ID: Subject: Re: [PATCH v9 06/13] media: amphion: add vpu v4l2 m2m support From: Nicolas Dufresne To: Ming Qian , mchehab@kernel.org, shawnguo@kernel.org, robh+dt@kernel.org, s.hauer@pengutronix.de Cc: hverkuil-cisco@xs4all.nl, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, aisheng.dong@nxp.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org Date: Thu, 23 Sep 2021 10:39:32 -0400 In-Reply-To: <4142cb1f597a3fbb176cf18c6a3d6356cc0d4064.1631521295.git.ming.qian@nxp.com> References: <4142cb1f597a3fbb176cf18c6a3d6356cc0d4064.1631521295.git.ming.qian@nxp.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.40.4 (3.40.4-1.fc34) MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Le lundi 13 septembre 2021 à 17:11 +0800, Ming Qian a écrit : > vpu_v4l2.c implements the v4l2 m2m driver methods. > vpu_helpers.c implements the common helper functions > vpu_color.c converts the v4l2 colorspace with iso > > Signed-off-by: Ming Qian > Signed-off-by: Shijie Qin > Signed-off-by: Zhou Peng > Reported-by: kernel test robot > --- > drivers/media/platform/amphion/vpu_color.c | 192 ++++++ > drivers/media/platform/amphion/vpu_helpers.c | 453 ++++++++++++++ > drivers/media/platform/amphion/vpu_helpers.h | 72 +++ > drivers/media/platform/amphion/vpu_v4l2.c | 625 +++++++++++++++++++ > drivers/media/platform/amphion/vpu_v4l2.h | 53 ++ > 5 files changed, 1395 insertions(+) > create mode 100644 drivers/media/platform/amphion/vpu_color.c > create mode 100644 drivers/media/platform/amphion/vpu_helpers.c > create mode 100644 drivers/media/platform/amphion/vpu_helpers.h > create mode 100644 drivers/media/platform/amphion/vpu_v4l2.c > create mode 100644 drivers/media/platform/amphion/vpu_v4l2.h > > diff --git a/drivers/media/platform/amphion/vpu_color.c b/drivers/media/platform/amphion/vpu_color.c > new file mode 100644 > index 000000000000..29d1d5edc901 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_color.c > @@ -0,0 +1,192 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "COLOR" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_helpers.h" > + > +static const u8 colorprimaries[] = { > + 0, > + V4L2_COLORSPACE_REC709, /*Rec. ITU-R BT.709-6*/ > + 0, > + 0, > + V4L2_COLORSPACE_470_SYSTEM_M, /*Rec. ITU-R BT.470-6 System M*/ > + V4L2_COLORSPACE_470_SYSTEM_BG,/*Rec. ITU-R BT.470-6 System B, G*/ > + V4L2_COLORSPACE_SMPTE170M, /*SMPTE170M*/ > + V4L2_COLORSPACE_SMPTE240M, /*SMPTE240M*/ > + 0, /*Generic film*/ > + V4L2_COLORSPACE_BT2020, /*Rec. ITU-R BT.2020-2*/ > + 0, /*SMPTE ST 428-1*/ > +}; > + > +static const u8 colortransfers[] = { > + 0, > + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.709-6*/ > + 0, > + 0, > + 0, /*Rec. ITU-R BT.470-6 System M*/ > + 0, /*Rec. ITU-R BT.470-6 System B, G*/ > + V4L2_XFER_FUNC_709, /*SMPTE170M*/ > + V4L2_XFER_FUNC_SMPTE240M,/*SMPTE240M*/ > + V4L2_XFER_FUNC_NONE, /*Linear transfer characteristics*/ > + 0, > + 0, > + 0, /*IEC 61966-2-4*/ > + 0, /*Rec. ITU-R BT.1361-0 extended colour gamut*/ > + V4L2_XFER_FUNC_SRGB, /*IEC 61966-2-1 sRGB or sYCC*/ > + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.2020-2 (10 bit system)*/ > + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.2020-2 (12 bit system)*/ > + V4L2_XFER_FUNC_SMPTE2084,/*SMPTE ST 2084*/ > + 0, /*SMPTE ST 428-1*/ > + 0 /*Rec. ITU-R BT.2100-0 hybrid log-gamma (HLG)*/ > +}; > + > +static const u8 colormatrixcoefs[] = { > + 0, > + V4L2_YCBCR_ENC_709, /*Rec. ITU-R BT.709-6*/ > + 0, > + 0, > + 0, /*Title 47 Code of Federal Regulations*/ > + V4L2_YCBCR_ENC_601, /*Rec. ITU-R BT.601-7 625*/ > + V4L2_YCBCR_ENC_601, /*Rec. ITU-R BT.601-7 525*/ > + V4L2_YCBCR_ENC_SMPTE240M, /*SMPTE240M*/ > + 0, > + V4L2_YCBCR_ENC_BT2020, /*Rec. ITU-R BT.2020-2*/ > + V4L2_YCBCR_ENC_BT2020_CONST_LUM /*Rec. ITU-R BT.2020-2 constant*/ > +}; > + > +u32 vpu_color_cvrt_primaries_v2i(u32 primaries) > +{ > + return VPU_ARRAY_FIND(colorprimaries, primaries); > +} > + > +u32 vpu_color_cvrt_primaries_i2v(u32 primaries) > +{ > + return VPU_ARRAY_AT(colorprimaries, primaries); > +} > + > +u32 vpu_color_cvrt_transfers_v2i(u32 transfers) > +{ > + return VPU_ARRAY_FIND(colortransfers, transfers); > +} > + > +u32 vpu_color_cvrt_transfers_i2v(u32 transfers) > +{ > + return VPU_ARRAY_AT(colortransfers, transfers); > +} > + > +u32 vpu_color_cvrt_matrix_v2i(u32 matrix) > +{ > + return VPU_ARRAY_FIND(colormatrixcoefs, matrix); > +} > + > +u32 vpu_color_cvrt_matrix_i2v(u32 matrix) > +{ > + return VPU_ARRAY_AT(colormatrixcoefs, matrix); > +} > + > +u32 vpu_color_cvrt_full_range_v2i(u32 full_range) > +{ > + return (full_range == V4L2_QUANTIZATION_FULL_RANGE); > +} > + > +u32 vpu_color_cvrt_full_range_i2v(u32 full_range) > +{ > + if (full_range) > + return V4L2_QUANTIZATION_FULL_RANGE; > + > + return V4L2_QUANTIZATION_LIM_RANGE; > +} > + > +int vpu_color_check_primaries(u32 primaries) > +{ > + return vpu_color_cvrt_primaries_v2i(primaries) ? 0 : -EINVAL; > +} > + > +int vpu_color_check_transfers(u32 transfers) > +{ > + return vpu_color_cvrt_transfers_v2i(transfers) ? 0 : -EINVAL; > +} > + > +int vpu_color_check_matrix(u32 matrix) > +{ > + return vpu_color_cvrt_matrix_v2i(matrix) ? 0 : -EINVAL; > +} > + > +int vpu_color_check_full_range(u32 full_range) > +{ > + int ret = -EINVAL; > + > + switch (full_range) { > + case V4L2_QUANTIZATION_FULL_RANGE: > + case V4L2_QUANTIZATION_LIM_RANGE: > + ret = 0; > + break; > + default: > + break; > + > + } > + > + return ret; > +} > + > +int vpu_color_get_default(u32 primaries, > + u32 *ptransfers, u32 *pmatrix, u32 *pfull_range) > +{ > + u32 transfers; > + u32 matrix; > + u32 full_range; > + > + switch (primaries) { > + case V4L2_COLORSPACE_REC709: > + transfers = V4L2_XFER_FUNC_709; > + matrix = V4L2_YCBCR_ENC_709; > + full_range = V4L2_QUANTIZATION_LIM_RANGE; > + break; > + case V4L2_COLORSPACE_470_SYSTEM_M: > + case V4L2_COLORSPACE_470_SYSTEM_BG: > + case V4L2_COLORSPACE_SMPTE170M: > + transfers = V4L2_XFER_FUNC_709; > + matrix = V4L2_YCBCR_ENC_601; > + full_range = V4L2_QUANTIZATION_LIM_RANGE; > + break; > + case V4L2_COLORSPACE_SMPTE240M: > + transfers = V4L2_XFER_FUNC_SMPTE240M; > + matrix = V4L2_YCBCR_ENC_SMPTE240M; > + full_range = V4L2_QUANTIZATION_LIM_RANGE; > + break; > + case V4L2_COLORSPACE_BT2020: > + transfers = V4L2_XFER_FUNC_709; > + matrix = V4L2_YCBCR_ENC_BT2020; > + full_range = V4L2_QUANTIZATION_LIM_RANGE; > + break; > + default: > + transfers = V4L2_XFER_FUNC_709; > + matrix = V4L2_YCBCR_ENC_709; > + full_range = V4L2_QUANTIZATION_LIM_RANGE; > + break; > + } > + > + if (ptransfers) > + *ptransfers = transfers; > + if (pmatrix) > + *pmatrix = matrix; > + if (pfull_range) > + *pfull_range = full_range; > + > + > + return 0; > +} > diff --git a/drivers/media/platform/amphion/vpu_helpers.c b/drivers/media/platform/amphion/vpu_helpers.c > new file mode 100644 > index 000000000000..484575d2975e > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_helpers.c > @@ -0,0 +1,453 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "HELPER" > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_core.h" > +#include "vpu_rpc.h" > +#include "vpu_helpers.h" > +#include "vpu_log.h" > + > +int vpu_helper_find_in_array_u8(const u8 *array, u32 size, u32 x) > +{ > + int i; > + > + for (i = 0; i < size; i++) { > + if (array[i] == x) > + return i; > + } > + > + return 0; > +} > + > +bool vpu_helper_check_type(struct vpu_inst *inst, u32 type) > +{ > + const struct vpu_format *pfmt; > + > + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { > + if (vpu_core_check_fmt(inst->core, pfmt->pixfmt)) > + continue; > + if (pfmt->type == type) > + return true; > + } > + > + return false; > +} > + > +const struct vpu_format *vpu_helper_find_format(struct vpu_inst *inst, u32 type, u32 pixelfmt) > +{ > + const struct vpu_format *pfmt; > + > + if (!inst || !inst->formats) > + return NULL; > + > + if (vpu_core_check_fmt(inst->core, pixelfmt)) > + return NULL; > + > + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { > + if (vpu_core_check_fmt(inst->core, pfmt->pixfmt)) > + continue; > + > + if (pfmt->pixfmt == pixelfmt && (!type || type == pfmt->type)) > + return pfmt; > + } > + > + return NULL; > +} > + > +const struct vpu_format *vpu_helper_enum_format(struct vpu_inst *inst, u32 type, int index) > +{ > + const struct vpu_format *pfmt; > + int i = 0; > + > + if (!inst || !inst->formats) > + return NULL; > + > + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { > + if (vpu_core_check_fmt(inst->core, pfmt->pixfmt)) > + continue; > + > + if (pfmt->type == type) { > + if (index == i) > + return pfmt; > + i++; > + } > + } > + > + return NULL; > +} > + > +u32 vpu_helper_valid_frame_width(struct vpu_inst *inst, u32 width) > +{ > + const struct vpu_core_resources *res; > + > + if (!inst || !inst->core || !inst->core->res) > + return width; > + > + res = inst->core->res; > + if (res->max_width) > + width = clamp(width, res->min_width, res->max_width); > + if (res->step_width) > + width = ALIGN(width, res->step_width); > + > + return width; > +} > + > +u32 vpu_helper_valid_frame_height(struct vpu_inst *inst, u32 height) > +{ > + const struct vpu_core_resources *res; > + > + if (!inst || !inst->core || !inst->core->res) > + return height; > + > + res = inst->core->res; > + if (res->max_height) > + height = clamp(height, res->min_height, res->max_height); > + if (res->step_height) > + height = ALIGN(height, res->step_height); > + > + return height; > +} > + > +u32 vpu_helper_get_frame_size(u32 fmt, u32 width, u32 height) > +{ > + switch (fmt) { > + case V4L2_PIX_FMT_NV12: > + return ((width * 3) >> 1) * height; > + default: > + return width * height; > + } > +} > + > +static u32 get_nv12_plane_size(u32 width, u32 height, int plane_no, > + u32 stride, u32 interlaced, u32 *pbl) > +{ > + u32 bytesperline; > + u32 size = 0; > + > + bytesperline = ALIGN(width, stride); > + height = ALIGN(height, 2); > + if (plane_no == 0) > + size = bytesperline * height; > + else > + size = bytesperline * height >> 1; > + > + if (pbl) > + *pbl = bytesperline; > + > + return size; > +} > + > +static u32 get_tiled_8l128_plane_size(u32 fmt, u32 width, u32 height, int plane_no, > + u32 stride, u32 interlaced, u32 *pbl) > +{ > + u32 ws = 3; > + u32 hs = 7; > + u32 bitdepth = 8; > + u32 bytesperline; > + u32 size = 0; > + > + if (interlaced) > + hs++; > + if (fmt == V4L2_PIX_FMT_NV12_10BE_8L128) > + bitdepth = 10; > + bytesperline = DIV_ROUND_UP(width * bitdepth, BITS_PER_BYTE); > + bytesperline = ALIGN(bytesperline, 1 << ws); > + bytesperline = ALIGN(bytesperline, stride); > + height = ALIGN(height, 1 << hs); > + if (plane_no == 0) > + size = bytesperline * height; > + else if (plane_no == 1) > + size = (bytesperline * ALIGN(height, 1 << (hs + 1))) >> 1; > + > + if (pbl) > + *pbl = bytesperline; > + > + return size; > +} > + > +static u32 get_default_plane_size(u32 width, u32 height, int plane_no, > + u32 stride, u32 interlaced, u32 *pbl) > +{ > + u32 bytesperline; > + u32 size = 0; > + > + bytesperline = ALIGN(width, stride); > + if (plane_no == 0) > + size = bytesperline * height; > + > + if (pbl) > + *pbl = bytesperline; > + > + return size; > +} > + > +u32 vpu_helper_get_plane_size(u32 fmt, u32 w, u32 h, int plane_no, > + u32 stride, u32 interlaced, u32 *pbl) > +{ > + switch (fmt) { > + case V4L2_PIX_FMT_NV12: > + return get_nv12_plane_size(w, h, plane_no, stride, interlaced, pbl); > + case V4L2_PIX_FMT_NV12_8L128: > + case V4L2_PIX_FMT_NV12_10BE_8L128: > + return get_tiled_8l128_plane_size(fmt, w, h, plane_no, stride, interlaced, pbl); > + default: > + return get_default_plane_size(w, h, plane_no, stride, interlaced, pbl); > + } > +} > + > +u32 vpu_helper_copy_from_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *rptr, u32 size, void *dst) > +{ > + u32 offset; > + u32 start; > + u32 end; > + void *virt; > + > + if (!stream_buffer || !rptr || !dst) > + return -EINVAL; > + > + if (!size) > + return 0; > + > + offset = *rptr; > + start = stream_buffer->phys; > + end = start + stream_buffer->length; > + virt = stream_buffer->virt; > + > + if (offset < start || offset > end) { > + vpu_err("rptr 0x%x is out of range [0x%x, 0x%x]\n", > + offset, start, end); > + return -EINVAL; > + } > + > + if (offset + size <= end) { > + memcpy(dst, virt + (offset - start), size); > + } else { > + memcpy(dst, virt + (offset - start), end - offset); > + memcpy(dst + end - offset, virt, size + offset - end); > + } > + > + *rptr = vpu_helper_step_walk(stream_buffer, offset, size); > + return size; > +} > + > +u32 vpu_helper_copy_to_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *wptr, u32 size, void *src) > +{ > + u32 offset; > + u32 start; > + u32 end; > + void *virt; > + > + if (!stream_buffer || !wptr || !src) > + return -EINVAL; > + > + if (!size) > + return 0; > + > + offset = *wptr; > + start = stream_buffer->phys; > + end = start + stream_buffer->length; > + virt = stream_buffer->virt; > + if (offset < start || offset > end) { > + vpu_err("wptr 0x%x is out of range [0x%x, 0x%x]\n", > + offset, start, end); > + return -EINVAL; > + } > + > + if (offset + size <= end) { > + memcpy(virt + (offset - start), src, size); > + } else { > + memcpy(virt + (offset - start), src, end - offset); > + memcpy(virt, src + end - offset, size + offset - end); > + } > + > + *wptr = vpu_helper_step_walk(stream_buffer, offset, size); > + > + return size; > +} > + > +u32 vpu_helper_memset_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *wptr, u8 val, u32 size) > +{ > + u32 offset; > + u32 start; > + u32 end; > + void *virt; > + > + if (!stream_buffer || !wptr) > + return -EINVAL; > + > + if (!size) > + return 0; > + > + offset = *wptr; > + start = stream_buffer->phys; > + end = start + stream_buffer->length; > + virt = stream_buffer->virt; > + if (offset < start || offset > end) { > + vpu_err("wptr 0x%x is out of range [0x%x, 0x%x]\n", > + offset, start, end); > + return -EINVAL; > + } > + > + if (offset + size <= end) { > + memset(virt + (offset - start), val, size); > + } else { > + memset(virt + (offset - start), val, end - offset); > + memset(virt, val, size + offset - end); > + } > + > + offset += size; > + if (offset >= end) > + offset -= stream_buffer->length; > + > + *wptr = offset; > + > + return size; > +} > + > +u32 vpu_helper_get_free_space(struct vpu_inst *inst) > +{ > + struct vpu_rpc_buffer_desc desc; > + > + if (vpu_iface_get_stream_buffer_desc(inst, &desc)) > + return 0; > + > + if (desc.rptr > desc.wptr) > + return desc.rptr - desc.wptr; > + else if (desc.rptr < desc.wptr) > + return (desc.end - desc.start + desc.rptr - desc.wptr); > + else > + return desc.end - desc.start; > +} > + > +u32 vpu_helper_get_used_space(struct vpu_inst *inst) > +{ > + struct vpu_rpc_buffer_desc desc; > + > + if (vpu_iface_get_stream_buffer_desc(inst, &desc)) > + return 0; > + > + if (desc.wptr > desc.rptr) > + return desc.wptr - desc.rptr; > + else if (desc.wptr < desc.rptr) > + return (desc.end - desc.start + desc.wptr - desc.rptr); > + else > + return 0; > +} > + > +int vpu_helper_g_volatile_ctrl(struct v4l2_ctrl *ctrl) > +{ > + struct vpu_inst *inst = ctrl_to_inst(ctrl); > + > + switch (ctrl->id) { > + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: > + ctrl->val = inst->min_buffer_cap; > + break; > + case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: > + ctrl->val = inst->min_buffer_out; > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +u32 vpu_helper_calc_coprime(u32 *a, u32 *b) > +{ > + int m = *a; > + int n = *b; > + > + if (m == 0) > + return n; > + if (n == 0) > + return m; > + > + while (n != 0) { > + int tmp = m % n; > + > + m = n; > + n = tmp; > + } > + *a = (*a) / m; > + *b = (*b) / m; > + > + return m; > +} > + > +#define READ_BYTE(buffer, pos) (*(u8 *)((buffer)->virt + ((pos) % buffer->length))) > +int vpu_helper_find_startcode(struct vpu_buffer *stream_buffer, > + u32 pixelformat, u32 offset, u32 bytesused) > +{ > + u32 start_code; > + int start_code_size; > + u32 val = 0; > + int i; > + int ret = -EINVAL; > + > + if (!stream_buffer || !stream_buffer->virt) > + return -EINVAL; > + > + switch (pixelformat) { > + case V4L2_PIX_FMT_H264: > + start_code_size = 4; > + start_code = 0x00000001; > + break; > + default: > + return 0; > + } > + > + for (i = 0; i < bytesused; i++) { > + val = (val << 8) | READ_BYTE(stream_buffer, offset + i); > + if (i < start_code_size - 1) > + continue; > + if (val == start_code) { > + ret = i + 1 - start_code_size; > + break; > + } > + } > + > + return ret; > +} > + > +int vpu_find_dst_by_src(struct vpu_pair *pairs, u32 cnt, u32 src) > +{ > + u32 i; > + > + if (!pairs || !cnt) > + return -EINVAL; > + > + for (i = 0; i < cnt; i++) { > + if (pairs[i].src == src) > + return pairs[i].dst; > + } > + > + return -EINVAL; > +} > + > +int vpu_find_src_by_dst(struct vpu_pair *pairs, u32 cnt, u32 dst) > +{ > + u32 i; > + > + if (!pairs || !cnt) > + return -EINVAL; > + > + for (i = 0; i < cnt; i++) { > + if (pairs[i].dst == dst) > + return pairs[i].src; > + } > + > + return -EINVAL; > +} > diff --git a/drivers/media/platform/amphion/vpu_helpers.h b/drivers/media/platform/amphion/vpu_helpers.h > new file mode 100644 > index 000000000000..22029eab7b56 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_helpers.h > @@ -0,0 +1,72 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_HELPERS_H > +#define _AMPHION_VPU_HELPERS_H > + > +struct vpu_pair { > + u32 src; > + u32 dst; > +}; > + > +#define MAKE_TIMESTAMP(s, ns) (((s32)(s) * NSEC_PER_SEC) + (ns)) > +#define VPU_INVALID_TIMESTAMP MAKE_TIMESTAMP(-1, 0) > +#define VPU_ARRAY_AT(array, i) (((i) < ARRAY_SIZE(array)) ? array[i] : 0) > +#define VPU_ARRAY_FIND(array, x) vpu_helper_find_in_array_u8(array, ARRAY_SIZE(array), x) > + > +int vpu_helper_find_in_array_u8(const u8 *array, u32 size, u32 x); > +bool vpu_helper_check_type(struct vpu_inst *inst, u32 type); > +const struct vpu_format *vpu_helper_find_format(struct vpu_inst *inst, u32 type, u32 pixelfmt); > +const struct vpu_format *vpu_helper_enum_format(struct vpu_inst *inst, u32 type, int index); > +u32 vpu_helper_valid_frame_width(struct vpu_inst *inst, u32 width); > +u32 vpu_helper_valid_frame_height(struct vpu_inst *inst, u32 height); > +u32 vpu_helper_get_frame_size(u32 fmt, u32 width, u32 height); > +u32 vpu_helper_get_plane_size(u32 fmt, u32 width, u32 height, int plane_no, > + u32 stride, u32 interlaced, u32 *pbl); > +u32 vpu_helper_copy_from_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *rptr, u32 size, void *dst); > +u32 vpu_helper_copy_to_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *wptr, u32 size, void *src); > +u32 vpu_helper_memset_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 *wptr, u8 val, u32 size); > +u32 vpu_helper_get_free_space(struct vpu_inst *inst); > +u32 vpu_helper_get_used_space(struct vpu_inst *inst); > +int vpu_helper_g_volatile_ctrl(struct v4l2_ctrl *ctrl); > +u32 vpu_helper_calc_coprime(u32 *a, u32 *b); > +void vpu_helper_get_kmp_next(const u8 *pattern, int *next, int size); > +int vpu_helper_kmp_search(u8 *s, int s_len, const u8 *p, int p_len, int *next); > +int vpu_helper_kmp_search_in_stream_buffer(struct vpu_buffer *stream_buffer, > + u32 offset, int bytesused, > + const u8 *p, int p_len, int *next); > +int vpu_helper_find_startcode(struct vpu_buffer *stream_buffer, > + u32 pixelformat, u32 offset, u32 bytesused); > + > +static inline u32 vpu_helper_step_walk(struct vpu_buffer *stream_buffer, u32 pos, u32 step) > +{ > + pos += step; > + if (pos > stream_buffer->phys + stream_buffer->length) > + pos -= stream_buffer->length; > + > + return pos; > +} > + > +int vpu_color_check_primaries(u32 primaries); > +int vpu_color_check_transfers(u32 transfers); > +int vpu_color_check_matrix(u32 matrix); > +int vpu_color_check_full_range(u32 full_range); > +u32 vpu_color_cvrt_primaries_v2i(u32 primaries); > +u32 vpu_color_cvrt_primaries_i2v(u32 primaries); > +u32 vpu_color_cvrt_transfers_v2i(u32 transfers); > +u32 vpu_color_cvrt_transfers_i2v(u32 transfers); > +u32 vpu_color_cvrt_matrix_v2i(u32 matrix); > +u32 vpu_color_cvrt_matrix_i2v(u32 matrix); > +u32 vpu_color_cvrt_full_range_v2i(u32 full_range); > +u32 vpu_color_cvrt_full_range_i2v(u32 full_range); > +int vpu_color_get_default(u32 primaries, > + u32 *ptransfers, u32 *pmatrix, u32 *pfull_range); > + > +int vpu_find_dst_by_src(struct vpu_pair *pairs, u32 cnt, u32 src); > +int vpu_find_src_by_dst(struct vpu_pair *pairs, u32 cnt, u32 dst); > +#endif > diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c > new file mode 100644 > index 000000000000..eb764c5d48e5 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_v4l2.c > @@ -0,0 +1,625 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "V4L2" > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_core.h" > +#include "vpu_v4l2.h" > +#include "vpu_msgs.h" > +#include "vpu_helpers.h" > +#include "vpu_log.h" > + > +void vpu_inst_lock(struct vpu_inst *inst) > +{ > + mutex_lock(&inst->lock); > +} > + > +void vpu_inst_unlock(struct vpu_inst *inst) > +{ > + mutex_unlock(&inst->lock); > +} > + > +dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no) > +{ > + return vb2_dma_contig_plane_dma_addr(vb, plane_no) + > + vb->planes[plane_no].data_offset; I've change the num_planes to 1 (tried 2, but failed differently), and it crashed while running: GST_DEBUG="v4l2*:7" gst-launch-1.0 videotestsrc num-buffers=100 ! v4l2h264enc ! fakesink So perhaps there is a overall review of the buffer allocation vs S_FMT implementation to be done here. [ 81.520167] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 81.529168] Mem abort info: [ 81.532467] ESR = 0x96000004 [ 81.539550] EC = 0x25: DABT (current EL), IL = 32 bits [ 81.546053] SET = 0, FnV = 0 [ 81.549771] EA = 0, S1PTW = 0 [ 81.553186] FSC = 0x04: level 0 translation fault [ 81.558280] Data abort info: [ 81.561437] ISV = 0, ISS = 0x00000004 [ 81.565527] CM = 0, WnR = 0 [ 81.568581] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000882741000 [ 81.575840] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 [ 81.586637] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 81.592247] Modules linked in: amphion_vpu_core v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_common imx_sc_key imx_sc_thermal crct10dif_ce rtc_imx_sc imx_sc_wdt amphion_vpu_dev fsl_imx8_ddr_perf isl29018 mpl3115 industrialio_triggered_buffer kfifo_buf videodev mc fuse drm ip_tables x_tables ipv6 [ 81.622805] CPU: 0 PID: 348 Comm: videotestsrc0:s Not tainted 5.15.0-rc2- imx8qxp+ #2 [ 81.630562] Hardware name: Freescale i.MX8QXP MEK (DT) [ 81.635711] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 81.642687] pc : vpu_get_vb_phy_addr+0x28/0x50 [amphion_vpu_core] [ 81.648838] lr : vpu_get_vb_phy_addr+0x20/0x50 [amphion_vpu_core] [ 81.654971] sp : ffff800012fcba30 [ 81.658287] x29: ffff800012fcba30 x28: ffff800012bd1040 x27: 0000000000000000 [ 81.665449] x26: 0000000000000000 x25: ffff800012fcbd28 x24: ffff800012bd1010 [ 81.672607] x23: ffff800012bd3200 x22: 0000000000000000 x21: ffff800015807044 [ 81.679766] x20: ffff000806a1ec00 x19: 0000000000000003 x18: 0000000000000000 [ 81.686924] x17: 0000000000000000 x16: 0000000000000000 x15: 0000a95ba29c327a [ 81.694083] x14: 000000000000039f x13: 0000000000000000 x12: 0000000000000000 [ 81.701241] x11: 0000000000000000 x10: 0000000000000990 x9 : ffff800012fcb900 [ 81.708400] x8 : ffff0008068f97f0 x7 : ffff00083f98b180 x6 : ffff000802070af8 [ 81.715558] x5 : ffff000802070af8 x4 : ffff800009296000 x3 : ffff000802073480 [ 81.722717] x2 : ffff000806a1ec00 x1 : 0000000000000002 x0 : 0000000000000000 [ 81.729877] Call trace: [ 81.732332] vpu_get_vb_phy_addr+0x28/0x50 [amphion_vpu_core] [ 81.738119] vpu_windsor_input_frame+0x84/0xbc [amphion_vpu_core] [ 81.744252] venc_process_output+0x88/0x10c [amphion_vpu_core] [ 81.750125] vpu_process_output_buffer+0xac/0x100 [amphion_vpu_core] [ 81.756519] venc_start_session+0x264/0x2cc [amphion_vpu_core] [ 81.762392] vpu_vb2_start_streaming+0x88/0xf4 [amphion_vpu_core] [ 81.768525] vb2_start_streaming+0x68/0x15c [videobuf2_common] [ 81.774398] vb2_core_streamon+0x94/0x19c [videobuf2_common] [ 81.780088] vb2_streamon+0x20/0x70 [videobuf2_v4l2] [ 81.785083] v4l2_m2m_ioctl_streamon+0x3c/0xa0 [v4l2_mem2mem] [ 81.790869] v4l_streamon+0x28/0x34 [videodev] [ 81.795412] __video_do_ioctl+0x17c/0x3e0 [videodev] [ 81.800460] video_usercopy+0x368/0x7e0 [videodev] [ 81.805333] video_ioctl2+0x1c/0x3c [videodev] [ 81.809859] v4l2_ioctl+0x44/0x64 [videodev] [ 81.814211] __arm64_sys_ioctl+0xac/0xf0 [ 81.818155] invoke_syscall+0x48/0x114 [ 81.821917] el0_svc_common.constprop.0+0x44/0xfc [ 81.826635] do_el0_svc+0x2c/0x94 [ 81.829961] el0_svc+0x28/0x80 [ 81.833027] el0t_64_sync_handler+0xa8/0x130 [ 81.837311] el0t_64_sync+0x1a0/0x1a4 [ 81.840992] Code: aa0003f4 97ff02f9 d37f7e61 8b334033 (f9400000) [ 81.847099] ---[ end trace 46cf421377a59de1 ]--- > +} > + > +unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) > +{ > + if (plane_no >= vb->num_planes) > + return 0; > + return vb2_plane_size(vb, plane_no) - vb->planes[plane_no].data_offset; > +} > + > +void vpu_v4l2_set_error(struct vpu_inst *inst) > +{ > + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); > + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); > + > + if (src_q) > + src_q->error = 1; > + if (dst_q) > + dst_q->error = 1; > +} > + > +int vpu_notify_eos(struct vpu_inst *inst) > +{ > + const struct v4l2_event ev = { > + .id = 0, > + .type = V4L2_EVENT_EOS > + }; > + > + inst_dbg(inst, LVL_FLOW, "notify eos event\n"); > + v4l2_event_queue_fh(&inst->fh, &ev); > + > + return 0; > +} > + > +int vpu_notify_source_change(struct vpu_inst *inst) > +{ > + const struct v4l2_event ev = { > + .id = 0, > + .type = V4L2_EVENT_SOURCE_CHANGE, > + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION > + }; > + > + inst_dbg(inst, LVL_FLOW, "notify source change event\n"); > + v4l2_event_queue_fh(&inst->fh, &ev); > + return 0; > +} > + > +const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, > + struct v4l2_format *f) > +{ > + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; > + u32 type = f->type; > + u32 stride; > + u32 bytesperline; > + u32 sizeimage; > + const struct vpu_format *fmt; > + int i; > + > + fmt = vpu_helper_find_format(inst, type, pixmp->pixelformat); > + if (!fmt) { > + fmt = vpu_helper_enum_format(inst, type, 0); > + if (!fmt) > + return NULL; > + pixmp->pixelformat = fmt->pixfmt; > + } > + > + stride = inst->core->res->stride; > + pixmp->width = vpu_helper_valid_frame_width(inst, pixmp->width); > + pixmp->height = vpu_helper_valid_frame_height(inst, pixmp->height); > + pixmp->flags = fmt->flags; > + pixmp->num_planes = fmt->num_planes; > + if (pixmp->field == V4L2_FIELD_ANY) > + pixmp->field = V4L2_FIELD_NONE; > + for (i = 0; i < pixmp->num_planes; i++) { > + sizeimage = vpu_helper_get_plane_size(pixmp->pixelformat, > + pixmp->width, pixmp->height, i, stride, > + pixmp->field == V4L2_FIELD_INTERLACED ? 1 : 0, > + &bytesperline); > + if ((s32)(pixmp->plane_fmt[i].bytesperline) <= 0) > + pixmp->plane_fmt[i].bytesperline = bytesperline; > + if ((s32)(pixmp->plane_fmt[i].sizeimage) <= 0) > + pixmp->plane_fmt[i].sizeimage = sizeimage; > + if (pixmp->plane_fmt[i].bytesperline < bytesperline) > + pixmp->plane_fmt[i].bytesperline = bytesperline; > + if (pixmp->plane_fmt[i].sizeimage <= sizeimage) > + pixmp->plane_fmt[i].sizeimage = sizeimage; > + } > + > + return fmt; > +} > + > +static bool vpu_check_ready(struct vpu_inst *inst, u32 type) > +{ > + if (!inst) > + return false; > + if (inst->state == VPU_CODEC_STATE_DEINIT || inst->id < 0) > + return false; > + if (!inst->ops->check_ready) > + return true; > + return call_vop(inst, check_ready, type); > +} > + > +int vpu_process_output_buffer(struct vpu_inst *inst) > +{ > + struct v4l2_m2m_buffer *buf = NULL; > + struct vpu_vb2_buffer *vpu_buf = NULL; > + > + if (!inst) > + return -EINVAL; > + > + if (!vpu_check_ready(inst, inst->out_format.type)) > + return -EINVAL; > + > + v4l2_m2m_for_each_src_buf(inst->m2m_ctx, buf) { > + vpu_buf = container_of(buf, struct vpu_vb2_buffer, m2m_buf); > + if (vpu_buf->state == VPU_BUF_STATE_IDLE) > + break; > + vpu_buf = NULL; > + } > + > + if (!vpu_buf) > + return -EINVAL; > + > + inst_dbg(inst, LVL_DEBUG, "frame id = %d / %d\n", > + vpu_buf->m2m_buf.vb.sequence, inst->sequence); > + return call_vop(inst, process_output, &vpu_buf->m2m_buf.vb.vb2_buf); > +} > + > +int vpu_process_capture_buffer(struct vpu_inst *inst) > +{ > + struct v4l2_m2m_buffer *buf = NULL; > + struct vpu_vb2_buffer *vpu_buf = NULL; > + > + if (!inst) > + return -EINVAL; > + > + if (!vpu_check_ready(inst, inst->cap_format.type)) > + return -EINVAL; > + > + v4l2_m2m_for_each_dst_buf(inst->m2m_ctx, buf) { > + vpu_buf = container_of(buf, struct vpu_vb2_buffer, m2m_buf); > + if (vpu_buf->state == VPU_BUF_STATE_IDLE) > + break; > + vpu_buf = NULL; > + } > + if (!vpu_buf) > + return -EINVAL; > + > + return call_vop(inst, process_capture, &vpu_buf->m2m_buf.vb.vb2_buf); > +} > + > +struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, > + u32 type, u32 sequence) > +{ > + struct v4l2_m2m_buffer *buf = NULL; > + struct vb2_v4l2_buffer *vbuf = NULL; > + > + if (V4L2_TYPE_IS_OUTPUT(type)) { > + v4l2_m2m_for_each_src_buf(inst->m2m_ctx, buf) { > + vbuf = &buf->vb; > + if (vbuf->sequence == sequence) > + break; > + vbuf = NULL; > + } > + } else { > + v4l2_m2m_for_each_dst_buf(inst->m2m_ctx, buf) { > + vbuf = &buf->vb; > + if (vbuf->sequence == sequence) > + break; > + vbuf = NULL; > + } > + } > + > + return vbuf; > +} > + > +struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, > + u32 type, u32 idx) > +{ > + struct v4l2_m2m_buffer *buf = NULL; > + struct vb2_v4l2_buffer *vbuf = NULL; > + > + if (V4L2_TYPE_IS_OUTPUT(type)) { > + v4l2_m2m_for_each_src_buf(inst->m2m_ctx, buf) { > + vbuf = &buf->vb; > + if (vbuf->vb2_buf.index == idx) > + break; > + vbuf = NULL; > + } > + } else { > + v4l2_m2m_for_each_dst_buf(inst->m2m_ctx, buf) { > + vbuf = &buf->vb; > + if (vbuf->vb2_buf.index == idx) > + break; > + vbuf = NULL; > + } > + } > + > + return vbuf; > +} > + > +int vpu_get_num_buffers(struct vpu_inst *inst, u32 type) > +{ > + struct vb2_queue *q; > + > + if (!inst || !inst->m2m_ctx) > + return -EINVAL; > + if (V4L2_TYPE_IS_OUTPUT(type)) > + q = v4l2_m2m_get_src_vq(inst->m2m_ctx); > + else > + q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); > + > + return q->num_buffers; > +} > + > +static void vpu_m2m_device_run(void *priv) > +{ > +} > + > +static void vpu_m2m_job_abort(void *priv) > +{ > + struct vpu_inst *inst = priv; > + > + v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx); > +} > + > +static const struct v4l2_m2m_ops vpu_m2m_ops = { > + .device_run = vpu_m2m_device_run, > + .job_abort = vpu_m2m_job_abort > +}; > + > +static int vpu_vb2_queue_setup(struct vb2_queue *vq, > + unsigned int *buf_count, > + unsigned int *plane_count, > + unsigned int psize[], > + struct device *allocators[]) > +{ > + struct vpu_inst *inst = vb2_get_drv_priv(vq); > + struct vpu_format *cur_fmt; > + int i; > + > + cur_fmt = vpu_get_format(inst, vq->type); > + > + if (*plane_count) { > + if (*plane_count != cur_fmt->num_planes) > + return -EINVAL; > + for (i = 0; i < cur_fmt->num_planes; i++) { > + if (psize[i] < cur_fmt->sizeimage[i]) > + return -EINVAL; > + } > + } > + > + *plane_count = cur_fmt->num_planes; > + for (i = 0; i < cur_fmt->num_planes; i++) > + psize[i] = cur_fmt->sizeimage[i]; > + > + inst_dbg(inst, LVL_FLOW, "%s queue setup : %u; %u, %u\n", > + vpu_type_name(vq->type), > + *buf_count, > + psize[0], psize[1]); > + > + return 0; > +} > + > +static int vpu_vb2_buf_init(struct vb2_buffer *vb) > +{ > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); > + > + vpu_buf->state = VPU_BUF_STATE_IDLE; > + > + return 0; > +} > + > +static void vpu_vb2_buf_cleanup(struct vb2_buffer *vb) > +{ > +} > + > +static int vpu_vb2_buf_prepare(struct vb2_buffer *vb) > +{ > + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); > + struct vpu_format *cur_fmt; > + u32 i; > + > + cur_fmt = vpu_get_format(inst, vb->type); > + if (vb->num_planes != cur_fmt->num_planes) > + return -EINVAL; > + for (i = 0; i < cur_fmt->num_planes; i++) { > + if (vpu_get_vb_length(vb, i) < cur_fmt->sizeimage[i]) { > + inst_err(inst, "%s buf[%d] is invalid\n", > + vpu_type_name(vb->type), > + vb->index); > + vpu_buf->state = VPU_BUF_STATE_ERROR; > + } > + } > + > + return 0; > +} > + > +static void vpu_vb2_buf_finish(struct vb2_buffer *vb) > +{ > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); > + struct vb2_queue *q = vb->vb2_queue; > + > + if (vbuf->flags & V4L2_BUF_FLAG_LAST) > + vpu_notify_eos(inst); > + > + if (list_empty(&q->done_list)) > + call_vop(inst, on_queue_empty, q->type); > +} > + > +void vpu_vb2_buffers_return(struct vpu_inst *inst, > + unsigned int type, enum vb2_buffer_state state) > +{ > + struct vb2_v4l2_buffer *buf; > + > + if (!inst || !inst->m2m_ctx) > + return; > + > + if (V4L2_TYPE_IS_OUTPUT(type)) { > + while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx))) > + v4l2_m2m_buf_done(buf, state); > + } else { > + while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx))) > + v4l2_m2m_buf_done(buf, state); > + } > +} > + > +static int vpu_vb2_start_streaming(struct vb2_queue *q, unsigned int count) > +{ > + struct vpu_inst *inst = vb2_get_drv_priv(q); > + int ret; > + > + vpu_inst_unlock(inst); > + ret = vpu_inst_register(inst); > + vpu_inst_lock(inst); > + if (ret) > + return ret; > + > + vpu_inst_get(inst); > + inst_dbg(inst, LVL_FLOW, "%s start streaming : %d\n", > + vpu_type_name(q->type), q->num_buffers); > + call_vop(inst, start, q->type); > + vb2_clear_last_buffer_dequeued(q); > + > + return 0; > +} > + > +static void vpu_vb2_stop_streaming(struct vb2_queue *q) > +{ > + struct vpu_inst *inst = vb2_get_drv_priv(q); > + > + inst_dbg(inst, LVL_FLOW, "%s stop streaming\n", vpu_type_name(q->type)); > + > + call_vop(inst, stop, q->type); > + vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_ERROR); > + if (V4L2_TYPE_IS_OUTPUT(q->type)) > + inst->sequence = 0; > + > + vpu_inst_put(inst); > +} > + > +static void vpu_vb2_buf_queue(struct vb2_buffer *vb) > +{ > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); > + > + inst_dbg(inst, LVL_DEBUG, "%s buf queue\n", vpu_type_name(vb->type)); > + > + if (V4L2_TYPE_IS_OUTPUT(vb->type)) { > + vbuf->sequence = inst->sequence++; > + if ((s64)vb->timestamp < 0) > + vb->timestamp = VPU_INVALID_TIMESTAMP; > + } > + > + v4l2_m2m_buf_queue(inst->m2m_ctx, vbuf); > + vpu_process_output_buffer(inst); > + vpu_process_capture_buffer(inst); > +} > + > +static struct vb2_ops vpu_vb2_ops = { > + .queue_setup = vpu_vb2_queue_setup, > + .buf_init = vpu_vb2_buf_init, > + .buf_cleanup = vpu_vb2_buf_cleanup, > + .buf_prepare = vpu_vb2_buf_prepare, > + .buf_finish = vpu_vb2_buf_finish, > + .start_streaming = vpu_vb2_start_streaming, > + .stop_streaming = vpu_vb2_stop_streaming, > + .buf_queue = vpu_vb2_buf_queue, > + .wait_prepare = vb2_ops_wait_prepare, > + .wait_finish = vb2_ops_wait_finish, > +}; > + > +static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, > + struct vb2_queue *dst_vq) > +{ > + struct vpu_inst *inst = priv; > + int ret; > + > + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; > + src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; > + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; > + src_vq->ops = &vpu_vb2_ops; > + src_vq->mem_ops = &vb2_dma_contig_memops; > + if (inst->type == VPU_CORE_TYPE_DEC && inst->use_stream_buffer) > + src_vq->mem_ops = &vb2_vmalloc_memops; > + src_vq->drv_priv = inst; > + src_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); > + src_vq->allow_zero_bytesused = 1; > + src_vq->min_buffers_needed = 1; > + src_vq->dev = inst->core->dev; > + src_vq->lock = &inst->lock; > + ret = vb2_queue_init(src_vq); > + if (ret) > + return ret; > + > + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; > + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; > + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; > + dst_vq->ops = &vpu_vb2_ops; > + dst_vq->mem_ops = &vb2_dma_contig_memops; > + if (inst->type == VPU_CORE_TYPE_ENC && inst->use_stream_buffer) > + dst_vq->mem_ops = &vb2_vmalloc_memops; > + dst_vq->drv_priv = inst; > + dst_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); > + dst_vq->allow_zero_bytesused = 1; > + dst_vq->min_buffers_needed = 1; > + dst_vq->dev = inst->core->dev; > + dst_vq->lock = &inst->lock; > + ret = vb2_queue_init(dst_vq); > + if (ret) { > + vb2_queue_release(src_vq); > + return ret; > + } > + > + return 0; > +} > + > +static int vpu_v4l2_release(struct vpu_inst *inst) > +{ > + struct vpu_core *core = inst->core; > + > + inst_dbg(inst, LVL_FLOW, "%s\n", __func__); > + > + vpu_release_core(core); > + > + if (inst->workqueue) { > + cancel_work_sync(&inst->msg_work); > + destroy_workqueue(inst->workqueue); > + inst->workqueue = NULL; > + } > + if (inst->m2m_ctx) { > + v4l2_m2m_ctx_release(inst->m2m_ctx); > + inst->m2m_ctx = NULL; > + } > + if (inst->m2m_dev) { > + v4l2_m2m_release(inst->m2m_dev); > + inst->m2m_dev = NULL; > + } > + > + v4l2_ctrl_handler_free(&inst->ctrl_handler); > + mutex_destroy(&inst->lock); > + v4l2_fh_del(&inst->fh); > + v4l2_fh_exit(&inst->fh); > + > + call_vop(inst, cleanup); > + > + return 0; > +} > + > +int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) > +{ > + struct vpu_dev *vpu = video_drvdata(file); > + struct video_device *vdev; > + struct vpu_core *core = NULL; > + int ret = 0; > + > + WARN_ON(!file || !inst || !inst->ops); > + > + if (inst->type == VPU_CORE_TYPE_ENC) > + vdev = vpu->vdev_enc; > + else > + vdev = vpu->vdev_dec; > + > + mutex_init(&inst->lock); > + INIT_LIST_HEAD(&inst->cmd_q); > + > + inst->id = VPU_INST_NULL_ID; > + inst->release = vpu_v4l2_release; > + inst->core = vpu_request_core(vpu, inst->type); > + inst->pid = current->pid; > + inst->tgid = current->tgid; > + > + core = inst->core; > + if (!core) { > + vpu_err("there is no core for %s\n", > + vpu_core_type_desc(inst->type)); > + return -EINVAL; > + } > + > + inst->min_buffer_cap = 2; > + inst->min_buffer_out = 2; > + > + ret = call_vop(inst, ctrl_init); > + if (ret) > + goto error; > + > + inst->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops); > + if (IS_ERR(inst->m2m_dev)) { > + vpu_err("v4l2_m2m_init fail\n"); > + ret = PTR_ERR(inst->m2m_dev); > + goto error; > + } > + > + inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, > + inst, vpu_m2m_queue_init); > + if (IS_ERR(inst->m2m_ctx)) { > + vpu_err("v4l2_m2m_ctx_init fail\n"); > + ret = PTR_ERR(inst->m2m_dev); > + goto error; > + } > + > + v4l2_fh_init(&inst->fh, vdev); > + v4l2_fh_add(&inst->fh); > + inst->fh.ctrl_handler = &inst->ctrl_handler; > + inst->fh.m2m_ctx = inst->m2m_ctx; > + file->private_data = &inst->fh; > + inst->state = VPU_CODEC_STATE_DEINIT; > + inst->workqueue = alloc_workqueue("vpu_inst", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); > + if (inst->workqueue) { > + INIT_WORK(&inst->msg_work, vpu_inst_run_work); > + ret = kfifo_init(&inst->msg_fifo, > + inst->msg_buffer, > + roundup_pow_of_two(sizeof(inst->msg_buffer))); > + if (ret) { > + destroy_workqueue(inst->workqueue); > + inst->workqueue = NULL; > + } > + } > + atomic_set(&inst->ref_count, 0); > + vpu_inst_get(inst); > + vpu_dbg(LVL_FLOW, "open, tgid = %d, pid = %d\n", inst->tgid, inst->pid); > + > + return 0; > +error: > + if (inst->m2m_ctx) { > + v4l2_m2m_ctx_release(inst->m2m_ctx); > + inst->m2m_ctx = NULL; > + } > + if (inst->m2m_dev) { > + v4l2_m2m_release(inst->m2m_dev); > + inst->m2m_dev = NULL; > + } > + v4l2_ctrl_handler_free(&inst->ctrl_handler); > + vpu_release_core(inst->core); > + > + return ret; > +} > + > +int vpu_v4l2_close(struct file *file) > +{ > + struct vpu_inst *inst = to_inst(file); > + struct vb2_queue *src_q; > + struct vb2_queue *dst_q; > + > + inst_dbg(inst, LVL_FLOW, "close\n"); > + src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); > + dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); > + vpu_inst_lock(inst); > + if (vb2_is_streaming(src_q)) > + v4l2_m2m_streamoff(file, inst->m2m_ctx, src_q->type); > + if (vb2_is_streaming(dst_q)) > + v4l2_m2m_streamoff(file, inst->m2m_ctx, dst_q->type); > + vpu_inst_unlock(inst); > + > + call_vop(inst, release); > + vpu_inst_unregister(inst); > + vpu_inst_put(inst); > + > + return 0; > +} > diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h > new file mode 100644 > index 000000000000..8873e1f66072 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_v4l2.h > @@ -0,0 +1,53 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_V4L2_H > +#define _AMPHION_VPU_V4L2_H > + > +#include > + > +void vpu_inst_lock(struct vpu_inst *inst); > +void vpu_inst_unlock(struct vpu_inst *inst); > + > +int vpu_v4l2_open(struct file *file, struct vpu_inst *inst); > +int vpu_v4l2_close(struct file *file); > + > +const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f); > +int vpu_process_output_buffer(struct vpu_inst *inst); > +int vpu_process_capture_buffer(struct vpu_inst *inst); > +struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence); > +struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx); > +void vpu_v4l2_set_error(struct vpu_inst *inst); > +int vpu_notify_eos(struct vpu_inst *inst); > +int vpu_notify_source_change(struct vpu_inst *inst); > +void vpu_vb2_buffers_return(struct vpu_inst *inst, > + unsigned int type, enum vb2_buffer_state state); > +int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); > + > +dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no); > +unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no); > +static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) > +{ > + if (V4L2_TYPE_IS_OUTPUT(type)) > + return &inst->out_format; > + else > + return &inst->cap_format; > +} > + > +static inline char *vpu_type_name(u32 type) > +{ > + return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; > +} > + > +static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf) > +{ > +#ifdef V4L2_BUF_FLAG_CODECCONFIG > + return (vbuf->flags & V4L2_BUF_FLAG_CODECCONFIG) ? 1 : 0; > +#else > + return 0; > +#endif > +} > + > +#endif From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCB5DC433F5 for ; Thu, 23 Sep 2021 14:42:49 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AB3F7611C6 for ; Thu, 23 Sep 2021 14:42:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org AB3F7611C6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ndufresne.ca Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:Cc:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=KD/5bmPWRfvRYxpo+zDyFZe6gyCkgdfCsNixPTjQPEA=; b=QQyG3u2w2Ucmej wVUSEpSk3Ps9yDkEmc5T8VClIHsYnlogedlgZwabT1QxrDBfn06mN4ijAbB7g2V8KfNAr9UB6Sjio 68mMCFbAw6A4i6/ECQNY59kh9XYZkvJoJqGULXny0P8e7Soy2wwmmXqiyyXXDiK3zExBDP0gw49hU 7jHXHtkB+UwkvhFUHBRjg/n3+LxjdIZJjWkO+YCnHBhXVpNtP5v4FbFc45+QlsHt5uDZAoWjCNcWB r3rp0UA3FdqxdKMrTOGUtleAYEYhD3a+EVnVLiJYB89HL0Kh2DdN40JrIy1+HGyskFAOOL5g+ctoy mW+ZU+ziP0GTBZrqtnNQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mTPu4-00BrS0-5e; Thu, 23 Sep 2021 14:40:48 +0000 Received: from mail-qk1-x729.google.com ([2607:f8b0:4864:20::729]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mTPsu-00Br7Q-8G for linux-arm-kernel@lists.infradead.org; Thu, 23 Sep 2021 14:39:42 +0000 Received: by mail-qk1-x729.google.com with SMTP id q81so19085743qke.5 for ; Thu, 23 Sep 2021 07:39:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ndufresne-ca.20210112.gappssmtp.com; s=20210112; h=message-id:subject:from:to:cc:date:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=Fa6LZKz84Q6MojmcZUqxb0ZP/qUzgyt0GHuc22T9vXw=; b=FIJHJk8gobCXHWekmYCqLOQ+2FA1x+adCXlrmV0gmswS/qcZc8ix9NFqg0TfDpngiX BwTGlGn0mAsPGTrQ61p3fKsIc9tISK+u1XdLPEWy7fCdvRJO+nR0fLg9jGfO13Mk2bWl uKAzrDoG4plYkUFjc1gRBioV8Mn2KIO8/hs6yWinz5+sxlw5Dov6BeROgg8N7JX78NLq 2f+uwHYH0rb7wZiITjimMPFq9fXYNq3BlzyY+Mw4IJ2MK6nXc2UOeSlyZC+6GyPryLOp Cu6kjPjmaFsvXhs0GzMrG51f9ZpTM21O3rMW5hfbxHOOPZQilEYAIRkBm6rqj0xliMVw QXzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=Fa6LZKz84Q6MojmcZUqxb0ZP/qUzgyt0GHuc22T9vXw=; b=ww4SiTQ05QuKHOpGI+CUYXAJEPeB39YUcO41Pt1NoP9Et2tSrXGMLnYttJB2rWRJDc fK972KRNhh7RTYZC77shnQOYbmzPQlXVY0Ra+zesxroK/8RzjpKT7MUWmgnTb0Kpi+Dg lNfjSU8xiZ8ng42S7eZBwtgUpx9Zp04Uk1xg6S06Ubd8cXwuHU6vXb+T5OnJTDMh2Pza FfLqEIp0i+f4emmFPj86L5f6dMceVmrITFFuhcmfErUfMdpTEEePnIIt/ZedgfEGL9tS MF4hYi8jMEYyH0lVtEV8EiEWR1zXfLD89pg930NpdmMNPVm6Rz7WBQeRkoegLQ651COl qBHQ== X-Gm-Message-State: AOAM533eggrRuyMehR5ZXWOiuFwD5jIlzlVVPcjKLN9Trk3lloeic2pN EOKs5QZgcJ54wpQmE9T0kS72Ow== X-Google-Smtp-Source: ABdhPJxkuXpHKO2NQEkf/f4kuWYm4bFeTNSFdx1N+XiMJuvH30YJ2wQlMKjfhw+QzXkSzuebqEEtTg== X-Received: by 2002:a37:9fc1:: with SMTP id i184mr5294532qke.247.1632407974323; Thu, 23 Sep 2021 07:39:34 -0700 (PDT) Received: from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net. [173.246.12.168]) by smtp.gmail.com with ESMTPSA id l195sm4431074qke.98.2021.09.23.07.39.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Sep 2021 07:39:33 -0700 (PDT) Message-ID: Subject: Re: [PATCH v9 06/13] media: amphion: add vpu v4l2 m2m support From: Nicolas Dufresne To: Ming Qian , mchehab@kernel.org, shawnguo@kernel.org, robh+dt@kernel.org, s.hauer@pengutronix.de Cc: hverkuil-cisco@xs4all.nl, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, aisheng.dong@nxp.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org Date: Thu, 23 Sep 2021 10:39:32 -0400 In-Reply-To: <4142cb1f597a3fbb176cf18c6a3d6356cc0d4064.1631521295.git.ming.qian@nxp.com> References: <4142cb1f597a3fbb176cf18c6a3d6356cc0d4064.1631521295.git.ming.qian@nxp.com> User-Agent: Evolution 3.40.4 (3.40.4-1.fc34) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210923_073936_361621_C81F35EC X-CRM114-Status: GOOD ( 23.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org TGUgbHVuZGkgMTMgc2VwdGVtYnJlIDIwMjEgw6AgMTc6MTEgKzA4MDAsIE1pbmcgUWlhbiBhIMOp Y3JpdMKgOgo+IHZwdV92NGwyLmMgaW1wbGVtZW50cyB0aGUgdjRsMiBtMm0gZHJpdmVyIG1ldGhv ZHMuCj4gdnB1X2hlbHBlcnMuYyBpbXBsZW1lbnRzIHRoZSBjb21tb24gaGVscGVyIGZ1bmN0aW9u cwo+IHZwdV9jb2xvci5jIGNvbnZlcnRzIHRoZSB2NGwyIGNvbG9yc3BhY2Ugd2l0aCBpc28KPiAK PiBTaWduZWQtb2ZmLWJ5OiBNaW5nIFFpYW4gPG1pbmcucWlhbkBueHAuY29tPgo+IFNpZ25lZC1v ZmYtYnk6IFNoaWppZSBRaW4gPHNoaWppZS5xaW5AbnhwLmNvbT4KPiBTaWduZWQtb2ZmLWJ5OiBa aG91IFBlbmcgPGVhZ2xlLnpob3VAbnhwLmNvbT4KPiBSZXBvcnRlZC1ieToga2VybmVsIHRlc3Qg cm9ib3QgPGxrcEBpbnRlbC5jb20+Cj4gLS0tCj4gIGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1w aGlvbi92cHVfY29sb3IuYyAgIHwgMTkyICsrKysrKwo+ICBkcml2ZXJzL21lZGlhL3BsYXRmb3Jt L2FtcGhpb24vdnB1X2hlbHBlcnMuYyB8IDQ1MyArKysrKysrKysrKysrKwo+ICBkcml2ZXJzL21l ZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2hlbHBlcnMuaCB8ICA3MiArKysKPiAgZHJpdmVycy9t ZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV92NGwyLmMgICAgfCA2MjUgKysrKysrKysrKysrKysr KysrKwo+ICBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X3Y0bDIuaCAgICB8ICA1 MyArKwo+ICA1IGZpbGVzIGNoYW5nZWQsIDEzOTUgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9k ZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9jb2xvci5jCj4gIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2hlbHBl cnMuYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9u L3ZwdV9oZWxwZXJzLmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZv cm0vYW1waGlvbi92cHVfdjRsMi5jCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlh L3BsYXRmb3JtL2FtcGhpb24vdnB1X3Y0bDIuaAo+IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21l ZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2NvbG9yLmMgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3Jt L2FtcGhpb24vdnB1X2NvbG9yLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAw MDAwMDAwMC4uMjlkMWQ1ZWRjOTAxCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvbWVk aWEvcGxhdGZvcm0vYW1waGlvbi92cHVfY29sb3IuYwo+IEBAIC0wLDAgKzEsMTkyIEBACj4gKy8v IFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCj4gKy8qCj4gKyAqIENvcHlyaWdodCAy MDIwLTIwMjEgTlhQCj4gKyAqLwo+ICsKPiArI2RlZmluZSBUQUcJCSJDT0xPUiIKPiArCj4gKyNp bmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kZXZpY2UuaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L2lvY3RsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cj4gKyNpbmNs dWRlIDxsaW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5j bHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KPiArI2luY2x1 ZGUgPGxpbnV4L3R5cGVzLmg+Cj4gKyNpbmNsdWRlIDxtZWRpYS92NGwyLWRldmljZS5oPgo+ICsj aW5jbHVkZSAidnB1LmgiCj4gKyNpbmNsdWRlICJ2cHVfaGVscGVycy5oIgo+ICsKPiArc3RhdGlj IGNvbnN0IHU4IGNvbG9ycHJpbWFyaWVzW10gPSB7Cj4gKwkwLAo+ICsJVjRMMl9DT0xPUlNQQUNF X1JFQzcwOSwgICAgICAgIC8qUmVjLiBJVFUtUiBCVC43MDktNiovCj4gKwkwLAo+ICsJMCwKPiAr CVY0TDJfQ09MT1JTUEFDRV80NzBfU1lTVEVNX00sIC8qUmVjLiBJVFUtUiBCVC40NzAtNiBTeXN0 ZW0gTSovCj4gKwlWNEwyX0NPTE9SU1BBQ0VfNDcwX1NZU1RFTV9CRywvKlJlYy4gSVRVLVIgQlQu NDcwLTYgU3lzdGVtIEIsIEcqLwo+ICsJVjRMMl9DT0xPUlNQQUNFX1NNUFRFMTcwTSwgICAgLypT TVBURTE3ME0qLwo+ICsJVjRMMl9DT0xPUlNQQUNFX1NNUFRFMjQwTSwgICAgLypTTVBURTI0ME0q Lwo+ICsJMCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgLypHZW5lcmljIGZpbG0qLwo+ICsJ VjRMMl9DT0xPUlNQQUNFX0JUMjAyMCwgICAgICAgLypSZWMuIElUVS1SIEJULjIwMjAtMiovCj4g KwkwLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKlNNUFRFIFNUIDQyOC0xKi8KPiArfTsK PiArCj4gK3N0YXRpYyBjb25zdCB1OCBjb2xvcnRyYW5zZmVyc1tdID0gewo+ICsJMCwKPiArCVY0 TDJfWEZFUl9GVU5DXzcwOSwgICAgICAvKlJlYy4gSVRVLVIgQlQuNzA5LTYqLwo+ICsJMCwKPiAr CTAsCj4gKwkwLCAgICAgICAgICAgICAgICAgICAgICAgLypSZWMuIElUVS1SIEJULjQ3MC02IFN5 c3RlbSBNKi8KPiArCTAsICAgICAgICAgICAgICAgICAgICAgICAvKlJlYy4gSVRVLVIgQlQuNDcw LTYgU3lzdGVtIEIsIEcqLwo+ICsJVjRMMl9YRkVSX0ZVTkNfNzA5LCAgICAgIC8qU01QVEUxNzBN Ki8KPiArCVY0TDJfWEZFUl9GVU5DX1NNUFRFMjQwTSwvKlNNUFRFMjQwTSovCj4gKwlWNEwyX1hG RVJfRlVOQ19OT05FLCAgICAgLypMaW5lYXIgdHJhbnNmZXIgY2hhcmFjdGVyaXN0aWNzKi8KPiAr CTAsCj4gKwkwLAo+ICsJMCwgICAgICAgICAgICAgICAgICAgICAgIC8qSUVDIDYxOTY2LTItNCov Cj4gKwkwLCAgICAgICAgICAgICAgICAgICAgICAgLypSZWMuIElUVS1SIEJULjEzNjEtMCBleHRl bmRlZCBjb2xvdXIgZ2FtdXQqLwo+ICsJVjRMMl9YRkVSX0ZVTkNfU1JHQiwgICAgIC8qSUVDIDYx OTY2LTItMSBzUkdCIG9yIHNZQ0MqLwo+ICsJVjRMMl9YRkVSX0ZVTkNfNzA5LCAgICAgIC8qUmVj LiBJVFUtUiBCVC4yMDIwLTIgKDEwIGJpdCBzeXN0ZW0pKi8KPiArCVY0TDJfWEZFUl9GVU5DXzcw OSwgICAgICAvKlJlYy4gSVRVLVIgQlQuMjAyMC0yICgxMiBiaXQgc3lzdGVtKSovCj4gKwlWNEwy X1hGRVJfRlVOQ19TTVBURTIwODQsLypTTVBURSBTVCAyMDg0Ki8KPiArCTAsICAgICAgICAgICAg ICAgICAgICAgICAvKlNNUFRFIFNUIDQyOC0xKi8KPiArCTAgICAgICAgICAgICAgICAgICAgICAg ICAvKlJlYy4gSVRVLVIgQlQuMjEwMC0wIGh5YnJpZCBsb2ctZ2FtbWEgKEhMRykqLwo+ICt9Owo+ ICsKPiArc3RhdGljIGNvbnN0IHU4IGNvbG9ybWF0cml4Y29lZnNbXSA9IHsKPiArCTAsCj4gKwlW NEwyX1lDQkNSX0VOQ183MDksICAgICAgICAgICAgIC8qUmVjLiBJVFUtUiBCVC43MDktNiovCj4g KwkwLAo+ICsJMCwKPiArCTAsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLypUaXRsZSA0 NyBDb2RlIG9mIEZlZGVyYWwgUmVndWxhdGlvbnMqLwo+ICsJVjRMMl9ZQ0JDUl9FTkNfNjAxLCAg ICAgICAgICAgICAvKlJlYy4gSVRVLVIgQlQuNjAxLTcgNjI1Ki8KPiArCVY0TDJfWUNCQ1JfRU5D XzYwMSwgICAgICAgICAgICAgLypSZWMuIElUVS1SIEJULjYwMS03IDUyNSovCj4gKwlWNEwyX1lD QkNSX0VOQ19TTVBURTI0ME0sICAgICAgIC8qU01QVEUyNDBNKi8KPiArCTAsCj4gKwlWNEwyX1lD QkNSX0VOQ19CVDIwMjAsICAgICAgICAgIC8qUmVjLiBJVFUtUiBCVC4yMDIwLTIqLwo+ICsJVjRM Ml9ZQ0JDUl9FTkNfQlQyMDIwX0NPTlNUX0xVTSAvKlJlYy4gSVRVLVIgQlQuMjAyMC0yIGNvbnN0 YW50Ki8KPiArfTsKPiArCj4gK3UzMiB2cHVfY29sb3JfY3ZydF9wcmltYXJpZXNfdjJpKHUzMiBw cmltYXJpZXMpCj4gK3sKPiArCXJldHVybiBWUFVfQVJSQVlfRklORChjb2xvcnByaW1hcmllcywg cHJpbWFyaWVzKTsKPiArfQo+ICsKPiArdTMyIHZwdV9jb2xvcl9jdnJ0X3ByaW1hcmllc19pMnYo dTMyIHByaW1hcmllcykKPiArewo+ICsJcmV0dXJuIFZQVV9BUlJBWV9BVChjb2xvcnByaW1hcmll cywgcHJpbWFyaWVzKTsKPiArfQo+ICsKPiArdTMyIHZwdV9jb2xvcl9jdnJ0X3RyYW5zZmVyc192 MmkodTMyIHRyYW5zZmVycykKPiArewo+ICsJcmV0dXJuIFZQVV9BUlJBWV9GSU5EKGNvbG9ydHJh bnNmZXJzLCB0cmFuc2ZlcnMpOwo+ICt9Cj4gKwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfdHJhbnNm ZXJzX2kydih1MzIgdHJhbnNmZXJzKQo+ICt7Cj4gKwlyZXR1cm4gVlBVX0FSUkFZX0FUKGNvbG9y dHJhbnNmZXJzLCB0cmFuc2ZlcnMpOwo+ICt9Cj4gKwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfbWF0 cml4X3YyaSh1MzIgbWF0cml4KQo+ICt7Cj4gKwlyZXR1cm4gVlBVX0FSUkFZX0ZJTkQoY29sb3Jt YXRyaXhjb2VmcywgbWF0cml4KTsKPiArfQo+ICsKPiArdTMyIHZwdV9jb2xvcl9jdnJ0X21hdHJp eF9pMnYodTMyIG1hdHJpeCkKPiArewo+ICsJcmV0dXJuIFZQVV9BUlJBWV9BVChjb2xvcm1hdHJp eGNvZWZzLCBtYXRyaXgpOwo+ICt9Cj4gKwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfZnVsbF9yYW5n ZV92MmkodTMyIGZ1bGxfcmFuZ2UpCj4gK3sKPiArCXJldHVybiAoZnVsbF9yYW5nZSA9PSBWNEwy X1FVQU5USVpBVElPTl9GVUxMX1JBTkdFKTsKPiArfQo+ICsKPiArdTMyIHZwdV9jb2xvcl9jdnJ0 X2Z1bGxfcmFuZ2VfaTJ2KHUzMiBmdWxsX3JhbmdlKQo+ICt7Cj4gKwlpZiAoZnVsbF9yYW5nZSkK PiArCQlyZXR1cm4gVjRMMl9RVUFOVElaQVRJT05fRlVMTF9SQU5HRTsKPiArCj4gKwlyZXR1cm4g VjRMMl9RVUFOVElaQVRJT05fTElNX1JBTkdFOwo+ICt9Cj4gKwo+ICtpbnQgdnB1X2NvbG9yX2No ZWNrX3ByaW1hcmllcyh1MzIgcHJpbWFyaWVzKQo+ICt7Cj4gKwlyZXR1cm4gdnB1X2NvbG9yX2N2 cnRfcHJpbWFyaWVzX3YyaShwcmltYXJpZXMpID8gMCA6IC1FSU5WQUw7Cj4gK30KPiArCj4gK2lu dCB2cHVfY29sb3JfY2hlY2tfdHJhbnNmZXJzKHUzMiB0cmFuc2ZlcnMpCj4gK3sKPiArCXJldHVy biB2cHVfY29sb3JfY3ZydF90cmFuc2ZlcnNfdjJpKHRyYW5zZmVycykgPyAwIDogLUVJTlZBTDsK PiArfQo+ICsKPiAraW50IHZwdV9jb2xvcl9jaGVja19tYXRyaXgodTMyIG1hdHJpeCkKPiArewo+ ICsJcmV0dXJuIHZwdV9jb2xvcl9jdnJ0X21hdHJpeF92MmkobWF0cml4KSA/IDAgOiAtRUlOVkFM Owo+ICt9Cj4gKwo+ICtpbnQgdnB1X2NvbG9yX2NoZWNrX2Z1bGxfcmFuZ2UodTMyIGZ1bGxfcmFu Z2UpCj4gK3sKPiArCWludCByZXQgPSAtRUlOVkFMOwo+ICsKPiArCXN3aXRjaCAoZnVsbF9yYW5n ZSkgewo+ICsJY2FzZSBWNEwyX1FVQU5USVpBVElPTl9GVUxMX1JBTkdFOgo+ICsJY2FzZSBWNEwy X1FVQU5USVpBVElPTl9MSU1fUkFOR0U6Cj4gKwkJcmV0ID0gMDsKPiArCQlicmVhazsKPiArCWRl ZmF1bHQ6Cj4gKwkJYnJlYWs7Cj4gKwo+ICsJfQo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiAr Cj4gK2ludCB2cHVfY29sb3JfZ2V0X2RlZmF1bHQodTMyIHByaW1hcmllcywKPiArCQl1MzIgKnB0 cmFuc2ZlcnMsIHUzMiAqcG1hdHJpeCwgdTMyICpwZnVsbF9yYW5nZSkKPiArewo+ICsJdTMyIHRy YW5zZmVyczsKPiArCXUzMiBtYXRyaXg7Cj4gKwl1MzIgZnVsbF9yYW5nZTsKPiArCj4gKwlzd2l0 Y2ggKHByaW1hcmllcykgewo+ICsJY2FzZSBWNEwyX0NPTE9SU1BBQ0VfUkVDNzA5Ogo+ICsJCXRy YW5zZmVycyA9IFY0TDJfWEZFUl9GVU5DXzcwOTsKPiArCQltYXRyaXggPSBWNEwyX1lDQkNSX0VO Q183MDk7Cj4gKwkJZnVsbF9yYW5nZSA9IFY0TDJfUVVBTlRJWkFUSU9OX0xJTV9SQU5HRTsKPiAr CQlicmVhazsKPiArCWNhc2UgVjRMMl9DT0xPUlNQQUNFXzQ3MF9TWVNURU1fTToKPiArCWNhc2Ug VjRMMl9DT0xPUlNQQUNFXzQ3MF9TWVNURU1fQkc6Cj4gKwljYXNlIFY0TDJfQ09MT1JTUEFDRV9T TVBURTE3ME06Cj4gKwkJdHJhbnNmZXJzID0gVjRMMl9YRkVSX0ZVTkNfNzA5Owo+ICsJCW1hdHJp eCA9IFY0TDJfWUNCQ1JfRU5DXzYwMTsKPiArCQlmdWxsX3JhbmdlID0gVjRMMl9RVUFOVElaQVRJ T05fTElNX1JBTkdFOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBWNEwyX0NPTE9SU1BBQ0VfU01QVEUy NDBNOgo+ICsJCXRyYW5zZmVycyA9IFY0TDJfWEZFUl9GVU5DX1NNUFRFMjQwTTsKPiArCQltYXRy aXggPSBWNEwyX1lDQkNSX0VOQ19TTVBURTI0ME07Cj4gKwkJZnVsbF9yYW5nZSA9IFY0TDJfUVVB TlRJWkFUSU9OX0xJTV9SQU5HRTsKPiArCQlicmVhazsKPiArCWNhc2UgVjRMMl9DT0xPUlNQQUNF X0JUMjAyMDoKPiArCQl0cmFuc2ZlcnMgPSBWNEwyX1hGRVJfRlVOQ183MDk7Cj4gKwkJbWF0cml4 ID0gVjRMMl9ZQ0JDUl9FTkNfQlQyMDIwOwo+ICsJCWZ1bGxfcmFuZ2UgPSBWNEwyX1FVQU5USVpB VElPTl9MSU1fUkFOR0U7Cj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCXRyYW5zZmVycyA9 IFY0TDJfWEZFUl9GVU5DXzcwOTsKPiArCQltYXRyaXggPSBWNEwyX1lDQkNSX0VOQ183MDk7Cj4g KwkJZnVsbF9yYW5nZSA9IFY0TDJfUVVBTlRJWkFUSU9OX0xJTV9SQU5HRTsKPiArCQlicmVhazsK PiArCX0KPiArCj4gKwlpZiAocHRyYW5zZmVycykKPiArCQkqcHRyYW5zZmVycyA9IHRyYW5zZmVy czsKPiArCWlmIChwbWF0cml4KQo+ICsJCSpwbWF0cml4ID0gbWF0cml4Owo+ICsJaWYgKHBmdWxs X3JhbmdlKQo+ICsJCSpwZnVsbF9yYW5nZSA9IGZ1bGxfcmFuZ2U7Cj4gKwo+ICsKPiArCXJldHVy biAwOwo+ICt9Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92 cHVfaGVscGVycy5jIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9oZWxwZXJz LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uNDg0NTc1ZDI5 NzVlCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlv bi92cHVfaGVscGVycy5jCj4gQEAgLTAsMCArMSw0NTMgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlk ZW50aWZpZXI6IEdQTC0yLjAKPiArLyoKPiArICogQ29weXJpZ2h0IDIwMjAtMjAyMSBOWFAKPiAr ICovCj4gKwo+ICsjZGVmaW5lIFRBRwkJIkhFTFBFUiIKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQu aD4KPiArI2luY2x1ZGUgPGxpbnV4L2ludGVyY29ubmVjdC5oPgo+ICsjaW5jbHVkZSA8bGludXgv aW9jdGwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tl cm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9w bGF0Zm9ybV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgInZwdS5oIgo+ICsjaW5jbHVkZSAidnB1X2Nv cmUuaCIKPiArI2luY2x1ZGUgInZwdV9ycGMuaCIKPiArI2luY2x1ZGUgInZwdV9oZWxwZXJzLmgi Cj4gKyNpbmNsdWRlICJ2cHVfbG9nLmgiCj4gKwo+ICtpbnQgdnB1X2hlbHBlcl9maW5kX2luX2Fy cmF5X3U4KGNvbnN0IHU4ICphcnJheSwgdTMyIHNpemUsIHUzMiB4KQo+ICt7Cj4gKwlpbnQgaTsK PiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7Cj4gKwkJaWYgKGFycmF5W2ldID09 IHgpCj4gKwkJCXJldHVybiBpOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICti b29sIHZwdV9oZWxwZXJfY2hlY2tfdHlwZShzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUzMiB0eXBl KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgdnB1X2Zvcm1hdCAqcGZtdDsKPiArCj4gKwlmb3IgKHBm bXQgPSBpbnN0LT5mb3JtYXRzOyBwZm10LT5waXhmbXQ7IHBmbXQrKykgewo+ICsJCWlmICh2cHVf Y29yZV9jaGVja19mbXQoaW5zdC0+Y29yZSwgcGZtdC0+cGl4Zm10KSkKPiArCQkJY29udGludWU7 Cj4gKwkJaWYgKHBmbXQtPnR5cGUgPT0gdHlwZSkKPiArCQkJcmV0dXJuIHRydWU7Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICtjb25zdCBzdHJ1Y3QgdnB1X2Zvcm1hdCAq dnB1X2hlbHBlcl9maW5kX2Zvcm1hdChzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUzMiB0eXBlLCB1 MzIgcGl4ZWxmbXQpCj4gK3sKPiArCWNvbnN0IHN0cnVjdCB2cHVfZm9ybWF0ICpwZm10Owo+ICsK PiArCWlmICghaW5zdCB8fCAhaW5zdC0+Zm9ybWF0cykKPiArCQlyZXR1cm4gTlVMTDsKPiArCj4g KwlpZiAodnB1X2NvcmVfY2hlY2tfZm10KGluc3QtPmNvcmUsIHBpeGVsZm10KSkKPiArCQlyZXR1 cm4gTlVMTDsKPiArCj4gKwlmb3IgKHBmbXQgPSBpbnN0LT5mb3JtYXRzOyBwZm10LT5waXhmbXQ7 IHBmbXQrKykgewo+ICsJCWlmICh2cHVfY29yZV9jaGVja19mbXQoaW5zdC0+Y29yZSwgcGZtdC0+ cGl4Zm10KSkKPiArCQkJY29udGludWU7Cj4gKwo+ICsJCWlmIChwZm10LT5waXhmbXQgPT0gcGl4 ZWxmbXQgJiYgKCF0eXBlIHx8IHR5cGUgPT0gcGZtdC0+dHlwZSkpCj4gKwkJCXJldHVybiBwZm10 Owo+ICsJfQo+ICsKPiArCXJldHVybiBOVUxMOwo+ICt9Cj4gKwo+ICtjb25zdCBzdHJ1Y3QgdnB1 X2Zvcm1hdCAqdnB1X2hlbHBlcl9lbnVtX2Zvcm1hdChzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUz MiB0eXBlLCBpbnQgaW5kZXgpCj4gK3sKPiArCWNvbnN0IHN0cnVjdCB2cHVfZm9ybWF0ICpwZm10 Owo+ICsJaW50IGkgPSAwOwo+ICsKPiArCWlmICghaW5zdCB8fCAhaW5zdC0+Zm9ybWF0cykKPiAr CQlyZXR1cm4gTlVMTDsKPiArCj4gKwlmb3IgKHBmbXQgPSBpbnN0LT5mb3JtYXRzOyBwZm10LT5w aXhmbXQ7IHBmbXQrKykgewo+ICsJCWlmICh2cHVfY29yZV9jaGVja19mbXQoaW5zdC0+Y29yZSwg cGZtdC0+cGl4Zm10KSkKPiArCQkJY29udGludWU7Cj4gKwo+ICsJCWlmIChwZm10LT50eXBlID09 IHR5cGUpIHsKPiArCQkJaWYgKGluZGV4ID09IGkpCj4gKwkJCQlyZXR1cm4gcGZtdDsKPiArCQkJ aSsrOwo+ICsJCX0KPiArCX0KPiArCj4gKwlyZXR1cm4gTlVMTDsKPiArfQo+ICsKPiArdTMyIHZw dV9oZWxwZXJfdmFsaWRfZnJhbWVfd2lkdGgoc3RydWN0IHZwdV9pbnN0ICppbnN0LCB1MzIgd2lk dGgpCj4gK3sKPiArCWNvbnN0IHN0cnVjdCB2cHVfY29yZV9yZXNvdXJjZXMgKnJlczsKPiArCj4g KwlpZiAoIWluc3QgfHwgIWluc3QtPmNvcmUgfHwgIWluc3QtPmNvcmUtPnJlcykKPiArCQlyZXR1 cm4gd2lkdGg7Cj4gKwo+ICsJcmVzID0gaW5zdC0+Y29yZS0+cmVzOwo+ICsJaWYgKHJlcy0+bWF4 X3dpZHRoKQo+ICsJCXdpZHRoID0gY2xhbXAod2lkdGgsIHJlcy0+bWluX3dpZHRoLCByZXMtPm1h eF93aWR0aCk7Cj4gKwlpZiAocmVzLT5zdGVwX3dpZHRoKQo+ICsJCXdpZHRoID0gQUxJR04od2lk dGgsIHJlcy0+c3RlcF93aWR0aCk7Cj4gKwo+ICsJcmV0dXJuIHdpZHRoOwo+ICt9Cj4gKwo+ICt1 MzIgdnB1X2hlbHBlcl92YWxpZF9mcmFtZV9oZWlnaHQoc3RydWN0IHZwdV9pbnN0ICppbnN0LCB1 MzIgaGVpZ2h0KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgdnB1X2NvcmVfcmVzb3VyY2VzICpyZXM7 Cj4gKwo+ICsJaWYgKCFpbnN0IHx8ICFpbnN0LT5jb3JlIHx8ICFpbnN0LT5jb3JlLT5yZXMpCj4g KwkJcmV0dXJuIGhlaWdodDsKPiArCj4gKwlyZXMgPSBpbnN0LT5jb3JlLT5yZXM7Cj4gKwlpZiAo cmVzLT5tYXhfaGVpZ2h0KQo+ICsJCWhlaWdodCA9IGNsYW1wKGhlaWdodCwgcmVzLT5taW5faGVp Z2h0LCByZXMtPm1heF9oZWlnaHQpOwo+ICsJaWYgKHJlcy0+c3RlcF9oZWlnaHQpCj4gKwkJaGVp Z2h0ID0gQUxJR04oaGVpZ2h0LCByZXMtPnN0ZXBfaGVpZ2h0KTsKPiArCj4gKwlyZXR1cm4gaGVp Z2h0Owo+ICt9Cj4gKwo+ICt1MzIgdnB1X2hlbHBlcl9nZXRfZnJhbWVfc2l6ZSh1MzIgZm10LCB1 MzIgd2lkdGgsIHUzMiBoZWlnaHQpCj4gK3sKPiArCXN3aXRjaCAoZm10KSB7Cj4gKwljYXNlIFY0 TDJfUElYX0ZNVF9OVjEyOgo+ICsJCXJldHVybiAoKHdpZHRoICogMykgPj4gMSkgKiBoZWlnaHQ7 Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiB3aWR0aCAqIGhlaWdodDsKPiArCX0KPiArfQo+ICsK PiArc3RhdGljIHUzMiBnZXRfbnYxMl9wbGFuZV9zaXplKHUzMiB3aWR0aCwgdTMyIGhlaWdodCwg aW50IHBsYW5lX25vLAo+ICsJCQl1MzIgc3RyaWRlLCB1MzIgaW50ZXJsYWNlZCwgdTMyICpwYmwp Cj4gK3sKPiArCXUzMiBieXRlc3BlcmxpbmU7Cj4gKwl1MzIgc2l6ZSA9IDA7Cj4gKwo+ICsJYnl0 ZXNwZXJsaW5lID0gQUxJR04od2lkdGgsIHN0cmlkZSk7Cj4gKwloZWlnaHQgPSBBTElHTihoZWln aHQsIDIpOwo+ICsJaWYgKHBsYW5lX25vID09IDApCj4gKwkJc2l6ZSA9IGJ5dGVzcGVybGluZSAq IGhlaWdodDsKPiArCWVsc2UKPiArCQlzaXplID0gYnl0ZXNwZXJsaW5lICogaGVpZ2h0ID4+IDE7 Cj4gKwo+ICsJaWYgKHBibCkKPiArCQkqcGJsID0gYnl0ZXNwZXJsaW5lOwo+ICsKPiArCXJldHVy biBzaXplOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdTMyIGdldF90aWxlZF84bDEyOF9wbGFuZV9zaXpl KHUzMiBmbXQsIHUzMiB3aWR0aCwgdTMyIGhlaWdodCwgaW50IHBsYW5lX25vLAo+ICsJCQl1MzIg c3RyaWRlLCB1MzIgaW50ZXJsYWNlZCwgdTMyICpwYmwpCj4gK3sKPiArCXUzMiB3cyA9IDM7Cj4g Kwl1MzIgaHMgPSA3Owo+ICsJdTMyIGJpdGRlcHRoID0gODsKPiArCXUzMiBieXRlc3BlcmxpbmU7 Cj4gKwl1MzIgc2l6ZSA9IDA7Cj4gKwo+ICsJaWYgKGludGVybGFjZWQpCj4gKwkJaHMrKzsKPiAr CWlmIChmbXQgPT0gVjRMMl9QSVhfRk1UX05WMTJfMTBCRV84TDEyOCkKPiArCQliaXRkZXB0aCA9 IDEwOwo+ICsJYnl0ZXNwZXJsaW5lID0gRElWX1JPVU5EX1VQKHdpZHRoICogYml0ZGVwdGgsIEJJ VFNfUEVSX0JZVEUpOwo+ICsJYnl0ZXNwZXJsaW5lID0gQUxJR04oYnl0ZXNwZXJsaW5lLCAxIDw8 IHdzKTsKPiArCWJ5dGVzcGVybGluZSA9IEFMSUdOKGJ5dGVzcGVybGluZSwgc3RyaWRlKTsKPiAr CWhlaWdodCA9IEFMSUdOKGhlaWdodCwgMSA8PCBocyk7Cj4gKwlpZiAocGxhbmVfbm8gPT0gMCkK PiArCQlzaXplID0gYnl0ZXNwZXJsaW5lICogaGVpZ2h0Owo+ICsJZWxzZSBpZiAocGxhbmVfbm8g PT0gMSkKPiArCQlzaXplID0gKGJ5dGVzcGVybGluZSAqIEFMSUdOKGhlaWdodCwgMSA8PCAoaHMg KyAxKSkpID4+IDE7Cj4gKwo+ICsJaWYgKHBibCkKPiArCQkqcGJsID0gYnl0ZXNwZXJsaW5lOwo+ ICsKPiArCXJldHVybiBzaXplOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdTMyIGdldF9kZWZhdWx0X3Bs YW5lX3NpemUodTMyIHdpZHRoLCB1MzIgaGVpZ2h0LCBpbnQgcGxhbmVfbm8sCj4gKwkJCXUzMiBz dHJpZGUsIHUzMiBpbnRlcmxhY2VkLCB1MzIgKnBibCkKPiArewo+ICsJdTMyIGJ5dGVzcGVybGlu ZTsKPiArCXUzMiBzaXplID0gMDsKPiArCj4gKwlieXRlc3BlcmxpbmUgPSBBTElHTih3aWR0aCwg c3RyaWRlKTsKPiArCWlmIChwbGFuZV9ubyA9PSAwKQo+ICsJCXNpemUgPSBieXRlc3BlcmxpbmUg KiBoZWlnaHQ7Cj4gKwo+ICsJaWYgKHBibCkKPiArCQkqcGJsID0gYnl0ZXNwZXJsaW5lOwo+ICsK PiArCXJldHVybiBzaXplOwo+ICt9Cj4gKwo+ICt1MzIgdnB1X2hlbHBlcl9nZXRfcGxhbmVfc2l6 ZSh1MzIgZm10LCB1MzIgdywgdTMyIGgsIGludCBwbGFuZV9ubywKPiArCQl1MzIgc3RyaWRlLCB1 MzIgaW50ZXJsYWNlZCwgdTMyICpwYmwpCj4gK3sKPiArCXN3aXRjaCAoZm10KSB7Cj4gKwljYXNl IFY0TDJfUElYX0ZNVF9OVjEyOgo+ICsJCXJldHVybiBnZXRfbnYxMl9wbGFuZV9zaXplKHcsIGgs IHBsYW5lX25vLCBzdHJpZGUsIGludGVybGFjZWQsIHBibCk7Cj4gKwljYXNlIFY0TDJfUElYX0ZN VF9OVjEyXzhMMTI4Ogo+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTlYxMl8xMEJFXzhMMTI4Ogo+ICsJ CXJldHVybiBnZXRfdGlsZWRfOGwxMjhfcGxhbmVfc2l6ZShmbXQsIHcsIGgsIHBsYW5lX25vLCBz dHJpZGUsIGludGVybGFjZWQsIHBibCk7Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiBnZXRfZGVm YXVsdF9wbGFuZV9zaXplKHcsIGgsIHBsYW5lX25vLCBzdHJpZGUsIGludGVybGFjZWQsIHBibCk7 Cj4gKwl9Cj4gK30KPiArCj4gK3UzMiB2cHVfaGVscGVyX2NvcHlfZnJvbV9zdHJlYW1fYnVmZmVy KHN0cnVjdCB2cHVfYnVmZmVyICpzdHJlYW1fYnVmZmVyLAo+ICsJCQkJCXUzMiAqcnB0ciwgdTMy IHNpemUsIHZvaWQgKmRzdCkKPiArewo+ICsJdTMyIG9mZnNldDsKPiArCXUzMiBzdGFydDsKPiAr CXUzMiBlbmQ7Cj4gKwl2b2lkICp2aXJ0Owo+ICsKPiArCWlmICghc3RyZWFtX2J1ZmZlciB8fCAh cnB0ciB8fCAhZHN0KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmICghc2l6ZSkKPiAr CQlyZXR1cm4gMDsKPiArCj4gKwlvZmZzZXQgPSAqcnB0cjsKPiArCXN0YXJ0ID0gc3RyZWFtX2J1 ZmZlci0+cGh5czsKPiArCWVuZCA9IHN0YXJ0ICsgc3RyZWFtX2J1ZmZlci0+bGVuZ3RoOwo+ICsJ dmlydCA9IHN0cmVhbV9idWZmZXItPnZpcnQ7Cj4gKwo+ICsJaWYgKG9mZnNldCA8IHN0YXJ0IHx8 IG9mZnNldCA+IGVuZCkgewo+ICsJCXZwdV9lcnIoInJwdHIgMHgleCBpcyBvdXQgb2YgcmFuZ2Ug WzB4JXgsIDB4JXhdXG4iLAo+ICsJCQkJb2Zmc2V0LCBzdGFydCwgZW5kKTsKPiArCQlyZXR1cm4g LUVJTlZBTDsKPiArCX0KPiArCj4gKwlpZiAob2Zmc2V0ICsgc2l6ZSA8PSBlbmQpIHsKPiArCQlt ZW1jcHkoZHN0LCB2aXJ0ICsgKG9mZnNldCAtIHN0YXJ0KSwgc2l6ZSk7Cj4gKwl9IGVsc2Ugewo+ ICsJCW1lbWNweShkc3QsIHZpcnQgKyAob2Zmc2V0IC0gc3RhcnQpLCBlbmQgLSBvZmZzZXQpOwo+ ICsJCW1lbWNweShkc3QgKyBlbmQgLSBvZmZzZXQsIHZpcnQsIHNpemUgKyBvZmZzZXQgLSBlbmQp Owo+ICsJfQo+ICsKPiArCSpycHRyID0gdnB1X2hlbHBlcl9zdGVwX3dhbGsoc3RyZWFtX2J1ZmZl ciwgb2Zmc2V0LCBzaXplKTsKPiArCXJldHVybiBzaXplOwo+ICt9Cj4gKwo+ICt1MzIgdnB1X2hl bHBlcl9jb3B5X3RvX3N0cmVhbV9idWZmZXIoc3RydWN0IHZwdV9idWZmZXIgKnN0cmVhbV9idWZm ZXIsCj4gKwkJCQl1MzIgKndwdHIsIHUzMiBzaXplLCB2b2lkICpzcmMpCj4gK3sKPiArCXUzMiBv ZmZzZXQ7Cj4gKwl1MzIgc3RhcnQ7Cj4gKwl1MzIgZW5kOwo+ICsJdm9pZCAqdmlydDsKPiArCj4g KwlpZiAoIXN0cmVhbV9idWZmZXIgfHwgIXdwdHIgfHwgIXNyYykKPiArCQlyZXR1cm4gLUVJTlZB TDsKPiArCj4gKwlpZiAoIXNpemUpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJb2Zmc2V0ID0gKndw dHI7Cj4gKwlzdGFydCA9IHN0cmVhbV9idWZmZXItPnBoeXM7Cj4gKwllbmQgPSBzdGFydCArIHN0 cmVhbV9idWZmZXItPmxlbmd0aDsKPiArCXZpcnQgPSBzdHJlYW1fYnVmZmVyLT52aXJ0Owo+ICsJ aWYgKG9mZnNldCA8IHN0YXJ0IHx8IG9mZnNldCA+IGVuZCkgewo+ICsJCXZwdV9lcnIoIndwdHIg MHgleCBpcyBvdXQgb2YgcmFuZ2UgWzB4JXgsIDB4JXhdXG4iLAo+ICsJCQkJb2Zmc2V0LCBzdGFy dCwgZW5kKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlpZiAob2Zmc2V0ICsg c2l6ZSA8PSBlbmQpIHsKPiArCQltZW1jcHkodmlydCArIChvZmZzZXQgLSBzdGFydCksIHNyYywg c2l6ZSk7Cj4gKwl9IGVsc2Ugewo+ICsJCW1lbWNweSh2aXJ0ICsgKG9mZnNldCAtIHN0YXJ0KSwg c3JjLCBlbmQgLSBvZmZzZXQpOwo+ICsJCW1lbWNweSh2aXJ0LCBzcmMgKyBlbmQgLSBvZmZzZXQs IHNpemUgKyBvZmZzZXQgLSBlbmQpOwo+ICsJfQo+ICsKPiArCSp3cHRyID0gdnB1X2hlbHBlcl9z dGVwX3dhbGsoc3RyZWFtX2J1ZmZlciwgb2Zmc2V0LCBzaXplKTsKPiArCj4gKwlyZXR1cm4gc2l6 ZTsKPiArfQo+ICsKPiArdTMyIHZwdV9oZWxwZXJfbWVtc2V0X3N0cmVhbV9idWZmZXIoc3RydWN0 IHZwdV9idWZmZXIgKnN0cmVhbV9idWZmZXIsCj4gKwkJCQl1MzIgKndwdHIsIHU4IHZhbCwgdTMy IHNpemUpCj4gK3sKPiArCXUzMiBvZmZzZXQ7Cj4gKwl1MzIgc3RhcnQ7Cj4gKwl1MzIgZW5kOwo+ ICsJdm9pZCAqdmlydDsKPiArCj4gKwlpZiAoIXN0cmVhbV9idWZmZXIgfHwgIXdwdHIpCj4gKwkJ cmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJaWYgKCFzaXplKQo+ICsJCXJldHVybiAwOwo+ICsKPiAr CW9mZnNldCA9ICp3cHRyOwo+ICsJc3RhcnQgPSBzdHJlYW1fYnVmZmVyLT5waHlzOwo+ICsJZW5k ID0gc3RhcnQgKyBzdHJlYW1fYnVmZmVyLT5sZW5ndGg7Cj4gKwl2aXJ0ID0gc3RyZWFtX2J1ZmZl ci0+dmlydDsKPiArCWlmIChvZmZzZXQgPCBzdGFydCB8fCBvZmZzZXQgPiBlbmQpIHsKPiArCQl2 cHVfZXJyKCJ3cHRyIDB4JXggaXMgb3V0IG9mIHJhbmdlIFsweCV4LCAweCV4XVxuIiwKPiArCQkJ CW9mZnNldCwgc3RhcnQsIGVuZCk7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJ aWYgKG9mZnNldCArIHNpemUgPD0gZW5kKSB7Cj4gKwkJbWVtc2V0KHZpcnQgKyAob2Zmc2V0IC0g c3RhcnQpLCB2YWwsIHNpemUpOwo+ICsJfSBlbHNlIHsKPiArCQltZW1zZXQodmlydCArIChvZmZz ZXQgLSBzdGFydCksIHZhbCwgZW5kIC0gb2Zmc2V0KTsKPiArCQltZW1zZXQodmlydCwgdmFsLCBz aXplICsgb2Zmc2V0IC0gZW5kKTsKPiArCX0KPiArCj4gKwlvZmZzZXQgKz0gc2l6ZTsKPiArCWlm IChvZmZzZXQgPj0gZW5kKQo+ICsJCW9mZnNldCAtPSBzdHJlYW1fYnVmZmVyLT5sZW5ndGg7Cj4g Kwo+ICsJKndwdHIgPSBvZmZzZXQ7Cj4gKwo+ICsJcmV0dXJuIHNpemU7Cj4gK30KPiArCj4gK3Uz MiB2cHVfaGVscGVyX2dldF9mcmVlX3NwYWNlKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCkKPiArewo+ ICsJc3RydWN0IHZwdV9ycGNfYnVmZmVyX2Rlc2MgZGVzYzsKPiArCj4gKwlpZiAodnB1X2lmYWNl X2dldF9zdHJlYW1fYnVmZmVyX2Rlc2MoaW5zdCwgJmRlc2MpKQo+ICsJCXJldHVybiAwOwo+ICsK PiArCWlmIChkZXNjLnJwdHIgPiBkZXNjLndwdHIpCj4gKwkJcmV0dXJuIGRlc2MucnB0ciAtIGRl c2Mud3B0cjsKPiArCWVsc2UgaWYgKGRlc2MucnB0ciA8IGRlc2Mud3B0cikKPiArCQlyZXR1cm4g KGRlc2MuZW5kIC0gZGVzYy5zdGFydCArIGRlc2MucnB0ciAtIGRlc2Mud3B0cik7Cj4gKwllbHNl Cj4gKwkJcmV0dXJuIGRlc2MuZW5kIC0gZGVzYy5zdGFydDsKPiArfQo+ICsKPiArdTMyIHZwdV9o ZWxwZXJfZ2V0X3VzZWRfc3BhY2Uoc3RydWN0IHZwdV9pbnN0ICppbnN0KQo+ICt7Cj4gKwlzdHJ1 Y3QgdnB1X3JwY19idWZmZXJfZGVzYyBkZXNjOwo+ICsKPiArCWlmICh2cHVfaWZhY2VfZ2V0X3N0 cmVhbV9idWZmZXJfZGVzYyhpbnN0LCAmZGVzYykpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJaWYg KGRlc2Mud3B0ciA+IGRlc2MucnB0cikKPiArCQlyZXR1cm4gZGVzYy53cHRyIC0gZGVzYy5ycHRy Owo+ICsJZWxzZSBpZiAoZGVzYy53cHRyIDwgZGVzYy5ycHRyKQo+ICsJCXJldHVybiAoZGVzYy5l bmQgLSBkZXNjLnN0YXJ0ICsgZGVzYy53cHRyIC0gZGVzYy5ycHRyKTsKPiArCWVsc2UKPiArCQly ZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IHZwdV9oZWxwZXJfZ192b2xhdGlsZV9jdHJsKHN0cnVj dCB2NGwyX2N0cmwgKmN0cmwpCj4gK3sKPiArCXN0cnVjdCB2cHVfaW5zdCAqaW5zdCA9IGN0cmxf dG9faW5zdChjdHJsKTsKPiArCj4gKwlzd2l0Y2ggKGN0cmwtPmlkKSB7Cj4gKwljYXNlIFY0TDJf Q0lEX01JTl9CVUZGRVJTX0ZPUl9DQVBUVVJFOgo+ICsJCWN0cmwtPnZhbCA9IGluc3QtPm1pbl9i dWZmZXJfY2FwOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBWNEwyX0NJRF9NSU5fQlVGRkVSU19GT1Jf T1VUUFVUOgo+ICsJCWN0cmwtPnZhbCA9IGluc3QtPm1pbl9idWZmZXJfb3V0Owo+ICsJCWJyZWFr Owo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArdTMyIHZwdV9oZWxwZXJfY2FsY19jb3ByaW1lKHUzMiAqYSwgdTMyICpi KQo+ICt7Cj4gKwlpbnQgbSA9ICphOwo+ICsJaW50IG4gPSAqYjsKPiArCj4gKwlpZiAobSA9PSAw KQo+ICsJCXJldHVybiBuOwo+ICsJaWYgKG4gPT0gMCkKPiArCQlyZXR1cm4gbTsKPiArCj4gKwl3 aGlsZSAobiAhPSAwKSB7Cj4gKwkJaW50IHRtcCA9IG0gJSBuOwo+ICsKPiArCQltID0gbjsKPiAr CQluID0gdG1wOwo+ICsJfQo+ICsJKmEgPSAoKmEpIC8gbTsKPiArCSpiID0gKCpiKSAvIG07Cj4g Kwo+ICsJcmV0dXJuIG07Cj4gK30KPiArCj4gKyNkZWZpbmUgUkVBRF9CWVRFKGJ1ZmZlciwgcG9z KQkoKih1OCAqKSgoYnVmZmVyKS0+dmlydCArICgocG9zKSAlIGJ1ZmZlci0+bGVuZ3RoKSkpCj4g K2ludCB2cHVfaGVscGVyX2ZpbmRfc3RhcnRjb2RlKHN0cnVjdCB2cHVfYnVmZmVyICpzdHJlYW1f YnVmZmVyLAo+ICsJCQl1MzIgcGl4ZWxmb3JtYXQsIHUzMiBvZmZzZXQsIHUzMiBieXRlc3VzZWQp Cj4gK3sKPiArCXUzMiBzdGFydF9jb2RlOwo+ICsJaW50IHN0YXJ0X2NvZGVfc2l6ZTsKPiArCXUz MiB2YWwgPSAwOwo+ICsJaW50IGk7Cj4gKwlpbnQgcmV0ID0gLUVJTlZBTDsKPiArCj4gKwlpZiAo IXN0cmVhbV9idWZmZXIgfHwgIXN0cmVhbV9idWZmZXItPnZpcnQpCj4gKwkJcmV0dXJuIC1FSU5W QUw7Cj4gKwo+ICsJc3dpdGNoIChwaXhlbGZvcm1hdCkgewo+ICsJY2FzZSBWNEwyX1BJWF9GTVRf SDI2NDoKPiArCQlzdGFydF9jb2RlX3NpemUgPSA0Owo+ICsJCXN0YXJ0X2NvZGUgPSAweDAwMDAw MDAxOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4g Kwlmb3IgKGkgPSAwOyBpIDwgYnl0ZXN1c2VkOyBpKyspIHsKPiArCQl2YWwgPSAodmFsIDw8IDgp IHwgUkVBRF9CWVRFKHN0cmVhbV9idWZmZXIsIG9mZnNldCArIGkpOwo+ICsJCWlmIChpIDwgc3Rh cnRfY29kZV9zaXplIC0gMSkKPiArCQkJY29udGludWU7Cj4gKwkJaWYgKHZhbCA9PSBzdGFydF9j b2RlKSB7Cj4gKwkJCXJldCA9IGkgKyAxIC0gc3RhcnRfY29kZV9zaXplOwo+ICsJCQlicmVhazsK PiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAraW50IHZwdV9maW5k X2RzdF9ieV9zcmMoc3RydWN0IHZwdV9wYWlyICpwYWlycywgdTMyIGNudCwgdTMyIHNyYykKPiAr ewo+ICsJdTMyIGk7Cj4gKwo+ICsJaWYgKCFwYWlycyB8fCAhY250KQo+ICsJCXJldHVybiAtRUlO VkFMOwo+ICsKPiArCWZvciAoaSA9IDA7IGkgPCBjbnQ7IGkrKykgewo+ICsJCWlmIChwYWlyc1tp XS5zcmMgPT0gc3JjKQo+ICsJCQlyZXR1cm4gcGFpcnNbaV0uZHN0Owo+ICsJfQo+ICsKPiArCXJl dHVybiAtRUlOVkFMOwo+ICt9Cj4gKwo+ICtpbnQgdnB1X2ZpbmRfc3JjX2J5X2RzdChzdHJ1Y3Qg dnB1X3BhaXIgKnBhaXJzLCB1MzIgY250LCB1MzIgZHN0KQo+ICt7Cj4gKwl1MzIgaTsKPiArCj4g KwlpZiAoIXBhaXJzIHx8ICFjbnQpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJZm9yIChp ID0gMDsgaSA8IGNudDsgaSsrKSB7Cj4gKwkJaWYgKHBhaXJzW2ldLmRzdCA9PSBkc3QpCj4gKwkJ CXJldHVybiBwYWlyc1tpXS5zcmM7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FSU5WQUw7Cj4gK30K PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9oZWxwZXJz LmggYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2hlbHBlcnMuaAo+IG5ldyBm aWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi4yMjAyOWVhYjdiNTYKPiAtLS0g L2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9oZWxw ZXJzLmgKPiBAQCAtMCwwICsxLDcyIEBACj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wICovCj4gKy8qCj4gKyAqIENvcHlyaWdodCAyMDIwLTIwMjEgTlhQCj4gKyAqLwo+ICsK PiArI2lmbmRlZiBfQU1QSElPTl9WUFVfSEVMUEVSU19ICj4gKyNkZWZpbmUgX0FNUEhJT05fVlBV X0hFTFBFUlNfSAo+ICsKPiArc3RydWN0IHZwdV9wYWlyIHsKPiArCXUzMiBzcmM7Cj4gKwl1MzIg ZHN0Owo+ICt9Owo+ICsKPiArI2RlZmluZSBNQUtFX1RJTUVTVEFNUChzLCBucykJCSgoKHMzMiko cykgKiBOU0VDX1BFUl9TRUMpICsgKG5zKSkKPiArI2RlZmluZSBWUFVfSU5WQUxJRF9USU1FU1RB TVAJCU1BS0VfVElNRVNUQU1QKC0xLCAwKQo+ICsjZGVmaW5lCVZQVV9BUlJBWV9BVChhcnJheSwg aSkJCSgoKGkpIDwgQVJSQVlfU0laRShhcnJheSkpID8gYXJyYXlbaV0gOiAwKQo+ICsjZGVmaW5l IFZQVV9BUlJBWV9GSU5EKGFycmF5LCB4KQl2cHVfaGVscGVyX2ZpbmRfaW5fYXJyYXlfdTgoYXJy YXksIEFSUkFZX1NJWkUoYXJyYXkpLCB4KQo+ICsKPiAraW50IHZwdV9oZWxwZXJfZmluZF9pbl9h cnJheV91OChjb25zdCB1OCAqYXJyYXksIHUzMiBzaXplLCB1MzIgeCk7Cj4gK2Jvb2wgdnB1X2hl bHBlcl9jaGVja190eXBlKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCwgdTMyIHR5cGUpOwo+ICtjb25z dCBzdHJ1Y3QgdnB1X2Zvcm1hdCAqdnB1X2hlbHBlcl9maW5kX2Zvcm1hdChzdHJ1Y3QgdnB1X2lu c3QgKmluc3QsIHUzMiB0eXBlLCB1MzIgcGl4ZWxmbXQpOwo+ICtjb25zdCBzdHJ1Y3QgdnB1X2Zv cm1hdCAqdnB1X2hlbHBlcl9lbnVtX2Zvcm1hdChzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUzMiB0 eXBlLCBpbnQgaW5kZXgpOwo+ICt1MzIgdnB1X2hlbHBlcl92YWxpZF9mcmFtZV93aWR0aChzdHJ1 Y3QgdnB1X2luc3QgKmluc3QsIHUzMiB3aWR0aCk7Cj4gK3UzMiB2cHVfaGVscGVyX3ZhbGlkX2Zy YW1lX2hlaWdodChzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUzMiBoZWlnaHQpOwo+ICt1MzIgdnB1 X2hlbHBlcl9nZXRfZnJhbWVfc2l6ZSh1MzIgZm10LCB1MzIgd2lkdGgsIHUzMiBoZWlnaHQpOwo+ ICt1MzIgdnB1X2hlbHBlcl9nZXRfcGxhbmVfc2l6ZSh1MzIgZm10LCB1MzIgd2lkdGgsIHUzMiBo ZWlnaHQsIGludCBwbGFuZV9ubywKPiArCQkJCQl1MzIgc3RyaWRlLCB1MzIgaW50ZXJsYWNlZCwg dTMyICpwYmwpOwo+ICt1MzIgdnB1X2hlbHBlcl9jb3B5X2Zyb21fc3RyZWFtX2J1ZmZlcihzdHJ1 Y3QgdnB1X2J1ZmZlciAqc3RyZWFtX2J1ZmZlciwKPiArCQkJCQl1MzIgKnJwdHIsIHUzMiBzaXpl LCB2b2lkICpkc3QpOwo+ICt1MzIgdnB1X2hlbHBlcl9jb3B5X3RvX3N0cmVhbV9idWZmZXIoc3Ry dWN0IHZwdV9idWZmZXIgKnN0cmVhbV9idWZmZXIsCj4gKwkJCQl1MzIgKndwdHIsIHUzMiBzaXpl LCB2b2lkICpzcmMpOwo+ICt1MzIgdnB1X2hlbHBlcl9tZW1zZXRfc3RyZWFtX2J1ZmZlcihzdHJ1 Y3QgdnB1X2J1ZmZlciAqc3RyZWFtX2J1ZmZlciwKPiArCQkJCXUzMiAqd3B0ciwgdTggdmFsLCB1 MzIgc2l6ZSk7Cj4gK3UzMiB2cHVfaGVscGVyX2dldF9mcmVlX3NwYWNlKHN0cnVjdCB2cHVfaW5z dCAqaW5zdCk7Cj4gK3UzMiB2cHVfaGVscGVyX2dldF91c2VkX3NwYWNlKHN0cnVjdCB2cHVfaW5z dCAqaW5zdCk7Cj4gK2ludCB2cHVfaGVscGVyX2dfdm9sYXRpbGVfY3RybChzdHJ1Y3QgdjRsMl9j dHJsICpjdHJsKTsKPiArdTMyIHZwdV9oZWxwZXJfY2FsY19jb3ByaW1lKHUzMiAqYSwgdTMyICpi KTsKPiArdm9pZCB2cHVfaGVscGVyX2dldF9rbXBfbmV4dChjb25zdCB1OCAqcGF0dGVybiwgaW50 ICpuZXh0LCBpbnQgc2l6ZSk7Cj4gK2ludCB2cHVfaGVscGVyX2ttcF9zZWFyY2godTggKnMsIGlu dCBzX2xlbiwgY29uc3QgdTggKnAsIGludCBwX2xlbiwgaW50ICpuZXh0KTsKPiAraW50IHZwdV9o ZWxwZXJfa21wX3NlYXJjaF9pbl9zdHJlYW1fYnVmZmVyKHN0cnVjdCB2cHVfYnVmZmVyICpzdHJl YW1fYnVmZmVyLAo+ICsJCQkJCXUzMiBvZmZzZXQsIGludCBieXRlc3VzZWQsCj4gKwkJCQkJY29u c3QgdTggKnAsIGludCBwX2xlbiwgaW50ICpuZXh0KTsKPiAraW50IHZwdV9oZWxwZXJfZmluZF9z dGFydGNvZGUoc3RydWN0IHZwdV9idWZmZXIgKnN0cmVhbV9idWZmZXIsCj4gKwkJCXUzMiBwaXhl bGZvcm1hdCwgdTMyIG9mZnNldCwgdTMyIGJ5dGVzdXNlZCk7Cj4gKwo+ICtzdGF0aWMgaW5saW5l IHUzMiB2cHVfaGVscGVyX3N0ZXBfd2FsayhzdHJ1Y3QgdnB1X2J1ZmZlciAqc3RyZWFtX2J1ZmZl ciwgdTMyIHBvcywgdTMyIHN0ZXApCj4gK3sKPiArCXBvcyArPSBzdGVwOwo+ICsJaWYgKHBvcyA+ IHN0cmVhbV9idWZmZXItPnBoeXMgKyBzdHJlYW1fYnVmZmVyLT5sZW5ndGgpCj4gKwkJcG9zIC09 IHN0cmVhbV9idWZmZXItPmxlbmd0aDsKPiArCj4gKwlyZXR1cm4gcG9zOwo+ICt9Cj4gKwo+ICtp bnQgdnB1X2NvbG9yX2NoZWNrX3ByaW1hcmllcyh1MzIgcHJpbWFyaWVzKTsKPiAraW50IHZwdV9j b2xvcl9jaGVja190cmFuc2ZlcnModTMyIHRyYW5zZmVycyk7Cj4gK2ludCB2cHVfY29sb3JfY2hl Y2tfbWF0cml4KHUzMiBtYXRyaXgpOwo+ICtpbnQgdnB1X2NvbG9yX2NoZWNrX2Z1bGxfcmFuZ2Uo dTMyIGZ1bGxfcmFuZ2UpOwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfcHJpbWFyaWVzX3YyaSh1MzIg cHJpbWFyaWVzKTsKPiArdTMyIHZwdV9jb2xvcl9jdnJ0X3ByaW1hcmllc19pMnYodTMyIHByaW1h cmllcyk7Cj4gK3UzMiB2cHVfY29sb3JfY3ZydF90cmFuc2ZlcnNfdjJpKHUzMiB0cmFuc2ZlcnMp Owo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfdHJhbnNmZXJzX2kydih1MzIgdHJhbnNmZXJzKTsKPiAr dTMyIHZwdV9jb2xvcl9jdnJ0X21hdHJpeF92MmkodTMyIG1hdHJpeCk7Cj4gK3UzMiB2cHVfY29s b3JfY3ZydF9tYXRyaXhfaTJ2KHUzMiBtYXRyaXgpOwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfZnVs bF9yYW5nZV92MmkodTMyIGZ1bGxfcmFuZ2UpOwo+ICt1MzIgdnB1X2NvbG9yX2N2cnRfZnVsbF9y YW5nZV9pMnYodTMyIGZ1bGxfcmFuZ2UpOwo+ICtpbnQgdnB1X2NvbG9yX2dldF9kZWZhdWx0KHUz MiBwcmltYXJpZXMsCj4gKwkJdTMyICpwdHJhbnNmZXJzLCB1MzIgKnBtYXRyaXgsIHUzMiAqcGZ1 bGxfcmFuZ2UpOwo+ICsKPiAraW50IHZwdV9maW5kX2RzdF9ieV9zcmMoc3RydWN0IHZwdV9wYWly ICpwYWlycywgdTMyIGNudCwgdTMyIHNyYyk7Cj4gK2ludCB2cHVfZmluZF9zcmNfYnlfZHN0KHN0 cnVjdCB2cHVfcGFpciAqcGFpcnMsIHUzMiBjbnQsIHUzMiBkc3QpOwo+ICsjZW5kaWYKPiBkaWZm IC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV92NGwyLmMgYi9kcml2 ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X3Y0bDIuYwo+IG5ldyBmaWxlIG1vZGUgMTAw NjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi5lYjc2NGM1ZDQ4ZTUKPiAtLS0gL2Rldi9udWxsCj4g KysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV92NGwyLmMKPiBAQCAtMCww ICsxLDYyNSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICsvKgo+ ICsgKiBDb3B5cmlnaHQgMjAyMC0yMDIxIE5YUAo+ICsgKi8KPiArCj4gKyNkZWZpbmUgVEFHCQki VjRMMiIKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2ludGVy Y29ubmVjdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW9jdGwuaD4KPiArI2luY2x1ZGUgPGxpbnV4 L2xpc3QuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+Cj4gKyNpbmNsdWRlIDxs aW51eC92aWRlb2RldjIuaD4KPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItZGV2aWNlLmg+Cj4gKyNp bmNsdWRlIDxtZWRpYS92NGwyLWV2ZW50Lmg+Cj4gKyNpbmNsdWRlIDxtZWRpYS92NGwyLW1lbTJt ZW0uaD4KPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItaW9jdGwuaD4KPiArI2luY2x1ZGUgPG1lZGlh L3ZpZGVvYnVmMi12NGwyLmg+Cj4gKyNpbmNsdWRlIDxtZWRpYS92aWRlb2J1ZjItZG1hLWNvbnRp Zy5oPgo+ICsjaW5jbHVkZSA8bWVkaWEvdmlkZW9idWYyLXZtYWxsb2MuaD4KPiArI2luY2x1ZGUg InZwdS5oIgo+ICsjaW5jbHVkZSAidnB1X2NvcmUuaCIKPiArI2luY2x1ZGUgInZwdV92NGwyLmgi Cj4gKyNpbmNsdWRlICJ2cHVfbXNncy5oIgo+ICsjaW5jbHVkZSAidnB1X2hlbHBlcnMuaCIKPiAr I2luY2x1ZGUgInZwdV9sb2cuaCIKPiArCj4gK3ZvaWQgdnB1X2luc3RfbG9jayhzdHJ1Y3QgdnB1 X2luc3QgKmluc3QpCj4gK3sKPiArCW11dGV4X2xvY2soJmluc3QtPmxvY2spOwo+ICt9Cj4gKwo+ ICt2b2lkIHZwdV9pbnN0X3VubG9jayhzdHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4gK3sKPiArCW11 dGV4X3VubG9jaygmaW5zdC0+bG9jayk7Cj4gK30KPiArCj4gK2RtYV9hZGRyX3QgdnB1X2dldF92 Yl9waHlfYWRkcihzdHJ1Y3QgdmIyX2J1ZmZlciAqdmIsIHUzMiBwbGFuZV9ubykKPiArewo+ICsJ cmV0dXJuIHZiMl9kbWFfY29udGlnX3BsYW5lX2RtYV9hZGRyKHZiLCBwbGFuZV9ubykgKwo+ICsJ CQl2Yi0+cGxhbmVzW3BsYW5lX25vXS5kYXRhX29mZnNldDsKCkkndmUgY2hhbmdlIHRoZSBudW1f cGxhbmVzIHRvIDEgKHRyaWVkIDIsIGJ1dCBmYWlsZWQgZGlmZmVyZW50bHkpLCBhbmQgaXQKY3Jh c2hlZCB3aGlsZSBydW5uaW5nOgoKR1NUX0RFQlVHPSJ2NGwyKjo3IiBnc3QtbGF1bmNoLTEuMCB2 aWRlb3Rlc3RzcmMgbnVtLWJ1ZmZlcnM9MTAwICEgdjRsMmgyNjRlbmMgISBmYWtlc2luawoKU28g cGVyaGFwcyB0aGVyZSBpcyBhIG92ZXJhbGwgcmV2aWV3IG9mIHRoZSBidWZmZXIgYWxsb2NhdGlv biB2cyBTX0ZNVAppbXBsZW1lbnRhdGlvbiB0byBiZSBkb25lIGhlcmUuCgpbICAgODEuNTIwMTY3 XSBVbmFibGUgdG8gaGFuZGxlIGtlcm5lbCBOVUxMIHBvaW50ZXIgZGVyZWZlcmVuY2UgYXQgdmly dHVhbAphZGRyZXNzIDAwMDAwMDAwMDAwMDAwMDAKWyAgIDgxLjUyOTE2OF0gTWVtIGFib3J0IGlu Zm86ClsgICA4MS41MzI0NjddICAgRVNSID0gMHg5NjAwMDAwNApbICAgODEuNTM5NTUwXSAgIEVD ID0gMHgyNTogREFCVCAoY3VycmVudCBFTCksIElMID0gMzIgYml0cwpbICAgODEuNTQ2MDUzXSAg IFNFVCA9IDAsIEZuViA9IDAKWyAgIDgxLjU0OTc3MV0gICBFQSA9IDAsIFMxUFRXID0gMApbICAg ODEuNTUzMTg2XSAgIEZTQyA9IDB4MDQ6IGxldmVsIDAgdHJhbnNsYXRpb24gZmF1bHQKWyAgIDgx LjU1ODI4MF0gRGF0YSBhYm9ydCBpbmZvOgpbICAgODEuNTYxNDM3XSAgIElTViA9IDAsIElTUyA9 IDB4MDAwMDAwMDQKWyAgIDgxLjU2NTUyN10gICBDTSA9IDAsIFduUiA9IDAKWyAgIDgxLjU2ODU4 MV0gdXNlciBwZ3RhYmxlOiA0ayBwYWdlcywgNDgtYml0IFZBcywgcGdkcD0wMDAwMDAwODgyNzQx MDAwClsgICA4MS41NzU4NDBdIFswMDAwMDAwMDAwMDAwMDAwXSBwZ2Q9MDAwMDAwMDAwMDAwMDAw MCwgcDRkPTAwMDAwMDAwMDAwMDAwMDAKWyAgIDgxLjU4NjYzN10gSW50ZXJuYWwgZXJyb3I6IE9v cHM6IDk2MDAwMDA0IFsjMV0gUFJFRU1QVCBTTVAKWyAgIDgxLjU5MjI0N10gTW9kdWxlcyBsaW5r ZWQgaW46IGFtcGhpb25fdnB1X2NvcmUgdjRsMl9tZW0ybWVtCnZpZGVvYnVmMl92bWFsbG9jIHZp ZGVvYnVmMl9kbWFfY29udGlnIHZpZGVvYnVmMl9tZW1vcHMgdmlkZW9idWYyX3Y0bDIKdmlkZW9i dWYyX2NvbW1vbiBpbXhfc2Nfa2V5IGlteF9zY190aGVybWFsIGNyY3QxMGRpZl9jZSBydGNfaW14 X3NjIGlteF9zY193ZHQKYW1waGlvbl92cHVfZGV2IGZzbF9pbXg4X2Rkcl9wZXJmIGlzbDI5MDE4 IG1wbDMxMTUgaW5kdXN0cmlhbGlvX3RyaWdnZXJlZF9idWZmZXIKa2ZpZm9fYnVmIHZpZGVvZGV2 IG1jIGZ1c2UgZHJtIGlwX3RhYmxlcyB4X3RhYmxlcyBpcHY2ClsgICA4MS42MjI4MDVdIENQVTog MCBQSUQ6IDM0OCBDb21tOiB2aWRlb3Rlc3RzcmMwOnMgTm90IHRhaW50ZWQgNS4xNS4wLXJjMi0K aW14OHF4cCsgIzIKWyAgIDgxLjYzMDU2Ml0gSGFyZHdhcmUgbmFtZTogRnJlZXNjYWxlIGkuTVg4 UVhQIE1FSyAoRFQpClsgICA4MS42MzU3MTFdIHBzdGF0ZTogNjAwMDAwMDUgKG5aQ3YgZGFpZiAt UEFOIC1VQU8gLVRDTyAtRElUIC1TU0JTIEJUWVBFPS0tKQpbICAgODEuNjQyNjg3XSBwYyA6IHZw dV9nZXRfdmJfcGh5X2FkZHIrMHgyOC8weDUwIFthbXBoaW9uX3ZwdV9jb3JlXQpbICAgODEuNjQ4 ODM4XSBsciA6IHZwdV9nZXRfdmJfcGh5X2FkZHIrMHgyMC8weDUwIFthbXBoaW9uX3ZwdV9jb3Jl XQpbICAgODEuNjU0OTcxXSBzcCA6IGZmZmY4MDAwMTJmY2JhMzAKWyAgIDgxLjY1ODI4N10geDI5 OiBmZmZmODAwMDEyZmNiYTMwIHgyODogZmZmZjgwMDAxMmJkMTA0MCB4Mjc6IDAwMDAwMDAwMDAw MDAwMDAKWyAgIDgxLjY2NTQ0OV0geDI2OiAwMDAwMDAwMDAwMDAwMDAwIHgyNTogZmZmZjgwMDAx MmZjYmQyOCB4MjQ6IGZmZmY4MDAwMTJiZDEwMTAKWyAgIDgxLjY3MjYwN10geDIzOiBmZmZmODAw MDEyYmQzMjAwIHgyMjogMDAwMDAwMDAwMDAwMDAwMCB4MjE6IGZmZmY4MDAwMTU4MDcwNDQKWyAg IDgxLjY3OTc2Nl0geDIwOiBmZmZmMDAwODA2YTFlYzAwIHgxOTogMDAwMDAwMDAwMDAwMDAwMyB4 MTg6IDAwMDAwMDAwMDAwMDAwMDAKWyAgIDgxLjY4NjkyNF0geDE3OiAwMDAwMDAwMDAwMDAwMDAw IHgxNjogMDAwMDAwMDAwMDAwMDAwMCB4MTU6IDAwMDBhOTViYTI5YzMyN2EKWyAgIDgxLjY5NDA4 M10geDE0OiAwMDAwMDAwMDAwMDAwMzlmIHgxMzogMDAwMDAwMDAwMDAwMDAwMCB4MTI6IDAwMDAw MDAwMDAwMDAwMDAKWyAgIDgxLjcwMTI0MV0geDExOiAwMDAwMDAwMDAwMDAwMDAwIHgxMDogMDAw MDAwMDAwMDAwMDk5MCB4OSA6IGZmZmY4MDAwMTJmY2I5MDAKWyAgIDgxLjcwODQwMF0geDggOiBm ZmZmMDAwODA2OGY5N2YwIHg3IDogZmZmZjAwMDgzZjk4YjE4MCB4NiA6IGZmZmYwMDA4MDIwNzBh ZjgKWyAgIDgxLjcxNTU1OF0geDUgOiBmZmZmMDAwODAyMDcwYWY4IHg0IDogZmZmZjgwMDAwOTI5 NjAwMCB4MyA6IGZmZmYwMDA4MDIwNzM0ODAKWyAgIDgxLjcyMjcxN10geDIgOiBmZmZmMDAwODA2 YTFlYzAwIHgxIDogMDAwMDAwMDAwMDAwMDAwMiB4MCA6IDAwMDAwMDAwMDAwMDAwMDAKWyAgIDgx LjcyOTg3N10gQ2FsbCB0cmFjZToKWyAgIDgxLjczMjMzMl0gIHZwdV9nZXRfdmJfcGh5X2FkZHIr MHgyOC8weDUwIFthbXBoaW9uX3ZwdV9jb3JlXQpbICAgODEuNzM4MTE5XSAgdnB1X3dpbmRzb3Jf aW5wdXRfZnJhbWUrMHg4NC8weGJjIFthbXBoaW9uX3ZwdV9jb3JlXQpbICAgODEuNzQ0MjUyXSAg dmVuY19wcm9jZXNzX291dHB1dCsweDg4LzB4MTBjIFthbXBoaW9uX3ZwdV9jb3JlXQpbICAgODEu NzUwMTI1XSAgdnB1X3Byb2Nlc3Nfb3V0cHV0X2J1ZmZlcisweGFjLzB4MTAwIFthbXBoaW9uX3Zw dV9jb3JlXQpbICAgODEuNzU2NTE5XSAgdmVuY19zdGFydF9zZXNzaW9uKzB4MjY0LzB4MmNjIFth bXBoaW9uX3ZwdV9jb3JlXQpbICAgODEuNzYyMzkyXSAgdnB1X3ZiMl9zdGFydF9zdHJlYW1pbmcr MHg4OC8weGY0IFthbXBoaW9uX3ZwdV9jb3JlXQpbICAgODEuNzY4NTI1XSAgdmIyX3N0YXJ0X3N0 cmVhbWluZysweDY4LzB4MTVjIFt2aWRlb2J1ZjJfY29tbW9uXQpbICAgODEuNzc0Mzk4XSAgdmIy X2NvcmVfc3RyZWFtb24rMHg5NC8weDE5YyBbdmlkZW9idWYyX2NvbW1vbl0KWyAgIDgxLjc4MDA4 OF0gIHZiMl9zdHJlYW1vbisweDIwLzB4NzAgW3ZpZGVvYnVmMl92NGwyXQpbICAgODEuNzg1MDgz XSAgdjRsMl9tMm1faW9jdGxfc3RyZWFtb24rMHgzYy8weGEwIFt2NGwyX21lbTJtZW1dClsgICA4 MS43OTA4NjldICB2NGxfc3RyZWFtb24rMHgyOC8weDM0IFt2aWRlb2Rldl0KWyAgIDgxLjc5NTQx Ml0gIF9fdmlkZW9fZG9faW9jdGwrMHgxN2MvMHgzZTAgW3ZpZGVvZGV2XQpbICAgODEuODAwNDYw XSAgdmlkZW9fdXNlcmNvcHkrMHgzNjgvMHg3ZTAgW3ZpZGVvZGV2XQpbICAgODEuODA1MzMzXSAg dmlkZW9faW9jdGwyKzB4MWMvMHgzYyBbdmlkZW9kZXZdClsgICA4MS44MDk4NTldICB2NGwyX2lv Y3RsKzB4NDQvMHg2NCBbdmlkZW9kZXZdClsgICA4MS44MTQyMTFdICBfX2FybTY0X3N5c19pb2N0 bCsweGFjLzB4ZjAKWyAgIDgxLjgxODE1NV0gIGludm9rZV9zeXNjYWxsKzB4NDgvMHgxMTQKWyAg IDgxLjgyMTkxN10gIGVsMF9zdmNfY29tbW9uLmNvbnN0cHJvcC4wKzB4NDQvMHhmYwpbICAgODEu ODI2NjM1XSAgZG9fZWwwX3N2YysweDJjLzB4OTQKWyAgIDgxLjgyOTk2MV0gIGVsMF9zdmMrMHgy OC8weDgwClsgICA4MS44MzMwMjddICBlbDB0XzY0X3N5bmNfaGFuZGxlcisweGE4LzB4MTMwClsg ICA4MS44MzczMTFdICBlbDB0XzY0X3N5bmMrMHgxYTAvMHgxYTQKWyAgIDgxLjg0MDk5Ml0gQ29k ZTogYWEwMDAzZjQgOTdmZjAyZjkgZDM3ZjdlNjEgOGIzMzQwMzMgKGY5NDAwMDAwKSAKWyAgIDgx Ljg0NzA5OV0gLS0tWyBlbmQgdHJhY2UgNDZjZjQyMTM3N2E1OWRlMSBdLS0tCgoKCgo+ICt9Cj4g Kwo+ICt1bnNpZ25lZCBpbnQgdnB1X2dldF92Yl9sZW5ndGgoc3RydWN0IHZiMl9idWZmZXIgKnZi LCB1MzIgcGxhbmVfbm8pCj4gK3sKPiArCWlmIChwbGFuZV9ubyA+PSB2Yi0+bnVtX3BsYW5lcykK PiArCQlyZXR1cm4gMDsKPiArCXJldHVybiB2YjJfcGxhbmVfc2l6ZSh2YiwgcGxhbmVfbm8pIC0g dmItPnBsYW5lc1twbGFuZV9ub10uZGF0YV9vZmZzZXQ7Cj4gK30KPiArCj4gK3ZvaWQgdnB1X3Y0 bDJfc2V0X2Vycm9yKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCkKPiArewo+ICsJc3RydWN0IHZiMl9x dWV1ZSAqc3JjX3EgPSB2NGwyX20ybV9nZXRfc3JjX3ZxKGluc3QtPm0ybV9jdHgpOwo+ICsJc3Ry dWN0IHZiMl9xdWV1ZSAqZHN0X3EgPSB2NGwyX20ybV9nZXRfZHN0X3ZxKGluc3QtPm0ybV9jdHgp Owo+ICsKPiArCWlmIChzcmNfcSkKPiArCQlzcmNfcS0+ZXJyb3IgPSAxOwo+ICsJaWYgKGRzdF9x KQo+ICsJCWRzdF9xLT5lcnJvciA9IDE7Cj4gK30KPiArCj4gK2ludCB2cHVfbm90aWZ5X2Vvcyhz dHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4gK3sKPiArCWNvbnN0IHN0cnVjdCB2NGwyX2V2ZW50IGV2 ID0gewo+ICsJCS5pZCA9IDAsCj4gKwkJLnR5cGUgPSBWNEwyX0VWRU5UX0VPUwo+ICsJfTsKPiAr Cj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfRkxPVywgIm5vdGlmeSBlb3MgZXZlbnRcbiIpOwo+ICsJ djRsMl9ldmVudF9xdWV1ZV9maCgmaW5zdC0+ZmgsICZldik7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gK2ludCB2cHVfbm90aWZ5X3NvdXJjZV9jaGFuZ2Uoc3RydWN0IHZwdV9pbnN0ICpp bnN0KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgdjRsMl9ldmVudCBldiA9IHsKPiArCQkuaWQgPSAw LAo+ICsJCS50eXBlID0gVjRMMl9FVkVOVF9TT1VSQ0VfQ0hBTkdFLAo+ICsJCS51LnNyY19jaGFu Z2UuY2hhbmdlcyA9IFY0TDJfRVZFTlRfU1JDX0NIX1JFU09MVVRJT04KPiArCX07Cj4gKwo+ICsJ aW5zdF9kYmcoaW5zdCwgTFZMX0ZMT1csICJub3RpZnkgc291cmNlIGNoYW5nZSBldmVudFxuIik7 Cj4gKwl2NGwyX2V2ZW50X3F1ZXVlX2ZoKCZpbnN0LT5maCwgJmV2KTsKPiArCXJldHVybiAwOwo+ ICt9Cj4gKwo+ICtjb25zdCBzdHJ1Y3QgdnB1X2Zvcm1hdCAqdnB1X3RyeV9mbXRfY29tbW9uKHN0 cnVjdCB2cHVfaW5zdCAqaW5zdCwKPiArCQkgc3RydWN0IHY0bDJfZm9ybWF0ICpmKQo+ICt7Cj4g KwlzdHJ1Y3QgdjRsMl9waXhfZm9ybWF0X21wbGFuZSAqcGl4bXAgPSAmZi0+Zm10LnBpeF9tcDsK PiArCXUzMiB0eXBlID0gZi0+dHlwZTsKPiArCXUzMiBzdHJpZGU7Cj4gKwl1MzIgYnl0ZXNwZXJs aW5lOwo+ICsJdTMyIHNpemVpbWFnZTsKPiArCWNvbnN0IHN0cnVjdCB2cHVfZm9ybWF0ICpmbXQ7 Cj4gKwlpbnQgaTsKPiArCj4gKwlmbXQgPSB2cHVfaGVscGVyX2ZpbmRfZm9ybWF0KGluc3QsIHR5 cGUsIHBpeG1wLT5waXhlbGZvcm1hdCk7Cj4gKwlpZiAoIWZtdCkgewo+ICsJCWZtdCA9IHZwdV9o ZWxwZXJfZW51bV9mb3JtYXQoaW5zdCwgdHlwZSwgMCk7Cj4gKwkJaWYgKCFmbXQpCj4gKwkJCXJl dHVybiBOVUxMOwo+ICsJCXBpeG1wLT5waXhlbGZvcm1hdCA9IGZtdC0+cGl4Zm10Owo+ICsJfQo+ ICsKPiArCXN0cmlkZSA9IGluc3QtPmNvcmUtPnJlcy0+c3RyaWRlOwo+ICsJcGl4bXAtPndpZHRo ID0gdnB1X2hlbHBlcl92YWxpZF9mcmFtZV93aWR0aChpbnN0LCBwaXhtcC0+d2lkdGgpOwo+ICsJ cGl4bXAtPmhlaWdodCA9IHZwdV9oZWxwZXJfdmFsaWRfZnJhbWVfaGVpZ2h0KGluc3QsIHBpeG1w LT5oZWlnaHQpOwo+ICsJcGl4bXAtPmZsYWdzID0gZm10LT5mbGFnczsKPiArCXBpeG1wLT5udW1f cGxhbmVzID0gZm10LT5udW1fcGxhbmVzOwo+ICsJaWYgKHBpeG1wLT5maWVsZCA9PSBWNEwyX0ZJ RUxEX0FOWSkKPiArCQlwaXhtcC0+ZmllbGQgPSBWNEwyX0ZJRUxEX05PTkU7Cj4gKwlmb3IgKGkg PSAwOyBpIDwgcGl4bXAtPm51bV9wbGFuZXM7IGkrKykgewo+ICsJCXNpemVpbWFnZSA9IHZwdV9o ZWxwZXJfZ2V0X3BsYW5lX3NpemUocGl4bXAtPnBpeGVsZm9ybWF0LAo+ICsJCQkJcGl4bXAtPndp ZHRoLCBwaXhtcC0+aGVpZ2h0LCBpLCBzdHJpZGUsCj4gKwkJCQlwaXhtcC0+ZmllbGQgPT0gVjRM Ml9GSUVMRF9JTlRFUkxBQ0VEID8gMSA6IDAsCj4gKwkJCQkmYnl0ZXNwZXJsaW5lKTsKPiArCQlp ZiAoKHMzMikocGl4bXAtPnBsYW5lX2ZtdFtpXS5ieXRlc3BlcmxpbmUpIDw9IDApCj4gKwkJCXBp eG1wLT5wbGFuZV9mbXRbaV0uYnl0ZXNwZXJsaW5lID0gYnl0ZXNwZXJsaW5lOwo+ICsJCWlmICgo czMyKShwaXhtcC0+cGxhbmVfZm10W2ldLnNpemVpbWFnZSkgPD0gMCkKPiArCQkJcGl4bXAtPnBs YW5lX2ZtdFtpXS5zaXplaW1hZ2UgPSBzaXplaW1hZ2U7Cj4gKwkJaWYgKHBpeG1wLT5wbGFuZV9m bXRbaV0uYnl0ZXNwZXJsaW5lIDwgYnl0ZXNwZXJsaW5lKQo+ICsJCQlwaXhtcC0+cGxhbmVfZm10 W2ldLmJ5dGVzcGVybGluZSA9IGJ5dGVzcGVybGluZTsKPiArCQlpZiAocGl4bXAtPnBsYW5lX2Zt dFtpXS5zaXplaW1hZ2UgPD0gc2l6ZWltYWdlKQo+ICsJCQlwaXhtcC0+cGxhbmVfZm10W2ldLnNp emVpbWFnZSA9IHNpemVpbWFnZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gZm10Owo+ICt9Cj4gKwo+ ICtzdGF0aWMgYm9vbCB2cHVfY2hlY2tfcmVhZHkoc3RydWN0IHZwdV9pbnN0ICppbnN0LCB1MzIg dHlwZSkKPiArewo+ICsJaWYgKCFpbnN0KQo+ICsJCXJldHVybiBmYWxzZTsKPiArCWlmIChpbnN0 LT5zdGF0ZSA9PSBWUFVfQ09ERUNfU1RBVEVfREVJTklUIHx8IGluc3QtPmlkIDwgMCkKPiArCQly ZXR1cm4gZmFsc2U7Cj4gKwlpZiAoIWluc3QtPm9wcy0+Y2hlY2tfcmVhZHkpCj4gKwkJcmV0dXJu IHRydWU7Cj4gKwlyZXR1cm4gY2FsbF92b3AoaW5zdCwgY2hlY2tfcmVhZHksIHR5cGUpOwo+ICt9 Cj4gKwo+ICtpbnQgdnB1X3Byb2Nlc3Nfb3V0cHV0X2J1ZmZlcihzdHJ1Y3QgdnB1X2luc3QgKmlu c3QpCj4gK3sKPiArCXN0cnVjdCB2NGwyX20ybV9idWZmZXIgKmJ1ZiA9IE5VTEw7Cj4gKwlzdHJ1 Y3QgdnB1X3ZiMl9idWZmZXIgKnZwdV9idWYgPSBOVUxMOwo+ICsKPiArCWlmICghaW5zdCkKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlpZiAoIXZwdV9jaGVja19yZWFkeShpbnN0LCBpbnN0 LT5vdXRfZm9ybWF0LnR5cGUpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXY0bDJfbTJt X2Zvcl9lYWNoX3NyY19idWYoaW5zdC0+bTJtX2N0eCwgYnVmKSB7Cj4gKwkJdnB1X2J1ZiA9IGNv bnRhaW5lcl9vZihidWYsIHN0cnVjdCB2cHVfdmIyX2J1ZmZlciwgbTJtX2J1Zik7Cj4gKwkJaWYg KHZwdV9idWYtPnN0YXRlID09IFZQVV9CVUZfU1RBVEVfSURMRSkKPiArCQkJYnJlYWs7Cj4gKwkJ dnB1X2J1ZiA9IE5VTEw7Cj4gKwl9Cj4gKwo+ICsJaWYgKCF2cHVfYnVmKQo+ICsJCXJldHVybiAt RUlOVkFMOwo+ICsKPiArCWluc3RfZGJnKGluc3QsIExWTF9ERUJVRywgImZyYW1lIGlkID0gJWQg LyAlZFxuIiwKPiArCQkJdnB1X2J1Zi0+bTJtX2J1Zi52Yi5zZXF1ZW5jZSwgaW5zdC0+c2VxdWVu Y2UpOwo+ICsJcmV0dXJuIGNhbGxfdm9wKGluc3QsIHByb2Nlc3Nfb3V0cHV0LCAmdnB1X2J1Zi0+ bTJtX2J1Zi52Yi52YjJfYnVmKTsKPiArfQo+ICsKPiAraW50IHZwdV9wcm9jZXNzX2NhcHR1cmVf YnVmZmVyKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCkKPiArewo+ICsJc3RydWN0IHY0bDJfbTJtX2J1 ZmZlciAqYnVmID0gTlVMTDsKPiArCXN0cnVjdCB2cHVfdmIyX2J1ZmZlciAqdnB1X2J1ZiA9IE5V TEw7Cj4gKwo+ICsJaWYgKCFpbnN0KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmICgh dnB1X2NoZWNrX3JlYWR5KGluc3QsIGluc3QtPmNhcF9mb3JtYXQudHlwZSkpCj4gKwkJcmV0dXJu IC1FSU5WQUw7Cj4gKwo+ICsJdjRsMl9tMm1fZm9yX2VhY2hfZHN0X2J1ZihpbnN0LT5tMm1fY3R4 LCBidWYpIHsKPiArCQl2cHVfYnVmID0gY29udGFpbmVyX29mKGJ1Ziwgc3RydWN0IHZwdV92YjJf YnVmZmVyLCBtMm1fYnVmKTsKPiArCQlpZiAodnB1X2J1Zi0+c3RhdGUgPT0gVlBVX0JVRl9TVEFU RV9JRExFKQo+ICsJCQlicmVhazsKPiArCQl2cHVfYnVmID0gTlVMTDsKPiArCX0KPiArCWlmICgh dnB1X2J1ZikKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gY2FsbF92b3AoaW5z dCwgcHJvY2Vzc19jYXB0dXJlLCAmdnB1X2J1Zi0+bTJtX2J1Zi52Yi52YjJfYnVmKTsKPiArfQo+ ICsKPiArc3RydWN0IHZiMl92NGwyX2J1ZmZlciAqdnB1X2ZpbmRfYnVmX2J5X3NlcXVlbmNlKHN0 cnVjdCB2cHVfaW5zdCAqaW5zdCwKPiArCQkJCQkJdTMyIHR5cGUsIHUzMiBzZXF1ZW5jZSkKPiAr ewo+ICsJc3RydWN0IHY0bDJfbTJtX2J1ZmZlciAqYnVmID0gTlVMTDsKPiArCXN0cnVjdCB2YjJf djRsMl9idWZmZXIgKnZidWYgPSBOVUxMOwo+ICsKPiArCWlmIChWNEwyX1RZUEVfSVNfT1VUUFVU KHR5cGUpKSB7Cj4gKwkJdjRsMl9tMm1fZm9yX2VhY2hfc3JjX2J1ZihpbnN0LT5tMm1fY3R4LCBi dWYpIHsKPiArCQkJdmJ1ZiA9ICZidWYtPnZiOwo+ICsJCQlpZiAodmJ1Zi0+c2VxdWVuY2UgPT0g c2VxdWVuY2UpCj4gKwkJCQlicmVhazsKPiArCQkJdmJ1ZiA9IE5VTEw7Cj4gKwkJfQo+ICsJfSBl bHNlIHsKPiArCQl2NGwyX20ybV9mb3JfZWFjaF9kc3RfYnVmKGluc3QtPm0ybV9jdHgsIGJ1Zikg ewo+ICsJCQl2YnVmID0gJmJ1Zi0+dmI7Cj4gKwkJCWlmICh2YnVmLT5zZXF1ZW5jZSA9PSBzZXF1 ZW5jZSkKPiArCQkJCWJyZWFrOwo+ICsJCQl2YnVmID0gTlVMTDsKPiArCQl9Cj4gKwl9Cj4gKwo+ ICsJcmV0dXJuIHZidWY7Cj4gK30KPiArCj4gK3N0cnVjdCB2YjJfdjRsMl9idWZmZXIgKnZwdV9m aW5kX2J1Zl9ieV9pZHgoc3RydWN0IHZwdV9pbnN0ICppbnN0LAo+ICsJCQkJCQl1MzIgdHlwZSwg dTMyIGlkeCkKPiArewo+ICsJc3RydWN0IHY0bDJfbTJtX2J1ZmZlciAqYnVmID0gTlVMTDsKPiAr CXN0cnVjdCB2YjJfdjRsMl9idWZmZXIgKnZidWYgPSBOVUxMOwo+ICsKPiArCWlmIChWNEwyX1RZ UEVfSVNfT1VUUFVUKHR5cGUpKSB7Cj4gKwkJdjRsMl9tMm1fZm9yX2VhY2hfc3JjX2J1ZihpbnN0 LT5tMm1fY3R4LCBidWYpIHsKPiArCQkJdmJ1ZiA9ICZidWYtPnZiOwo+ICsJCQlpZiAodmJ1Zi0+ dmIyX2J1Zi5pbmRleCA9PSBpZHgpCj4gKwkJCQlicmVhazsKPiArCQkJdmJ1ZiA9IE5VTEw7Cj4g KwkJfQo+ICsJfSBlbHNlIHsKPiArCQl2NGwyX20ybV9mb3JfZWFjaF9kc3RfYnVmKGluc3QtPm0y bV9jdHgsIGJ1Zikgewo+ICsJCQl2YnVmID0gJmJ1Zi0+dmI7Cj4gKwkJCWlmICh2YnVmLT52YjJf YnVmLmluZGV4ID09IGlkeCkKPiArCQkJCWJyZWFrOwo+ICsJCQl2YnVmID0gTlVMTDsKPiArCQl9 Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHZidWY7Cj4gK30KPiArCj4gK2ludCB2cHVfZ2V0X251bV9i dWZmZXJzKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCwgdTMyIHR5cGUpCj4gK3sKPiArCXN0cnVjdCB2 YjJfcXVldWUgKnE7Cj4gKwo+ICsJaWYgKCFpbnN0IHx8ICFpbnN0LT5tMm1fY3R4KQo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsJaWYgKFY0TDJfVFlQRV9JU19PVVRQVVQodHlwZSkpCj4gKwkJcSA9 IHY0bDJfbTJtX2dldF9zcmNfdnEoaW5zdC0+bTJtX2N0eCk7Cj4gKwllbHNlCj4gKwkJcSA9IHY0 bDJfbTJtX2dldF9kc3RfdnEoaW5zdC0+bTJtX2N0eCk7Cj4gKwo+ICsJcmV0dXJuIHEtPm51bV9i dWZmZXJzOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2cHVfbTJtX2RldmljZV9ydW4odm9pZCAq cHJpdikKPiArewo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2cHVfbTJtX2pvYl9hYm9ydCh2b2lk ICpwcml2KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2luc3QgKmluc3QgPSBwcml2Owo+ICsKPiArCXY0 bDJfbTJtX2pvYl9maW5pc2goaW5zdC0+bTJtX2RldiwgaW5zdC0+bTJtX2N0eCk7Cj4gK30KPiAr Cj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9tMm1fb3BzIHZwdV9tMm1fb3BzID0gewo+ICsJ LmRldmljZV9ydW4gPSB2cHVfbTJtX2RldmljZV9ydW4sCj4gKwkuam9iX2Fib3J0ID0gdnB1X20y bV9qb2JfYWJvcnQKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgdnB1X3ZiMl9xdWV1ZV9zZXR1cChz dHJ1Y3QgdmIyX3F1ZXVlICp2cSwKPiArCQkJCXVuc2lnbmVkIGludCAqYnVmX2NvdW50LAo+ICsJ CQkJdW5zaWduZWQgaW50ICpwbGFuZV9jb3VudCwKPiArCQkJCXVuc2lnbmVkIGludCBwc2l6ZVtd LAo+ICsJCQkJc3RydWN0IGRldmljZSAqYWxsb2NhdG9yc1tdKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1 X2luc3QgKmluc3QgPSB2YjJfZ2V0X2Rydl9wcml2KHZxKTsKPiArCXN0cnVjdCB2cHVfZm9ybWF0 ICpjdXJfZm10Owo+ICsJaW50IGk7Cj4gKwo+ICsJY3VyX2ZtdCA9IHZwdV9nZXRfZm9ybWF0KGlu c3QsIHZxLT50eXBlKTsKPiArCj4gKwlpZiAoKnBsYW5lX2NvdW50KSB7Cj4gKwkJaWYgKCpwbGFu ZV9jb3VudCAhPSBjdXJfZm10LT5udW1fcGxhbmVzKQo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiAr CQlmb3IgKGkgPSAwOyBpIDwgY3VyX2ZtdC0+bnVtX3BsYW5lczsgaSsrKSB7Cj4gKwkJCWlmIChw c2l6ZVtpXSA8IGN1cl9mbXQtPnNpemVpbWFnZVtpXSkKPiArCQkJCXJldHVybiAtRUlOVkFMOwo+ ICsJCX0KPiArCX0KPiArCj4gKwkqcGxhbmVfY291bnQgPSBjdXJfZm10LT5udW1fcGxhbmVzOwo+ ICsJZm9yIChpID0gMDsgaSA8IGN1cl9mbXQtPm51bV9wbGFuZXM7IGkrKykKPiArCQlwc2l6ZVtp XSA9IGN1cl9mbXQtPnNpemVpbWFnZVtpXTsKPiArCj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfRkxP VywgIiVzIHF1ZXVlIHNldHVwIDogJXU7ICV1LCAldVxuIiwKPiArCQkJdnB1X3R5cGVfbmFtZSh2 cS0+dHlwZSksCj4gKwkJCSpidWZfY291bnQsCj4gKwkJCXBzaXplWzBdLCBwc2l6ZVsxXSk7Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X3ZiMl9idWZfaW5pdChz dHJ1Y3QgdmIyX2J1ZmZlciAqdmIpCj4gK3sKPiArCXN0cnVjdCB2YjJfdjRsMl9idWZmZXIgKnZi dWYgPSB0b192YjJfdjRsMl9idWZmZXIodmIpOwo+ICsJc3RydWN0IHZwdV92YjJfYnVmZmVyICp2 cHVfYnVmID0gdG9fdnB1X3ZiMl9idWZmZXIodmJ1Zik7Cj4gKwo+ICsJdnB1X2J1Zi0+c3RhdGUg PSBWUFVfQlVGX1NUQVRFX0lETEU7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyB2b2lkIHZwdV92YjJfYnVmX2NsZWFudXAoc3RydWN0IHZiMl9idWZmZXIgKnZiKQo+ICt7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X3ZiMl9idWZfcHJlcGFyZShzdHJ1Y3QgdmIyX2J1ZmZl ciAqdmIpCj4gK3sKPiArCXN0cnVjdCB2cHVfaW5zdCAqaW5zdCA9IHZiMl9nZXRfZHJ2X3ByaXYo dmItPnZiMl9xdWV1ZSk7Cj4gKwlzdHJ1Y3QgdmIyX3Y0bDJfYnVmZmVyICp2YnVmID0gdG9fdmIy X3Y0bDJfYnVmZmVyKHZiKTsKPiArCXN0cnVjdCB2cHVfdmIyX2J1ZmZlciAqdnB1X2J1ZiA9IHRv X3ZwdV92YjJfYnVmZmVyKHZidWYpOwo+ICsJc3RydWN0IHZwdV9mb3JtYXQgKmN1cl9mbXQ7Cj4g Kwl1MzIgaTsKPiArCj4gKwljdXJfZm10ID0gdnB1X2dldF9mb3JtYXQoaW5zdCwgdmItPnR5cGUp Owo+ICsJaWYgKHZiLT5udW1fcGxhbmVzICE9IGN1cl9mbXQtPm51bV9wbGFuZXMpCj4gKwkJcmV0 dXJuIC1FSU5WQUw7Cj4gKwlmb3IgKGkgPSAwOyBpIDwgY3VyX2ZtdC0+bnVtX3BsYW5lczsgaSsr KSB7Cj4gKwkJaWYgKHZwdV9nZXRfdmJfbGVuZ3RoKHZiLCBpKSA8IGN1cl9mbXQtPnNpemVpbWFn ZVtpXSkgewo+ICsJCQlpbnN0X2VycihpbnN0LCAiJXMgYnVmWyVkXSBpcyBpbnZhbGlkXG4iLAo+ ICsJCQkJCXZwdV90eXBlX25hbWUodmItPnR5cGUpLAo+ICsJCQkJCXZiLT5pbmRleCk7Cj4gKwkJ CXZwdV9idWYtPnN0YXRlID0gVlBVX0JVRl9TVEFURV9FUlJPUjsKPiArCQl9Cj4gKwl9Cj4gKwo+ ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZwdV92YjJfYnVmX2ZpbmlzaChz dHJ1Y3QgdmIyX2J1ZmZlciAqdmIpCj4gK3sKPiArCXN0cnVjdCB2YjJfdjRsMl9idWZmZXIgKnZi dWYgPSB0b192YjJfdjRsMl9idWZmZXIodmIpOwo+ICsJc3RydWN0IHZwdV9pbnN0ICppbnN0ID0g dmIyX2dldF9kcnZfcHJpdih2Yi0+dmIyX3F1ZXVlKTsKPiArCXN0cnVjdCB2YjJfcXVldWUgKnEg PSB2Yi0+dmIyX3F1ZXVlOwo+ICsKPiArCWlmICh2YnVmLT5mbGFncyAmIFY0TDJfQlVGX0ZMQUdf TEFTVCkKPiArCQl2cHVfbm90aWZ5X2VvcyhpbnN0KTsKPiArCj4gKwlpZiAobGlzdF9lbXB0eSgm cS0+ZG9uZV9saXN0KSkKPiArCQljYWxsX3ZvcChpbnN0LCBvbl9xdWV1ZV9lbXB0eSwgcS0+dHlw ZSk7Cj4gK30KPiArCj4gK3ZvaWQgdnB1X3ZiMl9idWZmZXJzX3JldHVybihzdHJ1Y3QgdnB1X2lu c3QgKmluc3QsCj4gKwkJdW5zaWduZWQgaW50IHR5cGUsIGVudW0gdmIyX2J1ZmZlcl9zdGF0ZSBz dGF0ZSkKPiArewo+ICsJc3RydWN0IHZiMl92NGwyX2J1ZmZlciAqYnVmOwo+ICsKPiArCWlmICgh aW5zdCB8fCAhaW5zdC0+bTJtX2N0eCkKPiArCQlyZXR1cm47Cj4gKwo+ICsJaWYgKFY0TDJfVFlQ RV9JU19PVVRQVVQodHlwZSkpIHsKPiArCQl3aGlsZSAoKGJ1ZiA9IHY0bDJfbTJtX3NyY19idWZf cmVtb3ZlKGluc3QtPm0ybV9jdHgpKSkKPiArCQkJdjRsMl9tMm1fYnVmX2RvbmUoYnVmLCBzdGF0 ZSk7Cj4gKwl9IGVsc2Ugewo+ICsJCXdoaWxlICgoYnVmID0gdjRsMl9tMm1fZHN0X2J1Zl9yZW1v dmUoaW5zdC0+bTJtX2N0eCkpKQo+ICsJCQl2NGwyX20ybV9idWZfZG9uZShidWYsIHN0YXRlKTsK PiArCX0KPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVfdmIyX3N0YXJ0X3N0cmVhbWluZyhzdHJ1 Y3QgdmIyX3F1ZXVlICpxLCB1bnNpZ25lZCBpbnQgY291bnQpCj4gK3sKPiArCXN0cnVjdCB2cHVf aW5zdCAqaW5zdCA9IHZiMl9nZXRfZHJ2X3ByaXYocSk7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXZw dV9pbnN0X3VubG9jayhpbnN0KTsKPiArCXJldCA9IHZwdV9pbnN0X3JlZ2lzdGVyKGluc3QpOwo+ ICsJdnB1X2luc3RfbG9jayhpbnN0KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiAr Cj4gKwl2cHVfaW5zdF9nZXQoaW5zdCk7Cj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfRkxPVywgIiVz IHN0YXJ0IHN0cmVhbWluZyA6ICVkXG4iLAo+ICsJCQl2cHVfdHlwZV9uYW1lKHEtPnR5cGUpLCBx LT5udW1fYnVmZmVycyk7Cj4gKwljYWxsX3ZvcChpbnN0LCBzdGFydCwgcS0+dHlwZSk7Cj4gKwl2 YjJfY2xlYXJfbGFzdF9idWZmZXJfZGVxdWV1ZWQocSk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30K PiArCj4gK3N0YXRpYyB2b2lkIHZwdV92YjJfc3RvcF9zdHJlYW1pbmcoc3RydWN0IHZiMl9xdWV1 ZSAqcSkKPiArewo+ICsJc3RydWN0IHZwdV9pbnN0ICppbnN0ID0gdmIyX2dldF9kcnZfcHJpdihx KTsKPiArCj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfRkxPVywgIiVzIHN0b3Agc3RyZWFtaW5nXG4i LCB2cHVfdHlwZV9uYW1lKHEtPnR5cGUpKTsKPiArCj4gKwljYWxsX3ZvcChpbnN0LCBzdG9wLCBx LT50eXBlKTsKPiArCXZwdV92YjJfYnVmZmVyc19yZXR1cm4oaW5zdCwgcS0+dHlwZSwgVkIyX0JV Rl9TVEFURV9FUlJPUik7Cj4gKwlpZiAoVjRMMl9UWVBFX0lTX09VVFBVVChxLT50eXBlKSkKPiAr CQlpbnN0LT5zZXF1ZW5jZSA9IDA7Cj4gKwo+ICsJdnB1X2luc3RfcHV0KGluc3QpOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgdm9pZCB2cHVfdmIyX2J1Zl9xdWV1ZShzdHJ1Y3QgdmIyX2J1ZmZlciAqdmIp Cj4gK3sKPiArCXN0cnVjdCB2YjJfdjRsMl9idWZmZXIgKnZidWYgPSB0b192YjJfdjRsMl9idWZm ZXIodmIpOwo+ICsJc3RydWN0IHZwdV9pbnN0ICppbnN0ID0gdmIyX2dldF9kcnZfcHJpdih2Yi0+ dmIyX3F1ZXVlKTsKPiArCj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfREVCVUcsICIlcyBidWYgcXVl dWVcbiIsIHZwdV90eXBlX25hbWUodmItPnR5cGUpKTsKPiArCj4gKwlpZiAoVjRMMl9UWVBFX0lT X09VVFBVVCh2Yi0+dHlwZSkpIHsKPiArCQl2YnVmLT5zZXF1ZW5jZSA9IGluc3QtPnNlcXVlbmNl Kys7Cj4gKwkJaWYgKChzNjQpdmItPnRpbWVzdGFtcCA8IDApCj4gKwkJCXZiLT50aW1lc3RhbXAg PSBWUFVfSU5WQUxJRF9USU1FU1RBTVA7Cj4gKwl9Cj4gKwo+ICsJdjRsMl9tMm1fYnVmX3F1ZXVl KGluc3QtPm0ybV9jdHgsIHZidWYpOwo+ICsJdnB1X3Byb2Nlc3Nfb3V0cHV0X2J1ZmZlcihpbnN0 KTsKPiArCXZwdV9wcm9jZXNzX2NhcHR1cmVfYnVmZmVyKGluc3QpOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgc3RydWN0IHZiMl9vcHMgdnB1X3ZiMl9vcHMgPSB7Cj4gKwkucXVldWVfc2V0dXAgICAgICAg ID0gdnB1X3ZiMl9xdWV1ZV9zZXR1cCwKPiArCS5idWZfaW5pdCAgICAgICAgICAgPSB2cHVfdmIy X2J1Zl9pbml0LAo+ICsJLmJ1Zl9jbGVhbnVwICAgICAgICA9IHZwdV92YjJfYnVmX2NsZWFudXAs Cj4gKwkuYnVmX3ByZXBhcmUgICAgICAgID0gdnB1X3ZiMl9idWZfcHJlcGFyZSwKPiArCS5idWZf ZmluaXNoICAgICAgICAgPSB2cHVfdmIyX2J1Zl9maW5pc2gsCj4gKwkuc3RhcnRfc3RyZWFtaW5n ICAgID0gdnB1X3ZiMl9zdGFydF9zdHJlYW1pbmcsCj4gKwkuc3RvcF9zdHJlYW1pbmcgICAgID0g dnB1X3ZiMl9zdG9wX3N0cmVhbWluZywKPiArCS5idWZfcXVldWUgICAgICAgICAgPSB2cHVfdmIy X2J1Zl9xdWV1ZSwKPiArCS53YWl0X3ByZXBhcmUgICAgICAgPSB2YjJfb3BzX3dhaXRfcHJlcGFy ZSwKPiArCS53YWl0X2ZpbmlzaCAgICAgICAgPSB2YjJfb3BzX3dhaXRfZmluaXNoLAo+ICt9Owo+ ICsKPiArc3RhdGljIGludCB2cHVfbTJtX3F1ZXVlX2luaXQodm9pZCAqcHJpdiwgc3RydWN0IHZi Ml9xdWV1ZSAqc3JjX3ZxLAo+ICsJCQkgIHN0cnVjdCB2YjJfcXVldWUgKmRzdF92cSkKPiArewo+ ICsJc3RydWN0IHZwdV9pbnN0ICppbnN0ID0gcHJpdjsKPiArCWludCByZXQ7Cj4gKwo+ICsJc3Jj X3ZxLT50eXBlID0gVjRMMl9CVUZfVFlQRV9WSURFT19PVVRQVVRfTVBMQU5FOwo+ICsJc3JjX3Zx LT5pb19tb2RlcyA9IFZCMl9NTUFQIHwgVkIyX1VTRVJQVFIgfCBWQjJfRE1BQlVGOwo+ICsJc3Jj X3ZxLT50aW1lc3RhbXBfZmxhZ3MgPSBWNEwyX0JVRl9GTEFHX1RJTUVTVEFNUF9DT1BZOwo+ICsJ c3JjX3ZxLT5vcHMgPSAmdnB1X3ZiMl9vcHM7Cj4gKwlzcmNfdnEtPm1lbV9vcHMgPSAmdmIyX2Rt YV9jb250aWdfbWVtb3BzOwo+ICsJaWYgKGluc3QtPnR5cGUgPT0gVlBVX0NPUkVfVFlQRV9ERUMg JiYgaW5zdC0+dXNlX3N0cmVhbV9idWZmZXIpCj4gKwkJc3JjX3ZxLT5tZW1fb3BzID0gJnZiMl92 bWFsbG9jX21lbW9wczsKPiArCXNyY192cS0+ZHJ2X3ByaXYgPSBpbnN0Owo+ICsJc3JjX3ZxLT5i dWZfc3RydWN0X3NpemUgPSBzaXplb2Yoc3RydWN0IHZwdV92YjJfYnVmZmVyKTsKPiArCXNyY192 cS0+YWxsb3dfemVyb19ieXRlc3VzZWQgPSAxOwo+ICsJc3JjX3ZxLT5taW5fYnVmZmVyc19uZWVk ZWQgPSAxOwo+ICsJc3JjX3ZxLT5kZXYgPSBpbnN0LT5jb3JlLT5kZXY7Cj4gKwlzcmNfdnEtPmxv Y2sgPSAmaW5zdC0+bG9jazsKPiArCXJldCA9IHZiMl9xdWV1ZV9pbml0KHNyY192cSk7Cj4gKwlp ZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJZHN0X3ZxLT50eXBlID0gVjRMMl9CVUZf VFlQRV9WSURFT19DQVBUVVJFX01QTEFORTsKPiArCWRzdF92cS0+aW9fbW9kZXMgPSBWQjJfTU1B UCB8IFZCMl9VU0VSUFRSIHwgVkIyX0RNQUJVRjsKPiArCWRzdF92cS0+dGltZXN0YW1wX2ZsYWdz ID0gVjRMMl9CVUZfRkxBR19USU1FU1RBTVBfQ09QWTsKPiArCWRzdF92cS0+b3BzID0gJnZwdV92 YjJfb3BzOwo+ICsJZHN0X3ZxLT5tZW1fb3BzID0gJnZiMl9kbWFfY29udGlnX21lbW9wczsKPiAr CWlmIChpbnN0LT50eXBlID09IFZQVV9DT1JFX1RZUEVfRU5DICYmIGluc3QtPnVzZV9zdHJlYW1f YnVmZmVyKQo+ICsJCWRzdF92cS0+bWVtX29wcyA9ICZ2YjJfdm1hbGxvY19tZW1vcHM7Cj4gKwlk c3RfdnEtPmRydl9wcml2ID0gaW5zdDsKPiArCWRzdF92cS0+YnVmX3N0cnVjdF9zaXplID0gc2l6 ZW9mKHN0cnVjdCB2cHVfdmIyX2J1ZmZlcik7Cj4gKwlkc3RfdnEtPmFsbG93X3plcm9fYnl0ZXN1 c2VkID0gMTsKPiArCWRzdF92cS0+bWluX2J1ZmZlcnNfbmVlZGVkID0gMTsKPiArCWRzdF92cS0+ ZGV2ID0gaW5zdC0+Y29yZS0+ZGV2Owo+ICsJZHN0X3ZxLT5sb2NrID0gJmluc3QtPmxvY2s7Cj4g KwlyZXQgPSB2YjJfcXVldWVfaW5pdChkc3RfdnEpOwo+ICsJaWYgKHJldCkgewo+ICsJCXZiMl9x dWV1ZV9yZWxlYXNlKHNyY192cSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1 cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVfdjRsMl9yZWxlYXNlKHN0cnVjdCB2cHVf aW5zdCAqaW5zdCkKPiArewo+ICsJc3RydWN0IHZwdV9jb3JlICpjb3JlID0gaW5zdC0+Y29yZTsK PiArCj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxfRkxPVywgIiVzXG4iLCBfX2Z1bmNfXyk7Cj4gKwo+ ICsJdnB1X3JlbGVhc2VfY29yZShjb3JlKTsKPiArCj4gKwlpZiAoaW5zdC0+d29ya3F1ZXVlKSB7 Cj4gKwkJY2FuY2VsX3dvcmtfc3luYygmaW5zdC0+bXNnX3dvcmspOwo+ICsJCWRlc3Ryb3lfd29y a3F1ZXVlKGluc3QtPndvcmtxdWV1ZSk7Cj4gKwkJaW5zdC0+d29ya3F1ZXVlID0gTlVMTDsKPiAr CX0KPiArCWlmIChpbnN0LT5tMm1fY3R4KSB7Cj4gKwkJdjRsMl9tMm1fY3R4X3JlbGVhc2UoaW5z dC0+bTJtX2N0eCk7Cj4gKwkJaW5zdC0+bTJtX2N0eCA9IE5VTEw7Cj4gKwl9Cj4gKwlpZiAoaW5z dC0+bTJtX2Rldikgewo+ICsJCXY0bDJfbTJtX3JlbGVhc2UoaW5zdC0+bTJtX2Rldik7Cj4gKwkJ aW5zdC0+bTJtX2RldiA9IE5VTEw7Cj4gKwl9Cj4gKwo+ICsJdjRsMl9jdHJsX2hhbmRsZXJfZnJl ZSgmaW5zdC0+Y3RybF9oYW5kbGVyKTsKPiArCW11dGV4X2Rlc3Ryb3koJmluc3QtPmxvY2spOwo+ ICsJdjRsMl9maF9kZWwoJmluc3QtPmZoKTsKPiArCXY0bDJfZmhfZXhpdCgmaW5zdC0+ZmgpOwo+ ICsKPiArCWNhbGxfdm9wKGluc3QsIGNsZWFudXApOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4g Kwo+ICtpbnQgdnB1X3Y0bDJfb3BlbihzdHJ1Y3QgZmlsZSAqZmlsZSwgc3RydWN0IHZwdV9pbnN0 ICppbnN0KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2RldiAqdnB1ID0gdmlkZW9fZHJ2ZGF0YShmaWxl KTsKPiArCXN0cnVjdCB2aWRlb19kZXZpY2UgKnZkZXY7Cj4gKwlzdHJ1Y3QgdnB1X2NvcmUgKmNv cmUgPSBOVUxMOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJV0FSTl9PTighZmlsZSB8fCAhaW5z dCB8fCAhaW5zdC0+b3BzKTsKPiArCj4gKwlpZiAoaW5zdC0+dHlwZSA9PSBWUFVfQ09SRV9UWVBF X0VOQykKPiArCQl2ZGV2ID0gdnB1LT52ZGV2X2VuYzsKPiArCWVsc2UKPiArCQl2ZGV2ID0gdnB1 LT52ZGV2X2RlYzsKPiArCj4gKwltdXRleF9pbml0KCZpbnN0LT5sb2NrKTsKPiArCUlOSVRfTElT VF9IRUFEKCZpbnN0LT5jbWRfcSk7Cj4gKwo+ICsJaW5zdC0+aWQgPSBWUFVfSU5TVF9OVUxMX0lE Owo+ICsJaW5zdC0+cmVsZWFzZSA9IHZwdV92NGwyX3JlbGVhc2U7Cj4gKwlpbnN0LT5jb3JlID0g dnB1X3JlcXVlc3RfY29yZSh2cHUsIGluc3QtPnR5cGUpOwo+ICsJaW5zdC0+cGlkID0gY3VycmVu dC0+cGlkOwo+ICsJaW5zdC0+dGdpZCA9IGN1cnJlbnQtPnRnaWQ7Cj4gKwo+ICsJY29yZSA9IGlu c3QtPmNvcmU7Cj4gKwlpZiAoIWNvcmUpIHsKPiArCQl2cHVfZXJyKCJ0aGVyZSBpcyBubyBjb3Jl IGZvciAlc1xuIiwKPiArCQkJdnB1X2NvcmVfdHlwZV9kZXNjKGluc3QtPnR5cGUpKTsKPiArCQly ZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlpbnN0LT5taW5fYnVmZmVyX2NhcCA9IDI7Cj4g KwlpbnN0LT5taW5fYnVmZmVyX291dCA9IDI7Cj4gKwo+ICsJcmV0ID0gY2FsbF92b3AoaW5zdCwg Y3RybF9pbml0KTsKPiArCWlmIChyZXQpCj4gKwkJZ290byBlcnJvcjsKPiArCj4gKwlpbnN0LT5t Mm1fZGV2ID0gdjRsMl9tMm1faW5pdCgmdnB1X20ybV9vcHMpOwo+ICsJaWYgKElTX0VSUihpbnN0 LT5tMm1fZGV2KSkgewo+ICsJCXZwdV9lcnIoInY0bDJfbTJtX2luaXQgZmFpbFxuIik7Cj4gKwkJ cmV0ID0gUFRSX0VSUihpbnN0LT5tMm1fZGV2KTsKPiArCQlnb3RvIGVycm9yOwo+ICsJfQo+ICsK PiArCWluc3QtPm0ybV9jdHggPSB2NGwyX20ybV9jdHhfaW5pdChpbnN0LT5tMm1fZGV2LAo+ICsJ CQkJCWluc3QsIHZwdV9tMm1fcXVldWVfaW5pdCk7Cj4gKwlpZiAoSVNfRVJSKGluc3QtPm0ybV9j dHgpKSB7Cj4gKwkJdnB1X2VycigidjRsMl9tMm1fY3R4X2luaXQgZmFpbFxuIik7Cj4gKwkJcmV0 ID0gUFRSX0VSUihpbnN0LT5tMm1fZGV2KTsKPiArCQlnb3RvIGVycm9yOwo+ICsJfQo+ICsKPiAr CXY0bDJfZmhfaW5pdCgmaW5zdC0+ZmgsIHZkZXYpOwo+ICsJdjRsMl9maF9hZGQoJmluc3QtPmZo KTsKPiArCWluc3QtPmZoLmN0cmxfaGFuZGxlciA9ICZpbnN0LT5jdHJsX2hhbmRsZXI7Cj4gKwlp bnN0LT5maC5tMm1fY3R4ID0gaW5zdC0+bTJtX2N0eDsKPiArCWZpbGUtPnByaXZhdGVfZGF0YSA9 ICZpbnN0LT5maDsKPiArCWluc3QtPnN0YXRlID0gVlBVX0NPREVDX1NUQVRFX0RFSU5JVDsKPiAr CWluc3QtPndvcmtxdWV1ZSA9IGFsbG9jX3dvcmtxdWV1ZSgidnB1X2luc3QiLCBXUV9VTkJPVU5E IHwgV1FfTUVNX1JFQ0xBSU0sIDEpOwo+ICsJaWYgKGluc3QtPndvcmtxdWV1ZSkgewo+ICsJCUlO SVRfV09SSygmaW5zdC0+bXNnX3dvcmssIHZwdV9pbnN0X3J1bl93b3JrKTsKPiArCQlyZXQgPSBr Zmlmb19pbml0KCZpbnN0LT5tc2dfZmlmbywKPiArCQkJCWluc3QtPm1zZ19idWZmZXIsCj4gKwkJ CQlyb3VuZHVwX3Bvd19vZl90d28oc2l6ZW9mKGluc3QtPm1zZ19idWZmZXIpKSk7Cj4gKwkJaWYg KHJldCkgewo+ICsJCQlkZXN0cm95X3dvcmtxdWV1ZShpbnN0LT53b3JrcXVldWUpOwo+ICsJCQlp bnN0LT53b3JrcXVldWUgPSBOVUxMOwo+ICsJCX0KPiArCX0KPiArCWF0b21pY19zZXQoJmluc3Qt PnJlZl9jb3VudCwgMCk7Cj4gKwl2cHVfaW5zdF9nZXQoaW5zdCk7Cj4gKwl2cHVfZGJnKExWTF9G TE9XLCAib3BlbiwgdGdpZCA9ICVkLCBwaWQgPSAlZFxuIiwgaW5zdC0+dGdpZCwgaW5zdC0+cGlk KTsKPiArCj4gKwlyZXR1cm4gMDsKPiArZXJyb3I6Cj4gKwlpZiAoaW5zdC0+bTJtX2N0eCkgewo+ ICsJCXY0bDJfbTJtX2N0eF9yZWxlYXNlKGluc3QtPm0ybV9jdHgpOwo+ICsJCWluc3QtPm0ybV9j dHggPSBOVUxMOwo+ICsJfQo+ICsJaWYgKGluc3QtPm0ybV9kZXYpIHsKPiArCQl2NGwyX20ybV9y ZWxlYXNlKGluc3QtPm0ybV9kZXYpOwo+ICsJCWluc3QtPm0ybV9kZXYgPSBOVUxMOwo+ICsJfQo+ ICsJdjRsMl9jdHJsX2hhbmRsZXJfZnJlZSgmaW5zdC0+Y3RybF9oYW5kbGVyKTsKPiArCXZwdV9y ZWxlYXNlX2NvcmUoaW5zdC0+Y29yZSk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAr aW50IHZwdV92NGwyX2Nsb3NlKHN0cnVjdCBmaWxlICpmaWxlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1 X2luc3QgKmluc3QgPSB0b19pbnN0KGZpbGUpOwo+ICsJc3RydWN0IHZiMl9xdWV1ZSAqc3JjX3E7 Cj4gKwlzdHJ1Y3QgdmIyX3F1ZXVlICpkc3RfcTsKPiArCj4gKwlpbnN0X2RiZyhpbnN0LCBMVkxf RkxPVywgImNsb3NlXG4iKTsKPiArCXNyY19xID0gdjRsMl9tMm1fZ2V0X3NyY192cShpbnN0LT5t Mm1fY3R4KTsKPiArCWRzdF9xID0gdjRsMl9tMm1fZ2V0X2RzdF92cShpbnN0LT5tMm1fY3R4KTsK PiArCXZwdV9pbnN0X2xvY2soaW5zdCk7Cj4gKwlpZiAodmIyX2lzX3N0cmVhbWluZyhzcmNfcSkp Cj4gKwkJdjRsMl9tMm1fc3RyZWFtb2ZmKGZpbGUsIGluc3QtPm0ybV9jdHgsIHNyY19xLT50eXBl KTsKPiArCWlmICh2YjJfaXNfc3RyZWFtaW5nKGRzdF9xKSkKPiArCQl2NGwyX20ybV9zdHJlYW1v ZmYoZmlsZSwgaW5zdC0+bTJtX2N0eCwgZHN0X3EtPnR5cGUpOwo+ICsJdnB1X2luc3RfdW5sb2Nr KGluc3QpOwo+ICsKPiArCWNhbGxfdm9wKGluc3QsIHJlbGVhc2UpOwo+ICsJdnB1X2luc3RfdW5y ZWdpc3RlcihpbnN0KTsKPiArCXZwdV9pbnN0X3B1dChpbnN0KTsKPiArCj4gKwlyZXR1cm4gMDsK PiArfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X3Y0 bDIuaCBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfdjRsMi5oCj4gbmV3IGZp bGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjg4NzNlMWY2NjA3Mgo+IC0tLSAv ZGV2L251bGwKPiArKysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X3Y0bDIu aAo+IEBAIC0wLDAgKzEsNTMgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0y LjAgKi8KPiArLyoKPiArICogQ29weXJpZ2h0IDIwMjAtMjAyMSBOWFAKPiArICovCj4gKwo+ICsj aWZuZGVmIF9BTVBISU9OX1ZQVV9WNEwyX0gKPiArI2RlZmluZSBfQU1QSElPTl9WUFVfVjRMMl9I Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvdmlkZW9kZXYyLmg+Cj4gKwo+ICt2b2lkIHZwdV9pbnN0 X2xvY2soc3RydWN0IHZwdV9pbnN0ICppbnN0KTsKPiArdm9pZCB2cHVfaW5zdF91bmxvY2soc3Ry dWN0IHZwdV9pbnN0ICppbnN0KTsKPiArCj4gK2ludCB2cHVfdjRsMl9vcGVuKHN0cnVjdCBmaWxl ICpmaWxlLCBzdHJ1Y3QgdnB1X2luc3QgKmluc3QpOwo+ICtpbnQgdnB1X3Y0bDJfY2xvc2Uoc3Ry dWN0IGZpbGUgKmZpbGUpOwo+ICsKPiArY29uc3Qgc3RydWN0IHZwdV9mb3JtYXQgKnZwdV90cnlf Zm10X2NvbW1vbihzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHN0cnVjdCB2NGwyX2Zvcm1hdCAqZik7 Cj4gK2ludCB2cHVfcHJvY2Vzc19vdXRwdXRfYnVmZmVyKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCk7 Cj4gK2ludCB2cHVfcHJvY2Vzc19jYXB0dXJlX2J1ZmZlcihzdHJ1Y3QgdnB1X2luc3QgKmluc3Qp Owo+ICtzdHJ1Y3QgdmIyX3Y0bDJfYnVmZmVyICp2cHVfZmluZF9idWZfYnlfc2VxdWVuY2Uoc3Ry dWN0IHZwdV9pbnN0ICppbnN0LCB1MzIgdHlwZSwgdTMyIHNlcXVlbmNlKTsKPiArc3RydWN0IHZi Ml92NGwyX2J1ZmZlciAqdnB1X2ZpbmRfYnVmX2J5X2lkeChzdHJ1Y3QgdnB1X2luc3QgKmluc3Qs IHUzMiB0eXBlLCB1MzIgaWR4KTsKPiArdm9pZCB2cHVfdjRsMl9zZXRfZXJyb3Ioc3RydWN0IHZw dV9pbnN0ICppbnN0KTsKPiAraW50IHZwdV9ub3RpZnlfZW9zKHN0cnVjdCB2cHVfaW5zdCAqaW5z dCk7Cj4gK2ludCB2cHVfbm90aWZ5X3NvdXJjZV9jaGFuZ2Uoc3RydWN0IHZwdV9pbnN0ICppbnN0 KTsKPiArdm9pZCB2cHVfdmIyX2J1ZmZlcnNfcmV0dXJuKHN0cnVjdCB2cHVfaW5zdCAqaW5zdCwK PiArCQl1bnNpZ25lZCBpbnQgdHlwZSwgZW51bSB2YjJfYnVmZmVyX3N0YXRlIHN0YXRlKTsKPiAr aW50IHZwdV9nZXRfbnVtX2J1ZmZlcnMoc3RydWN0IHZwdV9pbnN0ICppbnN0LCB1MzIgdHlwZSk7 Cj4gKwo+ICtkbWFfYWRkcl90IHZwdV9nZXRfdmJfcGh5X2FkZHIoc3RydWN0IHZiMl9idWZmZXIg KnZiLCB1MzIgcGxhbmVfbm8pOwo+ICt1bnNpZ25lZCBpbnQgdnB1X2dldF92Yl9sZW5ndGgoc3Ry dWN0IHZiMl9idWZmZXIgKnZiLCB1MzIgcGxhbmVfbm8pOwo+ICtzdGF0aWMgaW5saW5lIHN0cnVj dCB2cHVfZm9ybWF0ICp2cHVfZ2V0X2Zvcm1hdChzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHUzMiB0 eXBlKQo+ICt7Cj4gKwlpZiAoVjRMMl9UWVBFX0lTX09VVFBVVCh0eXBlKSkKPiArCQlyZXR1cm4g Jmluc3QtPm91dF9mb3JtYXQ7Cj4gKwllbHNlCj4gKwkJcmV0dXJuICZpbnN0LT5jYXBfZm9ybWF0 Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGNoYXIgKnZwdV90eXBlX25hbWUodTMyIHR5cGUp Cj4gK3sKPiArCXJldHVybiBWNEwyX1RZUEVfSVNfT1VUUFVUKHR5cGUpID8gIm91dHB1dCIgOiAi Y2FwdHVyZSI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50IHZwdV92Yl9pc19jb2RlY2Nv bmZpZyhzdHJ1Y3QgdmIyX3Y0bDJfYnVmZmVyICp2YnVmKQo+ICt7Cj4gKyNpZmRlZiBWNEwyX0JV Rl9GTEFHX0NPREVDQ09ORklHCj4gKwlyZXR1cm4gKHZidWYtPmZsYWdzICYgVjRMMl9CVUZfRkxB R19DT0RFQ0NPTkZJRykgPyAxIDogMDsKPiArI2Vsc2UKPiArCXJldHVybiAwOwo+ICsjZW5kaWYK PiArfQo+ICsKPiArI2VuZGlmCgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJu ZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFu L2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK